diff --git a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee index 10674c2ff..b1abfec81 100644 --- a/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee +++ b/app/assets/javascripts/app/controllers/_application_controller_form.js.coffee @@ -354,10 +354,17 @@ class App.ControllerForm extends App.Controller # textarea else if attribute.tag is 'textarea' - item = $( App.view('generic/textarea')( attribute: attribute ) ) + fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 ) + item = $( App.view('generic/textarea')( attribute: attribute ) + '
' ) + + a = => + $( item[0] ).expanding() + $( item[0] ).on('focus', -> + $( item[0] ).expanding() + ) + App.Delay.set( a, 80 ) + if attribute.upload - fileUploaderId = 'file-uploader-' + new Date().getTime() + '-' + Math.floor( Math.random() * 99999 ) - item = $( App.view('generic/textarea')( attribute: attribute ) + '' ) # add file uploader u = => @@ -378,7 +385,7 @@ class App.ControllerForm extends App.Controller fail: '' debug: false ) - App.Delay.set( u, 80, undefined, 'form_upload' ) + App.Delay.set( u, 100, undefined, 'form_upload' ) # article else if attribute.tag is 'article' @@ -954,9 +961,6 @@ class App.ControllerForm extends App.Controller # if attribute.onchange[] ui = @ -# item.bind('focus', -> -# ui.log 'focus', attribute -# ); item.bind('change', -> if ui.form_data params = App.ControllerForm.params(@) diff --git a/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee index ec420a724..297d847ac 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee @@ -71,7 +71,6 @@ class App.TicketCreate extends App.Controller activate: => @navupdate '#' - @el.find('textarea').elastic() changed: => formCurrent = @formParam( @el.find('.ticket-create') ) @@ -184,12 +183,6 @@ class App.TicketCreate extends App.Controller params: params ) - # add elastic to textarea - @el.find('textarea').elastic() - - # update textarea size - @el.find('textarea').trigger('change') - # show template UI new App.WidgetTemplate( el: @el.find('.ticket_template') diff --git a/app/assets/javascripts/app/controllers/customer_ticket_create.js.coffee b/app/assets/javascripts/app/controllers/customer_ticket_create.js.coffee index 7f5e043e3..c21be26be 100644 --- a/app/assets/javascripts/app/controllers/customer_ticket_create.js.coffee +++ b/app/assets/javascripts/app/controllers/customer_ticket_create.js.coffee @@ -108,12 +108,6 @@ class Index extends App.ControllerContent form_data: @edit_form ) - # add elastic to textarea - @el.find('textarea').elastic() - - # update textarea size - @el.find('textarea').trigger('change') - new App.ControllerDrox( el: @el.find('.sidebar') data: diff --git a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee index 880be8b87..e098ced86 100644 --- a/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/ticket_zoom.js.coffee @@ -48,7 +48,6 @@ class App.TicketZoom extends App.Controller activate: => @navupdate '#' - @el.find('textarea').elastic() changed: => formCurrent = @formParam( @el.find('.ticket-update') ) @@ -414,8 +413,6 @@ class Edit extends App.Controller ] ) - @el.find('textarea').elastic() - # remember form defaults @ui.formDefault = @formParam( @el.find('.ticket-update') ) diff --git a/app/assets/javascripts/app/controllers/user_zoom.js.coffee b/app/assets/javascripts/app/controllers/user_zoom.js.coffee index 8c4b7e249..a23b33403 100644 --- a/app/assets/javascripts/app/controllers/user_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/user_zoom.js.coffee @@ -27,7 +27,6 @@ class App.UserZoom extends App.Controller activate: => @navupdate '#' - @el.find('textarea').elastic() changed: => formCurrent = @formParam( @el.find('.ticket-update') ) diff --git a/app/assets/javascripts/app/lib/base/expanding.js b/app/assets/javascripts/app/lib/base/expanding.js new file mode 100644 index 000000000..e2efb50cd --- /dev/null +++ b/app/assets/javascripts/app/lib/base/expanding.js @@ -0,0 +1,222 @@ +// Expanding Textareas v0.1.1 +// MIT License +// https://github.com/bgrins/ExpandingTextareas + +(function(factory) { + // Add jQuery via AMD registration or browser globals + if (typeof define === 'function' && define.amd) { + define([ 'jquery' ], factory); + } + else { + factory(jQuery); + } +}(function ($) { + + var Expanding = function($textarea, opts) { + Expanding._registry.push(this); + + this.$textarea = $textarea; + this.$textCopy = $(""); + this.$clone = $("").prepend(this.$textCopy); + + this._resetStyles(); + this._setCloneStyles(); + this._setTextareaStyles(); + + $textarea + .wrap($("")) + .after(this.$clone); + + this.attach(); + this.update(); + if (opts.update) $textarea.bind("update.expanding", opts.update); + }; + + // Stores (active) `Expanding` instances + // Destroyed instances are removed + Expanding._registry = []; + + // Returns the `Expanding` instance given a DOM node + Expanding.getExpandingInstance = function(textarea) { + var $textareas = $.map(Expanding._registry, function(instance) { + return instance.$textarea[0]; + }), + index = $.inArray(textarea, $textareas); + return index > -1 ? Expanding._registry[index] : null; + }; + + // Returns the version of Internet Explorer or -1 + // (indicating the use of another browser). + // From: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx#ParsingUA + var ieVersion = (function() { + var v = -1; + if (navigator.appName === "Microsoft Internet Explorer") { + var ua = navigator.userAgent; + var re = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})"); + if (re.exec(ua) !== null) v = parseFloat(RegExp.$1); + } + return v; + })(); + + // Check for oninput support + // IE9 supports oninput, but not when deleting text, so keyup is used. + // onpropertychange _is_ supported by IE8/9, but may not be fired unless + // attached with `attachEvent` + // (see: http://stackoverflow.com/questions/18436424/ie-onpropertychange-event-doesnt-fire), + // and so is avoided altogether. + var inputSupported = "oninput" in document.createElement("input") && ieVersion !== 9; + + Expanding.prototype = { + + // Attaches input events + // Only attaches `keyup` events if `input` is not fully suported + attach: function() { + var events = 'input.expanding change.expanding', + _this = this; + if(!inputSupported) events += ' keyup.expanding'; + this.$textarea.bind(events, function() { _this.update(); }); + }, + + // Updates the clone with the textarea value + update: function() { + this.$textCopy.text(this.$textarea.val().replace(/\r\n/g, "\n")); + + // Use `triggerHandler` to prevent conflicts with `update` in Prototype.js + this.$textarea.triggerHandler("update.expanding"); + }, + + // Tears down the plugin: removes generated elements, applies styles + // that were prevously present, removes instance from registry, + // unbinds events + destroy: function() { + this.$clone.remove(); + this.$textarea + .unwrap() + .attr('style', this._oldTextareaStyles || ''); + delete this._oldTextareaStyles; + var index = $.inArray(this, Expanding._registry); + if (index > -1) Expanding._registry.splice(index, 1); + this.$textarea.unbind( + 'input.expanding change.expanding keyup.expanding update.expanding'); + }, + + // Applies reset styles to the textarea and clone + // Stores the original textarea styles in case of destroying + _resetStyles: function() { + this._oldTextareaStyles = this.$textarea.attr('style'); + + this.$textarea.add(this.$clone).css({ + margin: 0, + webkitBoxSizing: "border-box", + mozBoxSizing: "border-box", + boxSizing: "border-box", + width: "100%" + }); + }, + + // Sets the basic clone styles and copies styles over from the textarea + _setCloneStyles: function() { + var css = { + display: 'block', + border: '0 solid', + visibility: 'hidden', + minHeight: this.$textarea.outerHeight() + }; + + if(this.$textarea.attr("wrap") === "off") css.overflowX = "scroll"; + else css.whiteSpace = "pre-wrap"; + + this.$clone.css(css); + this._copyTextareaStylesToClone(); + }, + + _copyTextareaStylesToClone: function() { + var _this = this, + properties = [ + 'lineHeight', 'textDecoration', 'letterSpacing', + 'fontSize', 'fontFamily', 'fontStyle', + 'fontWeight', 'textTransform', 'textAlign', + 'direction', 'wordSpacing', 'fontSizeAdjust', + 'wordWrap', 'word-break', + 'borderLeftWidth', 'borderRightWidth', + 'borderTopWidth','borderBottomWidth', + 'paddingLeft', 'paddingRight', + 'paddingTop','paddingBottom', 'maxHeight']; + + $.each(properties, function(i, property) { + var val = _this.$textarea.css(property); + + // Prevent overriding percentage css values. + if(_this.$clone.css(property) !== val) { + _this.$clone.css(property, val); + if(property === 'maxHeight' && val !== 'none') { + _this.$clone.css('overflow', 'hidden'); + } + } + }); + }, + + _setTextareaStyles: function() { + this.$textarea.css({ + position: "absolute", + top: 0, + left: 0, + height: "100%", + resize: "none", + overflow: "auto" + }); + } + }; + + $.expanding = $.extend({ + autoInitialize: true, + initialSelector: "textarea.expanding", + opts: { + update: function() { } + } + }, $.expanding || {}); + + $.fn.expanding = function(o) { + + if (o === "destroy") { + this.each(function() { + var instance = Expanding.getExpandingInstance(this); + if (instance) instance.destroy(); + }); + return this; + } + + // Checks to see if any of the given DOM nodes have the + // expanding behaviour. + if (o === "active") { + return !!this.filter(function() { + return !!Expanding.getExpandingInstance(this); + }).length; + } + + var opts = $.extend({ }, $.expanding.opts, o); + + this.filter("textarea").each(function() { + var visible = this.offsetWidth > 0 || this.offsetHeight > 0, + initialized = Expanding.getExpandingInstance(this); + + if(visible && !initialized) new Expanding($(this), opts); + else { + if(!visible) _warn("ExpandingTextareas: attempt to initialize an invisible textarea. Call expanding() again once it has been inserted into the page and/or is visible."); + if(initialized) _warn("ExpandingTextareas: attempt to initialize a textarea that has already been initialized. Subsequent calls are ignored."); + } + }); + return this; + }; + + function _warn(text) { + if(window.console && console.warn) console.warn(text); + } + + $(function () { + if ($.expanding.autoInitialize) { + $($.expanding.initialSelector).expanding(); + } + }); + +})); \ No newline at end of file diff --git a/app/assets/javascripts/app/lib/base/jquery.elastic.source.js b/app/assets/javascripts/app/lib/base/jquery.elastic.source.js deleted file mode 100644 index 9b1ed2b83..000000000 --- a/app/assets/javascripts/app/lib/base/jquery.elastic.source.js +++ /dev/null @@ -1,162 +0,0 @@ -/** -* @name Elastic -* @descripton Elastic is jQuery plugin that grow and shrink your textareas automatically -* @version 1.6.11 -* @requires jQuery 1.2.6+ -* -* @author Jan Jarfalk -* @author-email jan.jarfalk@unwrongest.com -* @author-website http://www.unwrongest.com -* -* @licence MIT License - http://www.opensource.org/licenses/mit-license.php -*/ - -(function($){ - jQuery.fn.extend({ - elastic: function() { - - // We will create a div clone of the textarea - // by copying these attributes from the textarea to the div. - var mimics = [ - 'paddingTop', - 'paddingRight', - 'paddingBottom', - 'paddingLeft', - 'fontSize', - 'lineHeight', - 'fontFamily', - 'width', - 'fontWeight', - 'border-top-width', - 'border-right-width', - 'border-bottom-width', - 'border-left-width', - 'borderTopStyle', - 'borderTopColor', - 'borderRightStyle', - 'borderRightColor', - 'borderBottomStyle', - 'borderBottomColor', - 'borderLeftStyle', - 'borderLeftColor' - ]; - - return this.each( function() { - - // Elastic only works on textareas - if ( this.type !== 'textarea' ) { - return false; - } - - var $textarea = jQuery(this), - $twin = jQuery('').css({ - 'position' : 'absolute', - 'display' : 'none', - 'word-wrap' : 'break-word', - 'white-space' :'pre-wrap' - }), - lineHeight = parseInt($textarea.css('line-height'),10) || parseInt($textarea.css('font-size'),'10'), - minheight = parseInt($textarea.css('height'),10) || lineHeight*3, - maxheight = parseInt($textarea.css('max-height'),10) || Number.MAX_VALUE, - goalheight = 0; - - // Opera returns max-height of -1 if not set - if (maxheight < 0) { maxheight = Number.MAX_VALUE; } - - // Append the twin to the DOM - // We are going to meassure the height of this, not the textarea. - $twin.appendTo($textarea.parent()); - - // Copy the essential styles (mimics) from the textarea to the twin - var i = mimics.length; - while(i--){ - $twin.css(mimics[i].toString(),$textarea.css(mimics[i].toString())); - } - - // Updates the width of the twin. (solution for textareas with widths in percent) - function setTwinWidth(){ - var curatedWidth = Math.floor(parseInt($textarea.width(),10)); - if($twin.width() !== curatedWidth){ - $twin.css({'width': curatedWidth + 'px'}); - - // Update height of textarea - update(true); - } - } - - // Sets a given height and overflow state on the textarea - function setHeightAndOverflow(height, overflow){ - - var curratedHeight = Math.floor(parseInt(height,10)); - if($textarea.height() !== curratedHeight){ - $textarea.css({'height': curratedHeight + 'px','overflow':overflow}); - } - } - - // This function will update the height of the textarea if necessary - function update(forced) { - - // Get curated content from the textarea. - var textareaContent = $textarea.val().replace(/&/g,'&').replace(/ {2}/g, ' ').replace(/<|>/g, '>').replace(/\n/g, '