From bbe9a08cafef2c052749a6da229b5335d6e1752c Mon Sep 17 00:00:00 2001 From: Pavel Reznikov Date: Thu, 8 Jan 2015 19:41:07 -0800 Subject: [PATCH] improve touch support --- README.md | 23 +++++++++++++++++++++++ dist/gridstack.min.css | 2 +- dist/gridstack.min.js | 2 +- src/gridstack.css | 4 ++++ src/gridstack.js | 5 +++-- 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 84708d2..92332e2 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,8 @@ $(function () { ## Options +- `always_show_resize_handle` - if `true` the resizing handles are shown even the user is not hovering over the widget + (default: `false`) - `animate` - turns animation on (default: `false`) - `auto` - if `false` it tells to do not initialize existing items (default: `true`) - `cell_height` - one cell height (default: `60`) @@ -251,6 +253,22 @@ Sorts array of nodes - `dir` - `1` for asc, `-1` for desc - `width` - width of the grid. If `undefined` the width will be calculated automatically. +## Touch devices support + +Please use (jQuery UI Touch Punch)[https://github.com/furf/jquery-ui-touch-punch] to make jQuery UI Draggable/Resizable +working on touch-based devices. + +Also `always_show_resize_handle` option may be useful: + +```javascript +$(function () { + var options = { + always_show_resize_handle: /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + }; + $('.grid-stack').gridstack(options); +}); +``` + ## Use with knockout.js ```javascript @@ -339,6 +357,11 @@ and so on. Changes ======= +#### v0.2.3 (currently development version) + +- improved touch devices support +- add `always_show_resize_handle` option + #### v0.2.2 (2014-12-23) - fix grid initialization diff --git a/dist/gridstack.min.css b/dist/gridstack.min.css index 9905e90..25bcffd 100644 --- a/dist/gridstack.min.css +++ b/dist/gridstack.min.css @@ -1 +1 @@ -.grid-stack{position:relative}.grid-stack-item{position:absolute;padding:0}.grid-stack-item .grid-stack-item-content,.grid-stack-item .placeholder-content{margin:0;position:absolute;top:0;left:10px;right:10px;bottom:0;width:auto;z-index:0 !important;overflow:auto}.grid-stack-placeholder .placeholder-content{border:1px dashed lightgray}.grid-stack-item.ui-draggable-dragging,.grid-stack-item.ui-resizable-resizing{z-index:100}.grid-stack-item.ui-draggable-dragging .grid-stack-item-content,.grid-stack-item.ui-resizable-resizing .grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,0.2);opacity:.8}.grid-stack-item .ui-resizable-handle{padding:3px;margin:3px 0;cursor:nwse-resize;color:gray;position:absolute;bottom:0;right:15px;font:normal normal normal 14px/1 FontAwesome;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);font-size:10px}.grid-stack-item .ui-resizable-handle::before{content:"\f065"}.grid-stack-item[data-gs-width="12"]{width:100%}.grid-stack-item[data-gs-width="11"]{width:91.66666667%}.grid-stack-item[data-gs-width="10"]{width:83.33333333%}.grid-stack-item[data-gs-width="9"]{width:75%}.grid-stack-item[data-gs-width="8"]{width:66.66666667%}.grid-stack-item[data-gs-width="7"]{width:58.33333333%}.grid-stack-item[data-gs-width="6"]{width:50%}.grid-stack-item[data-gs-width="5"]{width:41.66666667%}.grid-stack-item[data-gs-width="4"]{width:33.33333333%}.grid-stack-item[data-gs-width="3"]{width:25%}.grid-stack-item[data-gs-width="2"]{width:16.66666667%}.grid-stack-item[data-gs-width="1"]{width:8.33333333%}.grid-stack-item[data-gs-x="12"]{left:100%}.grid-stack-item[data-gs-x="11"]{left:91.66666667%}.grid-stack-item[data-gs-x="10"]{left:83.33333333%}.grid-stack-item[data-gs-x="9"]{left:75%}.grid-stack-item[data-gs-x="8"]{left:66.66666667%}.grid-stack-item[data-gs-x="7"]{left:58.33333333%}.grid-stack-item[data-gs-x="6"]{left:50%}.grid-stack-item[data-gs-x="5"]{left:41.66666667%}.grid-stack-item[data-gs-x="4"]{left:33.33333333%}.grid-stack-item[data-gs-x="3"]{left:25%}.grid-stack-item[data-gs-x="2"]{left:16.66666667%}.grid-stack-item[data-gs-x="1"]{left:8.33333333%}@media(max-width:768px){.grid-stack-item{position:relative !important;width:auto !important;left:0 !important;top:auto !important;margin-bottom:20px}.grid-stack{height:auto !important}}.grid-stack.grid-stack-animate,.grid-stack.grid-stack-animate .grid-stack-item{-webkit-transition:left .3s,top .3s,height .3s,width .3s;-moz-transition:left .3s,top .3s,height .3s,width .3s;-o-transition:left .3s,top .3s,height .3s,width .3s;-ms-transition:left .3s,top .3s,height .3s,width .3s;transition:left .3s,top .3s,height .3s,width .3s}.grid-stack.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack.grid-stack-animate .grid-stack-item.ui-resizable-resizing,.grid-stack.grid-stack-animate .grid-stack-item.grid-stack-placeholder{-webkit-transition:left 0,top 0,height 0,width 0;-moz-transition:left 0,top 0,height 0,width 0;-o-transition:left 0,top 0,height 0,width 0;transition:left 0,top 0,height 0,width 0} \ No newline at end of file +.grid-stack{position:relative}.grid-stack-item{position:absolute;padding:0}.grid-stack-item .grid-stack-item-content,.grid-stack-item .placeholder-content{margin:0;position:absolute;top:0;left:10px;right:10px;bottom:0;width:auto;z-index:0 !important;overflow:auto}.grid-stack-placeholder .placeholder-content{border:1px dashed lightgray}.grid-stack-item.ui-draggable-dragging,.grid-stack-item.ui-resizable-resizing{z-index:100}.grid-stack-item.ui-draggable-dragging .grid-stack-item-content,.grid-stack-item.ui-resizable-resizing .grid-stack-item-content{box-shadow:1px 4px 6px rgba(0,0,0,0.2);opacity:.8}.grid-stack-item .ui-resizable-handle{padding:3px;margin:3px 0;cursor:nwse-resize;color:gray;position:absolute;bottom:0;right:15px;font:normal normal normal 14px/1 FontAwesome;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg);font-size:10px}.grid-stack-item .ui-resizable-handle::before{content:"\f065"}.grid-stack-item[data-gs-width="12"]{width:100%}.grid-stack-item[data-gs-width="11"]{width:91.66666667%}.grid-stack-item[data-gs-width="10"]{width:83.33333333%}.grid-stack-item[data-gs-width="9"]{width:75%}.grid-stack-item[data-gs-width="8"]{width:66.66666667%}.grid-stack-item[data-gs-width="7"]{width:58.33333333%}.grid-stack-item[data-gs-width="6"]{width:50%}.grid-stack-item[data-gs-width="5"]{width:41.66666667%}.grid-stack-item[data-gs-width="4"]{width:33.33333333%}.grid-stack-item[data-gs-width="3"]{width:25%}.grid-stack-item[data-gs-width="2"]{width:16.66666667%}.grid-stack-item[data-gs-width="1"]{width:8.33333333%}.grid-stack-item[data-gs-x="12"]{left:100%}.grid-stack-item[data-gs-x="11"]{left:91.66666667%}.grid-stack-item[data-gs-x="10"]{left:83.33333333%}.grid-stack-item[data-gs-x="9"]{left:75%}.grid-stack-item[data-gs-x="8"]{left:66.66666667%}.grid-stack-item[data-gs-x="7"]{left:58.33333333%}.grid-stack-item[data-gs-x="6"]{left:50%}.grid-stack-item[data-gs-x="5"]{left:41.66666667%}.grid-stack-item[data-gs-x="4"]{left:33.33333333%}.grid-stack-item[data-gs-x="3"]{left:25%}.grid-stack-item[data-gs-x="2"]{left:16.66666667%}.grid-stack-item[data-gs-x="1"]{left:8.33333333%}@media(max-width:768px){.grid-stack-item{position:relative !important;width:auto !important;left:0 !important;top:auto !important;margin-bottom:20px}.grid-stack-item .ui-resizable-handle{display:none}.grid-stack{height:auto !important}}.grid-stack.grid-stack-animate,.grid-stack.grid-stack-animate .grid-stack-item{-webkit-transition:left .3s,top .3s,height .3s,width .3s;-moz-transition:left .3s,top .3s,height .3s,width .3s;-o-transition:left .3s,top .3s,height .3s,width .3s;-ms-transition:left .3s,top .3s,height .3s,width .3s;transition:left .3s,top .3s,height .3s,width .3s}.grid-stack.grid-stack-animate .grid-stack-item.ui-draggable-dragging,.grid-stack.grid-stack-animate .grid-stack-item.ui-resizable-resizing,.grid-stack.grid-stack-animate .grid-stack-item.grid-stack-placeholder{-webkit-transition:left 0,top 0,height 0,width 0;-moz-transition:left 0,top 0,height 0,width 0;-o-transition:left 0,top 0,height 0,width 0;transition:left 0,top 0,height 0,width 0} \ No newline at end of file diff --git a/dist/gridstack.min.js b/dist/gridstack.min.js index e3e489a..e9cb021 100644 --- a/dist/gridstack.min.js +++ b/dist/gridstack.min.js @@ -1 +1 @@ -(function(scope,_){var Utils={is_intercepted:function(a,b){return!(a.x+a.width<=b.x||b.x+b.width<=a.x||a.y+a.height<=b.y||b.y+b.height<=a.y)},sort:function(nodes,dir,width){width=width||_.chain(nodes).map(function(node){return node.x+node.width}).max().value();dir=dir!=-1?1:-1;return _.sortBy(nodes,function(n){return dir*(n.x+n.y*width)})},create_stylesheet:function(){var style=document.createElement("style");style.appendChild(document.createTextNode(""));document.head.appendChild(style);return style.sheet},toBool:function(v){if(typeof v=="boolean")return v;if(typeof v=="string"){v=v.toLowerCase();return!(v==""||v=="no"||v=="false"||v=="0")}return Boolean(v)}};var id_seq=0;var GridStackEngine=function(width,onchange,float,height,items){this.width=width;this.float=float||false;this.height=height||0;this.nodes=items||[];this.onchange=onchange||function(){}};GridStackEngine.prototype._fix_collisions=function(node){this._sort_nodes(-1);var nn=node,has_locked=Boolean(_.find(this.nodes,function(n){return n.locked}));if(!this.float&&!has_locked){nn={x:0,y:node.y,width:this.width,height:node.height}}while(true){var collision_node=_.find(this.nodes,function(n){return n!=node&&Utils.is_intercepted(n,nn)},this);if(typeof collision_node=="undefined"){return}this.move_node(collision_node,collision_node.x,node.y+node.height,collision_node.width,collision_node.height,true)}};GridStackEngine.prototype._sort_nodes=function(dir){this.nodes=Utils.sort(this.nodes,dir,this.width)};GridStackEngine.prototype._pack_nodes=function(){this._sort_nodes();if(this.float){_.each(this.nodes,function(n,i){if(n._updating||typeof n._orig_y=="undefined"||n.y==n._orig_y)return;var new_y=n.y;while(new_y>=n._orig_y){var collision_node=_.chain(this.nodes).find(function(bn){return n!=bn&&Utils.is_intercepted({x:n.x,y:new_y,width:n.width,height:n.height},bn)}).value();if(!collision_node){n._dirty=true;n.y=new_y}--new_y}},this)}else{_.each(this.nodes,function(n,i){if(n.locked)return;while(n.y>0){var new_y=n.y-1;var can_be_moved=i==0;if(i>0){var collision_node=_.chain(this.nodes).first(i).find(function(bn){return Utils.is_intercepted({x:n.x,y:new_y,width:n.width,height:n.height},bn)}).value();can_be_moved=typeof collision_node=="undefined"}if(!can_be_moved){break}n._dirty=n.y!=new_y;n.y=new_y}},this)}};GridStackEngine.prototype._prepare_node=function(node,resizing){node=_.defaults(node||{},{width:1,height:1,x:0,y:0});node.x=parseInt(""+node.x);node.y=parseInt(""+node.y);node.width=parseInt(""+node.width);node.height=parseInt(""+node.height);node.auto_position=node.auto_position||false;node.no_resize=node.no_resize||false;node.no_move=node.no_move||false;if(node.width>this.width){node.width=this.width}else if(node.width<1){node.width=1}if(node.height<1){node.height=1}if(node.x<0){node.x=0}if(node.x+node.width>this.width){if(resizing){node.width=this.width-node.x}else{node.x=this.width-node.width}}if(node.y<0){node.y=0}return node};GridStackEngine.prototype._notify=function(){var deleted_nodes=Array.prototype.slice.call(arguments,1).concat(this.get_dirty_nodes());deleted_nodes=deleted_nodes.concat(this.get_dirty_nodes());this.onchange(deleted_nodes)};GridStackEngine.prototype.clean_nodes=function(){_.each(this.nodes,function(n){n._dirty=false})};GridStackEngine.prototype.get_dirty_nodes=function(){return _.filter(this.nodes,function(n){return n._dirty})};GridStackEngine.prototype.add_node=function(node){node=this._prepare_node(node);if(typeof node.max_width!="undefined")node.width=Math.min(node.width,node.max_width);if(typeof node.max_height!="undefined")node.height=Math.min(node.height,node.max_height);if(typeof node.min_width!="undefined")node.width=Math.max(node.width,node.min_width);if(typeof node.min_height!="undefined")node.height=Math.max(node.height,node.min_height);node._id=++id_seq;node._dirty=true;if(node.auto_position){this._sort_nodes();for(var i=0;;++i){var x=i%this.width,y=Math.floor(i/this.width);if(x+node.width>this.width){continue}if(!_.find(this.nodes,function(n){return Utils.is_intercepted({x:x,y:y,width:node.width,height:node.height},n)})){node.x=x;node.y=y;break}}}this.nodes.push(node);this._fix_collisions(node);this._pack_nodes();this._notify();return node};GridStackEngine.prototype.remove_node=function(node){node._id=null;this.nodes=_.without(this.nodes,node);this._pack_nodes();this._notify(node)};GridStackEngine.prototype.can_move_node=function(node,x,y,width,height){var has_locked=Boolean(_.find(this.nodes,function(n){return n.locked}));if(!this.height&&!has_locked)return true;var cloned_node;var clone=new GridStackEngine(this.width,null,this.float,0,_.map(this.nodes,function(n){if(n==node){cloned_node=$.extend({},n);return cloned_node}return $.extend({},n)}));clone.move_node(cloned_node,x,y,width,height);var res=true;if(has_locked)res&=!Boolean(_.find(clone.nodes,function(n){return n!=cloned_node&&Boolean(n.locked)&&Boolean(n._dirty)}));if(this.height)res&=clone.get_grid_height()<=this.height;return res};GridStackEngine.prototype.can_be_placed_with_respect_to_height=function(node){if(!this.height)return true;var clone=new GridStackEngine(this.width,null,this.float,0,_.map(this.nodes,function(n){return $.extend({},n)}));clone.add_node(node);return clone.get_grid_height()<=this.height};GridStackEngine.prototype.move_node=function(node,x,y,width,height,no_pack){if(typeof x!="number")x=node.x;if(typeof y!="number")y=node.y;if(typeof width!="number")width=node.width;if(typeof height!="number")height=node.height;if(typeof node.max_width!="undefined")width=Math.min(width,node.max_width);if(typeof node.max_height!="undefined")height=Math.min(height,node.max_height);if(typeof node.min_width!="undefined")width=Math.max(width,node.min_width);if(typeof node.min_height!="undefined")height=Math.max(height,node.min_height);if(node.x==x&&node.y==y&&node.width==width&&node.height==height){return node}var resizing=node.width!=width;node._dirty=true;node.x=x;node.y=y;node.width=width;node.height=height;node=this._prepare_node(node,resizing);this._fix_collisions(node);if(!no_pack){this._pack_nodes();this._notify()}return node};GridStackEngine.prototype.get_grid_height=function(){return _.reduce(this.nodes,function(memo,n){return Math.max(memo,n.y+n.height)},0)};GridStackEngine.prototype.begin_update=function(node){_.each(this.nodes,function(n){n._orig_y=n.y});node._updating=true};GridStackEngine.prototype.end_update=function(){var n=_.find(this.nodes,function(n){return n._updating});if(n){n._updating=false}};var GridStack=function(el,opts){var self=this,one_column_mode;this.container=$(el);this.opts=_.defaults(opts||{},{width:parseInt(this.container.attr("data-gs-width"))||12,height:parseInt(this.container.attr("data-gs-height"))||0,item_class:"grid-stack-item",placeholder_class:"grid-stack-placeholder",handle:".grid-stack-item-content",cell_height:60,vertical_margin:20,auto:true,min_width:768,"float":false,_class:"grid-stack-"+(Math.random()*1e4).toFixed(0),animate:Boolean(this.container.attr("data-gs-animate"))||false});this.container.addClass(this.opts._class);this._styles=Utils.create_stylesheet();this._styles._max=0;this.grid=new GridStackEngine(this.opts.width,function(nodes){var max_height=0;_.each(nodes,function(n){if(n._id==null){n.el.remove()}else{n.el.attr("data-gs-x",n.x).attr("data-gs-y",n.y).attr("data-gs-width",n.width).attr("data-gs-height",n.height);max_height=Math.max(max_height,n.y+n.height)}});self._update_styles(max_height+10)},this.opts.float,this.opts.height);if(this.opts.auto){var elements=[];this.container.find("."+this.opts.item_class).each(function(index,el){el=$(el);elements.push({el:el,i:parseInt(el.attr("data-gs-x"))+parseInt(el.attr("data-gs-y"))*parseInt(el.attr("data-gs-width"))})});_.chain(elements).sortBy(function(x){return x.i}).each(function(i){self._prepare_element(i.el)})}this.set_animation(this.opts.animate);this.placeholder=$('
').hide();this.container.append(this.placeholder);this.container.height(this.grid.get_grid_height()*(this.opts.cell_height+this.opts.vertical_margin)-this.opts.vertical_margin);var on_resize_handler=function(){if(self._is_one_column_mode()){if(one_column_mode)return;one_column_mode=true;_.each(self.grid.nodes,function(node){if(!node.no_move){node.el.draggable("disable")}if(!node.no_resize){node.el.resizable("disable")}})}else{if(!one_column_mode)return;one_column_mode=false;_.each(self.grid.nodes,function(node){if(!node.no_move){node.el.draggable("enable")}if(!node.no_resize){node.el.resizable("enable")}})}};$(window).resize(on_resize_handler);on_resize_handler()};GridStack.prototype._update_styles=function(max_height){if(typeof max_height=="undefined"){max_height=this._styles._max;this._styles._max=0;while(this._styles.rules.length){this._styles.removeRule(0)}this._update_container_height()}if(max_height>this._styles._max){for(var i=this._styles._max;i=n._orig_y){var collision_node=_.chain(this.nodes).find(function(bn){return n!=bn&&Utils.is_intercepted({x:n.x,y:new_y,width:n.width,height:n.height},bn)}).value();if(!collision_node){n._dirty=true;n.y=new_y}--new_y}},this)}else{_.each(this.nodes,function(n,i){if(n.locked)return;while(n.y>0){var new_y=n.y-1;var can_be_moved=i==0;if(i>0){var collision_node=_.chain(this.nodes).first(i).find(function(bn){return Utils.is_intercepted({x:n.x,y:new_y,width:n.width,height:n.height},bn)}).value();can_be_moved=typeof collision_node=="undefined"}if(!can_be_moved){break}n._dirty=n.y!=new_y;n.y=new_y}},this)}};GridStackEngine.prototype._prepare_node=function(node,resizing){node=_.defaults(node||{},{width:1,height:1,x:0,y:0});node.x=parseInt(""+node.x);node.y=parseInt(""+node.y);node.width=parseInt(""+node.width);node.height=parseInt(""+node.height);node.auto_position=node.auto_position||false;node.no_resize=node.no_resize||false;node.no_move=node.no_move||false;if(node.width>this.width){node.width=this.width}else if(node.width<1){node.width=1}if(node.height<1){node.height=1}if(node.x<0){node.x=0}if(node.x+node.width>this.width){if(resizing){node.width=this.width-node.x}else{node.x=this.width-node.width}}if(node.y<0){node.y=0}return node};GridStackEngine.prototype._notify=function(){var deleted_nodes=Array.prototype.slice.call(arguments,1).concat(this.get_dirty_nodes());deleted_nodes=deleted_nodes.concat(this.get_dirty_nodes());this.onchange(deleted_nodes)};GridStackEngine.prototype.clean_nodes=function(){_.each(this.nodes,function(n){n._dirty=false})};GridStackEngine.prototype.get_dirty_nodes=function(){return _.filter(this.nodes,function(n){return n._dirty})};GridStackEngine.prototype.add_node=function(node){node=this._prepare_node(node);if(typeof node.max_width!="undefined")node.width=Math.min(node.width,node.max_width);if(typeof node.max_height!="undefined")node.height=Math.min(node.height,node.max_height);if(typeof node.min_width!="undefined")node.width=Math.max(node.width,node.min_width);if(typeof node.min_height!="undefined")node.height=Math.max(node.height,node.min_height);node._id=++id_seq;node._dirty=true;if(node.auto_position){this._sort_nodes();for(var i=0;;++i){var x=i%this.width,y=Math.floor(i/this.width);if(x+node.width>this.width){continue}if(!_.find(this.nodes,function(n){return Utils.is_intercepted({x:x,y:y,width:node.width,height:node.height},n)})){node.x=x;node.y=y;break}}}this.nodes.push(node);this._fix_collisions(node);this._pack_nodes();this._notify();return node};GridStackEngine.prototype.remove_node=function(node){node._id=null;this.nodes=_.without(this.nodes,node);this._pack_nodes();this._notify(node)};GridStackEngine.prototype.can_move_node=function(node,x,y,width,height){var has_locked=Boolean(_.find(this.nodes,function(n){return n.locked}));if(!this.height&&!has_locked)return true;var cloned_node;var clone=new GridStackEngine(this.width,null,this.float,0,_.map(this.nodes,function(n){if(n==node){cloned_node=$.extend({},n);return cloned_node}return $.extend({},n)}));clone.move_node(cloned_node,x,y,width,height);var res=true;if(has_locked)res&=!Boolean(_.find(clone.nodes,function(n){return n!=cloned_node&&Boolean(n.locked)&&Boolean(n._dirty)}));if(this.height)res&=clone.get_grid_height()<=this.height;return res};GridStackEngine.prototype.can_be_placed_with_respect_to_height=function(node){if(!this.height)return true;var clone=new GridStackEngine(this.width,null,this.float,0,_.map(this.nodes,function(n){return $.extend({},n)}));clone.add_node(node);return clone.get_grid_height()<=this.height};GridStackEngine.prototype.move_node=function(node,x,y,width,height,no_pack){if(typeof x!="number")x=node.x;if(typeof y!="number")y=node.y;if(typeof width!="number")width=node.width;if(typeof height!="number")height=node.height;if(typeof node.max_width!="undefined")width=Math.min(width,node.max_width);if(typeof node.max_height!="undefined")height=Math.min(height,node.max_height);if(typeof node.min_width!="undefined")width=Math.max(width,node.min_width);if(typeof node.min_height!="undefined")height=Math.max(height,node.min_height);if(node.x==x&&node.y==y&&node.width==width&&node.height==height){return node}var resizing=node.width!=width;node._dirty=true;node.x=x;node.y=y;node.width=width;node.height=height;node=this._prepare_node(node,resizing);this._fix_collisions(node);if(!no_pack){this._pack_nodes();this._notify()}return node};GridStackEngine.prototype.get_grid_height=function(){return _.reduce(this.nodes,function(memo,n){return Math.max(memo,n.y+n.height)},0)};GridStackEngine.prototype.begin_update=function(node){_.each(this.nodes,function(n){n._orig_y=n.y});node._updating=true};GridStackEngine.prototype.end_update=function(){var n=_.find(this.nodes,function(n){return n._updating});if(n){n._updating=false}};var GridStack=function(el,opts){var self=this,one_column_mode;this.container=$(el);this.opts=_.defaults(opts||{},{width:parseInt(this.container.attr("data-gs-width"))||12,height:parseInt(this.container.attr("data-gs-height"))||0,item_class:"grid-stack-item",placeholder_class:"grid-stack-placeholder",handle:".grid-stack-item-content",cell_height:60,vertical_margin:20,auto:true,min_width:768,"float":false,_class:"grid-stack-"+(Math.random()*1e4).toFixed(0),animate:Boolean(this.container.attr("data-gs-animate"))||false,always_show_resize_handle:opts.always_show_resize_handle||false});this.container.addClass(this.opts._class);this._styles=Utils.create_stylesheet();this._styles._max=0;this.grid=new GridStackEngine(this.opts.width,function(nodes){var max_height=0;_.each(nodes,function(n){if(n._id==null){n.el.remove()}else{n.el.attr("data-gs-x",n.x).attr("data-gs-y",n.y).attr("data-gs-width",n.width).attr("data-gs-height",n.height);max_height=Math.max(max_height,n.y+n.height)}});self._update_styles(max_height+10)},this.opts.float,this.opts.height);if(this.opts.auto){var elements=[];this.container.find("."+this.opts.item_class).each(function(index,el){el=$(el);elements.push({el:el,i:parseInt(el.attr("data-gs-x"))+parseInt(el.attr("data-gs-y"))*parseInt(el.attr("data-gs-width"))})});_.chain(elements).sortBy(function(x){return x.i}).each(function(i){self._prepare_element(i.el)})}this.set_animation(this.opts.animate);this.placeholder=$('
').hide();this.container.append(this.placeholder);this.container.height(this.grid.get_grid_height()*(this.opts.cell_height+this.opts.vertical_margin)-this.opts.vertical_margin);var on_resize_handler=function(){if(self._is_one_column_mode()){if(one_column_mode)return;one_column_mode=true;_.each(self.grid.nodes,function(node){if(!node.no_move){node.el.draggable("disable")}if(!node.no_resize){node.el.resizable("disable")}})}else{if(!one_column_mode)return;one_column_mode=false;_.each(self.grid.nodes,function(node){if(!node.no_move){node.el.draggable("enable")}if(!node.no_resize){node.el.resizable("enable")}})}};$(window).resize(on_resize_handler);on_resize_handler()};GridStack.prototype._update_styles=function(max_height){if(typeof max_height=="undefined"){max_height=this._styles._max;this._styles._max=0;while(this._styles.rules.length){this._styles.removeRule(0)}this._update_container_height()}if(max_height>this._styles._max){for(var i=this._styles._max;i