/** * @name jQuery limitText plugin * */ ;(function ($) { var TextLimiter = function (element, options) { var limit = options.limit || 30 var limitBy = options.limitBy || 'count' var showLimitBox = options.showLimitBox || true var position = options.position || 'outer' var _this = null var keyPress = false var tmpValue = '' return { init: function () { _this = this _this.cache() _this.bindEvent() if (showLimitBox) { _this.bindTemplate(position) } return _this }, cache: function () { _this.$element = $(element) }, bindEvent: function () { _this.$element.off('keydown').on('keydown', _this.onKeydown) _this.$element.off('keyup').on('keyup', _this.onKeyup) _this.$element.off('paste').on('paste', _this.onPaste) }, getCurrentValues: function (e) { var $target = $(e.target) var currentValue = $target.val() var updatedValue = (e.type === 'paste') ? $target.val() + e.originalEvent.clipboardData.getData('Text') : $target.val() + String.fromCharCode(e.keyCode) return { currentValue: currentValue, updatedValue: updatedValue } }, countValue: function (value) { var count = (limitBy === 'byte') ? _this.getByteLength(value) : value.length _this.$element.parent().find('.num').text(count) }, onKeydown: function (e) { if (keyPress && [8, 46].indexOf(e.keyCode) === -1) { return false } tmpValue = _this.$element.val() keyPress = true if (options.onKeydown && typeof options.onKeyup === 'function') { options.onKeydown.call(element, e) } }, onKeyup: function (e) { var value = _this.$element.val() keyPress = false if (_this.isValid({ updatedValue: value })) { if (showLimitBox) { _this.countValue(value) } } else { _this.$element.val(tmpValue) _this.countValue(tmpValue) if (options.onOverCount && typeof options.onOverCount === 'function') { options.onOverCount.call(element, { currentValue: tmpValue, updatedValue: value }) } } if (options.onKeyup && typeof options.onKeyup === 'function') { options.onKeyup.call(element, e) } }, onPaste: function (e) { _this.update(_this.getCurrentValues(e)) }, /** * @private * @param {object} data *
       *   currentValue: 기존값
       *   updatedValue: 변경된 값
       * 
* */ isValid: function (data) { if (limitBy === 'byte' && _this.getByteLength(data.updatedValue) > limit || limitBy === 'count' && data.updatedValue.length > limit) { return false } else { return true } }, getByteLength: function (s, b, i, c) { for (b = i = 0; c = s.charCodeAt(i++); b += c >> 11 ? 2 : c >> 7 ? 2 : 1); return b }, bindTemplate: function (position) { var currentCount = this.$element.val().length var limitBox = showLimitBox ? [ '

', '(' + currentCount + ' / ' + limit + ')', '

' ].join('\n') : '' switch (position) { case 'inner': var $limitBox = $(limitBox).addClass('inner') this.$element.addClass('xe-form-control').wrapAll('
').before($limitBox) break case 'outer': var $limitBox = $(limitBox) this.$element.addClass('xe-form-control').wrapAll('
').before($limitBox) break default: } } } } /** * * @external "jQuery.fn" * @function external:"jQuery.fn".limitText * @param options {object} *
   * - limit: 100 default 30,
   * - limitBy: 'byte' or 'count' default 'count',
   * - showLimitBox: true,
   * - position: 'inner' or 'outer' default 'outer',
   * - onOverCount: function() {}
   * - onKeyup: function() {}
   * - onKeydown: function() {}
   * 
* */ $.fn.limitText = function (options) { return this.each(function () { var Component = new TextLimiter(this, options || {}) Component.init() }) } })(window.jQuery)