Actualización
This commit is contained in:
704
main/inc/lib/javascript/jqgrid/plugins/grid.addons.js
Normal file
704
main/inc/lib/javascript/jqgrid/plugins/grid.addons.js
Normal file
@@ -0,0 +1,704 @@
|
||||
(function($){
|
||||
/*
|
||||
* jqGrid methods without support. Use as you wish
|
||||
* Tony Tomov tony@trirand.com
|
||||
* http://trirand.com/blog/
|
||||
* 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
|
||||
*
|
||||
* This list of deprecated methods.
|
||||
* If you instead want to use them, please include this file after the grid main file.
|
||||
* Some methods will be then overwritten.
|
||||
*
|
||||
*/
|
||||
/*global jQuery, $ */
|
||||
|
||||
$.jgrid.extend({
|
||||
// This is the ols search Filter method used in navigator.
|
||||
searchGrid : function (p) {
|
||||
p = $.extend({
|
||||
recreateFilter: false,
|
||||
drag: true,
|
||||
sField:'searchField',
|
||||
sValue:'searchString',
|
||||
sOper: 'searchOper',
|
||||
sFilter: 'filters',
|
||||
loadDefaults: true, // this options activates loading of default filters from grid's postData for Multipe Search only.
|
||||
beforeShowSearch: null,
|
||||
afterShowSearch : null,
|
||||
onInitializeSearch: null,
|
||||
closeAfterSearch : false,
|
||||
closeAfterReset: false,
|
||||
closeOnEscape : false,
|
||||
multipleSearch : false,
|
||||
cloneSearchRowOnAdd: true,
|
||||
// translation
|
||||
// if you want to change or remove the order change it in sopt
|
||||
// ['bw','eq','ne','lt','le','gt','ge','ew','cn']
|
||||
sopt: null,
|
||||
// Note: stringResult is intentionally declared "undefined by default".
|
||||
// you are velcome to define stringResult expressly in the options you pass to searchGrid()
|
||||
// stringResult is a "safeguard" measure to insure we post sensible data when communicated as form-encoded
|
||||
// see http://github.com/tonytomov/jqGrid/issues/#issue/36
|
||||
//
|
||||
// If this value is not expressly defined in the incoming options,
|
||||
// lower in the code we will infer the value based on value of multipleSearch
|
||||
stringResult: undefined,
|
||||
onClose : null,
|
||||
// useDataProxy allows ADD, EDIT and DEL code to bypass calling $.ajax
|
||||
// directly when grid's 'dataProxy' property (grid.p.dataProxy) is a function.
|
||||
// Used for "editGridRow" and "delGridRow" below and automatically flipped to TRUE
|
||||
// when ajax setting's 'url' (grid's 'editurl') property is undefined.
|
||||
// When 'useDataProxy' is true, instead of calling $.ajax.call(gridDOMobj, o, i) we call
|
||||
// gridDOMobj.p.dataProxy.call(gridDOMobj, o, i)
|
||||
//
|
||||
// Behavior is extremely similar to when 'datatype' is a function, but arguments are slightly different.
|
||||
// Normally the following is fed to datatype.call(a, b, c):
|
||||
// a = Pointer to grid's table DOM element, b = grid.p.postdata, c = "load_"+grid's ID
|
||||
// In cases of "edit" and "del" the following is fed:
|
||||
// a = Pointer to grid's table DOM element (same),
|
||||
// b = extended Ajax Options including postdata in "data" property. (different object type)
|
||||
// c = "set_"+grid's ID in case of "edit" and "del_"+grid's ID in case of "del" (same type, different content)
|
||||
// The major difference is that complete ajax options object, with attached "complete" and "error"
|
||||
// callback functions is fed instead of only post data.
|
||||
// This allows you to emulate a $.ajax call (including calling "complete"/"error"),
|
||||
// while retrieving the data locally in the browser.
|
||||
useDataProxy: false,
|
||||
overlay : true
|
||||
}, $.jgrid.search, p || {});
|
||||
return this.each(function() {
|
||||
var $t = this;
|
||||
if(!$t.grid) {return;}
|
||||
var fid = "fbox_"+$t.p.id,
|
||||
showFrm = true;
|
||||
function applyDefaultFilters(gridDOMobj, filterSettings) {
|
||||
/*
|
||||
gridDOMobj = ointer to grid DOM object ( $(#list)[0] )
|
||||
What we need from gridDOMobj:
|
||||
gridDOMobj.SearchFilter is the pointer to the Search box, once it's created.
|
||||
gridDOMobj.p.postData - dictionary of post settings. These can be overriden at grid creation to
|
||||
contain default filter settings. We will parse these and will populate the search with defaults.
|
||||
filterSettings - same settings object you (would) pass to $().jqGrid('searchGrid', filterSettings);
|
||||
*/
|
||||
|
||||
// Pulling default filter settings out of postData property of grid's properties.:
|
||||
var defaultFilters = gridDOMobj.p.postData[filterSettings.sFilter];
|
||||
// example of what we might get: {"groupOp":"and","rules":[{"field":"amount","op":"eq","data":"100"}]}
|
||||
// suppose we have imported this with grid import, the this is a string.
|
||||
if(typeof(defaultFilters) == "string") {
|
||||
defaultFilters = $.jgrid.parse(defaultFilters);
|
||||
}
|
||||
if (defaultFilters) {
|
||||
if (defaultFilters.groupOp) {
|
||||
gridDOMobj.SearchFilter.setGroupOp(defaultFilters.groupOp);
|
||||
}
|
||||
if (defaultFilters.rules) {
|
||||
var f, i = 0, li = defaultFilters.rules.length, success = false;
|
||||
for (; i < li; i++) {
|
||||
f = defaultFilters.rules[i];
|
||||
// we are not trying to counter all issues with filter declaration here. Just the basics to avoid lookup exceptions.
|
||||
if (f.field !== undefined && f.op !== undefined && f.data !== undefined) {
|
||||
success = gridDOMobj.SearchFilter.setFilter({
|
||||
'sfref':gridDOMobj.SearchFilter.$.find(".sf:last"),
|
||||
'filter':$.extend({},f)
|
||||
});
|
||||
if (success) { gridDOMobj.SearchFilter.add(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end of applyDefaultFilters
|
||||
function hideFilter(selector) {
|
||||
if(p.onClose){
|
||||
var fclm = p.onClose(selector);
|
||||
if(typeof fclm == 'boolean' && !fclm) { return; }
|
||||
}
|
||||
selector.hide();
|
||||
if(p.overlay === true) {
|
||||
$(".jqgrid-overlay:first","#gbox_"+$t.p.id).hide();
|
||||
}
|
||||
}
|
||||
function showFilter(){
|
||||
var fl = $(".ui-searchFilter").length;
|
||||
if(fl > 1) {
|
||||
var zI = $("#"+fid).css("zIndex");
|
||||
$("#"+fid).css({zIndex:parseInt(zI,10)+fl});
|
||||
}
|
||||
$("#"+fid).show();
|
||||
if(p.overlay === true) {
|
||||
$(".jqgrid-overlay:first","#gbox_"+$t.p.id).show();
|
||||
}
|
||||
try{$(':input:visible',"#"+fid)[0].focus();}catch(_){}
|
||||
}
|
||||
function searchFilters(filters) {
|
||||
var hasFilters = (filters !== undefined),
|
||||
grid = $("#"+$t.p.id),
|
||||
sdata={};
|
||||
if(p.multipleSearch===false) {
|
||||
sdata[p.sField] = filters.rules[0].field;
|
||||
sdata[p.sValue] = filters.rules[0].data;
|
||||
sdata[p.sOper] = filters.rules[0].op;
|
||||
if(sdata.hasOwnProperty(p.sFilter) ) {
|
||||
delete sdata[p.sFilter];
|
||||
}
|
||||
} else {
|
||||
sdata[p.sFilter] = filters;
|
||||
$.each([p.sField, p.sValue, p.sOper], function(i, n){
|
||||
if(sdata.hasOwnProperty(n)) { delete sdata[n];}
|
||||
});
|
||||
}
|
||||
grid[0].p.search = hasFilters;
|
||||
$.extend(grid[0].p.postData,sdata);
|
||||
grid.trigger("reloadGrid",[{page:1}]);
|
||||
if(p.closeAfterSearch) { hideFilter($("#"+fid)); }
|
||||
}
|
||||
function resetFilters(op) {
|
||||
var reload = op && op.hasOwnProperty("reload") ? op.reload : true,
|
||||
grid = $("#"+$t.p.id),
|
||||
sdata={};
|
||||
grid[0].p.search = false;
|
||||
if(p.multipleSearch===false) {
|
||||
sdata[p.sField] = sdata[p.sValue] = sdata[p.sOper] = "";
|
||||
} else {
|
||||
sdata[p.sFilter] = "";
|
||||
}
|
||||
$.extend(grid[0].p.postData,sdata);
|
||||
if(reload) {
|
||||
grid.trigger("reloadGrid",[{page:1}]);
|
||||
}
|
||||
if(p.closeAfterReset) { hideFilter($("#"+fid)); }
|
||||
}
|
||||
if($.fn.searchFilter) {
|
||||
if(p.recreateFilter===true) {$("#"+fid).remove();}
|
||||
if( $("#"+fid).html() !== null ) {
|
||||
if ( $.isFunction(p.beforeShowSearch) ) {
|
||||
showFrm = p.beforeShowSearch($("#"+fid));
|
||||
if(typeof(showFrm) == "undefined") {
|
||||
showFrm = true;
|
||||
}
|
||||
}
|
||||
if(showFrm === false) { return; }
|
||||
showFilter();
|
||||
if( $.isFunction(p.afterShowSearch) ) { p.afterShowSearch($("#"+fid)); }
|
||||
} else {
|
||||
var fields = [],
|
||||
colNames = $("#"+$t.p.id).jqGrid("getGridParam","colNames"),
|
||||
colModel = $("#"+$t.p.id).jqGrid("getGridParam","colModel"),
|
||||
stempl = ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc'],
|
||||
j,pos,k,oprtr=[];
|
||||
if (p.sopt !==null) {
|
||||
k=0;
|
||||
for(j=0;j<p.sopt.length;j++) {
|
||||
if( (pos= $.inArray(p.sopt[j],stempl)) != -1 ){
|
||||
oprtr[k] = {op:p.sopt[j],text: p.odata[pos]};
|
||||
k++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(j=0;j<stempl.length;j++) {
|
||||
oprtr[j] = {op:stempl[j],text: p.odata[j]};
|
||||
}
|
||||
}
|
||||
$.each(colModel, function(i, v) {
|
||||
var searchable = (typeof v.search === 'undefined') ? true: v.search ,
|
||||
hidden = (v.hidden === true),
|
||||
soptions = $.extend({}, {text: colNames[i], itemval: v.index || v.name}, this.searchoptions),
|
||||
ignoreHiding = (soptions.searchhidden === true);
|
||||
if(typeof soptions.sopt !== 'undefined') {
|
||||
k=0;
|
||||
soptions.ops =[];
|
||||
if(soptions.sopt.length>0) {
|
||||
for(j=0;j<soptions.sopt.length;j++) {
|
||||
if( (pos= $.inArray(soptions.sopt[j],stempl)) != -1 ){
|
||||
soptions.ops[k] = {op:soptions.sopt[j],text: p.odata[pos]};
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(typeof(this.stype) === 'undefined') { this.stype='text'; }
|
||||
if(this.stype == 'select') {
|
||||
if ( soptions.dataUrl !== undefined) {}
|
||||
else {
|
||||
var eov;
|
||||
if(soptions.value) {
|
||||
eov = soptions.value;
|
||||
} else if(this.editoptions) {
|
||||
eov = this.editoptions.value;
|
||||
}
|
||||
if(eov) {
|
||||
soptions.dataValues =[];
|
||||
if(typeof(eov) === 'string') {
|
||||
var so = eov.split(";"),sv;
|
||||
for(j=0;j<so.length;j++) {
|
||||
sv = so[j].split(":");
|
||||
soptions.dataValues[j] ={value:sv[0],text:sv[1]};
|
||||
}
|
||||
} else if (typeof(eov) === 'object') {
|
||||
j=0;
|
||||
for (var key in eov) {
|
||||
if(eov.hasOwnProperty(key)) {
|
||||
soptions.dataValues[j] ={value:key,text:eov[key]};
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((ignoreHiding && searchable) || (searchable && !hidden)) {
|
||||
fields.push(soptions);
|
||||
}
|
||||
});
|
||||
if(fields.length>0){
|
||||
$("<div id='"+fid+"' role='dialog' tabindex='-1'></div>").insertBefore("#gview_"+$t.p.id);
|
||||
// Before we create searchFilter we need to decide if we want to get back a string or a JS object.
|
||||
// see http://github.com/tonytomov/jqGrid/issues/#issue/36 for background on the issue.
|
||||
// If p.stringResult is defined, it was explisitly passed to us by user. Honor the choice, whatever it is.
|
||||
if (p.stringResult===undefined) {
|
||||
// to provide backward compatibility, inferring stringResult value from multipleSearch
|
||||
p.stringResult = p.multipleSearch;
|
||||
}
|
||||
// we preserve the return value here to retain access to .add() and other good methods of search form.
|
||||
$t.SearchFilter = $("#"+fid).searchFilter(fields, { groupOps: p.groupOps, operators: oprtr, onClose:hideFilter, resetText: p.Reset, searchText: p.Find, windowTitle: p.caption, rulesText:p.rulesText, matchText:p.matchText, onSearch: searchFilters, onReset: resetFilters,stringResult:p.stringResult, ajaxSelectOptions: $.extend({},$.jgrid.ajaxOptions,$t.p.ajaxSelectOptions ||{}), clone: p.cloneSearchRowOnAdd });
|
||||
$(".ui-widget-overlay","#"+fid).remove();
|
||||
if($t.p.direction=="rtl") { $(".ui-closer","#"+fid).css("float","left"); }
|
||||
if (p.drag===true) {
|
||||
$("#"+fid+" table thead tr:first td:first").css('cursor','move');
|
||||
if(jQuery.fn.jqDrag) {
|
||||
$("#"+fid).jqDrag($("#"+fid+" table thead tr:first td:first"));
|
||||
} else {
|
||||
try {
|
||||
$("#"+fid).draggable({handle: $("#"+fid+" table thead tr:first td:first")});
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
if(p.multipleSearch === false) {
|
||||
$(".ui-del, .ui-add, .ui-del, .ui-add-last, .matchText, .rulesText", "#"+fid).hide();
|
||||
$("select[name='groupOp']","#"+fid).hide();
|
||||
}
|
||||
if (p.multipleSearch === true && p.loadDefaults === true) {
|
||||
applyDefaultFilters($t, p);
|
||||
}
|
||||
if ( $.isFunction(p.onInitializeSearch) ) { p.onInitializeSearch( $("#"+fid) ); }
|
||||
if ( $.isFunction(p.beforeShowSearch) ) {
|
||||
showFrm = p.beforeShowSearch($("#"+fid));
|
||||
if(typeof(showFrm) == "undefined") {
|
||||
showFrm = true;
|
||||
}
|
||||
}
|
||||
if(showFrm === false) { return; }
|
||||
showFilter();
|
||||
if( $.isFunction(p.afterShowSearch) ) { p.afterShowSearch($("#"+fid)); }
|
||||
if(p.closeOnEscape===true){
|
||||
$("#"+fid).keydown( function( e ) {
|
||||
if( e.which == 27 ) {
|
||||
hideFilter($("#"+fid));
|
||||
}
|
||||
if (e.which == 13) {
|
||||
$(".ui-search", this).click();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// methods taken from grid.custom.
|
||||
updateGridRows : function (data, rowidname, jsonreader) {
|
||||
var nm, success=false, title;
|
||||
this.each(function(){
|
||||
var t = this, vl, ind, srow, sid;
|
||||
if(!t.grid) {return false;}
|
||||
if(!rowidname) { rowidname = "id"; }
|
||||
if( data && data.length >0 ) {
|
||||
$(data).each(function(j){
|
||||
srow = this;
|
||||
ind = t.rows.namedItem(srow[rowidname]);
|
||||
if(ind) {
|
||||
sid = srow[rowidname];
|
||||
if(jsonreader === true){
|
||||
if(t.p.jsonReader.repeatitems === true) {
|
||||
if(t.p.jsonReader.cell) {srow = srow[t.p.jsonReader.cell];}
|
||||
for (var k=0;k<srow.length;k++) {
|
||||
vl = t.formatter( sid, srow[k], k, srow, 'edit');
|
||||
title = t.p.colModel[k].title ? {"title":$.jgrid.stripHtml(vl)} : {};
|
||||
if(t.p.treeGrid===true && nm == t.p.ExpandColumn) {
|
||||
$("td:eq("+k+") > span:first",ind).html(vl).attr(title);
|
||||
} else {
|
||||
$("td:eq("+k+")",ind).html(vl).attr(title);
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
$(t.p.colModel).each(function(i){
|
||||
nm = jsonreader===true ? this.jsonmap || this.name :this.name;
|
||||
if( srow[nm] !== undefined) {
|
||||
vl = t.formatter( sid, srow[nm], i, srow, 'edit');
|
||||
title = this.title ? {"title":$.jgrid.stripHtml(vl)} : {};
|
||||
if(t.p.treeGrid===true && nm == t.p.ExpandColumn) {
|
||||
$("td:eq("+i+") > span:first",ind).html(vl).attr(title);
|
||||
} else {
|
||||
$("td:eq("+i+")",ind).html(vl).attr(title);
|
||||
}
|
||||
success = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return success;
|
||||
},
|
||||
// Form search - sorry for this method. Instead use ne jqFilter method.
|
||||
filterGrid : function(gridid,p){
|
||||
p = $.extend({
|
||||
gridModel : false,
|
||||
gridNames : false,
|
||||
gridToolbar : false,
|
||||
filterModel: [], // label/name/stype/defval/surl/sopt
|
||||
formtype : "horizontal", // horizontal/vertical
|
||||
autosearch: true, // if set to false a serch button should be enabled.
|
||||
formclass: "filterform",
|
||||
tableclass: "filtertable",
|
||||
buttonclass: "filterbutton",
|
||||
searchButton: "Search",
|
||||
clearButton: "Clear",
|
||||
enableSearch : false,
|
||||
enableClear: false,
|
||||
beforeSearch: null,
|
||||
afterSearch: null,
|
||||
beforeClear: null,
|
||||
afterClear: null,
|
||||
url : '',
|
||||
marksearched: true
|
||||
},p || {});
|
||||
return this.each(function(){
|
||||
var self = this;
|
||||
this.p = p;
|
||||
if(this.p.filterModel.length === 0 && this.p.gridModel===false) { alert("No filter is set"); return;}
|
||||
if( !gridid) {alert("No target grid is set!"); return;}
|
||||
this.p.gridid = gridid.indexOf("#") != -1 ? gridid : "#"+gridid;
|
||||
var gcolMod = $(this.p.gridid).jqGrid("getGridParam",'colModel');
|
||||
if(gcolMod) {
|
||||
if( this.p.gridModel === true) {
|
||||
var thegrid = $(this.p.gridid)[0];
|
||||
var sh;
|
||||
// we should use the options search, edittype, editoptions
|
||||
// additionally surl and defval can be added in grid colModel
|
||||
$.each(gcolMod, function (i,n) {
|
||||
var tmpFil = [];
|
||||
this.search = this.search === false ? false : true;
|
||||
if(this.editrules && this.editrules.searchhidden === true) {
|
||||
sh = true;
|
||||
} else {
|
||||
if(this.hidden === true ) {
|
||||
sh = false;
|
||||
} else {
|
||||
sh = true;
|
||||
}
|
||||
}
|
||||
if( this.search === true && sh === true) {
|
||||
if(self.p.gridNames===true) {
|
||||
tmpFil.label = thegrid.p.colNames[i];
|
||||
} else {
|
||||
tmpFil.label = '';
|
||||
}
|
||||
tmpFil.name = this.name;
|
||||
tmpFil.index = this.index || this.name;
|
||||
// we support only text and selects, so all other to text
|
||||
tmpFil.stype = this.edittype || 'text';
|
||||
if(tmpFil.stype != 'select' ) {
|
||||
tmpFil.stype = 'text';
|
||||
}
|
||||
tmpFil.defval = this.defval || '';
|
||||
tmpFil.surl = this.surl || '';
|
||||
tmpFil.sopt = this.editoptions || {};
|
||||
tmpFil.width = this.width;
|
||||
self.p.filterModel.push(tmpFil);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$.each(self.p.filterModel,function(i,n) {
|
||||
for(var j=0;j<gcolMod.length;j++) {
|
||||
if(this.name == gcolMod[j].name) {
|
||||
this.index = gcolMod[j].index || this.name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!this.index) {
|
||||
this.index = this.name;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
alert("Could not get grid colModel"); return;
|
||||
}
|
||||
var triggerSearch = function() {
|
||||
var sdata={}, j=0, v;
|
||||
var gr = $(self.p.gridid)[0], nm;
|
||||
gr.p.searchdata = {};
|
||||
if($.isFunction(self.p.beforeSearch)){self.p.beforeSearch();}
|
||||
$.each(self.p.filterModel,function(i,n){
|
||||
nm = this.index;
|
||||
if(this.stype === 'select') {
|
||||
v = $("select[name="+nm+"]",self).val();
|
||||
if(v) {
|
||||
sdata[nm] = v;
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell");
|
||||
}
|
||||
j++;
|
||||
} else {
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell");
|
||||
}
|
||||
try {
|
||||
delete gr.p.postData[this.index];
|
||||
} catch (e) {}
|
||||
}
|
||||
} else {
|
||||
v = $("input[name="+nm+"]",self).val();
|
||||
if(v) {
|
||||
sdata[nm] = v;
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell");
|
||||
}
|
||||
j++;
|
||||
} else {
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell");
|
||||
}
|
||||
try {
|
||||
delete gr.p.postData[this.index];
|
||||
} catch(x) {}
|
||||
}
|
||||
}
|
||||
});
|
||||
var sd = j>0 ? true : false;
|
||||
$.extend(gr.p.postData,sdata);
|
||||
var saveurl;
|
||||
if(self.p.url) {
|
||||
saveurl = $(gr).jqGrid("getGridParam",'url');
|
||||
$(gr).jqGrid("setGridParam",{url:self.p.url});
|
||||
}
|
||||
$(gr).jqGrid("setGridParam",{search:sd}).trigger("reloadGrid",[{page:1}]);
|
||||
if(saveurl) {$(gr).jqGrid("setGridParam",{url:saveurl});}
|
||||
if($.isFunction(self.p.afterSearch)){self.p.afterSearch();}
|
||||
};
|
||||
var clearSearch = function(){
|
||||
var sdata={}, v, j=0;
|
||||
var gr = $(self.p.gridid)[0], nm;
|
||||
if($.isFunction(self.p.beforeClear)){self.p.beforeClear();}
|
||||
$.each(self.p.filterModel,function(i,n){
|
||||
nm = this.index;
|
||||
v = (this.defval) ? this.defval : "";
|
||||
if(!this.stype){this.stype='text';}
|
||||
switch (this.stype) {
|
||||
case 'select' :
|
||||
var v1;
|
||||
$("select[name="+nm+"] option",self).each(function (i){
|
||||
if(i===0) { this.selected = true; }
|
||||
if ($(this).text() == v) {
|
||||
this.selected = true;
|
||||
v1 = $(this).val();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if(v1) {
|
||||
// post the key and not the text
|
||||
sdata[nm] = v1;
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell");
|
||||
}
|
||||
j++;
|
||||
} else {
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell");
|
||||
}
|
||||
try {
|
||||
delete gr.p.postData[this.index];
|
||||
} catch (e) {}
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
$("input[name="+nm+"]",self).val(v);
|
||||
if(v) {
|
||||
sdata[nm] = v;
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).addClass("dirty-cell");
|
||||
}
|
||||
j++;
|
||||
} else {
|
||||
if(self.p.marksearched){
|
||||
$("#jqgh_"+this.name,gr.grid.hDiv).removeClass("dirty-cell");
|
||||
}
|
||||
try {
|
||||
delete gr.p.postData[this.index];
|
||||
} catch (k) {}
|
||||
}
|
||||
break;
|
||||
}
|
||||
});
|
||||
var sd = j>0 ? true : false;
|
||||
$.extend(gr.p.postData,sdata);
|
||||
var saveurl;
|
||||
if(self.p.url) {
|
||||
saveurl = $(gr).jqGrid("getGridParam",'url');
|
||||
$(gr).jqGrid("setGridParam",{url:self.p.url});
|
||||
}
|
||||
$(gr).jqGrid("setGridParam",{search:sd}).trigger("reloadGrid",[{page:1}]);
|
||||
if(saveurl) {$(gr).jqGrid("setGridParam",{url:saveurl});}
|
||||
if($.isFunction(self.p.afterClear)){self.p.afterClear();}
|
||||
};
|
||||
var tbl;
|
||||
var formFill = function(){
|
||||
var tr = document.createElement("tr");
|
||||
var tr1, sb, cb,tl,td;
|
||||
if(self.p.formtype=='horizontal'){
|
||||
$(tbl).append(tr);
|
||||
}
|
||||
$.each(self.p.filterModel,function(i,n){
|
||||
tl = document.createElement("td");
|
||||
$(tl).append("<label for='"+this.name+"'>"+this.label+"</label>");
|
||||
td = document.createElement("td");
|
||||
var $t=this;
|
||||
if(!this.stype) { this.stype='text';}
|
||||
switch (this.stype)
|
||||
{
|
||||
case "select":
|
||||
if(this.surl) {
|
||||
// data returned should have already constructed html select
|
||||
$(td).load(this.surl,function(){
|
||||
if($t.defval) { $("select",this).val($t.defval); }
|
||||
$("select",this).attr({name:$t.index || $t.name, id: "sg_"+$t.name});
|
||||
if($t.sopt) { $("select",this).attr($t.sopt); }
|
||||
if(self.p.gridToolbar===true && $t.width) {
|
||||
$("select",this).width($t.width);
|
||||
}
|
||||
if(self.p.autosearch===true){
|
||||
$("select",this).change(function(e){
|
||||
triggerSearch();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// sopt to construct the values
|
||||
if($t.sopt.value) {
|
||||
var oSv = $t.sopt.value;
|
||||
var elem = document.createElement("select");
|
||||
$(elem).attr({name:$t.index || $t.name, id: "sg_"+$t.name}).attr($t.sopt);
|
||||
var so, sv, ov;
|
||||
if(typeof oSv === "string") {
|
||||
so = oSv.split(";");
|
||||
for(var k=0; k<so.length;k++){
|
||||
sv = so[k].split(":");
|
||||
ov = document.createElement("option");
|
||||
ov.value = sv[0]; ov.innerHTML = sv[1];
|
||||
if (sv[1]==$t.defval) { ov.selected ="selected"; }
|
||||
elem.appendChild(ov);
|
||||
}
|
||||
} else if(typeof oSv === "object" ) {
|
||||
for ( var key in oSv) {
|
||||
if(oSv.hasOwnProperty(key)) {
|
||||
i++;
|
||||
ov = document.createElement("option");
|
||||
ov.value = key; ov.innerHTML = oSv[key];
|
||||
if (oSv[key]==$t.defval) { ov.selected ="selected"; }
|
||||
elem.appendChild(ov);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(self.p.gridToolbar===true && $t.width) {
|
||||
$(elem).width($t.width);
|
||||
}
|
||||
$(td).append(elem);
|
||||
if(self.p.autosearch===true){
|
||||
$(elem).change(function(e){
|
||||
triggerSearch();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'text':
|
||||
var df = this.defval ? this.defval: "";
|
||||
$(td).append("<input type='text' name='"+(this.index || this.name)+"' id='sg_"+this.name+"' value='"+df+"'/>");
|
||||
if($t.sopt) { $("input",td).attr($t.sopt); }
|
||||
if(self.p.gridToolbar===true && $t.width) {
|
||||
if($.browser.msie) {
|
||||
$("input",td).width($t.width-4);
|
||||
} else {
|
||||
$("input",td).width($t.width-2);
|
||||
}
|
||||
}
|
||||
if(self.p.autosearch===true){
|
||||
$("input",td).keypress(function(e){
|
||||
var key = e.charCode ? e.charCode : e.keyCode ? e.keyCode : 0;
|
||||
if(key == 13){
|
||||
triggerSearch();
|
||||
return false;
|
||||
}
|
||||
return this;
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(self.p.formtype=='horizontal'){
|
||||
if(self.p.gridToolbar===true && self.p.gridNames===false) {
|
||||
$(tr).append(td);
|
||||
} else {
|
||||
$(tr).append(tl).append(td);
|
||||
}
|
||||
$(tr).append(td);
|
||||
} else {
|
||||
tr1 = document.createElement("tr");
|
||||
$(tr1).append(tl).append(td);
|
||||
$(tbl).append(tr1);
|
||||
}
|
||||
});
|
||||
td = document.createElement("td");
|
||||
if(self.p.enableSearch === true){
|
||||
sb = "<input type='button' id='sButton' class='"+self.p.buttonclass+"' value='"+self.p.searchButton+"'/>";
|
||||
$(td).append(sb);
|
||||
$("input#sButton",td).click(function(){
|
||||
triggerSearch();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if(self.p.enableClear === true) {
|
||||
cb = "<input type='button' id='cButton' class='"+self.p.buttonclass+"' value='"+self.p.clearButton+"'/>";
|
||||
$(td).append(cb);
|
||||
$("input#cButton",td).click(function(){
|
||||
clearSearch();
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if(self.p.enableClear === true || self.p.enableSearch === true) {
|
||||
if(self.p.formtype=='horizontal') {
|
||||
$(tr).append(td);
|
||||
} else {
|
||||
tr1 = document.createElement("tr");
|
||||
$(tr1).append("<td> </td>").append(td);
|
||||
$(tbl).append(tr1);
|
||||
}
|
||||
}
|
||||
};
|
||||
var frm = $("<form name='SearchForm' style=display:inline;' class='"+this.p.formclass+"'></form>");
|
||||
tbl =$("<table class='"+this.p.tableclass+"' cellspacing='0' cellpading='0' border='0'><tbody></tbody></table>");
|
||||
$(frm).append(tbl);
|
||||
formFill();
|
||||
$(this).append(frm);
|
||||
this.triggerSearch = triggerSearch;
|
||||
this.clearSearch = clearSearch;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
})(jQuery);
|
||||
64
main/inc/lib/javascript/jqgrid/plugins/grid.postext.js
Normal file
64
main/inc/lib/javascript/jqgrid/plugins/grid.postext.js
Normal file
@@ -0,0 +1,64 @@
|
||||
;(function($){
|
||||
/**
|
||||
* jqGrid extension
|
||||
* Paul Tiseo ptiseo@wasteconsultants.com
|
||||
*
|
||||
* 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
|
||||
**/
|
||||
$.jgrid.extend({
|
||||
getPostData : function(){
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
return $t.p.postData;
|
||||
},
|
||||
setPostData : function( newdata ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
// check if newdata is correct type
|
||||
if ( typeof(newdata) === 'object' ) {
|
||||
$t.p.postData = newdata;
|
||||
}
|
||||
else {
|
||||
alert("Error: cannot add a non-object postData value. postData unchanged.");
|
||||
}
|
||||
},
|
||||
appendPostData : function( newdata ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
// check if newdata is correct type
|
||||
if ( typeof(newdata) === 'object' ) {
|
||||
$.extend($t.p.postData, newdata);
|
||||
}
|
||||
else {
|
||||
alert("Error: cannot append a non-object postData value. postData unchanged.");
|
||||
}
|
||||
},
|
||||
setPostDataItem : function( key, val ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
$t.p.postData[key] = val;
|
||||
},
|
||||
getPostDataItem : function( key ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
return $t.p.postData[key];
|
||||
},
|
||||
removePostDataItem : function( key ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
delete $t.p.postData[key];
|
||||
},
|
||||
getUserData : function(){
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
return $t.p.userData;
|
||||
},
|
||||
getUserDataItem : function( key ) {
|
||||
var $t = this[0];
|
||||
if(!$t.grid) { return; }
|
||||
return $t.p.userData[key];
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
126
main/inc/lib/javascript/jqgrid/plugins/grid.setcolumns.js
Normal file
126
main/inc/lib/javascript/jqgrid/plugins/grid.setcolumns.js
Normal file
@@ -0,0 +1,126 @@
|
||||
;(function($){
|
||||
/**
|
||||
* jqGrid extension for manipulating columns properties
|
||||
* Piotr Roznicki roznicki@o2.pl
|
||||
* http://www.roznicki.prv.pl
|
||||
* 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
|
||||
**/
|
||||
$.jgrid.extend({
|
||||
setColumns : function(p) {
|
||||
p = $.extend({
|
||||
top : 0,
|
||||
left: 0,
|
||||
width: 200,
|
||||
height: 'auto',
|
||||
dataheight: 'auto',
|
||||
modal: false,
|
||||
drag: true,
|
||||
beforeShowForm: null,
|
||||
afterShowForm: null,
|
||||
afterSubmitForm: null,
|
||||
closeOnEscape : true,
|
||||
ShrinkToFit : false,
|
||||
jqModal : false,
|
||||
saveicon: [true,"left","ui-icon-disk"],
|
||||
closeicon: [true,"left","ui-icon-close"],
|
||||
onClose : null,
|
||||
colnameview : true,
|
||||
closeAfterSubmit : true,
|
||||
updateAfterCheck : false,
|
||||
recreateForm : false
|
||||
}, $.jgrid.col, p ||{});
|
||||
return this.each(function(){
|
||||
var $t = this;
|
||||
if (!$t.grid ) { return; }
|
||||
var onBeforeShow = typeof p.beforeShowForm === 'function' ? true: false;
|
||||
var onAfterShow = typeof p.afterShowForm === 'function' ? true: false;
|
||||
var onAfterSubmit = typeof p.afterSubmitForm === 'function' ? true: false;
|
||||
var gID = $t.p.id,
|
||||
dtbl = "ColTbl_"+gID,
|
||||
IDs = {themodal:'colmod'+gID,modalhead:'colhd'+gID,modalcontent:'colcnt'+gID, scrollelm: dtbl};
|
||||
if(p.recreateForm===true && $("#"+IDs.themodal).html() != null) {
|
||||
$("#"+IDs.themodal).remove();
|
||||
}
|
||||
if ( $("#"+IDs.themodal).html() != null ) {
|
||||
if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); }
|
||||
$.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, jqM:false, modal:p.modal});
|
||||
if(onAfterShow) { p.afterShowForm($("#"+dtbl)); }
|
||||
} else {
|
||||
var dh = isNaN(p.dataheight) ? p.dataheight : p.dataheight+"px";
|
||||
var formdata = "<div id='"+dtbl+"' class='formdata' style='width:100%;overflow:auto;position:relative;height:"+dh+";'>";
|
||||
formdata += "<table class='ColTable' cellspacing='1' cellpading='2' border='0'><tbody>";
|
||||
for(i=0;i<this.p.colNames.length;i++){
|
||||
if(!$t.p.colModel[i].hidedlg) { // added from T. Tomov
|
||||
formdata += "<tr><td style='white-space: pre;'><input type='checkbox' style='margin-right:5px;' id='col_" + this.p.colModel[i].name + "' class='cbox' value='T' " +
|
||||
((this.p.colModel[i].hidden===false)?"checked":"") + "/>" + "<label for='col_" + this.p.colModel[i].name + "'>" + this.p.colNames[i] + ((p.colnameview) ? " (" + this.p.colModel[i].name + ")" : "" )+ "</label></td></tr>";
|
||||
}
|
||||
}
|
||||
formdata += "</tbody></table></div>"
|
||||
var bS = !p.updateAfterCheck ? "<a href='javascript:void(0)' id='dData' class='fm-button ui-state-default ui-corner-all'>"+p.bSubmit+"</a>" : "",
|
||||
bC ="<a href='javascript:void(0)' id='eData' class='fm-button ui-state-default ui-corner-all'>"+p.bCancel+"</a>";
|
||||
formdata += "<table border='0' class='EditTable' id='"+dtbl+"_2'><tbody><tr style='display:block;height:3px;'><td></td></tr><tr><td class='DataTD ui-widget-content'></td></tr><tr><td class='ColButton EditButton'>"+bS+" "+bC+"</td></tr></tbody></table>";
|
||||
p.gbox = "#gbox_"+gID;
|
||||
$.jgrid.createModal(IDs,formdata,p,"#gview_"+$t.p.id,$("#gview_"+$t.p.id)[0]);
|
||||
if(p.saveicon[0]==true) {
|
||||
$("#dData","#"+dtbl+"_2").addClass(p.saveicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left')
|
||||
.append("<span class='ui-icon "+p.saveicon[2]+"'></span>");
|
||||
}
|
||||
if(p.closeicon[0]==true) {
|
||||
$("#eData","#"+dtbl+"_2").addClass(p.closeicon[1] == "right" ? 'fm-button-icon-right' : 'fm-button-icon-left')
|
||||
.append("<span class='ui-icon "+p.closeicon[2]+"'></span>");
|
||||
}
|
||||
if(!p.updateAfterCheck) {
|
||||
$("#dData","#"+dtbl+"_2").click(function(e){
|
||||
for(i=0;i<$t.p.colModel.length;i++){
|
||||
if(!$t.p.colModel[i].hidedlg) { // added from T. Tomov
|
||||
var nm = $t.p.colModel[i].name.replace(/\./g, "\\.");
|
||||
if($("#col_" + nm,"#"+dtbl).attr("checked")) {
|
||||
$($t).jqGrid("showCol",$t.p.colModel[i].name);
|
||||
$("#col_" + nm,"#"+dtbl).attr("defaultChecked",true); // Added from T. Tomov IE BUG
|
||||
} else {
|
||||
$($t).jqGrid("hideCol",$t.p.colModel[i].name);
|
||||
$("#col_" + nm,"#"+dtbl).attr("defaultChecked",""); // Added from T. Tomov IE BUG
|
||||
}
|
||||
}
|
||||
}
|
||||
if(p.ShrinkToFit===true) {
|
||||
$($t).jqGrid("setGridWidth",$t.grid.width-0.001,true);
|
||||
}
|
||||
if(p.closeAfterSubmit) $.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: p.onClose});
|
||||
if (onAfterSubmit) { p.afterSubmitForm($("#"+dtbl)); }
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
$(":input","#"+dtbl).click(function(e){
|
||||
var cn = this.id.substr(4);
|
||||
if(cn){
|
||||
if(this.checked) {
|
||||
$($t).jqGrid("showCol",cn);
|
||||
} else {
|
||||
$($t).jqGrid("hideCol",cn);
|
||||
}
|
||||
if(p.ShrinkToFit===true) {
|
||||
$($t).jqGrid("setGridWidth",$t.grid.width-0.001,true);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
});
|
||||
}
|
||||
$("#eData", "#"+dtbl+"_2").click(function(e){
|
||||
$.jgrid.hideModal("#"+IDs.themodal,{gb:"#gbox_"+gID,jqm:p.jqModal, onClose: p.onClose});
|
||||
return false;
|
||||
});
|
||||
$("#dData, #eData","#"+dtbl+"_2").hover(
|
||||
function(){$(this).addClass('ui-state-hover');},
|
||||
function(){$(this).removeClass('ui-state-hover');}
|
||||
);
|
||||
if(onBeforeShow) { p.beforeShowForm($("#"+dtbl)); }
|
||||
$.jgrid.viewModal("#"+IDs.themodal,{gbox:"#gbox_"+gID,jqm:p.jqModal, jqM: true, modal:p.modal});
|
||||
if(onAfterShow) { p.afterShowForm($("#"+dtbl)); }
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
147
main/inc/lib/javascript/jqgrid/plugins/jquery.contextmenu.js
Normal file
147
main/inc/lib/javascript/jqgrid/plugins/jquery.contextmenu.js
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* ContextMenu - jQuery plugin for right-click context menus
|
||||
*
|
||||
* Author: Chris Domigan
|
||||
* Contributors: Dan G. Switzer, II
|
||||
* Parts of this plugin are inspired by Joern Zaefferer's Tooltip plugin
|
||||
*
|
||||
* Dual licensed under the MIT and GPL licenses:
|
||||
* http://www.opensource.org/licenses/mit-license.php
|
||||
* http://www.gnu.org/licenses/gpl.html
|
||||
*
|
||||
* Version: r2
|
||||
* Date: 16 July 2007
|
||||
*
|
||||
* For documentation visit http://www.trendskitchens.co.nz/jquery/contextmenu/
|
||||
*
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
|
||||
var menu, shadow, content, hash, currentTarget;
|
||||
var defaults = {
|
||||
menuStyle: {
|
||||
listStyle: 'none',
|
||||
padding: '1px',
|
||||
margin: '0px',
|
||||
backgroundColor: '#fff',
|
||||
border: '1px solid #999',
|
||||
width: '100px'
|
||||
},
|
||||
itemStyle: {
|
||||
margin: '0px',
|
||||
color: '#000',
|
||||
display: 'block',
|
||||
cursor: 'default',
|
||||
padding: '3px',
|
||||
border: '1px solid #fff',
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
itemHoverStyle: {
|
||||
border: '1px solid #0a246a',
|
||||
backgroundColor: '#b6bdd2'
|
||||
},
|
||||
eventPosX: 'pageX',
|
||||
eventPosY: 'pageY',
|
||||
shadow : true,
|
||||
onContextMenu: null,
|
||||
onShowMenu: null
|
||||
};
|
||||
|
||||
$.fn.contextMenu = function(id, options) {
|
||||
if (!menu) { // Create singleton menu
|
||||
menu = $('<div id="jqContextMenu"></div>')
|
||||
.hide()
|
||||
.css({position:'absolute', zIndex:'500'})
|
||||
.appendTo('body')
|
||||
.bind('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
if (!shadow) {
|
||||
shadow = $('<div></div>')
|
||||
.css({backgroundColor:'#000',position:'absolute',opacity:0.2,zIndex:499})
|
||||
.appendTo('body')
|
||||
.hide();
|
||||
}
|
||||
hash = hash || [];
|
||||
hash.push({
|
||||
id : id,
|
||||
menuStyle: $.extend({}, defaults.menuStyle, options.menuStyle || {}),
|
||||
itemStyle: $.extend({}, defaults.itemStyle, options.itemStyle || {}),
|
||||
itemHoverStyle: $.extend({}, defaults.itemHoverStyle, options.itemHoverStyle || {}),
|
||||
bindings: options.bindings || {},
|
||||
shadow: options.shadow || options.shadow === false ? options.shadow : defaults.shadow,
|
||||
onContextMenu: options.onContextMenu || defaults.onContextMenu,
|
||||
onShowMenu: options.onShowMenu || defaults.onShowMenu,
|
||||
eventPosX: options.eventPosX || defaults.eventPosX,
|
||||
eventPosY: options.eventPosY || defaults.eventPosY
|
||||
});
|
||||
|
||||
var index = hash.length - 1;
|
||||
$(this).bind('contextmenu', function(e) {
|
||||
// Check if onContextMenu() defined
|
||||
var bShowContext = (!!hash[index].onContextMenu) ? hash[index].onContextMenu(e) : true;
|
||||
currentTarget = e.target;
|
||||
if (bShowContext) {
|
||||
display(index, this, e );
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
function display(index, trigger, e ) {
|
||||
var cur = hash[index];
|
||||
content = $('#'+cur.id).find('ul:first').clone(true);
|
||||
content.css(cur.menuStyle).find('li').css(cur.itemStyle).hover(
|
||||
function() {
|
||||
$(this).css(cur.itemHoverStyle);
|
||||
},
|
||||
function(){
|
||||
$(this).css(cur.itemStyle);
|
||||
}
|
||||
).find('img').css({verticalAlign:'middle',paddingRight:'2px'});
|
||||
|
||||
// Send the content to the menu
|
||||
menu.html(content);
|
||||
|
||||
// if there's an onShowMenu, run it now -- must run after content has been added
|
||||
// if you try to alter the content variable before the menu.html(), IE6 has issues
|
||||
// updating the content
|
||||
if (!!cur.onShowMenu) menu = cur.onShowMenu(e, menu);
|
||||
|
||||
$.each(cur.bindings, function(id, func) {
|
||||
$('#'+id, menu).bind('click', function() {
|
||||
hide();
|
||||
func(trigger, currentTarget);
|
||||
});
|
||||
});
|
||||
|
||||
menu.css({'left':e[cur.eventPosX],'top':e[cur.eventPosY]}).show();
|
||||
if (cur.shadow) shadow.css({width:menu.width(),height:menu.height(),left:e.pageX+2,top:e.pageY+2}).show();
|
||||
$(document).one('click', hide);
|
||||
}
|
||||
|
||||
function hide() {
|
||||
menu.hide();
|
||||
shadow.hide();
|
||||
}
|
||||
|
||||
// Apply defaults
|
||||
$.contextMenu = {
|
||||
defaults : function(userDefaults) {
|
||||
$.each(userDefaults, function(i, val) {
|
||||
if (typeof val == 'object' && defaults[i]) {
|
||||
$.extend(defaults[i], val);
|
||||
}
|
||||
else defaults[i] = val;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
$(function() {
|
||||
$('div.contextMenu').hide();
|
||||
});
|
||||
716
main/inc/lib/javascript/jqgrid/plugins/jquery.searchFilter.js
Normal file
716
main/inc/lib/javascript/jqgrid/plugins/jquery.searchFilter.js
Normal file
@@ -0,0 +1,716 @@
|
||||
/* Plugin: searchFilter v1.2.9
|
||||
* Author: Kasey Speakman (kasey@cornerspeed.com)
|
||||
* License: Dual Licensed, MIT and GPL v2 (http://www.gnu.org/licenses/gpl-2.0.html)
|
||||
*
|
||||
* REQUIREMENTS:
|
||||
* jQuery 1.3+ (http://jquery.com/)
|
||||
* A Themeroller Theme (http://jqueryui.com/themeroller/)
|
||||
*
|
||||
* SECURITY WARNING
|
||||
* You should always implement server-side checking to ensure that
|
||||
* the query will fail when forged/invalid data is received.
|
||||
* Clever users can send any value they want through JavaScript and HTTP POST/GET.
|
||||
*
|
||||
* THEMES
|
||||
* Simply include the CSS file for your Themeroller theme.
|
||||
*
|
||||
* DESCRIPTION
|
||||
* This plugin creates a new searchFilter object in the specified container
|
||||
*
|
||||
* INPUT TYPE
|
||||
* fields: an array of field objects. each object has the following properties:
|
||||
* text: a string containing the display name of the field (e.g. "Field 1")
|
||||
* itemval: a string containing the actual field name (e.g. "field1")
|
||||
* optional properties:
|
||||
* ops: an array of operators in the same format as jQuery.fn.searchFilter.defaults.operators
|
||||
* that is: [ { op: 'gt', text: 'greater than'}, { op:'lt', text: 'less than'}, ... ]
|
||||
* if not specified, the passed-in options used, and failting that, jQuery.fn.searchFilter.defaults.operators will be used
|
||||
* *** NOTE ***
|
||||
* Specifying a dataUrl or dataValues property means that a <select ...> (drop-down-list) will be generated
|
||||
* instead of a text input <input type='text'.../> where the user would normally type in their search data
|
||||
* ************
|
||||
* dataUrl: a url that will return the html select for this field, this url will only be called once for this field
|
||||
* dataValues: the possible values for this field in the form [ { text: 'Data Display Text', value: 'data_actual_value' }, { ... } ]
|
||||
* dataInit: a function that you can use to initialize the data field. this function is passed the jQuery-fied data element
|
||||
* dataEvents: list of events to apply to the data element. uses $("#id").bind(type, [data], fn) to bind events to data element
|
||||
* *** JSON of this object could look like this: ***
|
||||
* var fields = [
|
||||
* {
|
||||
* text: 'Field Display Name',
|
||||
* itemval: 'field_actual_name',
|
||||
* // below this are optional values
|
||||
* ops: [ // this format is the same as jQuery.fn.searchFilter.defaults.operators
|
||||
* { op: 'gt', text: 'greater than' },
|
||||
* { op: 'lt', text: 'less than' }
|
||||
* ],
|
||||
* dataUrl: 'http://server/path/script.php?propName=propValue', // using this creates a select for the data input instead of an input type='text'
|
||||
* dataValues: [ // using this creates a select for the data input instead of an input type='text'
|
||||
* { text: 'Data Value Display Name', value: 'data_actual_value' },
|
||||
* { ... }
|
||||
* ],
|
||||
* dataInit: function(jElem) { jElem.datepicker(options); },
|
||||
* dataEvents: [ // these are the same options that you pass to $("#id").bind(type, [data], fn)
|
||||
* { type: 'click', data: { i: 7 }, fn: function(e) { console.log(e.data.i); } },
|
||||
* { type: 'keypress', fn: function(e) { console.log('keypress'); } }
|
||||
* ]
|
||||
* },
|
||||
* { ... }
|
||||
* ]
|
||||
* options: name:value properties containing various creation options
|
||||
* see jQuery.fn.searchFilter.defaults for the overridable options
|
||||
*
|
||||
* RETURN TYPE: This plugin returns a SearchFilter object, which has additional SearchFilter methods:
|
||||
* Methods
|
||||
* add: Adds a filter. added to the end of the list unless a jQuery event object or valid row number is passed.
|
||||
* del: Removes a filter. removed from the end of the list unless a jQuery event object or valid row number is passed.
|
||||
* reset: resets filters back to original state (only one blank filter), and calls onReset
|
||||
* search: puts the search rules into an object and calls onSearch with it
|
||||
* close: calls the onClose event handler
|
||||
*
|
||||
* USAGE
|
||||
* HTML
|
||||
* <head>
|
||||
* ...
|
||||
* <script src="path/to/jquery.min.js" type="text/javascript"></script>
|
||||
* <link href="path/to/themeroller.css" rel="Stylesheet" type="text/css" />
|
||||
* <script src="path/to/jquery.searchFilter.js" type="text/javascript"></script>
|
||||
* <link href="path/to/jquery.searchFilter.css" rel="Stylesheet" type="text/css" />
|
||||
* ...
|
||||
* </head>
|
||||
* <body>
|
||||
* ...
|
||||
* <div id='mySearch'></div>
|
||||
* ...
|
||||
* </body>
|
||||
* JQUERY
|
||||
* Methods
|
||||
* initializing: $("#mySearch").searchFilter([{text: "Field 1", value: "field1"},{text: "Field 2", value: "field2"}], {onSearch: myFilterRuleReceiverFn, onReset: myFilterResetFn });
|
||||
* Manual Methods (there's no need to call these methods unless you are trying to manipulate searchFilter with script)
|
||||
* add: $("#mySearch").searchFilter().add(); // appends a blank filter
|
||||
* $("#mySearch").searchFilter().add(0); // copies the first filter as second
|
||||
* del: $("#mySearch").searchFilter().del(); // removes the bottom filter
|
||||
* $("#mySearch").searchFilter().del(1); // removes the second filter
|
||||
* search: $("#mySearch").searchFilter().search(); // invokes onSearch, passing it a ruleGroup object
|
||||
* reset: $("#mySearch").searchFilter().reset(); // resets rules and invokes onReset
|
||||
* close: $("#mySearch").searchFilter().close(); // without an onClose handler, equivalent to $("#mySearch").hide();
|
||||
*
|
||||
* NOTE: You can get the jQuery object back from the SearchFilter object by chaining .$
|
||||
* Example
|
||||
* $("#mySearch").searchFilter().add().add().reset().$.hide();
|
||||
* Verbose Example
|
||||
* $("#mySearch") // gets jQuery object for the HTML element with id="mySearch"
|
||||
* .searchFilter() // gets the SearchFilter object for an existing search filter
|
||||
* .add() // adds a new filter to the end of the list
|
||||
* .add() // adds another new filter to the end of the list
|
||||
* .reset() // resets filters back to original state, triggers onReset
|
||||
* .$ // returns jQuery object for $("#mySearch")
|
||||
* .hide(); // equivalent to $("#mySearch").hide();
|
||||
*/
|
||||
|
||||
jQuery.fn.searchFilter = function(fields, options) {
|
||||
|
||||
function SearchFilter(jQ, fields, options) {
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// PUBLIC VARS
|
||||
//---------------------------------------------------------------
|
||||
|
||||
this.$ = jQ; // makes the jQuery object available as .$ from the return value
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// PUBLIC FUNCTIONS
|
||||
//---------------------------------------------------------------
|
||||
|
||||
this.add = function(i) {
|
||||
if (i == null) jQ.find(".ui-add-last").click();
|
||||
else jQ.find(".sf:eq(" + i + ") .ui-add").click();
|
||||
return this;
|
||||
};
|
||||
|
||||
this.del = function(i) {
|
||||
if (i == null) jQ.find(".sf:last .ui-del").click();
|
||||
else jQ.find(".sf:eq(" + i + ") .ui-del").click();
|
||||
return this;
|
||||
};
|
||||
|
||||
this.search = function(e) {
|
||||
jQ.find(".ui-search").click();
|
||||
return this;
|
||||
};
|
||||
|
||||
this.reset = function(o) {
|
||||
if(o===undefined) o = false;
|
||||
jQ.find(".ui-reset").trigger('click',[o]);
|
||||
return this;
|
||||
};
|
||||
|
||||
this.close = function() {
|
||||
jQ.find(".ui-closer").click();
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// "CONSTRUCTOR" (in air quotes)
|
||||
//---------------------------------------------------------------
|
||||
|
||||
if (fields != null) { // type coercion matches undefined as well as null
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// UTILITY FUNCTIONS
|
||||
//---------------------------------------------------------------
|
||||
|
||||
function hover() {
|
||||
jQuery(this).toggleClass("ui-state-hover");
|
||||
return false;
|
||||
}
|
||||
|
||||
function active(e) {
|
||||
jQuery(this).toggleClass("ui-state-active", (e.type == "mousedown"));
|
||||
return false;
|
||||
}
|
||||
|
||||
function buildOpt(value, text) {
|
||||
return "<option value='" + value + "'>" + text + "</option>";
|
||||
}
|
||||
|
||||
function buildSel(className, options, isHidden) {
|
||||
return "<select class='" + className + "'" + (isHidden ? " style='display:none;'" : "") + ">" + options + "</select>";
|
||||
}
|
||||
|
||||
function initData(selector, fn) {
|
||||
var jElem = jQ.find("tr.sf td.data " + selector);
|
||||
if (jElem[0] != null)
|
||||
fn(jElem);
|
||||
}
|
||||
|
||||
function bindDataEvents(selector, events) {
|
||||
var jElem = jQ.find("tr.sf td.data " + selector);
|
||||
if (jElem[0] != null) {
|
||||
jQuery.each(events, function() {
|
||||
if (this.data != null)
|
||||
jElem.bind(this.type, this.data, this.fn);
|
||||
else
|
||||
jElem.bind(this.type, this.fn);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// SUPER IMPORTANT PRIVATE VARS
|
||||
//---------------------------------------------------------------
|
||||
|
||||
// copies jQuery.fn.searchFilter.defaults.options properties onto an empty object, then options onto that
|
||||
var opts = jQuery.extend({}, jQuery.fn.searchFilter.defaults, options);
|
||||
|
||||
// this is keeps track of the last asynchronous setup
|
||||
var highest_late_setup = -1;
|
||||
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// CREATION PROCESS STARTS
|
||||
//---------------------------------------------------------------
|
||||
|
||||
// generate the global ops
|
||||
var gOps_html = "";
|
||||
jQuery.each(opts.groupOps, function() { gOps_html += buildOpt(this.op, this.text); });
|
||||
gOps_html = "<select name='groupOp'>" + gOps_html + "</select>";
|
||||
|
||||
/* original content - doesn't minify very well
|
||||
jQ
|
||||
.html("") // clear any old content
|
||||
.addClass("ui-searchFilter") // add classes
|
||||
.append( // add content
|
||||
"\
|
||||
<div class='ui-widget-overlay' style='z-index: -1'> </div>\
|
||||
<table class='ui-widget-content ui-corner-all'>\
|
||||
<thead>\
|
||||
<tr>\
|
||||
<td colspan='5' class='ui-widget-header ui-corner-all' style='line-height: 18px;'>\
|
||||
<div class='ui-closer ui-state-default ui-corner-all ui-helper-clearfix' style='float: right;'>\
|
||||
<span class='ui-icon ui-icon-close'></span>\
|
||||
</div>\
|
||||
" + opts.windowTitle + "\
|
||||
</td>\
|
||||
</tr>\
|
||||
</thead>\
|
||||
<tbody>\
|
||||
<tr class='sf'>\
|
||||
<td class='fields'></td>\
|
||||
<td class='ops'></td>\
|
||||
<td class='data'></td>\
|
||||
<td><div class='ui-del ui-state-default ui-corner-all'><span class='ui-icon ui-icon-minus'></span></div></td>\
|
||||
<td><div class='ui-add ui-state-default ui-corner-all'><span class='ui-icon ui-icon-plus'></span></div></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td colspan='5' class='divider'><div> </div></td>\
|
||||
</tr>\
|
||||
</tbody>\
|
||||
<tfoot>\
|
||||
<tr>\
|
||||
<td colspan='3'>\
|
||||
<span class='ui-reset ui-state-default ui-corner-all' style='display: inline-block; float: left;'><span class='ui-icon ui-icon-arrowreturnthick-1-w' style='float: left;'></span><span style='line-height: 18px; padding: 0 7px 0 3px;'>" + opts.resetText + "</span></span>\
|
||||
<span class='ui-search ui-state-default ui-corner-all' style='display: inline-block; float: right;'><span class='ui-icon ui-icon-search' style='float: left;'></span><span style='line-height: 18px; padding: 0 7px 0 3px;'>" + opts.searchText + "</span></span>\
|
||||
<span class='matchText'>" + opts.matchText + "</span> \
|
||||
" + gOps_html + " \
|
||||
<span class='rulesText'>" + opts.rulesText + "</span>\
|
||||
</td>\
|
||||
<td> </td>\
|
||||
<td><div class='ui-add-last ui-state-default ui-corner-all'><span class='ui-icon ui-icon-plusthick'></span></div></td>\
|
||||
</tr>\
|
||||
</tfoot>\
|
||||
</table>\
|
||||
");
|
||||
/* end hard-to-minify code */
|
||||
/* begin easier to minify code */
|
||||
jQ.html("").addClass("ui-searchFilter").append("<div class='ui-widget-overlay' style='z-index: -1'> </div><table class='ui-widget-content ui-corner-all'><thead><tr><td colspan='5' class='ui-widget-header ui-corner-all' style='line-height: 18px;'><div class='ui-closer ui-state-default ui-corner-all ui-helper-clearfix' style='float: right;'><span class='ui-icon ui-icon-close'></span></div>" + opts.windowTitle + "</td></tr></thead><tbody><tr class='sf'><td class='fields'></td><td class='ops'></td><td class='data'></td><td><div class='ui-del ui-state-default ui-corner-all'><span class='ui-icon ui-icon-minus'></span></div></td><td><div class='ui-add ui-state-default ui-corner-all'><span class='ui-icon ui-icon-plus'></span></div></td></tr><tr><td colspan='5' class='divider'><hr class='ui-widget-content' style='margin:1px'/></td></tr></tbody><tfoot><tr><td colspan='3'><span class='ui-reset ui-state-default ui-corner-all' style='display: inline-block; float: left;'><span class='ui-icon ui-icon-arrowreturnthick-1-w' style='float: left;'></span><span style='line-height: 18px; padding: 0 7px 0 3px;'>" + opts.resetText + "</span></span><span class='ui-search ui-state-default ui-corner-all' style='display: inline-block; float: right;'><span class='ui-icon ui-icon-search' style='float: left;'></span><span style='line-height: 18px; padding: 0 7px 0 3px;'>" + opts.searchText + "</span></span><span class='matchText'>" + opts.matchText + "</span> " + gOps_html + " <span class='rulesText'>" + opts.rulesText + "</span></td><td> </td><td><div class='ui-add-last ui-state-default ui-corner-all'><span class='ui-icon ui-icon-plusthick'></span></div></td></tr></tfoot></table>");
|
||||
/* end easier-to-minify code */
|
||||
|
||||
var jRow = jQ.find("tr.sf");
|
||||
var jFields = jRow.find("td.fields");
|
||||
var jOps = jRow.find("td.ops");
|
||||
var jData = jRow.find("td.data");
|
||||
|
||||
// generate the defaults
|
||||
var default_ops_html = "";
|
||||
jQuery.each(opts.operators, function() { default_ops_html += buildOpt(this.op, this.text); });
|
||||
default_ops_html = buildSel("default", default_ops_html, true);
|
||||
jOps.append(default_ops_html);
|
||||
var default_data_html = "<input type='text' class='default' style='display:none;' />";
|
||||
jData.append(default_data_html);
|
||||
|
||||
// generate the field list as a string
|
||||
var fields_html = "";
|
||||
var has_custom_ops = false;
|
||||
var has_custom_data = false;
|
||||
jQuery.each(fields, function(i) {
|
||||
var field_num = i;
|
||||
fields_html += buildOpt(this.itemval, this.text);
|
||||
// add custom ops if they exist
|
||||
if (this.ops != null) {
|
||||
has_custom_ops = true;
|
||||
var custom_ops = "";
|
||||
jQuery.each(this.ops, function() { custom_ops += buildOpt(this.op, this.text); });
|
||||
custom_ops = buildSel("field" + field_num, custom_ops, true);
|
||||
jOps.append(custom_ops);
|
||||
}
|
||||
// add custom data if it is given
|
||||
if (this.dataUrl != null) {
|
||||
if (i > highest_late_setup) highest_late_setup = i;
|
||||
has_custom_data = true;
|
||||
var dEvents = this.dataEvents;
|
||||
var iEvent = this.dataInit;
|
||||
var bs = this.buildSelect;
|
||||
jQuery.ajax(jQuery.extend({
|
||||
url : this.dataUrl,
|
||||
complete: function(data) {
|
||||
var $d;
|
||||
if(bs != null) $d =jQuery("<div />").append(bs(data));
|
||||
else $d = jQuery("<div />").append(data.responseText);
|
||||
$d.find("select").addClass("field" + field_num).hide();
|
||||
jData.append($d.html());
|
||||
if (iEvent) initData(".field" + i, iEvent);
|
||||
if (dEvents) bindDataEvents(".field" + i, dEvents);
|
||||
if (i == highest_late_setup) { // change should get called no more than twice when this searchFilter is constructed
|
||||
jQ.find("tr.sf td.fields select[name='field']").change();
|
||||
}
|
||||
}
|
||||
},opts.ajaxSelectOptions));
|
||||
} else if (this.dataValues != null) {
|
||||
has_custom_data = true;
|
||||
var custom_data = "";
|
||||
jQuery.each(this.dataValues, function() { custom_data += buildOpt(this.value, this.text); });
|
||||
custom_data = buildSel("field" + field_num, custom_data, true);
|
||||
jData.append(custom_data);
|
||||
} else if (this.dataEvents != null || this.dataInit != null) {
|
||||
has_custom_data = true;
|
||||
var custom_data = "<input type='text' class='field" + field_num + "' />";
|
||||
jData.append(custom_data);
|
||||
}
|
||||
// attach events to data if they exist
|
||||
if (this.dataInit != null && i != highest_late_setup)
|
||||
initData(".field" + i, this.dataInit);
|
||||
if (this.dataEvents != null && i != highest_late_setup)
|
||||
bindDataEvents(".field" + i, this.dataEvents);
|
||||
});
|
||||
fields_html = "<select name='field'>" + fields_html + "</select>";
|
||||
jFields.append(fields_html);
|
||||
|
||||
// setup the field select with an on-change event if there are custom ops or data
|
||||
var jFSelect = jFields.find("select[name='field']");
|
||||
if (has_custom_ops) jFSelect.change(function(e) {
|
||||
var index = e.target.selectedIndex;
|
||||
var td = jQuery(e.target).parents("tr.sf").find("td.ops");
|
||||
td.find("select").removeAttr("name").hide(); // disown and hide all elements
|
||||
var jElem = td.find(".field" + index);
|
||||
if (jElem[0] == null) jElem = td.find(".default"); // if there's not an element for that field, use the default one
|
||||
jElem.attr("name", "op").show();
|
||||
return false;
|
||||
});
|
||||
else jOps.find(".default").attr("name", "op").show();
|
||||
if (has_custom_data) jFSelect.change(function(e) {
|
||||
var index = e.target.selectedIndex;
|
||||
var td = jQuery(e.target).parents("tr.sf").find("td.data");
|
||||
td.find("select,input").removeClass("vdata").hide(); // disown and hide all elements
|
||||
var jElem = td.find(".field" + index);
|
||||
if (jElem[0] == null) jElem = td.find(".default"); // if there's not an element for that field, use the default one
|
||||
jElem.show().addClass("vdata");
|
||||
return false;
|
||||
});
|
||||
else jData.find(".default").show().addClass("vdata");
|
||||
// go ahead and call the change event and setup the ops and data values
|
||||
if (has_custom_ops || has_custom_data) jFSelect.change();
|
||||
|
||||
// bind events
|
||||
jQ.find(".ui-state-default").hover(hover, hover).mousedown(active).mouseup(active); // add hover/active effects to all buttons
|
||||
jQ.find(".ui-closer").click(function(e) {
|
||||
opts.onClose(jQuery(jQ.selector));
|
||||
return false;
|
||||
});
|
||||
jQ.find(".ui-del").click(function(e) {
|
||||
var row = jQuery(e.target).parents(".sf");
|
||||
if (row.siblings(".sf").length > 0) { // doesn't remove if there's only one filter left
|
||||
if (opts.datepickerFix === true && jQuery.fn.datepicker !== undefined)
|
||||
row.find(".hasDatepicker").datepicker("destroy"); // clean up datepicker's $.data mess
|
||||
row.remove(); // also unbinds
|
||||
} else { // resets the filter if it's the last one
|
||||
row.find("select[name='field']")[0].selectedIndex = 0;
|
||||
row.find("select[name='op']")[0].selectedIndex = 0;
|
||||
row.find(".data input").val(""); // blank all input values
|
||||
row.find(".data select").each(function() { this.selectedIndex = 0; }); // select first option on all selects
|
||||
row.find("select[name='field']").change(function(event){event.stopPropagation();}); // trigger any change events
|
||||
}
|
||||
return false;
|
||||
});
|
||||
jQ.find(".ui-add").click(function(e) {
|
||||
var row = jQuery(e.target).parents(".sf");
|
||||
var newRow = row.clone(true).insertAfter(row);
|
||||
newRow.find(".ui-state-default").removeClass("ui-state-hover ui-state-active");
|
||||
if (opts.clone) {
|
||||
newRow.find("select[name='field']")[0].selectedIndex = row.find("select[name='field']")[0].selectedIndex;
|
||||
var stupid_browser = (newRow.find("select[name='op']")[0] == null); // true for IE6
|
||||
if (!stupid_browser)
|
||||
newRow.find("select[name='op']").focus()[0].selectedIndex = row.find("select[name='op']")[0].selectedIndex;
|
||||
var jElem = newRow.find("select.vdata");
|
||||
if (jElem[0] != null) // select doesn't copy it's selected index when cloned
|
||||
jElem[0].selectedIndex = row.find("select.vdata")[0].selectedIndex;
|
||||
} else {
|
||||
newRow.find(".data input").val(""); // blank all input values
|
||||
newRow.find("select[name='field']").focus();
|
||||
}
|
||||
if (opts.datepickerFix === true && jQuery.fn.datepicker !== undefined) { // using $.data to associate data with document elements is Not Good
|
||||
row.find(".hasDatepicker").each(function() {
|
||||
var settings = jQuery.data(this, "datepicker").settings;
|
||||
newRow.find("#" + this.id).unbind().removeAttr("id").removeClass("hasDatepicker").datepicker(settings);
|
||||
});
|
||||
}
|
||||
newRow.find("select[name='field']").change(function(event){event.stopPropagation();} );
|
||||
return false;
|
||||
});
|
||||
jQ.find(".ui-search").click(function(e) {
|
||||
var ui = jQuery(jQ.selector); // pointer to search box wrapper element
|
||||
var ruleGroup;
|
||||
var group_op = ui.find("select[name='groupOp'] :selected").val(); // puls "AND" or "OR"
|
||||
if (!opts.stringResult) {
|
||||
ruleGroup = {
|
||||
groupOp: group_op,
|
||||
rules: []
|
||||
};
|
||||
} else {
|
||||
ruleGroup = "{\"groupOp\":\"" + group_op + "\",\"rules\":[";
|
||||
}
|
||||
ui.find(".sf").each(function(i) {
|
||||
var tField = jQuery(this).find("select[name='field'] :selected").val();
|
||||
var tOp = jQuery(this).find("select[name='op'] :selected").val();
|
||||
var tData = jQuery(this).find("input.vdata,select.vdata :selected").val();
|
||||
tData += "";
|
||||
if (!opts.stringResult) {
|
||||
ruleGroup.rules.push({
|
||||
field: tField,
|
||||
op: tOp,
|
||||
data: tData
|
||||
});
|
||||
} else {
|
||||
tData = tData.replace(/\\/g,'\\\\').replace(/\"/g,'\\"');
|
||||
if (i > 0) ruleGroup += ",";
|
||||
ruleGroup += "{\"field\":\"" + tField + "\",";
|
||||
ruleGroup += "\"op\":\"" + tOp + "\",";
|
||||
ruleGroup += "\"data\":\"" + tData + "\"}";
|
||||
}
|
||||
});
|
||||
if (opts.stringResult) ruleGroup += "]}";
|
||||
opts.onSearch(ruleGroup);
|
||||
return false;
|
||||
});
|
||||
jQ.find(".ui-reset").click(function(e,op) {
|
||||
var ui = jQuery(jQ.selector);
|
||||
ui.find(".ui-del").click(); // removes all filters, resets the last one
|
||||
ui.find("select[name='groupOp']")[0].selectedIndex = 0; // changes the op back to the default one
|
||||
opts.onReset(op);
|
||||
return false;
|
||||
});
|
||||
jQ.find(".ui-add-last").click(function() {
|
||||
var row = jQuery(jQ.selector + " .sf:last");
|
||||
var newRow = row.clone(true).insertAfter(row);
|
||||
newRow.find(".ui-state-default").removeClass("ui-state-hover ui-state-active");
|
||||
newRow.find(".data input").val(""); // blank all input values
|
||||
newRow.find("select[name='field']").focus();
|
||||
if (opts.datepickerFix === true && jQuery.fn.datepicker !== undefined) { // using $.data to associate data with document elements is Not Good
|
||||
row.find(".hasDatepicker").each(function() {
|
||||
var settings = jQuery.data(this, "datepicker").settings;
|
||||
newRow.find("#" + this.id).unbind().removeAttr("id").removeClass("hasDatepicker").datepicker(settings);
|
||||
});
|
||||
}
|
||||
newRow.find("select[name='field']").change(function(event){event.stopPropagation();});
|
||||
return false;
|
||||
});
|
||||
|
||||
this.setGroupOp = function(setting) {
|
||||
/* a "setter" for groupping argument.
|
||||
* ("AND" or "OR")
|
||||
*
|
||||
* Inputs:
|
||||
* setting - a string
|
||||
*
|
||||
* Returns:
|
||||
* Does not return anything. May add success / failure reporting in future versions.
|
||||
*
|
||||
* author: Daniel Dotsenko (dotsa@hotmail.com)
|
||||
*/
|
||||
selDOMobj = jQ.find("select[name='groupOp']")[0];
|
||||
var indexmap = {}, l = selDOMobj.options.length, i;
|
||||
for (i=0; i<l; i++) {
|
||||
indexmap[selDOMobj.options[i].value] = i;
|
||||
}
|
||||
selDOMobj.selectedIndex = indexmap[setting];
|
||||
jQuery(selDOMobj).change(function(event){event.stopPropagation();});
|
||||
};
|
||||
|
||||
this.setFilter = function(settings) {
|
||||
/* a "setter" for an arbitrary SearchFilter's filter line.
|
||||
* designed to abstract the DOM manipulations required to infer
|
||||
* a particular filter is a fit to the search box.
|
||||
*
|
||||
* Inputs:
|
||||
* settings - an "object" (dictionary)
|
||||
* index (optional*) (to be implemented in the future) : signed integer index (from top to bottom per DOM) of the filter line to fill.
|
||||
* Negative integers (rooted in -1 and lower) denote position of the line from the bottom.
|
||||
* sfref (optional*) : DOM object referencing individual '.sf' (normally a TR element) to be populated. (optional)
|
||||
* filter (mandatory) : object (dictionary) of form {'field':'field_value','op':'op_value','data':'data value'}
|
||||
*
|
||||
* * It is mandatory to have either index or sfref defined.
|
||||
*
|
||||
* Returns:
|
||||
* Does not return anything. May add success / failure reporting in future versions.
|
||||
*
|
||||
* author: Daniel Dotsenko (dotsa@hotmail.com)
|
||||
*/
|
||||
|
||||
var o = settings['sfref'], filter = settings['filter'];
|
||||
|
||||
// setting up valueindexmap that we will need to manipulate SELECT elements.
|
||||
var fields = [], i, j , l, lj, li,
|
||||
valueindexmap = {};
|
||||
// example of valueindexmap:
|
||||
// {'field1':{'index':0,'ops':{'eq':0,'ne':1}},'fieldX':{'index':1,'ops':{'eq':0,'ne':1},'data':{'true':0,'false':1}}},
|
||||
// if data is undefined it's a INPUT field. If defined, it's SELECT
|
||||
selDOMobj = o.find("select[name='field']")[0];
|
||||
for (i=0, l=selDOMobj.options.length; i<l; i++) {
|
||||
valueindexmap[selDOMobj.options[i].value] = {'index':i,'ops':{}};
|
||||
fields.push(selDOMobj.options[i].value);
|
||||
}
|
||||
for (i=0, li=fields.length; i < li; i++) {
|
||||
selDOMobj = o.find(".ops > select[class='field"+i+"']")[0];
|
||||
if (selDOMobj) {
|
||||
for (j=0, lj=selDOMobj.options.length; j<lj; j++) {
|
||||
valueindexmap[fields[i]]['ops'][selDOMobj.options[j].value] = j;
|
||||
}
|
||||
}
|
||||
selDOMobj = o.find(".data > select[class='field"+i+"']")[0];
|
||||
if (selDOMobj) {
|
||||
valueindexmap[fields[i]]['data'] = {}; // this setting is the flag that 'data' is contained in a SELECT
|
||||
for (j=0, lj=selDOMobj.options.length; j<lj; j++) {
|
||||
valueindexmap[fields[i]]['data'][selDOMobj.options[j].value] = j;
|
||||
}
|
||||
}
|
||||
} // done populating valueindexmap
|
||||
|
||||
// preparsing the index values for SELECT elements.
|
||||
var fieldvalue, fieldindex, opindex, datavalue, dataindex;
|
||||
fieldvalue = filter['field'];
|
||||
if (valueindexmap[fieldvalue]) {
|
||||
fieldindex = valueindexmap[fieldvalue]['index'];
|
||||
}
|
||||
if (fieldindex != null) {
|
||||
opindex = valueindexmap[fieldvalue]['ops'][filter['op']];
|
||||
if(opindex === undefined) {
|
||||
for(i=0,li=options.operators.length; i<li;i++) {
|
||||
if(options.operators[i].op == filter.op ){
|
||||
opindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
datavalue = filter['data'];
|
||||
if (valueindexmap[fieldvalue]['data'] == null) {
|
||||
dataindex = -1; // 'data' is not SELECT, Making the var 'defined'
|
||||
} else {
|
||||
dataindex = valueindexmap[fieldvalue]['data'][datavalue]; // 'undefined' may come from here.
|
||||
}
|
||||
}
|
||||
// only if values for 'field' and 'op' and 'data' are 'found' in mapping...
|
||||
if (fieldindex != null && opindex != null && dataindex != null) {
|
||||
o.find("select[name='field']")[0].selectedIndex = fieldindex;
|
||||
o.find("select[name='field']").change();
|
||||
o.find("select[name='op']")[0].selectedIndex = opindex;
|
||||
o.find("input.vdata").val(datavalue); // if jquery does not find any INPUT, it does not set any. This means we deal with SELECT
|
||||
o = o.find("select.vdata")[0];
|
||||
if (o) {
|
||||
o.selectedIndex = dataindex;
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}; // end of this.setFilter fn
|
||||
} // end of if fields != null
|
||||
}
|
||||
return new SearchFilter(this, fields, options);
|
||||
};
|
||||
|
||||
jQuery.fn.searchFilter.version = '1.2.9';
|
||||
|
||||
/* This property contains the default options */
|
||||
jQuery.fn.searchFilter.defaults = {
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: boolean
|
||||
* DESCRIPTION: clone a row if it is added from an existing row
|
||||
* when false, any new added rows will be blank.
|
||||
*/
|
||||
clone: true,
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: boolean
|
||||
* DESCRIPTION: current version of datepicker uses a data store,
|
||||
* which is incompatible with $().clone(true)
|
||||
*/
|
||||
datepickerFix: true,
|
||||
|
||||
/*
|
||||
* FUNCTION
|
||||
* DESCRIPTION: the function that will be called when the user clicks Reset
|
||||
* INPUT TYPE: JS object if stringResult is false, otherwise is JSON string
|
||||
*/
|
||||
onReset: function(data) { alert("Reset Clicked. Data Returned: " + data) },
|
||||
|
||||
/*
|
||||
* FUNCTION
|
||||
* DESCRIPTION: the function that will be called when the user clicks Search
|
||||
* INPUT TYPE: JS object if stringResult is false, otherwise is JSON string
|
||||
*/
|
||||
onSearch: function(data) { alert("Search Clicked. Data Returned: " + data) },
|
||||
|
||||
/*
|
||||
* FUNCTION
|
||||
* DESCRIPTION: the function that will be called when the user clicks the Closer icon
|
||||
* or the close() function is called
|
||||
* if left null, it simply does a .hide() on the searchFilter
|
||||
* INPUT TYPE: a jQuery object for the searchFilter
|
||||
*/
|
||||
onClose: function(jElem) { jElem.hide(); },
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: array of objects, each object has the properties op and text
|
||||
* DESCRIPTION: the selectable operators that are applied between rules
|
||||
* e.g. for {op:"AND", text:"all"}
|
||||
* the search filter box will say: match all rules
|
||||
* the server should interpret this as putting the AND op between each rule:
|
||||
* rule1 AND rule2 AND rule3
|
||||
* text will be the option text, and op will be the option value
|
||||
*/
|
||||
groupOps: [
|
||||
{ op: "AND", text: "all" },
|
||||
{ op: "OR", text: "any" }
|
||||
],
|
||||
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: array of objects, each object has the properties op and text
|
||||
* DESCRIPTION: the operators that will appear as drop-down options
|
||||
* text will be the option text, and op will be the option value
|
||||
*/
|
||||
operators: [
|
||||
{ op: "eq", text: "is equal to" },
|
||||
{ op: "ne", text: "is not equal to" },
|
||||
{ op: "lt", text: "is less than" },
|
||||
{ op: "le", text: "is less or equal to" },
|
||||
{ op: "gt", text: "is greater than" },
|
||||
{ op: "ge", text: "is greater or equal to" },
|
||||
{ op: "in", text: "is in" },
|
||||
{ op: "ni", text: "is not in" },
|
||||
{ op: "bw", text: "begins with" },
|
||||
{ op: "bn", text: "does not begin with" },
|
||||
{ op: "ew", text: "ends with" },
|
||||
{ op: "en", text: "does not end with" },
|
||||
{ op: "cn", text: "contains" },
|
||||
{ op: "nc", text: "does not contain" }
|
||||
],
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: string
|
||||
* DESCRIPTION: part of the phrase: _match_ ANY/ALL rules
|
||||
*/
|
||||
matchText: "match",
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: string
|
||||
* DESCRIPTION: part of the phrase: match ANY/ALL _rules_
|
||||
*/
|
||||
rulesText: "rules",
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: string
|
||||
* DESCRIPTION: the text that will be displayed in the reset button
|
||||
*/
|
||||
resetText: "Reset",
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: string
|
||||
* DESCRIPTION: the text that will be displayed in the search button
|
||||
*/
|
||||
searchText: "Search",
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: boolean
|
||||
* DESCRIPTION: a flag that, when set, will make the onSearch and onReset return strings instead of objects
|
||||
*/
|
||||
stringResult: true,
|
||||
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: string
|
||||
* DESCRIPTION: the title of the searchFilter window
|
||||
*/
|
||||
windowTitle: "Search Rules",
|
||||
/*
|
||||
* PROPERTY
|
||||
* TYPE: object
|
||||
* DESCRIPTION: options to extend the ajax request
|
||||
*/
|
||||
ajaxSelectOptions : {}
|
||||
}; /* end of searchFilter */
|
||||
383
main/inc/lib/javascript/jqgrid/plugins/jquery.tablednd.js
Normal file
383
main/inc/lib/javascript/jqgrid/plugins/jquery.tablednd.js
Normal file
@@ -0,0 +1,383 @@
|
||||
/**
|
||||
* TableDnD plug-in for JQuery, allows you to drag and drop table rows
|
||||
* You can set up various options to control how the system will work
|
||||
* Copyright (c) Denis Howlett <denish@isocra.com>
|
||||
* Licensed like jQuery, see http://docs.jquery.com/License.
|
||||
*
|
||||
* Configuration options:
|
||||
*
|
||||
* onDragStyle
|
||||
* This is the style that is assigned to the row during drag. There are limitations to the styles that can be
|
||||
* associated with a row (such as you can't assign a border--well you can, but it won't be
|
||||
* displayed). (So instead consider using onDragClass.) The CSS style to apply is specified as
|
||||
* a map (as used in the jQuery css(...) function).
|
||||
* onDropStyle
|
||||
* This is the style that is assigned to the row when it is dropped. As for onDragStyle, there are limitations
|
||||
* to what you can do. Also this replaces the original style, so again consider using onDragClass which
|
||||
* is simply added and then removed on drop.
|
||||
* onDragClass
|
||||
* This class is added for the duration of the drag and then removed when the row is dropped. It is more
|
||||
* flexible than using onDragStyle since it can be inherited by the row cells and other content. The default
|
||||
* is class is tDnD_whileDrag. So to use the default, simply customise this CSS class in your
|
||||
* stylesheet.
|
||||
* onDrop
|
||||
* Pass a function that will be called when the row is dropped. The function takes 2 parameters: the table
|
||||
* and the row that was dropped. You can work out the new order of the rows by using
|
||||
* table.rows.
|
||||
* onDragStart
|
||||
* Pass a function that will be called when the user starts dragging. The function takes 2 parameters: the
|
||||
* table and the row which the user has started to drag.
|
||||
* onAllowDrop
|
||||
* Pass a function that will be called as a row is over another row. If the function returns true, allow
|
||||
* dropping on that row, otherwise not. The function takes 2 parameters: the dragged row and the row under
|
||||
* the cursor. It returns a boolean: true allows the drop, false doesn't allow it.
|
||||
* scrollAmount
|
||||
* This is the number of pixels to scroll if the user moves the mouse cursor to the top or bottom of the
|
||||
* window. The page should automatically scroll up or down as appropriate (tested in IE6, IE7, Safari, FF2,
|
||||
* FF3 beta
|
||||
* dragHandle
|
||||
* This is the name of a class that you assign to one or more cells in each row that is draggable. If you
|
||||
* specify this class, then you are responsible for setting cursor: move in the CSS and only these cells
|
||||
* will have the drag behaviour. If you do not specify a dragHandle, then you get the old behaviour where
|
||||
* the whole row is draggable.
|
||||
*
|
||||
* Other ways to control behaviour:
|
||||
*
|
||||
* Add class="nodrop" to any rows for which you don't want to allow dropping, and class="nodrag" to any rows
|
||||
* that you don't want to be draggable.
|
||||
*
|
||||
* Inside the onDrop method you can also call $.tableDnD.serialize() this returns a string of the form
|
||||
* <tableID>[]=<rowID1>&<tableID>[]=<rowID2> so that you can send this back to the server. The table must have
|
||||
* an ID as must all the rows.
|
||||
*
|
||||
* Other methods:
|
||||
*
|
||||
* $("...").tableDnDUpdate()
|
||||
* Will update all the matching tables, that is it will reapply the mousedown method to the rows (or handle cells).
|
||||
* This is useful if you have updated the table rows using Ajax and you want to make the table draggable again.
|
||||
* The table maintains the original configuration (so you don't have to specify it again).
|
||||
*
|
||||
* $("...").tableDnDSerialize()
|
||||
* Will serialize and return the serialized string as above, but for each of the matching tables--so it can be
|
||||
* called from anywhere and isn't dependent on the currentTable being set up correctly before calling
|
||||
*
|
||||
* Known problems:
|
||||
* - Auto-scoll has some problems with IE7 (it scrolls even when it shouldn't), work-around: set scrollAmount to 0
|
||||
*
|
||||
* Version 0.2: 2008-02-20 First public version
|
||||
* Version 0.3: 2008-02-07 Added onDragStart option
|
||||
* Made the scroll amount configurable (default is 5 as before)
|
||||
* Version 0.4: 2008-03-15 Changed the noDrag/noDrop attributes to nodrag/nodrop classes
|
||||
* Added onAllowDrop to control dropping
|
||||
* Fixed a bug which meant that you couldn't set the scroll amount in both directions
|
||||
* Added serialize method
|
||||
* Version 0.5: 2008-05-16 Changed so that if you specify a dragHandle class it doesn't make the whole row
|
||||
* draggable
|
||||
* Improved the serialize method to use a default (and settable) regular expression.
|
||||
* Added tableDnDupate() and tableDnDSerialize() to be called when you are outside the table
|
||||
*/
|
||||
jQuery.tableDnD = {
|
||||
/** Keep hold of the current table being dragged */
|
||||
currentTable : null,
|
||||
/** Keep hold of the current drag object if any */
|
||||
dragObject: null,
|
||||
/** The current mouse offset */
|
||||
mouseOffset: null,
|
||||
/** Remember the old value of Y so that we don't do too much processing */
|
||||
oldY: 0,
|
||||
|
||||
/** Actually build the structure */
|
||||
build: function(options) {
|
||||
// Set up the defaults if any
|
||||
|
||||
this.each(function() {
|
||||
// This is bound to each matching table, set up the defaults and override with user options
|
||||
this.tableDnDConfig = jQuery.extend({
|
||||
onDragStyle: null,
|
||||
onDropStyle: null,
|
||||
// Add in the default class for whileDragging
|
||||
onDragClass: "tDnD_whileDrag",
|
||||
onDrop: null,
|
||||
onDragStart: null,
|
||||
scrollAmount: 5,
|
||||
serializeRegexp: /[^\-]*$/, // The regular expression to use to trim row IDs
|
||||
serializeParamName: null, // If you want to specify another parameter name instead of the table ID
|
||||
dragHandle: null // If you give the name of a class here, then only Cells with this class will be draggable
|
||||
}, options || {});
|
||||
// Now make the rows draggable
|
||||
jQuery.tableDnD.makeDraggable(this);
|
||||
});
|
||||
|
||||
// Now we need to capture the mouse up and mouse move event
|
||||
// We can use bind so that we don't interfere with other event handlers
|
||||
jQuery(document)
|
||||
.bind('mousemove', jQuery.tableDnD.mousemove)
|
||||
.bind('mouseup', jQuery.tableDnD.mouseup);
|
||||
|
||||
// Don't break the chain
|
||||
return this;
|
||||
},
|
||||
|
||||
/** This function makes all the rows on the table draggable apart from those marked as "NoDrag" */
|
||||
makeDraggable: function(table) {
|
||||
var config = table.tableDnDConfig;
|
||||
if (table.tableDnDConfig.dragHandle) {
|
||||
// We only need to add the event to the specified cells
|
||||
var cells = jQuery("td."+table.tableDnDConfig.dragHandle, table);
|
||||
cells.each(function() {
|
||||
// The cell is bound to "this"
|
||||
jQuery(this).mousedown(function(ev) {
|
||||
jQuery.tableDnD.dragObject = this.parentNode;
|
||||
jQuery.tableDnD.currentTable = table;
|
||||
jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
|
||||
if (config.onDragStart) {
|
||||
// Call the onDrop method if there is one
|
||||
config.onDragStart(table, this);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
})
|
||||
} else {
|
||||
// For backwards compatibility, we add the event to the whole row
|
||||
var rows = jQuery("tr", table); // get all the rows as a wrapped set
|
||||
rows.each(function() {
|
||||
// Iterate through each row, the row is bound to "this"
|
||||
var row = jQuery(this);
|
||||
if (! row.hasClass("nodrag")) {
|
||||
row.mousedown(function(ev) {
|
||||
if (ev.target.tagName == "TD") {
|
||||
jQuery.tableDnD.dragObject = this;
|
||||
jQuery.tableDnD.currentTable = table;
|
||||
jQuery.tableDnD.mouseOffset = jQuery.tableDnD.getMouseOffset(this, ev);
|
||||
if (config.onDragStart) {
|
||||
// Call the onDrop method if there is one
|
||||
config.onDragStart(table, this);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}).css("cursor", "move"); // Store the tableDnD object
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
updateTables: function() {
|
||||
this.each(function() {
|
||||
// this is now bound to each matching table
|
||||
if (this.tableDnDConfig) {
|
||||
jQuery.tableDnD.makeDraggable(this);
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/** Get the mouse coordinates from the event (allowing for browser differences) */
|
||||
mouseCoords: function(ev){
|
||||
if(ev.pageX || ev.pageY){
|
||||
return {x:ev.pageX, y:ev.pageY};
|
||||
}
|
||||
return {
|
||||
x:ev.clientX + document.body.scrollLeft - document.body.clientLeft,
|
||||
y:ev.clientY + document.body.scrollTop - document.body.clientTop
|
||||
};
|
||||
},
|
||||
|
||||
/** Given a target element and a mouse event, get the mouse offset from that element.
|
||||
To do this we need the element's position and the mouse position */
|
||||
getMouseOffset: function(target, ev) {
|
||||
ev = ev || window.event;
|
||||
|
||||
var docPos = this.getPosition(target);
|
||||
var mousePos = this.mouseCoords(ev);
|
||||
return {x:mousePos.x - docPos.x, y:mousePos.y - docPos.y};
|
||||
},
|
||||
|
||||
/** Get the position of an element by going up the DOM tree and adding up all the offsets */
|
||||
getPosition: function(e){
|
||||
var left = 0;
|
||||
var top = 0;
|
||||
/** Safari fix -- thanks to Luis Chato for this! */
|
||||
if (e.offsetHeight == 0) {
|
||||
/** Safari 2 doesn't correctly grab the offsetTop of a table row
|
||||
this is detailed here:
|
||||
http://jacob.peargrove.com/blog/2006/technical/table-row-offsettop-bug-in-safari/
|
||||
the solution is likewise noted there, grab the offset of a table cell in the row - the firstChild.
|
||||
note that firefox will return a text node as a first child, so designing a more thorough
|
||||
solution may need to take that into account, for now this seems to work in firefox, safari, ie */
|
||||
e = e.firstChild; // a table cell
|
||||
}
|
||||
if (e && e.offsetParent) {
|
||||
while (e.offsetParent){
|
||||
left += e.offsetLeft;
|
||||
top += e.offsetTop;
|
||||
e = e.offsetParent;
|
||||
}
|
||||
|
||||
left += e.offsetLeft;
|
||||
top += e.offsetTop;
|
||||
}
|
||||
|
||||
return {x:left, y:top};
|
||||
},
|
||||
|
||||
mousemove: function(ev) {
|
||||
if (jQuery.tableDnD.dragObject == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
var dragObj = jQuery(jQuery.tableDnD.dragObject);
|
||||
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
||||
var mousePos = jQuery.tableDnD.mouseCoords(ev);
|
||||
var y = mousePos.y - jQuery.tableDnD.mouseOffset.y;
|
||||
//auto scroll the window
|
||||
var yOffset = window.pageYOffset;
|
||||
if (document.all) {
|
||||
// Windows version
|
||||
//yOffset=document.body.scrollTop;
|
||||
if (typeof document.compatMode != 'undefined' &&
|
||||
document.compatMode != 'BackCompat') {
|
||||
yOffset = document.documentElement.scrollTop;
|
||||
}
|
||||
else if (typeof document.body != 'undefined') {
|
||||
yOffset=document.body.scrollTop;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (mousePos.y-yOffset < config.scrollAmount) {
|
||||
window.scrollBy(0, -config.scrollAmount);
|
||||
} else {
|
||||
var windowHeight = window.innerHeight ? window.innerHeight
|
||||
: document.documentElement.clientHeight ? document.documentElement.clientHeight : document.body.clientHeight;
|
||||
if (windowHeight-(mousePos.y-yOffset) < config.scrollAmount) {
|
||||
window.scrollBy(0, config.scrollAmount);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (y != jQuery.tableDnD.oldY) {
|
||||
// work out if we're going up or down...
|
||||
var movingDown = y > jQuery.tableDnD.oldY;
|
||||
// update the old value
|
||||
jQuery.tableDnD.oldY = y;
|
||||
// update the style to show we're dragging
|
||||
if (config.onDragClass) {
|
||||
dragObj.addClass(config.onDragClass);
|
||||
} else {
|
||||
dragObj.css(config.onDragStyle);
|
||||
}
|
||||
// If we're over a row then move the dragged row to there so that the user sees the
|
||||
// effect dynamically
|
||||
var currentRow = jQuery.tableDnD.findDropTargetRow(dragObj, y);
|
||||
if (currentRow) {
|
||||
// TODO worry about what happens when there are multiple TBODIES
|
||||
if (movingDown && jQuery.tableDnD.dragObject != currentRow) {
|
||||
jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow.nextSibling);
|
||||
} else if (! movingDown && jQuery.tableDnD.dragObject != currentRow) {
|
||||
jQuery.tableDnD.dragObject.parentNode.insertBefore(jQuery.tableDnD.dragObject, currentRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/** We're only worried about the y position really, because we can only move rows up and down */
|
||||
findDropTargetRow: function(draggedRow, y) {
|
||||
var rows = jQuery.tableDnD.currentTable.rows;
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
var row = rows[i];
|
||||
var rowY = this.getPosition(row).y;
|
||||
var rowHeight = parseInt(row.offsetHeight)/2;
|
||||
if (row.offsetHeight == 0) {
|
||||
rowY = this.getPosition(row.firstChild).y;
|
||||
rowHeight = parseInt(row.firstChild.offsetHeight)/2;
|
||||
}
|
||||
// Because we always have to insert before, we need to offset the height a bit
|
||||
if ((y > rowY - rowHeight) && (y < (rowY + rowHeight))) {
|
||||
// that's the row we're over
|
||||
// If it's the same as the current row, ignore it
|
||||
if (row == draggedRow) {return null;}
|
||||
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
||||
if (config.onAllowDrop) {
|
||||
if (config.onAllowDrop(draggedRow, row)) {
|
||||
return row;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
// If a row has nodrop class, then don't allow dropping (inspired by John Tarr and Famic)
|
||||
var nodrop = jQuery(row).hasClass("nodrop");
|
||||
if (! nodrop) {
|
||||
return row;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
mouseup: function(e) {
|
||||
if (jQuery.tableDnD.currentTable && jQuery.tableDnD.dragObject) {
|
||||
var droppedRow = jQuery.tableDnD.dragObject;
|
||||
var config = jQuery.tableDnD.currentTable.tableDnDConfig;
|
||||
// If we have a dragObject, then we need to release it,
|
||||
// The row will already have been moved to the right place so we just reset stuff
|
||||
if (config.onDragClass) {
|
||||
jQuery(droppedRow).removeClass(config.onDragClass);
|
||||
} else {
|
||||
jQuery(droppedRow).css(config.onDropStyle);
|
||||
}
|
||||
jQuery.tableDnD.dragObject = null;
|
||||
if (config.onDrop) {
|
||||
// Call the onDrop method if there is one
|
||||
config.onDrop(jQuery.tableDnD.currentTable, droppedRow);
|
||||
}
|
||||
jQuery.tableDnD.currentTable = null; // let go of the table too
|
||||
}
|
||||
},
|
||||
|
||||
serialize: function() {
|
||||
if (jQuery.tableDnD.currentTable) {
|
||||
return jQuery.tableDnD.serializeTable(jQuery.tableDnD.currentTable);
|
||||
} else {
|
||||
return "Error: No Table id set, you need to set an id on your table and every row";
|
||||
}
|
||||
},
|
||||
|
||||
serializeTable: function(table) {
|
||||
var result = "";
|
||||
var tableId = table.id;
|
||||
var rows = table.rows;
|
||||
for (var i=0; i<rows.length; i++) {
|
||||
if (result.length > 0) result += "&";
|
||||
var rowId = rows[i].id;
|
||||
if (rowId && rowId && table.tableDnDConfig && table.tableDnDConfig.serializeRegexp) {
|
||||
rowId = rowId.match(table.tableDnDConfig.serializeRegexp)[0];
|
||||
}
|
||||
|
||||
result += tableId + '[]=' + rowId;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
serializeTables: function() {
|
||||
var result = "";
|
||||
this.each(function() {
|
||||
// this is now bound to each matching table
|
||||
result += jQuery.tableDnD.serializeTable(this);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
jQuery.fn.extend(
|
||||
{
|
||||
tableDnD : jQuery.tableDnD.build,
|
||||
tableDnDUpdate : jQuery.tableDnD.updateTables,
|
||||
tableDnDSerialize: jQuery.tableDnD.serializeTables
|
||||
}
|
||||
);
|
||||
6
main/inc/lib/javascript/jqgrid/plugins/searchFilter.css
Normal file
6
main/inc/lib/javascript/jqgrid/plugins/searchFilter.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.ui-searchFilter { display: none; position: absolute; z-index: 770; overflow: visible;}
|
||||
.ui-searchFilter table {position:relative; margin:0em; width:auto}
|
||||
.ui-searchFilter table td {margin: 0em; padding: 1px;}
|
||||
.ui-searchFilter table td input, .ui-searchFilter table td select {margin: 0.1em;}
|
||||
.ui-searchFilter .ui-state-default { cursor: pointer; }
|
||||
.ui-searchFilter .divider hr {margin: 1px; }
|
||||
30
main/inc/lib/javascript/jqgrid/plugins/ui.multiselect.css
Normal file
30
main/inc/lib/javascript/jqgrid/plugins/ui.multiselect.css
Normal file
@@ -0,0 +1,30 @@
|
||||
/* Multiselect
|
||||
----------------------------------*/
|
||||
|
||||
.ui-multiselect { border: solid 1px; font-size: 0.8em; }
|
||||
.ui-multiselect ul { -moz-user-select: none; }
|
||||
.ui-multiselect li { margin: 0; padding: 0; cursor: default; line-height: 20px; height: 20px; font-size: 11px; list-style: none; }
|
||||
.ui-multiselect li a { color: #999; text-decoration: none; padding: 0; display: block; float: left; cursor: pointer;}
|
||||
.ui-multiselect li.ui-draggable-dragging { padding-left: 10px; }
|
||||
|
||||
.ui-multiselect div.selected { position: relative; padding: 0; margin: 0; border: 0; float:left; }
|
||||
.ui-multiselect ul.selected { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; position: relative; width: 100%; }
|
||||
.ui-multiselect ul.selected li { }
|
||||
|
||||
.ui-multiselect div.available { position: relative; padding: 0; margin: 0; border: 0; float:left; border-left: 1px solid; }
|
||||
.ui-multiselect ul.available { position: relative; padding: 0; overflow: auto; overflow-x: hidden; background: #fff; margin: 0; list-style: none; border: 0; width: 100%; }
|
||||
.ui-multiselect ul.available li { padding-left: 10px; }
|
||||
|
||||
.ui-multiselect .ui-state-default { border: none; margin-bottom: 1px; position: relative; padding-left: 20px;}
|
||||
.ui-multiselect .ui-state-hover { border: none; }
|
||||
.ui-multiselect .ui-widget-header {border: none; font-size: 11px; margin-bottom: 1px;}
|
||||
|
||||
.ui-multiselect .add-all { float: right; padding: 7px;}
|
||||
.ui-multiselect .remove-all { float: right; padding: 7px;}
|
||||
.ui-multiselect .search { float: left; padding: 4px;}
|
||||
.ui-multiselect .count { float: left; padding: 7px;}
|
||||
|
||||
.ui-multiselect li span.ui-icon-arrowthick-2-n-s { position: absolute; left: 2px; }
|
||||
.ui-multiselect li a.action { position: absolute; right: 2px; top: 2px; }
|
||||
|
||||
.ui-multiselect input.search { height: 14px; padding: 1px; opacity: 0.5; margin: 4px; width: 100px; }
|
||||
314
main/inc/lib/javascript/jqgrid/plugins/ui.multiselect.js
Normal file
314
main/inc/lib/javascript/jqgrid/plugins/ui.multiselect.js
Normal file
@@ -0,0 +1,314 @@
|
||||
/*
|
||||
* jQuery UI Multiselect
|
||||
*
|
||||
* Authors:
|
||||
* Michael Aufreiter (quasipartikel.at)
|
||||
* Yanick Rochon (yanick.rochon[at]gmail[dot]com)
|
||||
*
|
||||
* Dual licensed under the MIT (MIT-LICENSE.txt)
|
||||
* and GPL (GPL-LICENSE.txt) licenses.
|
||||
*
|
||||
* http://www.quasipartikel.at/multiselect/
|
||||
*
|
||||
*
|
||||
* Depends:
|
||||
* ui.core.js
|
||||
* ui.sortable.js
|
||||
*
|
||||
* Optional:
|
||||
* localization (http://plugins.jquery.com/project/localisation)
|
||||
* scrollTo (http://plugins.jquery.com/project/ScrollTo)
|
||||
*
|
||||
* Todo:
|
||||
* Make batch actions faster
|
||||
* Implement dynamic insertion through remote calls
|
||||
*/
|
||||
|
||||
|
||||
(function($) {
|
||||
|
||||
$.widget("ui.multiselect", {
|
||||
_init: function() {
|
||||
this.element.hide();
|
||||
this.id = this.element.attr("id");
|
||||
this.container = $('<div class="ui-multiselect ui-helper-clearfix ui-widget"></div>').insertAfter(this.element);
|
||||
this.count = 0; // number of currently selected options
|
||||
this.selectedContainer = $('<div class="selected"></div>').appendTo(this.container);
|
||||
this.availableContainer = $('<div class="available"></div>').appendTo(this.container);
|
||||
this.selectedActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><span class="count">0 '+$.ui.multiselect.locale.itemsCount+'</span><a href="#" class="remove-all">'+$.ui.multiselect.locale.removeAll+'</a></div>').appendTo(this.selectedContainer);
|
||||
this.availableActions = $('<div class="actions ui-widget-header ui-helper-clearfix"><input type="text" class="search empty ui-widget-content ui-corner-all"/><a href="#" class="add-all">'+$.ui.multiselect.locale.addAll+'</a></div>').appendTo(this.availableContainer);
|
||||
this.selectedList = $('<ul class="selected connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.selectedContainer);
|
||||
this.availableList = $('<ul class="available connected-list"><li class="ui-helper-hidden-accessible"></li></ul>').bind('selectstart', function(){return false;}).appendTo(this.availableContainer);
|
||||
|
||||
var that = this;
|
||||
|
||||
// set dimensions
|
||||
this.container.width(this.element.width()+1);
|
||||
this.selectedContainer.width(Math.floor(this.element.width()*this.options.dividerLocation));
|
||||
this.availableContainer.width(Math.floor(this.element.width()*(1-this.options.dividerLocation)));
|
||||
|
||||
// fix list height to match <option> depending on their individual header's heights
|
||||
this.selectedList.height(Math.max(this.element.height()-this.selectedActions.height(),1));
|
||||
this.availableList.height(Math.max(this.element.height()-this.availableActions.height(),1));
|
||||
|
||||
if ( !this.options.animated ) {
|
||||
this.options.show = 'show';
|
||||
this.options.hide = 'hide';
|
||||
}
|
||||
|
||||
// init lists
|
||||
this._populateLists(this.element.find('option'));
|
||||
|
||||
// make selection sortable
|
||||
if (this.options.sortable) {
|
||||
$("ul.selected").sortable({
|
||||
placeholder: 'ui-state-highlight',
|
||||
axis: 'y',
|
||||
update: function(event, ui) {
|
||||
// apply the new sort order to the original selectbox
|
||||
that.selectedList.find('li').each(function() {
|
||||
if ($(this).data('optionLink'))
|
||||
$(this).data('optionLink').remove().appendTo(that.element);
|
||||
});
|
||||
},
|
||||
receive: function(event, ui) {
|
||||
ui.item.data('optionLink').attr('selected', true);
|
||||
// increment count
|
||||
that.count += 1;
|
||||
that._updateCount();
|
||||
// workaround, because there's no way to reference
|
||||
// the new element, see http://dev.jqueryui.com/ticket/4303
|
||||
that.selectedList.children('.ui-draggable').each(function() {
|
||||
$(this).removeClass('ui-draggable');
|
||||
$(this).data('optionLink', ui.item.data('optionLink'));
|
||||
$(this).data('idx', ui.item.data('idx'));
|
||||
that._applyItemState($(this), true);
|
||||
});
|
||||
|
||||
// workaround according to http://dev.jqueryui.com/ticket/4088
|
||||
setTimeout(function() { ui.item.remove(); }, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// set up livesearch
|
||||
if (this.options.searchable) {
|
||||
this._registerSearchEvents(this.availableContainer.find('input.search'));
|
||||
} else {
|
||||
$('.search').hide();
|
||||
}
|
||||
|
||||
// batch actions
|
||||
$(".remove-all").click(function() {
|
||||
that._populateLists(that.element.find('option').removeAttr('selected'));
|
||||
return false;
|
||||
});
|
||||
$(".add-all").click(function() {
|
||||
that._populateLists(that.element.find('option').attr('selected', 'selected'));
|
||||
return false;
|
||||
});
|
||||
},
|
||||
destroy: function() {
|
||||
this.element.show();
|
||||
this.container.remove();
|
||||
|
||||
$.widget.prototype.destroy.apply(this, arguments);
|
||||
},
|
||||
_populateLists: function(options) {
|
||||
this.selectedList.children('.ui-element').remove();
|
||||
this.availableList.children('.ui-element').remove();
|
||||
this.count = 0;
|
||||
|
||||
var that = this;
|
||||
var items = $(options.map(function(i) {
|
||||
var item = that._getOptionNode(this).appendTo(this.selected ? that.selectedList : that.availableList).show();
|
||||
|
||||
if (this.selected) that.count += 1;
|
||||
that._applyItemState(item, this.selected);
|
||||
item.data('idx', i);
|
||||
return item[0];
|
||||
}));
|
||||
|
||||
// update count
|
||||
this._updateCount();
|
||||
},
|
||||
_updateCount: function() {
|
||||
this.selectedContainer.find('span.count').text(this.count+" "+$.ui.multiselect.locale.itemsCount);
|
||||
},
|
||||
_getOptionNode: function(option) {
|
||||
option = $(option);
|
||||
var node = $('<li class="ui-state-default ui-element" title="'+option.text()+'"><span class="ui-icon"/>'+option.text()+'<a href="#" class="action"><span class="ui-corner-all ui-icon"/></a></li>').hide();
|
||||
node.data('optionLink', option);
|
||||
return node;
|
||||
},
|
||||
// clones an item with associated data
|
||||
// didn't find a smarter away around this
|
||||
_cloneWithData: function(clonee) {
|
||||
var clone = clonee.clone();
|
||||
clone.data('optionLink', clonee.data('optionLink'));
|
||||
clone.data('idx', clonee.data('idx'));
|
||||
return clone;
|
||||
},
|
||||
_setSelected: function(item, selected) {
|
||||
item.data('optionLink').attr('selected', selected);
|
||||
|
||||
if (selected) {
|
||||
var selectedItem = this._cloneWithData(item);
|
||||
item[this.options.hide](this.options.animated, function() { $(this).remove(); });
|
||||
selectedItem.appendTo(this.selectedList).hide()[this.options.show](this.options.animated);
|
||||
|
||||
this._applyItemState(selectedItem, true);
|
||||
return selectedItem;
|
||||
} else {
|
||||
|
||||
// look for successor based on initial option index
|
||||
var items = this.availableList.find('li'), comparator = this.options.nodeComparator;
|
||||
var succ = null, i = item.data('idx'), direction = comparator(item, $(items[i]));
|
||||
|
||||
// TODO: test needed for dynamic list populating
|
||||
if ( direction ) {
|
||||
while (i>=0 && i<items.length) {
|
||||
direction > 0 ? i++ : i--;
|
||||
if ( direction != comparator(item, $(items[i])) ) {
|
||||
// going up, go back one item down, otherwise leave as is
|
||||
succ = items[direction > 0 ? i : i+1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
succ = items[i];
|
||||
}
|
||||
|
||||
var availableItem = this._cloneWithData(item);
|
||||
succ ? availableItem.insertBefore($(succ)) : availableItem.appendTo(this.availableList);
|
||||
item[this.options.hide](this.options.animated, function() { $(this).remove(); });
|
||||
availableItem.hide()[this.options.show](this.options.animated);
|
||||
|
||||
this._applyItemState(availableItem, false);
|
||||
return availableItem;
|
||||
}
|
||||
},
|
||||
_applyItemState: function(item, selected) {
|
||||
if (selected) {
|
||||
if (this.options.sortable)
|
||||
item.children('span').addClass('ui-icon-arrowthick-2-n-s').removeClass('ui-helper-hidden').addClass('ui-icon');
|
||||
else
|
||||
item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
|
||||
item.find('a.action span').addClass('ui-icon-minus').removeClass('ui-icon-plus');
|
||||
this._registerRemoveEvents(item.find('a.action'));
|
||||
|
||||
} else {
|
||||
item.children('span').removeClass('ui-icon-arrowthick-2-n-s').addClass('ui-helper-hidden').removeClass('ui-icon');
|
||||
item.find('a.action span').addClass('ui-icon-plus').removeClass('ui-icon-minus');
|
||||
this._registerAddEvents(item.find('a.action'));
|
||||
}
|
||||
|
||||
this._registerHoverEvents(item);
|
||||
},
|
||||
// taken from John Resig's liveUpdate script
|
||||
_filter: function(list) {
|
||||
var input = $(this);
|
||||
var rows = list.children('li'),
|
||||
cache = rows.map(function(){
|
||||
|
||||
return $(this).text().toLowerCase();
|
||||
});
|
||||
|
||||
var term = $.trim(input.val().toLowerCase()), scores = [];
|
||||
|
||||
if (!term) {
|
||||
rows.show();
|
||||
} else {
|
||||
rows.hide();
|
||||
|
||||
cache.each(function(i) {
|
||||
if (this.indexOf(term)>-1) { scores.push(i); }
|
||||
});
|
||||
|
||||
$.each(scores, function() {
|
||||
$(rows[this]).show();
|
||||
});
|
||||
}
|
||||
},
|
||||
_registerHoverEvents: function(elements) {
|
||||
elements.removeClass('ui-state-hover');
|
||||
elements.mouseover(function() {
|
||||
$(this).addClass('ui-state-hover');
|
||||
});
|
||||
elements.mouseout(function() {
|
||||
$(this).removeClass('ui-state-hover');
|
||||
});
|
||||
},
|
||||
_registerAddEvents: function(elements) {
|
||||
var that = this;
|
||||
elements.click(function() {
|
||||
var item = that._setSelected($(this).parent(), true);
|
||||
that.count += 1;
|
||||
that._updateCount();
|
||||
return false;
|
||||
})
|
||||
// make draggable
|
||||
.each(function() {
|
||||
$(this).parent().draggable({
|
||||
connectToSortable: 'ul.selected',
|
||||
helper: function() {
|
||||
var selectedItem = that._cloneWithData($(this)).width($(this).width() - 50);
|
||||
selectedItem.width($(this).width());
|
||||
return selectedItem;
|
||||
},
|
||||
appendTo: '.ui-multiselect',
|
||||
containment: '.ui-multiselect',
|
||||
revert: 'invalid'
|
||||
});
|
||||
});
|
||||
},
|
||||
_registerRemoveEvents: function(elements) {
|
||||
var that = this;
|
||||
elements.click(function() {
|
||||
that._setSelected($(this).parent(), false);
|
||||
that.count -= 1;
|
||||
that._updateCount();
|
||||
return false;
|
||||
});
|
||||
},
|
||||
_registerSearchEvents: function(input) {
|
||||
var that = this;
|
||||
|
||||
input.focus(function() {
|
||||
$(this).addClass('ui-state-active');
|
||||
})
|
||||
.blur(function() {
|
||||
$(this).removeClass('ui-state-active');
|
||||
})
|
||||
.keypress(function(e) {
|
||||
if (e.keyCode == 13)
|
||||
return false;
|
||||
})
|
||||
.keyup(function() {
|
||||
that._filter.apply(this, [that.availableList]);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.ui.multiselect, {
|
||||
defaults: {
|
||||
sortable: true,
|
||||
searchable: true,
|
||||
animated: 'fast',
|
||||
show: 'slideDown',
|
||||
hide: 'slideUp',
|
||||
dividerLocation: 0.6,
|
||||
nodeComparator: function(node1,node2) {
|
||||
var text1 = node1.text(),
|
||||
text2 = node2.text();
|
||||
return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
|
||||
}
|
||||
},
|
||||
locale: {
|
||||
addAll:'Add all',
|
||||
removeAll:'Remove all',
|
||||
itemsCount:'items selected'
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user