summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Speicher <rspeicher@gmail.com>2016-02-01 16:55:00 -0500
committerRobert Speicher <rspeicher@gmail.com>2016-02-01 17:00:03 -0500
commit933834c4a60610710fc949daa2e15531c2c45780 (patch)
tree7b312b52c0cca80a881241866c3e43119ca235f9
parentea11f0218a0cb8c23091965989a5b0875fd1daae (diff)
downloadgitlab-ce-933834c4a60610710fc949daa2e15531c2c45780.tar.gz
Allow manual resize of js-autosize textareasrs-relax-autosize
First, the autosize library was being too controlling and removed the `resize` property from any elements to which it was attached, removing the drag handle. Second, we detect when the user manually resizes an autosize textarea, and then remove the autosize behavior from it and increase its max-height. This should allow for the best of both worlds. Closes #12832
-rw-r--r--app/assets/javascripts/behaviors/autosize.js.coffee20
-rw-r--r--app/assets/stylesheets/framework/markdown_area.scss2
-rw-r--r--app/assets/stylesheets/pages/note_form.scss2
-rw-r--r--spec/javascripts/behaviors/autosize_spec.js.coffee11
-rw-r--r--vendor/assets/javascripts/jquery.ba-resize.js246
5 files changed, 278 insertions, 3 deletions
diff --git a/app/assets/javascripts/behaviors/autosize.js.coffee b/app/assets/javascripts/behaviors/autosize.js.coffee
index b32072e61ee..a072fe48a98 100644
--- a/app/assets/javascripts/behaviors/autosize.js.coffee
+++ b/app/assets/javascripts/behaviors/autosize.js.coffee
@@ -1,4 +1,22 @@
+#= require jquery.ba-resize
#= require autosize
$ ->
- autosize($('.js-autosize'))
+ $fields = $('.js-autosize')
+
+ $fields.on 'autosize:resized', ->
+ $field = $(@)
+ $field.data('height', $field.outerHeight())
+
+ $fields.on 'resize.autosize', ->
+ $field = $(@)
+
+ if $field.data('height') != $field.outerHeight()
+ $field.data('height', $field.outerHeight())
+ autosize.destroy($field)
+ $field.css('max-height', window.outerHeight)
+
+ autosize($fields)
+ autosize.update($fields)
+
+ $fields.css('resize', 'vertical')
diff --git a/app/assets/stylesheets/framework/markdown_area.scss b/app/assets/stylesheets/framework/markdown_area.scss
index 6732343802a..1d8611b04dc 100644
--- a/app/assets/stylesheets/framework/markdown_area.scss
+++ b/app/assets/stylesheets/framework/markdown_area.scss
@@ -83,7 +83,7 @@
background: #FFF;
border: 1px solid #ddd;
min-height: 140px;
- max-height: 430px;
+ max-height: 500px;
padding: 5px;
box-shadow: none;
width: 100%;
diff --git a/app/assets/stylesheets/pages/note_form.scss b/app/assets/stylesheets/pages/note_form.scss
index 32ba1676333..158c2a47862 100644
--- a/app/assets/stylesheets/pages/note_form.scss
+++ b/app/assets/stylesheets/pages/note_form.scss
@@ -147,7 +147,7 @@
.edit_note {
.markdown-area {
min-height: 140px;
- max-height: 430px;
+ max-height: 500px;
}
.note-form-actions {
background: transparent;
diff --git a/spec/javascripts/behaviors/autosize_spec.js.coffee b/spec/javascripts/behaviors/autosize_spec.js.coffee
new file mode 100644
index 00000000000..7fc1d19c35f
--- /dev/null
+++ b/spec/javascripts/behaviors/autosize_spec.js.coffee
@@ -0,0 +1,11 @@
+#= require behaviors/autosize
+
+describe 'Autosize behavior', ->
+ beforeEach ->
+ fixture.set('<textarea class="js-autosize" style="resize: vertical"></textarea>')
+
+ it 'does not overwrite the resize property', ->
+ load()
+ expect($('textarea')).toHaveCss(resize: 'vertical')
+
+ load = -> $(document).trigger('page:load')
diff --git a/vendor/assets/javascripts/jquery.ba-resize.js b/vendor/assets/javascripts/jquery.ba-resize.js
new file mode 100644
index 00000000000..1f41d379153
--- /dev/null
+++ b/vendor/assets/javascripts/jquery.ba-resize.js
@@ -0,0 +1,246 @@
+/*!
+ * jQuery resize event - v1.1 - 3/14/2010
+ * http://benalman.com/projects/jquery-resize-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery resize event
+//
+// *Version: 1.1, Last updated: 3/14/2010*
+//
+// Project Home - http://benalman.com/projects/jquery-resize-plugin/
+// GitHub - http://github.com/cowboy/jquery-resize/
+// Source - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.js
+// (Minified) - http://github.com/cowboy/jquery-resize/raw/master/jquery.ba-resize.min.js (1.0kb)
+//
+// About: License
+//
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// About: Examples
+//
+// This working example, complete with fully commented code, illustrates a few
+// ways in which this plugin can be used.
+//
+// resize event - http://benalman.com/code/projects/jquery-resize/examples/resize/
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - 1.3.2, 1.4.1, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome, Opera 9.6-10.1.
+// Unit Tests - http://benalman.com/code/projects/jquery-resize/unit/
+//
+// About: Release History
+//
+// 1.1 - (3/14/2010) Fixed a minor bug that was causing the event to trigger
+// immediately after bind in some circumstances. Also changed $.fn.data
+// to $.data to improve performance.
+// 1.0 - (2/10/2010) Initial release
+
+(function($,window,undefined){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // A jQuery object containing all non-window elements to which the resize
+ // event is bound.
+ var elems = $([]),
+
+ // Extend $.resize if it already exists, otherwise create it.
+ jq_resize = $.resize = $.extend( $.resize, {} ),
+
+ timeout_id,
+
+ // Reused strings.
+ str_setTimeout = 'setTimeout',
+ str_resize = 'resize',
+ str_data = str_resize + '-special-event',
+ str_delay = 'delay',
+ str_throttle = 'throttleWindow';
+
+ // Property: jQuery.resize.delay
+ //
+ // The numeric interval (in milliseconds) at which the resize event polling
+ // loop executes. Defaults to 250.
+
+ jq_resize[ str_delay ] = 250;
+
+ // Property: jQuery.resize.throttleWindow
+ //
+ // Throttle the native window object resize event to fire no more than once
+ // every <jQuery.resize.delay> milliseconds. Defaults to true.
+ //
+ // Because the window object has its own resize event, it doesn't need to be
+ // provided by this plugin, and its execution can be left entirely up to the
+ // browser. However, since certain browsers fire the resize event continuously
+ // while others do not, enabling this will throttle the window resize event,
+ // making event behavior consistent across all elements in all browsers.
+ //
+ // While setting this property to false will disable window object resize
+ // event throttling, please note that this property must be changed before any
+ // window object resize event callbacks are bound.
+
+ jq_resize[ str_throttle ] = true;
+
+ // Event: resize event
+ //
+ // Fired when an element's width or height changes. Because browsers only
+ // provide this event for the window element, for other elements a polling
+ // loop is initialized, running every <jQuery.resize.delay> milliseconds
+ // to see if elements' dimensions have changed. You may bind with either
+ // .resize( fn ) or .bind( "resize", fn ), and unbind with .unbind( "resize" ).
+ //
+ // Usage:
+ //
+ // > jQuery('selector').bind( 'resize', function(e) {
+ // > // element's width or height has changed!
+ // > ...
+ // > });
+ //
+ // Additional Notes:
+ //
+ // * The polling loop is not created until at least one callback is actually
+ // bound to the 'resize' event, and this single polling loop is shared
+ // across all elements.
+ //
+ // Double firing issue in jQuery 1.3.2:
+ //
+ // While this plugin works in jQuery 1.3.2, if an element's event callbacks
+ // are manually triggered via .trigger( 'resize' ) or .resize() those
+ // callbacks may double-fire, due to limitations in the jQuery 1.3.2 special
+ // events system. This is not an issue when using jQuery 1.4+.
+ //
+ // > // While this works in jQuery 1.4+
+ // > $(elem).css({ width: new_w, height: new_h }).resize();
+ // >
+ // > // In jQuery 1.3.2, you need to do this:
+ // > var elem = $(elem);
+ // > elem.css({ width: new_w, height: new_h });
+ // > elem.data( 'resize-special-event', { width: elem.width(), height: elem.height() } );
+ // > elem.resize();
+
+ $.event.special[ str_resize ] = {
+
+ // Called only when the first 'resize' event callback is bound per element.
+ setup: function() {
+ // Since window has its own native 'resize' event, return false so that
+ // jQuery will bind the event using DOM methods. Since only 'window'
+ // objects have a .setTimeout method, this should be a sufficient test.
+ // Unless, of course, we're throttling the 'resize' event for window.
+ if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
+
+ var elem = $(this);
+
+ // Add this element to the list of internal elements to monitor.
+ elems = elems.add( elem );
+
+ // Initialize data store on the element.
+ $.data( this, str_data, { w: elem.width(), h: elem.height() } );
+
+ // If this is the first element added, start the polling loop.
+ if ( elems.length === 1 ) {
+ loopy();
+ }
+ },
+
+ // Called only when the last 'resize' event callback is unbound per element.
+ teardown: function() {
+ // Since window has its own native 'resize' event, return false so that
+ // jQuery will unbind the event using DOM methods. Since only 'window'
+ // objects have a .setTimeout method, this should be a sufficient test.
+ // Unless, of course, we're throttling the 'resize' event for window.
+ if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
+
+ var elem = $(this);
+
+ // Remove this element from the list of internal elements to monitor.
+ elems = elems.not( elem );
+
+ // Remove any data stored on the element.
+ elem.removeData( str_data );
+
+ // If this is the last element removed, stop the polling loop.
+ if ( !elems.length ) {
+ clearTimeout( timeout_id );
+ }
+ },
+
+ // Called every time a 'resize' event callback is bound per element (new in
+ // jQuery 1.4).
+ add: function( handleObj ) {
+ // Since window has its own native 'resize' event, return false so that
+ // jQuery doesn't modify the event object. Unless, of course, we're
+ // throttling the 'resize' event for window.
+ if ( !jq_resize[ str_throttle ] && this[ str_setTimeout ] ) { return false; }
+
+ var old_handler;
+
+ // The new_handler function is executed every time the event is triggered.
+ // This is used to update the internal element data store with the width
+ // and height when the event is triggered manually, to avoid double-firing
+ // of the event callback. See the "Double firing issue in jQuery 1.3.2"
+ // comments above for more information.
+
+ function new_handler( e, w, h ) {
+ var elem = $(this),
+ data = $.data( this, str_data );
+
+ // If called from the polling loop, w and h will be passed in as
+ // arguments. If called manually, via .trigger( 'resize' ) or .resize(),
+ // those values will need to be computed.
+ data.w = w !== undefined ? w : elem.width();
+ data.h = h !== undefined ? h : elem.height();
+
+ old_handler.apply( this, arguments );
+ };
+
+ // This may seem a little complicated, but it normalizes the special event
+ // .add method between jQuery 1.4/1.4.1 and 1.4.2+
+ if ( $.isFunction( handleObj ) ) {
+ // 1.4, 1.4.1
+ old_handler = handleObj;
+ return new_handler;
+ } else {
+ // 1.4.2+
+ old_handler = handleObj.handler;
+ handleObj.handler = new_handler;
+ }
+ }
+
+ };
+
+ function loopy() {
+
+ // Start the polling loop, asynchronously.
+ timeout_id = window[ str_setTimeout ](function(){
+
+ // Iterate over all elements to which the 'resize' event is bound.
+ elems.each(function(){
+ var elem = $(this),
+ width = elem.width(),
+ height = elem.height(),
+ data = $.data( this, str_data );
+
+ // If element size has changed since the last time, update the element
+ // data store and trigger the 'resize' event.
+ if ( width !== data.w || height !== data.h ) {
+ elem.trigger( str_resize, [ data.w = width, data.h = height ] );
+ }
+
+ });
+
+ // Loop.
+ loopy();
+
+ }, jq_resize[ str_delay ] );
+
+ };
+
+})(jQuery,this);