/**** onload and listeners ****/
var numStory = 20; //number of message to display, default 20
var storyCount = 0; //start with 0 count
var storyStart = 0; //start with most recent message (DESC 0)

var numTerm = 20; //number of message to display, default 20
var termCount = 0; //start with 0 count
var termStart = 0; //start with most recent message (DESC 0)

if (gup('c') && Number(gup('c')) <= 100) { //if set as param, use instead of default (no more than 100 per page load)
    numMsg = Number(gup('c'));
    numTerm = Number(gup('c'));
}

$(function() {
    //toggle the Add-a-Line directions on stories that already have lines added, default hidden
    if ($('#mostRecentLine #directions').html()) {
        $('#mostRecentLine #directions').hide();
        $('#mostRecentLine form').prepend('<a href="#" id="viewDirections">Add-a-Line Directions</a>');
        $('#viewDirections').click(function (){
            $('#mostRecentLine #directions').toggle();
            $('html, body').animate({scrollTop: $('#viewDirections').offset().top}, 1000);
            return false;
        });
    }
    
    //Add-a-Line pagination
    if ($('#archives').is('div')) {
        $.post("/ajax/addaline.php", {getStory: 'count'}, function(data){
            storyCount = data; //grab actual count for tabbing through stories
            $('#archives .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + (numStory + storyStart) + ' of ' + storyCount + ' archived stories '); //initialize pagination display based on count
            if (storyCount <= (numStory + storyStart)) { $('.calltoaction').hide(); } //hide pagination if displayed stories <= total stories
        });
    }
    
    //Add-a-Definition pagination
    if ($('#dictionary').is('div')) {
        $.post("/ajax/addadefinition.php", {getTerm: 'count'}, function(data){
            termCount = data; //grab actual count for tabbing through stories
            $('#dictionary .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + (numTerm + termStart) + ' of ' + termCount + ' terms '); //initialize pagination display based on count
            if (termCount <= (numTerm + termStart)) { $('#dictionary .calltoaction').hide(); } //hide pagination if displayed terms <= total terms
        });
    }
    
    //initialize Add-a-Line active stories tooltips
    $('#content #activeStories .title a').hover( function () {
        //add span element on first event to contain ajaxed content
        if (!$(this).siblings('span').html()) {
            $(this).parent().append('<span>Loading Summary</span>');
        }
        $storyId = $(this).parent().attr('id').split('_');
        if ($("#activeStories #activeStory_" + $storyId[1] + " span").html() == 'Loading Summary') {
            $("#activeStories #activeStory_" + $storyId[1] + " span").load(
                "/ajax/addaline.php",
                {getStorySummary: $storyId[1]},
                function () {
                    //set the tooltip value to the line summary content on ajax callback
                    $('#tooltip .body').html($("#activeStories #activeStory_" + $storyId[1] + " span").html());
                }
            );
        }
    }, function () { /*on off hover, do nothing*/ });
    
    //Add-a-Line active stories tooltip
    $('#content #activeStories .title a').tooltip({
        bodyHandler: function() {
            //display the tooltip with the initial "loading" message, ajax will fill in with proper content once loaded
            var id = $(this).parent().attr('id').split('_');
            return $('#activeStory_' + id[1] + ' span').html();
        },
        showURL: false,
        delay: 500,
        fade: 250
    });
    
    //initialize Add-a-Line archived stories
    if ($('#archives').is('div')) {
        $("#archivedStories").load("/ajax/addaline.php", {getStory: storyStart + ',' + numStory}, function () { displayArchiveSummaries(); });
    }
    
    //Add-a-Line archived stories pagination
    $('#archives .calltoaction span').after('<a href="" class="last">last-&gt;&gt;</a>');
    $('#archives .calltoaction span').after('<a href="" class="next">next-&gt;</a> ');
    $('#archives .calltoaction span').after('<a href="" class="prev">&lt;-prev</a> ');
    $('#archives .calltoaction span').after('<a href="" class="first">&lt;&lt;-first</a> ');
    $('#archives .calltoaction a.first').addClass('off');
    $('#archives .calltoaction a.prev').addClass('off');
    
    $('#archives .calltoaction a.first').click(function () {
        this.blur();
        if (storyStart > 0) {
            storyStart = 0;
            $("#archivedStories").load("/ajax/addaline.php", {getStory: storyStart + ',' + numStory},function () { displayArchiveSummaries(); $("#archivedStories").hide();$("#archivedStories").fadeIn("slow"); $('html, body').animate({scrollTop: $('#archives').offset().top}, 1000); });
            $('#archives .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + (numStory + storyStart) + ' of ' + storyCount + ' archived stories ');
            $('#archives .calltoaction a.first').addClass('off');
            $('#archives .calltoaction a.prev').addClass('off');
            $('#archives .calltoaction a.next').removeClass('off');
            $('#archives .calltoaction a.last').removeClass('off');
        }
        return false;
    });
    $('#archives .calltoaction a.prev').click(function () {
        this.blur();
        if (storyStart > 0) {
            storyStart = storyStart - numStory;
            $("#archivedStories").load("/ajax/addaline.php", {getStory: storyStart + ',' + numStory},function () { displayArchiveSummaries(); $("#archivedStories").hide();$("#archivedStories").fadeIn("slow"); $('html, body').animate({scrollTop: $('#archives').offset().top}, 1000); });
            $('#archives .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + (numStory + storyStart) + ' of ' + storyCount + ' archived stories ');
            $('#archives .calltoaction a.next').removeClass('off');
            $('#archives .calltoaction a.last').removeClass('off');
        }
        if (storyStart < numStory) {
            $('#archives .calltoaction a.first').addClass('off');
            $('#archives .calltoaction a.prev').addClass('off');
        }
        return false;
    });
    $('#archives .calltoaction a.next').click(function () {
        this.blur();
        if(storyStart < (storyCount - numStory)) {
             storyStart = storyStart + numStory;
            $("#archivedStories").load("/ajax/addaline.php", {getStory: storyStart + ',' + numStory},function () { displayArchiveSummaries(); $("#archivedStories").hide();$("#archivedStories").fadeIn("slow"); $('html, body').animate({scrollTop: $('#archives').offset().top}, 1000); });
            if (storyCount < (numStory + storyStart)) { var msgsOf = storyCount; } else { var msgsOf = (numStory + storyStart); }
            $('#archives .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + msgsOf + ' of ' + storyCount + ' archived stories ');
            $('#archives .calltoaction a.first').removeClass('off');
            $('#archives .calltoaction a.prev').removeClass('off');
        }
        if((storyStart + numStory) >= storyCount){
            $('a.next').addClass('off');
            $('a.last').addClass('off');
        }
        return false;
    });
    $('#archives .calltoaction a.last').click(function () {
        this.blur();
        if(storyStart < (storyCount - numStory)) {
             storyStart = storyCount - (storyCount%numStory);//start a the total stories minus the remainder or the total stories divided by number of stories to display
            if(storyStart == storyCount) { storyStart = storyCount - numStory; }//if this is the last story (no remainder), start with total stories minus the story count
            $("#archivedStories").load("/ajax/addaline.php", {getStory: storyStart + ',' + numStory},function () { displayArchiveSummaries; $("#archivedStories").hide();$("#archivedStories").fadeIn("slow"); $('html, body').animate({scrollTop: $('#archives').offset().top}, 1000); });
            $('#archives .calltoaction span').html('Displaying ' + (storyStart + 1) + ' - ' + storyCount + ' of ' + storyCount + ' archived stories ');
            $('#archives .calltoaction a.first').removeClass('off');
            $('#archives .calltoaction a.prev').removeClass('off');
            $('#archives .calltoaction a.next').addClass('off');
            $('#archives .calltoaction a.last').addClass('off');
        }
        return false;
    });
    
    //Add-a-Definition terms pagination
    $('#dictionary .calltoaction span').after('<a href="" class="last">last-&gt;&gt;</a>');
    $('#dictionary .calltoaction span').after('<a href="" class="next">next-&gt;</a> ');
    $('#dictionary .calltoaction span').after('<a href="" class="prev">&lt;-prev</a> ');
    $('#dictionary .calltoaction span').after('<a href="" class="first">&lt;&lt;-first</a> ');
    $('#dictionary .calltoaction a.first').addClass('off');
    $('#dictionary .calltoaction a.prev').addClass('off');
    
    $('#dictionary .calltoaction a.first').click(function () {
        this.blur();
        if (termStart > 0) {
            termStart = 0;
            $("#terms").load("/ajax/addadefinition.php", {getTerm: termStart + ',' + numTerm},function () { $("#terms").hide();$("#terms").fadeIn("slow"); $('html, body').animate({scrollTop: $('#dictionary').offset().top}, 1000); });
            $('#dictionary .calltoaction span').html('Displaying ' + (termStart + 1) + ' - ' + (numTerm + termStart) + ' of ' + termCount + ' terms ');
            $('#dictionary .calltoaction a.first').addClass('off');
            $('#dictionary .calltoaction a.prev').addClass('off');
            $('#dictionary .calltoaction a.next').removeClass('off');
            $('#dictionary .calltoaction a.last').removeClass('off');
        }
        return false;
    });
    $('#dictionary .calltoaction a.prev').click(function () {
        this.blur();
        if (termStart > 0) {
            termStart = termStart - numTerm;
            $("#terms").load("/ajax/addadefinition.php", {getTerm: termStart + ',' + numTerm},function () { $("#terms").hide();$("#terms").fadeIn("slow"); $('html, body').animate({scrollTop: $('#dictionary').offset().top}, 1000); });
            $('#dictionary .calltoaction span').html('Displaying ' + (termStart + 1) + ' - ' + (numTerm + termStart) + ' of ' + termCount + ' terms ');
            $('#dictionary .calltoaction a.next').removeClass('off');
            $('#dictionary .calltoaction a.last').removeClass('off');
        }
        if (termStart < numTerm) {
            $('#dictionary .calltoaction a.first').addClass('off');
            $('#dictionary .calltoaction a.prev').addClass('off');
        }
        return false;
    });
    $('#dictionary .calltoaction a.next').click(function () {
        this.blur();
        if(termStart < (termCount - numTerm)) {
            termStart = termStart + numTerm;
            $("#terms").load("/ajax/addadefinition.php", {getTerm: termStart + ',' + numTerm},function () { $("#terms").hide();$("#terms").fadeIn("slow"); $('html, body').animate({scrollTop: $('#dictionary').offset().top}, 1000); });
            if (termCount < (numTerm + termStart)) { var msgsOf = termCount; } else { var msgsOf = (numTerm + termStart); }
            $('#dictionary .calltoaction span').html('Displaying ' + (termStart + 1) + ' - ' + msgsOf + ' of ' + termCount + ' terms ');
            $('#dictionary .calltoaction a.first').removeClass('off');
            $('#dictionary .calltoaction a.prev').removeClass('off');
        }
        if((termStart + numTerm) >= termCount){
            $('a.next').addClass('off');
            $('a.last').addClass('off');
        }
        return false;
    });
    $('#dictionary .calltoaction a.last').click(function () {
        this.blur();
        if(termStart < (termCount - numTerm)) {
             termStart = termCount - (termCount%numTerm);//start a the total terms minus the remainder or the total terms divided by number of terms to display
            if(termStart == termCount) { termStart = termCount - numTerm; }//if this is the last term (no remainder), start with total terms minus the term count
            $("#terms").load("/ajax/addadefinition.php", {getTerm: termStart + ',' + numTerm},function () { $("#terms").hide();$("#terms").fadeIn("slow"); $('html, body').animate({scrollTop: $('#dictionary').offset().top}, 1000); });
            if (termCount < (numTerm + termStart)) { var msgsOf = termCount; } else { var msgsOf = (numTerm + termStart); }
            $('#dictionary .calltoaction span').html('Displaying ' + (termStart + 1) + ' - ' + msgsOf + ' of ' + termCount + ' terms ');
            $('#dictionary .calltoaction a.first').removeClass('off');
            $('#dictionary .calltoaction a.prev').removeClass('off');
            $('#dictionary .calltoaction a.next').addClass('off');
            $('#dictionary .calltoaction a.last').addClass('off');
        }
        return false;
    });
    
    //Add-a-Line archived story highlighting tools
    $('.story').prepend('<p id="highlight"><a href="#">Turn on Highlighting</a></p>');
    $('#highlight a').toggle( function () {
        $(this).html('Turn off Highlighting');
        $('html, body').animate({scrollTop: $('#highlight').offset().top}, 1000);
        //highlighting on
        $('#content #archivedStory .story span.even').css('background','#feefff');
        $('#content #archivedStory .story span.odd').css('background','#ffffdf');
        //show tooltips
        $('.line').tooltip({
            bodyHandler: function() {
                var id = $(this).attr('id').split("_");
                return $('#credit_' + id[1]).html();
            },
            showURL: false,
            delay: 500,
            fade: 250
        });
    }, function () {
        $(this).html('Turn on Highlighting');
        $('html, body').animate({scrollTop: $('#highlight').offset().top}, 1000);
        //highlighting off
        $('#content #archivedStory .story span.even').css('background','#fff');
        $('#content #archivedStory .story span.odd').css('background','#fff');
        //hide tooltips
        $('.line').tooltip($.tooltip.block);
    });
        
    //Add-a-Line active story maxlength on new line textarea
    var charLimit = $('#newLineRow .charsLeft span').html();
    $('#newLine').focus( function () {
        $('#newLineRow .charsLeft').html('<span>' + $('#newLineRow .charsLeft span').html() + '</span> charecter(s) remaining');
        $('#newLine').maxlength({'feedback' : '#newLineRow .charsLeft span'});
    });
    $('#newLine').blur( function () {
        if ($('#newLineRow .charsLeft span').html() > 0) {
            $('#newLineRow .charsLeft').html('You have a possible <span>' + $('#newLineRow .charsLeft span').html() + '</span> character(s) left.');
        } else {
            $('#newLineRow .charsLeft').html('You have reached the ' + charLimit + ' character limit.');
        }
    });
    
    //Add-a-Line active story being archived maxlength on summary textarea (only seen on active stories being archived)
    var summaryCharLimit = $('#summaryRow .charsLeft span').html();
    $('#storyDescription').focus( function () {
        $('#summaryRow .charsLeft').html('<span>' + $('#summaryRow .charsLeft span').html() + '</span> charecter(s) remaining');
        $('#storyDescription').maxlength({'feedback' : '#summaryRow .charsLeft span'});
    });
    $('#storyDescription').blur( function () {
        if ($('#summaryRow .charsLeft span').html() > 0) {
            $('#summaryRow .charsLeft').html('You have a possible <span>' + $('#summaryRow .charsLeft span').html() + '</span> character(s) left.');
        } else {
            $('#summaryRow .charsLeft').html('You have reached the ' + summaryCharLimit + ' character limit.');
        }
    });
    
    //Add-a-Line form handlers
    $('#newStoryForm').submit(function() { //submit a new story title form handler
        $('.validation').remove();
        if ($("#storyTitle").val() != '' && $("#usercaptcha").val() != '') {
            //submit the story for further validation, possibly insert into database, display results
            $.post(
                "/ajax/addaline.php",
                {submitNewStory: $("#storyTitle").val(), usercaptcha: $("#usercaptcha").val(), captchacombination: addslashes($("#captchacombination").val())},
                function(data){
                    if (data.substr(0, 2) == '1_') { //insert success
                        $('#newStoryForm').remove();
                        $('#newStory .note').remove();
                        $("#newStory .calltoaction").after('<div class="headerMsg"><div class="validation valid">Your new title has been successfully created. It is now ready to accept new lines. <a href="/addaline.php?story=' + data.substr(2) + '">Add the first line</a> or go back to the <a href="/addaline.php">Add-a-Line main page</a>.</div></div>');
                        //set captcha cookie
                        var nextweek = new Date();
                        nextweek.setTime(nextweek.getTime() + (7 * 24 * 60 * 60 * 1000));
                        $.cookie('v', '1', { expires: nextweek, path: '/' });
                        return false;
                    } else { //display error message
                        $("#newStory .calltoaction").after('<div class="headerMsg"><div class="validation error">' + data + '</div></div>');
                        return false;
                    }
                }
            );
            return false;
        } else { //display error messages for any required fields left empty
            if ($("#storyTitle").val() == '') {
                $("#storyTitle").parent().append('<span class="validation error">Please enter a title.</span>');
            }
            if ($("#usercaptcha").val() == '') {
                $("#usercaptcha").parent().append('<span class="validation error">Please enter the code.</span>');
            }
            return false;
        }
    });
    
    $('#newLineForm').submit(function() { //submit a new line form handler
        $('.validation').remove();
        if ($("#newLine").val() != '' && $("#usercaptcha").val() != '' && ($("#storyDescription").val() != '' || !$("#storyDescription").is('textarea'))) {
            //submit the line for further validation, possibly insert into database, display results
            $.post(
                "/ajax/addaline.php",
                {
                    submitNewLine: $("#newLine").val(),
                    storyDescription: $("#storyDescription").val(),
                    userName: $("#userName").val(),
                    userEmail: $("#userEmail").val(),
                    notes: $("#notes").val(),
                    lineStoryTitle: $("#lineStoryTitle").val(),
                    usercaptcha: $("#usercaptcha").val(),
                    captchacombination: addslashes($("#captchacombination").val())
                },
                function(data){
                    if (data.substr(0, 2) == '1_') { //insert success
                        $('#characters').remove();
                        $('#contributors').remove();
                        $('#mostRecentLine').remove();
                        $('#addToNewStory').remove();
                        $('#activeStory .calltoaction').after(data.substr(2));
                        //set captcha cookie
                        var nextweek = new Date();
                        nextweek.setTime(nextweek.getTime() + (7 * 24 * 60 * 60 * 1000));
                        $.cookie('v', '1', { expires: nextweek, path: '/' });
                    } else { //display error message
                        $("#mostRecentLine").prepend('<div class="headerMsg"><div class="validation error">' + data + '</div></div>');
                    }
                    $('html, body').animate({scrollTop: $('#container').offset().top}, 2000); //scroll to top for results message
                    return false;
                }
            );
            return false;
        } else { //display error messages for any required fields left empty
            if ($("#newLine").val() == '') {
                $("#newLine").parent().append('<span class="validation error">Please enter a line.</span>');
            }
            if ($("#usercaptcha").val() == '') {
                $("#usercaptcha").parent().append('<span class="validation error">Please enter the code.</span>');
            }
            if ($("#storyDescription").val() == '' && $("#storyDescription").is('textarea')) {
                $("#storyDescription").parent().append('<span class="validation error">Please enter a summary.</span>');
            }
            return false;
        }
    });
    
    //Add-a-Definition form handlers
    $('#newTermForm').submit(function() { //submit a new term form handler
        $('.validation').remove();
        if ($("#word").val() != '' && $("#usercaptcha").val() != '') {
            //submit the term for further validation, possibly insert into database, display results
            $.post(
                "/ajax/addadefinition.php",
                {submitNewTerm: $("#word").val(), usercaptcha: $("#usercaptcha").val(), captchacombination: addslashes($("#captchacombination").val())},
                function(data){
                    if (data.substr(0, 2) == '1_') { //insert success
                        $('#dictionaryNewTerm form').remove();
                        $("#dictionaryNewTerm .calltoaction").after('<div class="headerMsg"><div class="validation valid">Your term has been successfully added. <a href="/addadefinition.php?word='+data.substr(2)+'&amp;add=true">Add a definition</a> to it.</div></div>');
                        //set captcha cookie
                        var nextweek = new Date();
                        nextweek.setTime(nextweek.getTime() + (7 * 24 * 60 * 60 * 1000));
                        $.cookie('v', '1', { expires: nextweek, path: '/' });
                        setTimeout(function () { window.location = '/addadefinition.php?word='+data.substr(2)+'&amp;add=true'; }, 3000);
                        return false;
                    } else { //display error message
                        $("#dictionaryNewTerm .calltoaction").after('<div class="headerMsg"><div class="validation error">' + data + '</div></div>');
                        return false;
                    }
                }
            );
            return false;
        } else { //display error messages for any required fields left empty
            if ($("#word").val() == '') {
                $("#word").parent().append('<span class="validation error">Please enter a term.</span>');
            }
            if ($("#usercaptcha").val() == '') {
                $("#usercaptcha").parent().append('<span class="validation error">Please enter the code.</span>');
            }
            return false;
        }
    });
    
    $('#newDefinitionForm').submit(function() { //submit a new definition form handler
        $('.validation').remove();
        if ($("#definition").val() != '' && $("#usercaptcha").val() != '') {
            //submit the definition for further validation, possibly insert into database, display results
            $.post(
                "/ajax/addadefinition.php",
                {submitNewDefinition: $("#definition").val(), partOfSpeech: $('#partOfSpeech').val(), contributor: $('#contributor').val(), definitionword: $("#definitionword").val(), usercaptcha: $("#usercaptcha").val(), captchacombination: addslashes($("#captchacombination").val())},
                function(data){
                    if (data.substr(0, 2) == '1_') { //insert success
                        $('#dictionaryNewEntry form').remove();
                        $('#dictionaryNewEntry .calltoaction a.view').html('Add another definition to this term');
                        $('#dictionaryNewEntry .calltoaction a.view').attr('href',$('#dictionaryNewEntry .calltoaction a.view').attr('href') + '&add=true');
                        $("#dictionaryNewEntry .calltoaction").after(data.substr(2));
                        //set captcha cookie
                        var nextweek = new Date();
                        nextweek.setTime(nextweek.getTime() + (7 * 24 * 60 * 60 * 1000));
                        $.cookie('v', '1', { expires: nextweek, path: '/' });
                        return false;
                    } else { //display error message
                        $("#dictionaryNewEntry .calltoaction").after('<div class="headerMsg"><div class="validation error">' + data + '</div></div>');
                        return false;
                    }
                }
            );
            return false;
        } else { //display error messages for any required fields left empty
            if ($("#definition").val() == '') {
                $("#definition").parent().append('<span class="validation error">Please enter a definition.</span>');
            }
            if ($("#usercaptcha").val() == '') {
                $("#usercaptcha").parent().append('<span class="validation error">Please enter the code.</span>');
            }
            return false;
        }
    });
    
});

//Add-a-Line inserting ajaxed content into the tooltip for archived stories
function displayArchiveSummaries() {
    //on callback of archived stories initialization, get the archived story previews and load into tooltips
    $('#archives .title a').hover( function () {
        $storyId = $(this).parent().attr('id').split('_');
        //add lineSummary element on first event to contain ajaxed content
        if (!$(this).siblings('.lineSummary').html()) {
            $(this).parent().append('<div class="lineSummary">Loading Summary</div>');
        }
        if ($("#archives #story_" + $storyId[1] + " .lineSummary").html() == 'Loading Summary') {
            $("#archives #story_" + $storyId[1] + " .lineSummary").load(
                "/ajax/addaline.php",
                {getStorySummary: $storyId[1], storyTitle: $("#archives #story_" + $storyId[1] + " a").html()},
                function () {
                    //set the tooltip value to the line summary content on ajax callback
                    $('#tooltip .body').html($("#archives #story_" + $storyId[1] + " .lineSummary").html());
                }
            );
        }
    }, function () { /*on off hover, do nothing*/ });
    //display the tooltip with the initial "loading" message, ajax will fill in with proper content once loaded
    $('#archives .title a').tooltip({
        bodyHandler: function() {
            $storyId = $(this).parent().attr('id').split('_');
            return $("#archives #story_" + $storyId[1] + " .lineSummary").html();
        },
        showURL: false,
        delay: 500,
        fade: 250
    });
}


/*
  @author: remy sharp / http://remysharp.com
  @params:
    feedback - the selector for the element that gives the user feedback. Note that this will be relative to the form the plugin is run against.
    hardLimit - whether to stop the user being able to keep adding characters. Defaults to true.
    useInput - whether to look for a hidden input named 'maxlength' instead of the maxlength attribute. Defaults to false.
    words - limit by characters or words, set this to true to limit by words. Defaults to false.
  @license: Creative Commons License - ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
  @version: 1.2
  @changes: code tidy via Ariel Flesler and fix when pasting over limit and including \t or \n
*/

(function ($) {

$.fn.maxlength = function (settings) {

    if (typeof settings == 'string') {
        settings = { feedback : settings };
    }

    settings = $.extend({}, $.fn.maxlength.defaults, settings);

    function length(el) {
    	var parts = el.value;
    	if ( settings.words )
    		parts = el.value.length ? parts.split(/\s+/) : { length : 0 };
    	return parts.length;
    }
    
    return this.each(function () {
        var field = this,
        	$field = $(field),
        	$form = $(field.form),
        	limit = settings.useInput ? $form.find('input[name=maxlength]').val() : $field.attr('maxlength'),
        	$charsLeft = $form.find(settings.feedback);

    	function limitCheck(event) {
        	var len = length(this),
        	    exceeded = len >= limit,
        		code = event.keyCode;

        	if ( !exceeded )
        		return;

            switch (code) {
                case 8:  // allow delete
                case 9:
                case 17:
                case 36: // and cursor keys
                case 35:
                case 37: 
                case 38:
                case 39:
                case 40:
                case 46:
                case 65:
                    return;

                default:
                    return settings.words && code != 32 && code != 13 && len == limit;
            }
        }


        var updateCount = function () {
            var len = length(field),
            	diff = limit - len;

            $charsLeft.html( diff || "0" );

            // truncation code
            if (settings.hardLimit && diff < 0) {
            	field.value = settings.words ? 
            	    // split by white space, capturing it in the result, then glue them back
            		field.value.split(/(\s+)/, (limit*2)-1).join('') :
            		field.value.substr(0, limit);

                updateCount();
            }
        };

        $field.keyup(updateCount).change(updateCount);
        if (settings.hardLimit) {
            $field.keydown(limitCheck);
        }

        updateCount();
    });
};

$.fn.maxlength.defaults = {
    useInput : false,
    hardLimit : true,
    feedback : '.charsLeft',
    words : false
};

})(jQuery);