/*jshint evil:true, eqeqeq:false, eqnull:true, devel:true */ /*global jQuery */ (function($){ /* ** * jqGrid addons using jQuery UI * Author: Mark Williams * Dual licensed under the MIT and GPL licenses: * http://www.opensource.org/licenses/mit-license.php * http://www.gnu.org/licenses/gpl-2.0.html * depends on jQuery UI **/ "use strict"; if ($.jgrid.msie && $.jgrid.msiever()===8) { $.expr[":"].hidden = function(elem) { return elem.offsetWidth === 0 || elem.offsetHeight === 0 || elem.style.display === "none"; }; } // requiere load multiselect before grid $.jgrid._multiselect = false; if($.ui) { if ($.ui.multiselect ) { if($.ui.multiselect.prototype._setSelected) { var setSelected = $.ui.multiselect.prototype._setSelected; $.ui.multiselect.prototype._setSelected = function(item,selected) { var ret = setSelected.call(this,item,selected); if (selected && this.selectedList) { var elt = this.element; this.selectedList.find('li').each(function() { if ($(this).data('optionLink')) { $(this).data('optionLink').remove().appendTo(elt); } }); } return ret; }; } if($.ui.multiselect.prototype.destroy) { $.ui.multiselect.prototype.destroy = function() { this.element.show(); this.container.remove(); if ($.Widget === undefined) { $.widget.prototype.destroy.apply(this, arguments); } else { $.Widget.prototype.destroy.apply(this, arguments); } }; } $.jgrid._multiselect = true; } } $.jgrid.extend({ sortableColumns : function (tblrow) { return this.each(function (){ var ts = this, tid= $.jgrid.jqID( ts.p.id ); function start() {ts.p.disableClick = true;} var sortable_opts = { "tolerance" : "pointer", "axis" : "x", "scrollSensitivity": "1", "items": '>th:not(:has(#jqgh_'+tid+'_cb'+',#jqgh_'+tid+'_rn'+',#jqgh_'+tid+'_subgrid),:hidden)', "placeholder": { element: function(item) { var el = $(document.createElement(item[0].nodeName)) .addClass(item[0].className+" ui-sortable-placeholder ui-state-highlight") .removeClass("ui-sortable-helper")[0]; return el; }, update: function(self, p) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); } }, "update": function(event, ui) { var p = $(ui.item).parent(), th = $(">th", p), colModel = ts.p.colModel, cmMap = {}, tid= ts.p.id+"_"; $.each(colModel, function(i) { cmMap[this.name]=i; }); var permutation = []; th.each(function() { var id = $(">div", this).get(0).id.replace(/^jqgh_/, "").replace(tid,""); if (cmMap.hasOwnProperty(id)) { permutation.push(cmMap[id]); } }); $(ts).jqGrid("remapColumns",permutation, true, true); if ($.isFunction(ts.p.sortable.update)) { ts.p.sortable.update(permutation); } setTimeout(function(){ts.p.disableClick=false;}, 50); } }; if (ts.p.sortable.options) { $.extend(sortable_opts, ts.p.sortable.options); } else if ($.isFunction(ts.p.sortable)) { ts.p.sortable = { "update" : ts.p.sortable }; } if (sortable_opts.start) { var s = sortable_opts.start; sortable_opts.start = function(e,ui) { start(); s.call(this,e,ui); }; } else { sortable_opts.start = start; } if (ts.p.sortable.exclude) { sortable_opts.items += ":not("+ts.p.sortable.exclude+")"; } var $e = tblrow.sortable(sortable_opts), dataObj = $e.data("sortable") || $e.data("uiSortable"); if (dataObj != null) { dataObj.data("sortable").floating = true; } }); }, columnChooser : function(opts) { var self = this, selector, select, colMap = {}, fixedCols = [], dopts, mopts, $dialogContent, multiselectData, listHeight, colModel = self.jqGrid("getGridParam", "colModel"), colNames = self.jqGrid("getGridParam", "colNames"), getMultiselectWidgetData = function ($elem) { return ($.ui.multiselect.prototype && $elem.data($.ui.multiselect.prototype.widgetFullName || $.ui.multiselect.prototype.widgetName)) || $elem.data("ui-multiselect") || $elem.data("multiselect"); }; if ($("#colchooser_" + $.jgrid.jqID(self[0].p.id)).length) { return; } selector = $('
'); select = $('select', selector); function insert(perm,i,v) { var a, b; if(i>=0){ a = perm.slice(); b = a.splice(i,Math.max(perm.length-i,i)); if(i>perm.length) { i = perm.length; } a[i] = v; return a.concat(b); } return perm; } function call(fn, obj) { if (!fn) { return; } if (typeof fn === 'string') { if ($.fn[fn]) { $.fn[fn].apply(obj, $.makeArray(arguments).slice(2)); } } else if ($.isFunction(fn)) { fn.apply(obj, $.makeArray(arguments).slice(2)); } } opts = $.extend({ width : 400, height : 240, classname : null, done : function(perm) { if (perm) { self.jqGrid("remapColumns", perm, true); } }, /* msel is either the name of a ui widget class that extends a multiselect, or a function that supports creating a multiselect object (with no argument, or when passed an object), and destroying it (when passed the string "destroy"). */ msel : "multiselect", /* "msel_opts" : {}, */ /* dlog is either the name of a ui widget class that behaves in a dialog-like way, or a function, that supports creating a dialog (when passed dlog_opts) or destroying a dialog (when passed the string "destroy") */ dlog : "dialog", dialog_opts : { minWidth: 470, dialogClass: "ui-jqdialog" }, /* dlog_opts is either an option object to be passed to "dlog", or (more likely) a function that creates the options object. The default produces a suitable options object for ui.dialog */ dlog_opts : function(options) { var buttons = {}; buttons[options.bSubmit] = function() { options.apply_perm(); options.cleanup(false); }; buttons[options.bCancel] = function() { options.cleanup(true); }; return $.extend(true, { buttons: buttons, close: function() { options.cleanup(true); }, modal: options.modal || false, resizable: options.resizable || true, width: options.width + 70, resize: function () { var widgetData = getMultiselectWidgetData(select), $thisDialogContent = widgetData.container.closest(".ui-dialog-content"); if ($thisDialogContent.length > 0 && typeof $thisDialogContent[0].style === "object") { $thisDialogContent[0].style.width = ""; } else { $thisDialogContent.css("width", ""); // or just remove width style } widgetData.selectedList.height(Math.max(widgetData.selectedContainer.height() - widgetData.selectedActions.outerHeight() - 1, 1)); widgetData.availableList.height(Math.max(widgetData.availableContainer.height() - widgetData.availableActions.outerHeight() - 1, 1)); } }, options.dialog_opts || {}); }, /* Function to get the permutation array, and pass it to the "done" function */ apply_perm : function() { var perm = []; $('option',select).each(function() { if ($(this).is("[selected]")) { self.jqGrid("showCol", colModel[this.value].name); } else { self.jqGrid("hideCol", colModel[this.value].name); } }); //fixedCols.slice(0); $('option[selected]',select).each(function() { perm.push(parseInt(this.value,10)); }); $.each(perm, function() { delete colMap[colModel[parseInt(this,10)].name]; }); $.each(colMap, function() { var ti = parseInt(this,10); perm = insert(perm,ti,ti); }); if (opts.done) { opts.done.call(self, perm); } self.jqGrid("setGridWidth", self[0].p.tblwidth, self[0].p.shrinkToFit); }, /* Function to cleanup the dialog, and select. Also calls the done function with no permutation (to indicate that the columnChooser was aborted */ cleanup : function(calldone) { call(opts.dlog, selector, 'destroy'); call(opts.msel, select, 'destroy'); selector.remove(); if (calldone && opts.done) { opts.done.call(self); } }, msel_opts : {} }, $.jgrid.col, opts || {}); if($.ui) { if ($.ui.multiselect && $.ui.multiselect.defaults) { if (!$.jgrid._multiselect) { // should be in language file alert("Multiselect plugin loaded after jqGrid. Please load the plugin before the jqGrid!"); return; } // ??? the next line uses $.ui.multiselect.defaults which will be typically undefined opts.msel_opts = $.extend($.ui.multiselect.defaults, opts.msel_opts); } } if (opts.caption) { selector.attr("title", opts.caption); } if (opts.classname) { selector.addClass(opts.classname); select.addClass(opts.classname); } if (opts.width) { $(">div",selector).css({width: opts.width,margin:"0 auto"}); select.css("width", opts.width); } if (opts.height) { $(">div",selector).css("height", opts.height); select.css("height", opts.height - 10); } select.empty(); $.each(colModel, function(i) { colMap[this.name] = i; if (this.hidedlg) { if (!this.hidden) { fixedCols.push(i); } return; } select.append(""); }); dopts = $.isFunction(opts.dlog_opts) ? opts.dlog_opts.call(self, opts) : opts.dlog_opts; call(opts.dlog, selector, dopts); mopts = $.isFunction(opts.msel_opts) ? opts.msel_opts.call(self, opts) : opts.msel_opts; call(opts.msel, select, mopts); // fix height of elements of the multiselect widget $dialogContent = $("#colchooser_" + $.jgrid.jqID(self[0].p.id)); $dialogContent.css({ margin: "auto" }); $dialogContent.find(">div").css({ width: "100%", height: "100%", margin: "auto" }); multiselectData = getMultiselectWidgetData(select); multiselectData.container.css({ width: "100%", height: "100%", margin: "auto" }); multiselectData.selectedContainer.css({ width: multiselectData.options.dividerLocation * 100 + "%", height: "100%", margin: "auto", boxSizing: "border-box" }); multiselectData.availableContainer.css({ width: (100 - multiselectData.options.dividerLocation * 100) + "%", height: "100%", margin: "auto", boxSizing: "border-box" }); // set height for both selectedList and availableList multiselectData.selectedList.css("height", "auto"); multiselectData.availableList.css("height", "auto"); listHeight = Math.max(multiselectData.selectedList.height(), multiselectData.availableList.height()); listHeight = Math.min(listHeight, $(window).height()); multiselectData.selectedList.css("height", listHeight); multiselectData.availableList.css("height", listHeight); }, sortableRows : function (opts) { // Can accept all sortable options and events return this.each(function(){ var $t = this; if(!$t.grid) { return; } // Currently we disable a treeGrid sortable if($t.p.treeGrid) { return; } if($.fn.sortable) { opts = $.extend({ "cursor":"move", "axis" : "y", "items": ".jqgrow" }, opts || {}); if(opts.start && $.isFunction(opts.start)) { opts._start_ = opts.start; delete opts.start; } else {opts._start_=false;} if(opts.update && $.isFunction(opts.update)) { opts._update_ = opts.update; delete opts.update; } else {opts._update_ = false;} opts.start = function(ev,ui) { $(ui.item).css("border-width","0"); $("td",ui.item).each(function(i){ this.style.width = $t.grid.cols[i].style.width; }); if($t.p.subGrid) { var subgid = $(ui.item).attr("id"); try { $($t).jqGrid('collapseSubGridRow',subgid); } catch (e) {} } if(opts._start_) { opts._start_.apply(this,[ev,ui]); } }; opts.update = function (ev,ui) { $(ui.item).css("border-width",""); if($t.p.rownumbers === true) { $("td.jqgrid-rownum",$t.rows).each(function( i ){ $(this).html( i+1+(parseInt($t.p.page,10)-1)*parseInt($t.p.rowNum,10) ); }); } if(opts._update_) { opts._update_.apply(this,[ev,ui]); } }; $("tbody:first",$t).sortable(opts); $("tbody:first",$t).disableSelection(); } }); }, gridDnD : function(opts) { return this.each(function(){ var $t = this, i, cn; if(!$t.grid) { return; } // Currently we disable a treeGrid drag and drop if($t.p.treeGrid) { return; } if(!$.fn.draggable || !$.fn.droppable) { return; } function updateDnD () { var datadnd = $.data($t,"dnd"); $("tr.jqgrow:not(.ui-draggable)",$t).draggable($.isFunction(datadnd.drag) ? datadnd.drag.call($($t),datadnd) : datadnd.drag); } var appender = "
"; if($("#jqgrid_dnd")[0] === undefined) { $('body').append(appender); } if(typeof opts === 'string' && opts === 'updateDnD' && $t.p.jqgdnd===true) { updateDnD(); return; } opts = $.extend({ "drag" : function (opts) { return $.extend({ start : function (ev, ui) { var i, subgid; // if we are in subgrid mode try to collapse the node if($t.p.subGrid) { subgid = $(ui.helper).attr("id"); try { $($t).jqGrid('collapseSubGridRow',subgid); } catch (e) {} } // hack // drag and drop does not insert tr in table, when the table has no rows // we try to insert new empty row on the target(s) for (i=0;i<$.data($t,"dnd").connectWith.length;i++){ if($($.data($t,"dnd").connectWith[i]).jqGrid('getGridParam','reccount') === 0 ){ $($.data($t,"dnd").connectWith[i]).jqGrid('addRowData','jqg_empty_row',{}); } } ui.helper.addClass("ui-state-highlight"); $("td",ui.helper).each(function(i) { this.style.width = $t.grid.headers[i].width+"px"; }); if(opts.onstart && $.isFunction(opts.onstart) ) { opts.onstart.call($($t),ev,ui); } }, stop :function(ev,ui) { var i, ids; if(ui.helper.dropped && !opts.dragcopy) { ids = $(ui.helper).attr("id"); if(ids === undefined) { ids = $(this).attr("id"); } $($t).jqGrid('delRowData',ids ); } // if we have a empty row inserted from start event try to delete it for (i=0;i<$.data($t,"dnd").connectWith.length;i++){ $($.data($t,"dnd").connectWith[i]).jqGrid('delRowData','jqg_empty_row'); } if(opts.onstop && $.isFunction(opts.onstop) ) { opts.onstop.call($($t),ev,ui); } } },opts.drag_opts || {}); }, "drop" : function (opts) { return $.extend({ accept: function(d) { if (!$(d).hasClass('jqgrow')) { return d;} var tid = $(d).closest("table.ui-jqgrid-btable"); if(tid.length > 0 && $.data(tid[0],"dnd") !== undefined) { var cn = $.data(tid[0],"dnd").connectWith; return $.inArray('#'+$.jgrid.jqID(this.id),cn) !== -1 ? true : false; } return false; }, drop: function(ev, ui) { if (!$(ui.draggable).hasClass('jqgrow')) { return; } var accept = $(ui.draggable).attr("id"); var getdata = ui.draggable.parent().parent().jqGrid('getRowData',accept); if(!opts.dropbyname) { var j =0, tmpdata = {}, nm, key; var dropmodel = $("#"+$.jgrid.jqID(this.id)).jqGrid('getGridParam','colModel'); try { for (key in getdata) { if (getdata.hasOwnProperty(key)) { nm = dropmodel[j].name; if( !(nm === 'cb' || nm === 'rn' || nm === 'subgrid' )) { if(getdata.hasOwnProperty(key) && dropmodel[j]) { tmpdata[nm] = getdata[key]; } } j++; } } getdata = tmpdata; } catch (e) {} } ui.helper.dropped = true; if(opts.beforedrop && $.isFunction(opts.beforedrop) ) { //parameters to this callback - event, element, data to be inserted, sender, reciever // should return object which will be inserted into the reciever var datatoinsert = opts.beforedrop.call(this,ev,ui,getdata,$('#'+$.jgrid.jqID($t.p.id)),$(this)); if (datatoinsert !== undefined && datatoinsert !== null && typeof datatoinsert === "object") { getdata = datatoinsert; } } if(ui.helper.dropped) { var grid; if(opts.autoid) { if($.isFunction(opts.autoid)) { grid = opts.autoid.call(this,getdata); } else { grid = Math.ceil(Math.random()*1000); grid = opts.autoidprefix+grid; } } // NULL is interpreted as undefined while null as object $("#"+$.jgrid.jqID(this.id)).jqGrid('addRowData',grid,getdata,opts.droppos); } if(opts.ondrop && $.isFunction(opts.ondrop) ) { opts.ondrop.call(this,ev,ui, getdata); } }}, opts.drop_opts || {}); }, "onstart" : null, "onstop" : null, "beforedrop": null, "ondrop" : null, "drop_opts" : { "activeClass": "ui-state-active", "hoverClass": "ui-state-hover" }, "drag_opts" : { "revert": "invalid", "helper": "clone", "cursor": "move", "appendTo" : "#jqgrid_dnd", "zIndex": 5000 }, "dragcopy": false, "dropbyname" : false, "droppos" : "first", "autoid" : true, "autoidprefix" : "dnd_" }, opts || {}); if(!opts.connectWith) { return; } opts.connectWith = opts.connectWith.split(","); opts.connectWith = $.map(opts.connectWith,function(n){return $.trim(n);}); $.data($t,"dnd",opts); if($t.p.reccount !== 0 && !$t.p.jqgdnd) { updateDnD(); } $t.p.jqgdnd = true; for (i=0;i