/**
* jQuery Maxlength plugin
* @version		$Id: jquery.maxlength.js 18 2009-05-16 15:37:08Z emil@anon-design.se $
* @package		jQuery maxlength 1.0.5
* @copyright	Copyright (C) 2009 Emil Stjerneman / http://www.anon-design.se
* @license		GNU/GPL, see LICENSE.txt
*
* 25737917          May. 03/2012        Alan            Added UI.MaxLengthTextMessage
*                   APR 24 2013         Jeyong Lee      Modified updateStatus, checkChars and showAlert
*                                                       updateStatus - made syntax definition same as checkChars
*                                                       checkChars - blur current input selection when max is triggered
*                                                                  - trim until all characters are formatted to correct length
*                                                       showAlert - call custom modal window instead of simple alert();
* 47981095          May 15 2013         Jeyong Lee      checkChars - removed blur, and added functions to re-position cursors/selections after field value resets
*                                                       If application uses showAlert, we should re-implement blur with special cases
*/

(function ($) {

    $.fn.maxlength = function (options) {
        var settings = jQuery.extend(
		{
		    events: [], // Array of events to be triggerd
		    maxCharacters: 10, // Characters limit
		    status: true, // True to show status indicator bewlow the element
		    statusClass: "status", // The class on the status div
		    statusText: "character left", // The status text
		    notificationClass: "notification", // Will be added to the emement when maxlength is reached
		    showAlert: false, // True to show a regular alert message
		    alertText: "You have typed too many characters.", // Text in the alert message
		    slider: false, // Use counter slider
		    sliderOnShow: null,
		    sliderOnHide: null
		}, options);

        // Add the default event
        $.merge(settings.events, ['keyup', 'change', 'paste', 'onFocus']);     // ARR May/1/2012. Ticket: 25737917. -  Add 'change' and 'paste' events because with google chrome didn't validate when paste text longer than maxCharacters

        return this.each(function () {
            var item = $(this);
            var charactersLength = $(this).val().length;

            // Update the status text
            function updateStatus() {

                //occurances of line break
                var lineBreakCount = (item.val().match(/\n/g) || []).length;
                var currentLength = charactersLength + lineBreakCount;
                var count = currentLength; // settings.maxCharacters - currentLength;
                if (count < 0)
                    count = 0;

                if (count > settings.maxCharacters)
                    count = settings.maxCharacters;

                if (currentLength >= settings.maxCharacters)
                    item.next("div").addClass("max");
                else
                    item.next("div").removeClass("max");

                item.next("div").html(count + settings.statusText);
            }

            function checkChars() {

                var lineBreakCount = (item.val().match(/\n/g) || []).length;
                var currentLength = charactersLength + lineBreakCount;
                if (currentLength > settings.maxCharacters) {

                    var trimmedText = item.val().substr(0, settings.maxCharacters);
                    var lineBreakCountInTrimmedText = (trimmedText.match(/\n/g) || []).length;
                    var actualLength = trimmedText.length + lineBreakCountInTrimmedText;

                    while (actualLength > settings.maxCharacters) {
                        trimmedText = trimmedText.substr(0, settings.maxCharacters - lineBreakCountInTrimmedText);
                        lineBreakCountInTrimmedText = (trimmedText.match(/\n/g) || []).length;
                        actualLength = trimmedText.length + lineBreakCountInTrimmedText;
                    }

                    if (actualLength < settings.maxCharacters)
                        trimmedText += " ";

                    var currentPos = item.scrollTop();
                    var currentSelStart = item.prop("selectionStart");
                    var currentSelEnd = item.prop("selectionEnd");

                    item.val(trimmedText);
                    item.scrollTop(currentPos);

                    if (this.createTextRange) {
                        var selRange = this.createTextRange();
                        selRange.collapse(true);
                        selRange.moveStart('character', currentSelStart);
                        selRange.moveEnd('character', currentSelEnd);
                        selRange.select();
                    } else if (this.setSelectionRange) {
                        this.setSelectionRange(currentSelStart, currentSelEnd);
                    } else if (this.selectionStart) {
                        this.selectionStart = currentSelStart;
                        this.selectionEnd = currentSelEnd;
                    }

                    showAlert();
                }
                else {
                    // Remove the notification class
                    if (item.hasClass(settings.notificationClass)) {
                        item.removeClass(settings.notificationClass);
                    }
                }

                if (settings.status) {
                    updateStatus();
                }
            }

            // Shows an alert msg
            function showAlert() {
                if (settings.showAlert) {
                    alert(settings.alertText);
                }
            }

            // Check if the element is valid.
            function validateElement() {
                var ret = false;

                if (item.is('textarea')) {
                    ret = true;
                } else if (item.filter("input[type=text]")) {
                    ret = true;
                } else if (item.filter("input[type=password]")) {
                    ret = true;
                }

                return ret;
            }

            // Validate
            if (!validateElement()) {
                return false;
            }

            // Loop through the events and bind them to the element
            $.each(settings.events, function (i, n) {
                item.bind(n, function () {
                    charactersLength = item.val().length;
                    checkChars();
                });
            });

            // Insert the status div
            if (settings.status) {
                item.after($("<div/>").addClass(settings.statusClass).html('-'));
                updateStatus();
            }

            // Remove the status div
            if (!settings.status) {
                var removeThisDiv = item.next("div." + settings.statusClass);

                if (removeThisDiv) {
                    removeThisDiv.remove();
                }

            }

            // Slide counter
            if (settings.slider) {
                item.next().hide();
                item.on('focus', function () {        // AX-24898.24919.2 focus(function () {

                    charactersLength = item.val().length;
                    checkChars();

                    item.next().slideDown('fast', function () {
                        if (settings.sliderOnShow != null)
                            settings.sliderOnShow();
                    });
                });

                item.on('blur', function () {			// AX-24898.24919.2 .blur(function() {

                    charactersLength = item.val().length;
                    checkChars();

                    item.next().slideUp('fast', function () {
                        if (settings.sliderOnHide != null)
                            settings.sliderOnHide();
                    });
                });
            } else {
                item.on('focus', function () {        // AX-24898.24919.2 focus(function () {
                    charactersLength = item.val().length;
                    checkChars();
                });
                item.on('blur', function () {			// AX-24898.24919.2 .blur(function() {
                    charactersLength = item.val().length;
                    checkChars();
                });
            }

        });
    };
})(jQuery);
