From 3c38f222c261065266a0e1fbcc9f62e522024259 Mon Sep 17 00:00:00 2001 From: Martin Edenhofer Date: Sun, 6 May 2012 11:14:44 +0200 Subject: [PATCH] Added elastic for text area and mark/reply text feature. --- .../controllers/agent_ticket_create.js.coffee | 8 +- .../controllers/agent_ticket_zoom.js.coffee | 18 +- app/assets/javascripts/app/index.js.coffee | 16 ++ .../app/lib/jquery.elastic.source.js | 162 ++++++++++++++++++ 4 files changed, 201 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/app/lib/jquery.elastic.source.js 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 a884c1072..54ce2b6a9 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_create.js.coffee @@ -75,7 +75,13 @@ class Index extends App.Controller head: 'New Ticket', form: @formGen( model: { configure_attributes: configure_attributes, className: 'create' } ), ) - + + # add elastic to textarea + @el.find('textarea').elastic() + + # update textarea size + @el.find('textarea').trigger('change') + # start customer info controller if defaults['customer_id'] $('#create_customer_id').val( defaults['customer_id'] ) diff --git a/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee b/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee index c034502ab..d2c97379e 100644 --- a/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee +++ b/app/assets/javascripts/app/controllers/agent_ticket_zoom.js.coffee @@ -91,14 +91,14 @@ class Index extends App.Controller # preview mode if preview_mode - article['html'] = article['html'].replace /^----SEEMORE----\n/m, (match) => + article['html'] = article['html'].replace /^\n----SEEMORE----\n/m, (match) => notify + '
' article['html'] = article['html'] + '
' # hide signatures and so on else @article_changed = false - article['html'] = article['html'].replace /^(--|__)/m, (match) => + article['html'] = article['html'].replace /^\n(--|__)/m, (match) => @article_changed = true notify + '
' + match if @article_changed @@ -173,6 +173,8 @@ class Index extends App.Controller form_article: form_article, ) + @el.find('textarea').elastic() + @userPopups() # start customer info controller @@ -302,6 +304,18 @@ class Index extends App.Controller @el.find('[name="to"]').val(article.from) # @log 'reply ', article, @el.find('[name="to"]') + # add quoted text if needed + if window.Session['UISeletion'] + body = @el.find('[name="body"]').val() || '' + selection = window.Session['UISeletion'] + selection = selection.replace /^(.*)$/mg, (match) => + '> ' + match + body = body + selection + @el.find('[name="body"]').val(body) + + # update textarea size + @el.find('[name="body"]').trigger('change') + update: (e) => e.preventDefault() params = @formParam(e.target) diff --git a/app/assets/javascripts/app/index.js.coffee b/app/assets/javascripts/app/index.js.coffee index 1ed374528..c4be8d9f9 100644 --- a/app/assets/javascripts/app/index.js.coffee +++ b/app/assets/javascripts/app/index.js.coffee @@ -18,6 +18,7 @@ #= require ./lib/jquery.noty.js #= require ./lib/waypoints.js #= require ./lib/fileuploader.js +#= require ./lib/jquery.elastic.source.js #not_used= require_tree ./lib #= require_self @@ -197,6 +198,11 @@ class App.Run extends Spine.Controller # start content new App.Content( el: @el.find('#content') ); + # bind to fill selected text into + $(@el).bind('mouseup', => + window.Session['UISeletion'] = @getSelected() + '' + ) + @ws = new WebSocket("ws://localhost:3001/"); # Set event handlers. @@ -217,6 +223,16 @@ class App.Run extends Spine.Controller @ws.onerror = -> console.log("onerror") + + getSelected: -> + text = ''; + if window.getSelection + text = window.getSelection() + else if document.getSelection + text = document.getSelection() + else if document.selection + text = document.selection.createRange().text + text class App.Content extends Spine.Controller className: 'container' diff --git a/app/assets/javascripts/app/lib/jquery.elastic.source.js b/app/assets/javascripts/app/lib/jquery.elastic.source.js new file mode 100644 index 000000000..9b1ed2b83 --- /dev/null +++ b/app/assets/javascripts/app/lib/jquery.elastic.source.js @@ -0,0 +1,162 @@ +/** +* @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, '
'); + + // Compare curated content with curated twin. + var twinContent = $twin.html().replace(/
/ig,'
'); + + if(forced || textareaContent+' ' !== twinContent){ + + // Add an extra white space so new rows are added when you are at the end of a row. + $twin.html(textareaContent+' '); + + // Change textarea height if twin plus the height of one line differs more than 3 pixel from textarea height + if(Math.abs($twin.height() + lineHeight - $textarea.height()) > 3){ + + var goalheight = $twin.height()+lineHeight; + if(goalheight >= maxheight) { + setHeightAndOverflow(maxheight,'auto'); + } else if(goalheight <= minheight) { + setHeightAndOverflow(minheight,'hidden'); + } else { + setHeightAndOverflow(goalheight,'hidden'); + } + + } + + } + + } + + // Hide scrollbars + $textarea.css({'overflow':'hidden'}); + + // Update textarea size on keyup, change, cut and paste + $textarea.bind('keyup change cut paste', function(){ + update(); + }); + + // Update width of twin if browser or textarea is resized (solution for textareas with widths in percent) + $(window).bind('resize', setTwinWidth); + $textarea.bind('resize', setTwinWidth); + $textarea.bind('update', update); + + // Compact textarea on blur + $textarea.bind('blur',function(){ + if($twin.height() < maxheight){ + if($twin.height() > minheight) { + $textarea.height($twin.height()); + } else { + $textarea.height(minheight); + } + } + }); + + // And this line is to catch the browser paste event + $textarea.bind('input paste',function(e){ setTimeout( update, 250); }); + + // Run update once when elastic is initialized + update(); + + }); + + } + }); +})(jQuery); \ No newline at end of file