First commit of version 0.1.1-2
This commit is contained in:
commit
a0a273350e
|
@ -0,0 +1,11 @@
|
|||
Package: flexview
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Version: 0.1.1-2
|
||||
Architecture: mipsel
|
||||
Maintainer: mymsman
|
||||
Depends: webif(>=1.4.0)
|
||||
Description: Provides an alternative 'flexible view' of your recordings through the Web Interface.
|
||||
Can sort and filter on most attributes. Has a customisable display format.
|
||||
|
||||
Tags: http://wiki.hummy.tv/wiki/FlexView
|
|
@ -0,0 +1 @@
|
|||
{"name":"default","curdirsel":null,"tablewidth":0,"tabledepth":0,"dircolwidth":0,"flcolwidth":0,"dircolhidden":false,"dirshrinktofit":false,"flshrinktofit":false,"datefmt":"d M y H:i","timefmt":"H:i:s","dirColChg":{},"flColChg":{},"sel":{},"exp":{"-media":true,"-media-My-Video":true},"excl":{}}
|
|
@ -0,0 +1 @@
|
|||
{"name":"fixed size table","curdirsel":null,"tablewidth":1302,"tabledepth":458,"dircolwidth":350,"flcolwidth":930,"dircolhidden":false,"dirshrinktofit":false,"flshrinktofit":false,"datefmt":"d M y H:i","timefmt":"H:i:s","dirColChg":{"title":{"width":177}},"flColChg":{},"sel":{},"excl":{},"exp":{"-media-My-Video":true}}
|
|
@ -0,0 +1,98 @@
|
|||
// Column definition for Directory tree table
|
||||
|
||||
{name:"id", key:true, width: 250, hidden:true},
|
||||
{ name: "sel", label: 'Sel',
|
||||
hidden:false, width: 20, sortable:false, search: false,
|
||||
formatter: "checkbox", formatoptions: {disabled: false},
|
||||
},
|
||||
{ name: "title", label: "Directory",
|
||||
hidden:false, width: 250, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"]},
|
||||
},
|
||||
{ name:'opt', label: "Opt+", hidden:false, width:47,
|
||||
sortable:false, search: false,
|
||||
formatter: fmtDOpt
|
||||
},
|
||||
{ name: "dir", label: "Directory path", hidden: true,
|
||||
width: 250, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"]},
|
||||
},
|
||||
{ name: "psize", label: "Size", hidden:false, width: 70,
|
||||
align: "right", sorttype: "number", index: "dsize" ,
|
||||
searchoptions: {sopt: ["lt", "gt"],searchOperMenu: true, clearSearch: false},
|
||||
},
|
||||
{ name: "dsize", label: "unformatted size Kb",
|
||||
hidden: true, width: 90,
|
||||
align: "right", sorttype: "number" ,
|
||||
searchoptions: {sopt: ["lt", "gt"],searchOperMenu: true, clearSearch: false},
|
||||
},
|
||||
{ name:'autodecryptR',
|
||||
label: icons.autodecryptr + ' Recursive Auto-Decrypt',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Rec Auto-Decrypt",0:"Not Auto-Decrypt",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autodecryptr}
|
||||
},
|
||||
{ name:'autodecrypt',
|
||||
label: icons.autodecrypt + ' Auto-Decrypt',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-Decrypt",0:"Not Auto-Decrypt",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autodecrypt}
|
||||
},
|
||||
{ name:'autoshrinkR',
|
||||
label: icons.autoshrinkr + ' Recursive Auto Shrink',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Rec Auto-Shrink",0:"Not Auto-Shrink",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autoshrinkr}
|
||||
},
|
||||
{ name:'autoshrink',
|
||||
label: icons.autoshrink + ' Auto-Shrink',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-Shrink",0:"Not Auto-Shrink",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autoshrink}
|
||||
},
|
||||
{ name:'autodedup',
|
||||
label: icons.autodedup + ' Auto-Deduplicate',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-Deduplicate",0:"Not Auto-Deduplicate",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autodedup}
|
||||
},
|
||||
{ name:'autoexpire',
|
||||
label: icons.autoexpire + ' Auto-Expire',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-Expire",0:"Not Auto-Expire",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autoexpire}
|
||||
},
|
||||
{ name:'autompg',
|
||||
label: icons.autompg + ' Auto-mpg',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-mpg",0:"Not Auto-mpg",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.autompg}
|
||||
},
|
||||
{ name:'automp3',
|
||||
label: icons.automp3 + ' Auto-mp3',
|
||||
hidden:false, width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Auto-mp3",0:"Not Auto-mp3",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.automp3}
|
||||
},
|
||||
{ name:'tvdbseriesid',
|
||||
label: icons.tvdb + ' theTVDB',
|
||||
hidden:false, width:25,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"theTVDB",0:"Not theTVDB",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.tvdb}
|
||||
},
|
||||
{ name:'series',
|
||||
label: icons.series + ' Series',
|
||||
hidden:false, width:35,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Series",0:"Not Series",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.series}
|
||||
},
|
|
@ -0,0 +1,266 @@
|
|||
// Column Definitions for File List table
|
||||
{ name:"id", key:true, width: 250, hidden:true},
|
||||
{ name: "sel", label: '<input type="checkbox" id="chkbox" value="Yes" selected=true onclick="selAll(event)" /> Sel',
|
||||
hidden:false, width: 20, sortable:false, search: false,
|
||||
formatter: fmtCheckbox,
|
||||
},
|
||||
{ name: "fname", label: "File Name", hidden: false,
|
||||
width: 300, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"],searchOperMenu: true},
|
||||
formatter: fmtfname
|
||||
},
|
||||
{ name:'opt', label: "Opt+",
|
||||
hidden:false, width:47, sortable:false, search: false,
|
||||
formatter: fmtOpt
|
||||
},
|
||||
{ name: "dir", label: "Directory path", hidden: true,
|
||||
width: 250, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"]},
|
||||
},
|
||||
{ name: "title", label: "Title", hidden: true,
|
||||
width: 250, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"]},
|
||||
},
|
||||
{ name: "synopsis", label: "Synopsis", hidden: true,
|
||||
width: 250, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"]},
|
||||
},
|
||||
{ name: "channel_name", label: "Channel name", hidden: false,
|
||||
width: 22, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"], searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtChannel
|
||||
},
|
||||
{ name: "channel_num", label: "Channel number", hidden: true,
|
||||
width: 30, sorttype: "number",
|
||||
searchoptions: {sopt: ["eq", "lt", "gt"], searchOperMenu: false, clearSearch: false},
|
||||
},
|
||||
{ name: "start", label: "Start time", width: 90, hidden: false,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.datetimefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false,
|
||||
// dataInit is the client-side event that fires upon initializing the toolbar search field for a column
|
||||
// use it to place a third party control to customize the toolbar
|
||||
dataInit: function (element) {
|
||||
$(element).datepicker({
|
||||
id: 'start_datePicker',
|
||||
dateFormat: fvConfig.datefmt,
|
||||
showOn: 'focus'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{ name: "duration", label: "Duration", width: 50, hidden: false,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.timefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false},
|
||||
},
|
||||
{ name: "end", label: "End Time", width: 90, hidden: true,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.datetimefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false,
|
||||
// dataInit is the client-side event that fires upon initializing the toolbar search field for a column
|
||||
// use it to place a third party control to customize the toolbar
|
||||
dataInit: function (element) {
|
||||
$(element).datepicker({
|
||||
id: 'end_datePicker',
|
||||
dateFormat: fvConfig.datefmt,
|
||||
showOn: 'focus'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{ name: "schedstart", label: "Scheduled Start time", width: 90, hidden: true,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.datetimefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false,
|
||||
// dataInit is the client-side event that fires upon initializing the toolbar search field for a column
|
||||
// use it to place a third party control to customize the toolbar
|
||||
dataInit: function (element) {
|
||||
$(element).datepicker({
|
||||
id: 'schstart_datePicker',
|
||||
dateFormat: fvConfig.datefmt,
|
||||
showOn: 'focus'
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{ name: "scheddur", label: "Scheduled Duration", width: 50, hidden: true,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.timefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false},
|
||||
},
|
||||
{ name: "resume", label: "Resume point", width: 50, hidden: true,
|
||||
align: "right", sorttype: "date",
|
||||
formatter: "date",
|
||||
formatoptions: {srcformat:"U" ,newformat: fvConfig.timefmt},
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false},
|
||||
},
|
||||
{ name: "psize", label: "Size", width: 70, hidden: false,
|
||||
align: "right", sorttype: "number", index: "fsize" ,
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false},
|
||||
},
|
||||
{ name: "fsize", label: "unformatted Size", hidden: true,
|
||||
width: 70,
|
||||
searchoptions: {sopt: ["lt", "gt"], clearSearch: false},
|
||||
align: "right", sorttype: "number"
|
||||
},
|
||||
{ name: "bookmarks", label: icons.bookmark +" Bookmark count", hidden: false,
|
||||
width: 35,
|
||||
searchoptions: {sopt: ["gt", "lt", "eq"], clearSearch: false},
|
||||
align: "right", sorttype: "number"
|
||||
},
|
||||
{ name: "seriesnum", label: "Series number", hidden: true,
|
||||
width: 22,
|
||||
searchoptions: {sopt: ["gt", "lt", "eq"], clearSearch: false},
|
||||
align: "right", sorttype: "number"
|
||||
},
|
||||
{ name: "episodenum", label: "Episode number", hidden: true,
|
||||
width: 22,
|
||||
searchoptions: {sopt: ["gt", "lt", "eq"], clearSearch: false},
|
||||
align: "right", sorttype: "number"
|
||||
},
|
||||
{ name: "episodetot", label: "Episode total", hidden: true,
|
||||
width: 22,
|
||||
searchoptions: {sopt: ["gt", "lt", "eq"], clearSearch: false},
|
||||
align: "right", sorttype: "number"
|
||||
},
|
||||
{ name: "showrow", label: "show row", hidden: true,
|
||||
width: 50, align: "right",
|
||||
searchoptions: {sopt: ["eq"], defaultValue: "true", searchhidden: true, searchOperMenu: false, clearSearch: false},
|
||||
},
|
||||
{ name: "status", label: "Status", hidden: false,
|
||||
width: 70, align: "right",
|
||||
searchoptions: {sopt: ["cn", "bw", "eq"], searchhidden: true, searchOperMenu: false, clearSearch: false},
|
||||
},
|
||||
{ name: "definition", label: "Def", hidden: false,
|
||||
width: 24, sorttype: "text",
|
||||
stype: 'select',
|
||||
searchoptions: {sopt: ["cn"],value: {"HD":icons.HD+'HD',"SD":icons.SD+'SD','':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: 'select', editoptions: {value: {"HD":icons.HD,"SD":icons.SD,'':"Unknown"}},
|
||||
},
|
||||
{ name: "genre", label: "Genre", hidden: false,
|
||||
width: 24, sorttype: "mumber",
|
||||
stype: 'select',
|
||||
searchoptions: {sopt: ["eq"],value: genrelist, searchOperMenu: false, clearSearch: false},
|
||||
formatter: 'select', editoptions: {value: genrelist},
|
||||
},
|
||||
{ name:'flags_list', label: "Flags", hidden: true,
|
||||
width:70,
|
||||
searchoptions: {sopt: ["cn"], searchOperMenu: false, clearSearch: false},
|
||||
},
|
||||
{ name: "guidance", label: icons.guidance +" Guidance text", hidden: false,
|
||||
width: 22, sorttype: "text",
|
||||
searchoptions: {sopt: ["cn", "bw", "ew"], searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtGuidance
|
||||
},
|
||||
{ name:'Guidance', hidden: true,
|
||||
label: icons.guidance + ' Guidance flag',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Guidance",0:"No Guidance",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.guidance}
|
||||
},
|
||||
{ name:'GGuidance', hidden: true,
|
||||
label: icons.Gguidance + ' General Guidance',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Guidance",0:"No Guidance",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.Gguidance}
|
||||
},
|
||||
{ name:'inuse', hidden: false,
|
||||
label: icons.inuse + ' In use',
|
||||
width:45,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"In use",0:"Not in use",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.inuse}
|
||||
},
|
||||
{ name:'New', hidden: false,
|
||||
label: icons.new + ' New',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"New",0:"Not New",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.new}
|
||||
},
|
||||
{ name:'ODEncrypted', hidden: true,
|
||||
label: icons.ODE + ' On Disk Encrypted',
|
||||
width:28,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"On Disk Encrypted",0:"Not On Disk Encrypted",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.ODE}
|
||||
},
|
||||
{ name:'Decrypted', hidden: false,
|
||||
label: icons.DEC + ' Decrypted',
|
||||
width:25,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Decrypted",0:"Not Decrypted",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.DEC}
|
||||
},
|
||||
{ name:'Encrypted', hidden: false,
|
||||
label: icons.ENC + ' Encrypted (Protected)',
|
||||
width:25,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Encrypted",0:"Not Encrypted",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.ENC}
|
||||
},
|
||||
{ name:'Radio', hidden: false,
|
||||
label: icons.Radio + ' Radio',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Radio",0:"Not Radio",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.Radio}
|
||||
},
|
||||
{ name:'Locked', hidden: false,
|
||||
label: icons.Locked + ' Locked',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Locked",0:"Not Locked",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.Locked}
|
||||
},
|
||||
{ name:'Shrunk', hidden: false,
|
||||
label: icons.Shrunk + ' Shrunk',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Shrunk",0:"Not Shrunk",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.Shrunk}
|
||||
},
|
||||
{ name:'Deduped', hidden: false,
|
||||
label: icons.Deduped + ' De-duped',
|
||||
width:25,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"De-duped",0:"Not De-duped",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.Deduped}
|
||||
},
|
||||
{ name:'thmok', hidden: true,
|
||||
label: icons.thumb + ' Thumbnail exists',
|
||||
width:22,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"Thumbnail",0:"No Thumbnail",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.thumb}
|
||||
},
|
||||
{ name:'thmimg', hidden: true,
|
||||
label: icons.thumb + ' Thumbnail image',
|
||||
width:140,
|
||||
stype: 'select', index: 'thmok',
|
||||
searchoptions: {value: {1:"Thumbnail",0:"No Thumbnail",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtThumbnail,
|
||||
},
|
||||
{ name:'dlna',
|
||||
label: icons.DLNA + ' DLNA indexed',
|
||||
width:22,
|
||||
hidden: false,
|
||||
stype: 'select',
|
||||
searchoptions: {value: {1:"DLNA",0:"No DLNA",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
formatter: fmtIcon, formatoptions: {img: icons.DLNA}
|
||||
},
|
||||
{ name:'dlnaIndex',
|
||||
label: icons.DLNA + ' DLNA index',
|
||||
hidden: true,
|
||||
width:50,
|
||||
search:false,
|
||||
formatter: "link"
|
||||
},
|
|
@ -0,0 +1,10 @@
|
|||
# generate selection list for fvConfig files
|
||||
|
||||
set configl [glob -nocomplain /mod/etc/fvConfig_*.json]
|
||||
|
||||
proc genConfigList {} {
|
||||
foreach file [lsort $::configl] {
|
||||
set config [string range $file 18 end-5]
|
||||
puts "<option value=\"$config\">$config</option>"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
// Browse context menu enablement - extracted from browse.js
|
||||
// extremely unfortunate the need to duplicate code
|
||||
// but needs to be (re)done whenever grids are redrawn since elements
|
||||
// being tracked are not created at document ready
|
||||
|
||||
|
||||
function dirListReady() {
|
||||
// Bind context menu to opt+ image
|
||||
$('img.dopt').contextMenu(
|
||||
{
|
||||
menu: 'doptmenu',
|
||||
leftButton: true,
|
||||
beforeShow: preparedmenu
|
||||
},
|
||||
dmenuclick
|
||||
);
|
||||
|
||||
$('img.doopt').contextMenu(
|
||||
{
|
||||
menu: 'dooptmenu',
|
||||
leftButton: true,
|
||||
beforeShow: preparedmenu
|
||||
},
|
||||
dmenuclick
|
||||
);
|
||||
};
|
||||
|
||||
function fileListReady() {
|
||||
// Bind context menu to opt+ image
|
||||
$('img.opt').contextMenu(
|
||||
{
|
||||
menu: 'optmenu',
|
||||
leftButton: true,
|
||||
beforeShow: preparemenu
|
||||
},
|
||||
menuclick
|
||||
);
|
||||
|
||||
$('img.oopt').contextMenu(
|
||||
{
|
||||
menu: 'ooptmenu',
|
||||
leftButton: true,
|
||||
beforeShow: prepareomenu
|
||||
},
|
||||
omenuclick
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
// Cant trigger the imput.fs changed function from grid
|
||||
function inputChanged() {
|
||||
var num = $('input.fs:checked').size();
|
||||
if (num > 0)
|
||||
$('.onesel').enable();
|
||||
else
|
||||
$('.onesel').disable();
|
||||
|
||||
var num = $('input.fsts:checked').size();
|
||||
if (num > 0)
|
||||
$('.tsonesel').enable();
|
||||
else
|
||||
$('.tsonesel').disable();
|
||||
if (num > 1)
|
||||
$('.tstwosel').enable();
|
||||
else
|
||||
$('.tstwosel').disable();
|
||||
};
|
||||
|
||||
|
||||
// use browse media view dialog adapted for FV, may need changing if Browse dialog changes
|
||||
function viewFile(rowid) {
|
||||
|
||||
// Use jqGrid column data instead of HTML attributes
|
||||
var record = $("#filelist").jqGrid('getLocalRow',rowid);
|
||||
var file = record.dir +'/'+ record.fname;
|
||||
var file = encodeURI(record.dir +'/'+ record.fname);
|
||||
var type = record.ftype;
|
||||
var dlna = record.dlna;
|
||||
var decr = record.Decrypted;
|
||||
// e.preventDefault();
|
||||
|
||||
// var file = $(this).attr('file');
|
||||
// var type = $(this).attr('type');
|
||||
// var opt = $(this).nextAll('a').find('img.opt');
|
||||
|
||||
var url = '/browse/file.jim?file=' + file
|
||||
+ '&type=' + type;
|
||||
$.dialog.load(url);
|
||||
|
||||
$.dialog.attr('file', file);
|
||||
$.dialog.attr('type', type);
|
||||
|
||||
if (type == 'ts' &&
|
||||
(decr == 1 || dlna == 1))
|
||||
// (opt.attr('odencd') == 0 || opt.attr('dlna') == 1))
|
||||
$.dialog.dialog("option", "buttons", $buttonsp);
|
||||
else
|
||||
$.dialog.dialog("option", "buttons", $buttons);
|
||||
$.dialog.dialog('open');
|
||||
|
||||
};
|
||||
|
||||
|
||||
var $buttons = {
|
||||
"Close" : function() {$(this).dialog('close');}
|
||||
};
|
||||
var $buttonsp = $.extend(
|
||||
{"Play" : function() { //doplay();
|
||||
window.location = '/play/play.jim?' +
|
||||
'dir=' + encodeURIComponent(dir) +
|
||||
'&file=' + encodeURIComponent(file);
|
||||
}
|
||||
},
|
||||
$buttons);
|
||||
|
||||
$(function() {
|
||||
// Create reusable dialogue.
|
||||
if (!$.dialog)
|
||||
$.dialog = $('#dialogue').dialog({
|
||||
title: "Media Details",
|
||||
modal: false, autoOpen: false,
|
||||
height: 600, width: 700,
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: true, resizable: true,
|
||||
buttons: $buttons,
|
||||
close: function(e,u) { $('#dialogue').empty().html(
|
||||
'<img src="/img/loading.gif">Retrieving data...'); }
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
/*Grid*/
|
||||
.ui-jqgrid {
|
||||
position: relative;
|
||||
-moz-box-sizing: content-box;
|
||||
-webkit-box-sizing: content-box;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-view {position: relative;left:0; top: 0; padding: 0; font-size:11px; z-index:100;}
|
||||
.ui-jqgrid .ui-common-table {border-width: 0px; border-style: none; border-spacing: 0px; padding: 0;}
|
||||
/* caption*/
|
||||
.ui-jqgrid .ui-jqgrid-titlebar {height:19px; padding: .3em .2em .2em .3em; position: relative; font-size: 12px; border-left: 0 none;border-right: 0 none; border-top: 0 none;}
|
||||
.ui-jqgrid .ui-jqgrid-caption {text-align: left;}
|
||||
.ui-jqgrid .ui-jqgrid-title { margin: .1em 0 .2em; }
|
||||
.ui-jqgrid .ui-jqgrid-titlebar-close { position: absolute;top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height:18px; cursor:pointer;}
|
||||
.ui-jqgrid .ui-jqgrid-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-jqgrid .ui-jqgrid-titlebar-close:hover { padding: 0; }
|
||||
/* header*/
|
||||
.ui-jqgrid .ui-jqgrid-hdiv {position: relative; margin: 0;padding: 0; overflow: hidden; border-left: 0 none !important; border-top : 0 none !important; border-right : 0 none !important;}
|
||||
.ui-jqgrid .ui-jqgrid-hbox {float: left; padding-right: 20px;}
|
||||
.ui-jqgrid .ui-jqgrid-htable {table-layout:fixed;margin:0;border-collapse: separate;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th { height: 27px; padding: 0 2px 0 2px;}
|
||||
.ui-jqgrid .ui-jqgrid-htable th div {overflow: hidden; position:relative;margin: .1em 0em .1em 0em;}
|
||||
.ui-th-column, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column {overflow: hidden;white-space: nowrap;text-align:center;border-top : 0 none;border-bottom : 0 none;}
|
||||
.ui-th-column-header, .ui-jqgrid .ui-jqgrid-htable th.ui-th-column-header {overflow: hidden;white-space: nowrap;text-align:center;border-top : 0 none; height: 26px;}
|
||||
.ui-th-ltr, .ui-jqgrid .ui-jqgrid-htable th.ui-th-ltr {border-left : 0 none;}
|
||||
.ui-th-rtl, .ui-jqgrid .ui-jqgrid-htable th.ui-th-rtl {border-right : 0 none;}
|
||||
.ui-first-th-ltr {border-right: 1px solid; }
|
||||
.ui-first-th-rtl {border-left: 1px solid; }
|
||||
.ui-jqgrid .ui-th-div-ie {white-space: nowrap; zoom :1; height:17px;}
|
||||
.ui-jqgrid .ui-jqgrid-resize {height:20px !important;position: relative; cursor :e-resize;display: inline;overflow: hidden;}
|
||||
.ui-jqgrid .ui-grid-ico-sort {overflow:hidden;position:absolute;display:inline; cursor: pointer !important;}
|
||||
.ui-jqgrid .ui-icon-asc {margin-top:-3px; height:12px;}
|
||||
.ui-jqgrid .ui-icon-desc {margin-top:3px;margin-left:-1px;height:12px;}
|
||||
.ui-jqgrid .ui-i-asc {margin-top:0;height:18px;}
|
||||
.ui-jqgrid .ui-i-desc {margin-top:0;margin-left:12px;height:18px;}
|
||||
.ui-jqgrid .ui-single-sort-asc {margin-top:0;height:18px;}
|
||||
.ui-jqgrid .ui-single-sort-desc {margin-top:-1px;height:18px;}
|
||||
.ui-jqgrid .ui-jqgrid-sortable {cursor:pointer;height:14px}
|
||||
.ui-jqgrid tr.ui-search-toolbar th { }
|
||||
.ui-jqgrid .ui-search-table td.ui-search-clear { width:25px;}
|
||||
.ui-jqgrid tr.ui-search-toolbar td > input { padding-right: 0px; width: 95%;}
|
||||
.ui-jqgrid tr.ui-search-toolbar select {}
|
||||
/* body */
|
||||
.ui-jqgrid .ui-jqgrid-bdiv {position: relative; margin: 0; padding:0; overflow: auto; text-align:left;z-index: 101;}
|
||||
.ui-jqgrid .ui-jqgrid-btable {table-layout:fixed; margin:0; outline-style: none; border-collapse: separate;}
|
||||
.ui-jqgrid tr.jqgrow { outline-style: none; }
|
||||
.ui-jqgrid tr.jqgroup { outline-style: none; }
|
||||
.ui-jqgrid tr.jqgrow td {font-weight: normal; overflow: hidden; white-space: pre; height: 23px;padding: 1px 2px 1px 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
|
||||
.ui-jqgrid tr.jqgfirstrow td {padding: 0 2px 0 2px;border-right-width: 1px; border-right-style: solid; height:auto;}
|
||||
.ui-jqgrid tr.jqgroup td {font-weight: normal; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
|
||||
.ui-jqgrid tr.jqfoot td {font-weight: bold; overflow: hidden; white-space: pre; height: 22px;padding: 0 2px 0 2px;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
|
||||
.ui-jqgrid tr.ui-row-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}
|
||||
.ui-jqgrid tr.ui-row-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}
|
||||
.ui-jqgrid td.jqgrid-rownum { padding: 0 2px 0 2px; margin: 0; border: 0 none;}
|
||||
.ui-jqgrid .ui-jqgrid-resize-mark { width:2px; left:0; background-color:#777; cursor: e-resize; cursor: col-resize; position:absolute; top:0; height:100px; overflow:hidden; display:none; border:0 none; z-index: 99999;}
|
||||
/* footer */
|
||||
.ui-jqgrid .ui-jqgrid-sdiv {position: relative; margin: 0;padding: 0; overflow: hidden; border-left: 0 none !important; border-top : 0 none !important; border-right : 0 none !important;}
|
||||
.ui-jqgrid .ui-jqgrid-ftable {table-layout:fixed; margin-bottom:0;border-collapse: separate;}
|
||||
.ui-jqgrid tr.footrow td {font-weight: bold; overflow: hidden; white-space:nowrap; height: 20px;padding: 0 2px 0 2px;border-top-width: 1px; border-top-color: inherit; border-top-style: solid;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
|
||||
.ui-jqgrid tr.footrow-ltr td {text-align:left;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;}
|
||||
.ui-jqgrid tr.footrow-rtl td {text-align:right;border-left-width: 1px; border-left-color: inherit; border-left-style: solid;}
|
||||
/* Pager*/
|
||||
.ui-jqgrid .ui-jqgrid-pager { border-left: 0 none !important;border-right: 0 none !important; border-bottom: 0 none !important; border-top: 0 none; margin: 0 !important; padding: 0 !important; position: relative; height: auto; min-height: 28px; white-space: nowrap;overflow: hidden;font-size:11px; z-index:101}
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pager-control, .ui-jqgrid .ui-jqgrid-pager .ui-pager-control {position: relative;border-left: 0;border-bottom: 0;border-top: 0; height: 28px;}
|
||||
.ui-jqgrid .ui-pg-table {position: relative; padding: 1px 0; width:auto; margin: 0;}
|
||||
.ui-jqgrid .ui-pg-table td {font-weight:normal; vertical-align:middle; padding:0px 1px;}
|
||||
.ui-jqgrid .ui-pg-button { height:auto}
|
||||
.ui-jqgrid .ui-pg-button span { display: block; margin: 2px; float:left;}
|
||||
.ui-jqgrid .ui-pg-button:hover { padding: 0;}
|
||||
.ui-jqgrid .ui-state-disabled:hover {padding:0px;}
|
||||
.ui-jqgrid .ui-pg-input,.ui-jqgrid .ui-jqgrid-toppager .ui-pg-input { height:14px;width: auto;font-size:.9em; margin:0;line-height: inherit;border: none; padding: 3px 2px}
|
||||
.ui-jqgrid .ui-pg-selbox, .ui-jqgrid .ui-jqgrid-toppager .ui-pg-selbox {font-size:.9em; line-height:inherit; display:block; height:19px; margin: 0; padding: 3px 0px; border:none;}
|
||||
.ui-jqgrid .ui-separator {height: 18px; border-left: 2px solid #ccc ;}
|
||||
.ui-separator-li {height: 2px; border : none;border-top: 2px solid #ccc ; margin: 0; padding: 0; width:100%}
|
||||
.ui-jqgrid .dropdownmenu {
|
||||
padding: 3px 0 3px 0;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-pg-div,
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div
|
||||
{padding:1px 0;float:left;position:relative; line-height: 20px;}
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-pg-button,
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pg-button
|
||||
{ cursor:pointer; }
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-pg-div span.ui-icon,
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div span.ui-icon
|
||||
{float:left;margin: 2px; width:18px;}
|
||||
.ui-jqgrid td input, .ui-jqgrid td select, .ui-jqgrid td textarea { margin: 0; padding-top:5px;padding-bottom: 5px;}
|
||||
.ui-jqgrid td textarea {width:auto;height:auto;}
|
||||
.ui-jqgrid .ui-jqgrid-toppager {border-left: 0 none !important;border-right: 0 none !important; border-top: 0 none !important; margin: 0 !important; padding: 0 !important; position: relative;white-space: nowrap;overflow: hidden;}
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-pager-table {
|
||||
width:100%;
|
||||
table-layout:fixed;
|
||||
height:100%;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-paging-info {
|
||||
font-weight: normal;
|
||||
height:auto;
|
||||
margin-top:3px;
|
||||
margin-right:4px;
|
||||
display: inline;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-pager .ui-paging-pager {
|
||||
table-layout:auto;
|
||||
height:100%;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-pager .navtable {
|
||||
float:left;
|
||||
table-layout:auto;
|
||||
height:100%;
|
||||
}
|
||||
|
||||
/*.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div {padding:1px 0;float:left;position:relative; line-height: 20px; margin-right:3px;}
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pg-button { cursor:pointer; }
|
||||
.ui-jqgrid .ui-jqgrid-toppager .ui-pg-div span.ui-icon {float:left;margin: 2px; width:18px;}
|
||||
*/
|
||||
|
||||
/*subgrid*/
|
||||
.ui-jqgrid .ui-jqgrid-btable .ui-sgcollapsed span {display: block;}
|
||||
.ui-jqgrid .ui-subgrid {margin:0;padding:0; width:100%;}
|
||||
.ui-jqgrid .ui-subgrid table {table-layout: fixed;}
|
||||
.ui-jqgrid .ui-subgrid tr.ui-subtblcell td {height:18px;border-right-width: 1px; border-right-color: inherit; border-right-style: solid;border-bottom-width: 1px; border-bottom-color: inherit; border-bottom-style: solid;}
|
||||
.ui-jqgrid .ui-subgrid td.subgrid-data {border-top: 0 none !important; border-left: 0 none !important;}
|
||||
.ui-jqgrid .ui-subgrid td.subgrid-cell {border-width: 0 1px 1px 0;}
|
||||
.ui-jqgrid .ui-th-subgrid {height:20px;}
|
||||
/* loading */
|
||||
.ui-jqgrid .loading {position: absolute; top: 45%;left: 45%;width: auto;z-index:101;padding: 6px; margin: 5px;text-align: center;font-weight: bold;display: none;border-width: 2px !important; font-size:11px;}
|
||||
.ui-jqgrid .jqgrid-overlay {display:none;z-index:100;}
|
||||
/* IE * html .jqgrid-overlay {width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');} */
|
||||
* .jqgrid-overlay iframe {position:absolute;top:0;left:0;z-index:-1;}
|
||||
/* IE width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/
|
||||
/* end loading div */
|
||||
/* toolbar */
|
||||
.ui-jqgrid .ui-userdata {border-left: 0 none; border-right: 0 none; height : 27px;overflow: hidden; }
|
||||
/*Modal Window */
|
||||
.ui-jqdialog { font-size:11px !important; }
|
||||
.ui-jqdialog { display: none; width: 300px; position: absolute; padding: .2em; font-size:11px; overflow:visible;}
|
||||
.ui-jqdialog .ui-jqdialog-titlebar { padding: .3em .2em; position: relative; height:20px;}
|
||||
.ui-jqdialog .ui-jqdialog-title { margin: .3em .2em .2em .2em;}
|
||||
.ui-jqdialog .ui-jqdialog-titlebar-close { position: absolute; top: 50%; width: 19px; margin: -12px 0 0 0; padding: 1px; height: 18px; cursor:pointer;}
|
||||
|
||||
.ui-jqdialog .ui-jqdialog-titlebar-close span { display: block; margin: 1px; }
|
||||
.ui-jqdialog .ui-jqdialog-titlebar-close:hover, .ui-jqdialog .ui-jqdialog-titlebar-close:focus { padding: 0; }
|
||||
.ui-jqdialog-content, .ui-jqdialog .ui-jqdialog-content { border: 0; padding: .3em .2em; background: none; height:auto;}
|
||||
.ui-jqdialog .ui-jqconfirm {padding: .4em 1em; border-width:3px;position:absolute;bottom:10px;right:10px;overflow:visible;display:none;height:80px;width:220px;text-align:center;}
|
||||
.ui-jqdialog>.ui-resizable-se { bottom: -3px; right: -3px}
|
||||
.ui-jqgrid>.ui-resizable-se { bottom: -3px; right: -3px }
|
||||
/* end Modal window*/
|
||||
/* Form edit */
|
||||
.ui-jqdialog-content .FormGrid {margin: 0; overflow:auto;position:relative;}
|
||||
.ui-jqdialog-content .EditTable { width: 100%; margin-bottom:0;}
|
||||
.ui-jqdialog-content .DelTable { width: 100%; margin-bottom:0;}
|
||||
.EditTable td input, .EditTable td select, .EditTable td textarea {margin: 0;}
|
||||
.EditTable td textarea { width:auto; height:auto;}
|
||||
.ui-jqdialog-content td.EditButton {text-align: right;border-top: 0 none;border-left: 0 none;border-right: 0 none; padding-bottom:5px; padding-top:5px;}
|
||||
.ui-jqdialog-content td.navButton {text-align: center; border-left: 0 none;border-top: 0 none;border-right: 0 none; padding-bottom:5px; padding-top:5px;}
|
||||
.ui-jqdialog-content input.FormElement {padding: .5em .3em; margin-bottom: 3px}
|
||||
.ui-jqdialog-content select.FormElement {padding:.3em; margin-bottom: 3px;}
|
||||
.ui-jqdialog-content .data-line {padding-top:.1em;border: 0 none;}
|
||||
|
||||
.ui-jqdialog-content .CaptionTD {vertical-align: middle;border: 0 none; padding: 2px;white-space: nowrap;}
|
||||
.ui-jqdialog-content .DataTD {padding: 2px; border: 0 none; vertical-align: top;}
|
||||
.ui-jqdialog-content .form-view-data {white-space:pre}
|
||||
.fm-button { height: 18px; display: inline-block; margin:2px 4px 0 0; padding: .6em .5em .2em .5em; text-decoration:none !important; cursor:pointer; position: relative; text-align: center; zoom: 1; }
|
||||
.fm-button-icon-left { padding-left: 1.9em; }
|
||||
.fm-button-icon-right { padding-right: 1.9em; }
|
||||
.fm-button-icon-left .ui-icon { right: auto; left: .2em; margin-left: 0; position: absolute; top: 50%; margin-top: -8px; }
|
||||
.fm-button-icon-right .ui-icon { left: auto; right: .2em; margin-left: 0; position: absolute; top: 50%; margin-top: -8px;}
|
||||
#nData, #pData { float: left; margin:3px;padding: 0; width: 15px; }
|
||||
.ViewTable {
|
||||
border-width: 0;
|
||||
border-style: none;
|
||||
border-spacing: 1px;
|
||||
padding: 4px;
|
||||
table-layout: fixed;
|
||||
}
|
||||
.ViewTable .CaptionTD, .ViewTable .DataTD {padding : 4px;}
|
||||
/* End Eorm edit */
|
||||
/*cell edit*/
|
||||
.ui-jqgrid .edit-cell {
|
||||
padding: 4px 0px 4px 4px;
|
||||
}
|
||||
.ui-jqgrid .selected-row, div.ui-jqgrid .selected-row td {font-style : normal;border-left: 0 none;}
|
||||
/* inline edit actions button*/
|
||||
.ui-inline-del.ui-state-hover span, .ui-inline-edit.ui-state-hover span,
|
||||
.ui-inline-save.ui-state-hover span, .ui-inline-cancel.ui-state-hover span {
|
||||
margin: -1px;
|
||||
}
|
||||
.ui-inline-del, .ui-inline-cancel {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.ui-jqgrid .inline-edit-cell {
|
||||
padding: 4px 0px 4px 4px;
|
||||
}
|
||||
/* Tree Grid */
|
||||
.ui-jqgrid .tree-wrap {float: left; position: relative;height: 18px;white-space: nowrap;overflow: hidden;}
|
||||
.ui-jqgrid .tree-minus {position: absolute; height: 18px; width: 18px; overflow: hidden;}
|
||||
.ui-jqgrid .tree-plus {position: absolute; height: 18px; width: 18px; overflow: hidden;}
|
||||
.ui-jqgrid .tree-leaf {position: absolute; height: 18px; width: 18px;overflow: hidden;}
|
||||
.ui-jqgrid .treeclick {cursor: pointer;}
|
||||
/* moda dialog */
|
||||
* iframe.jqm {position:absolute;top:0;left:0;z-index:-1;}
|
||||
/* width: expression(this.parentNode.offsetWidth+'px');height: expression(this.parentNode.offsetHeight+'px');}*/
|
||||
.ui-jqgrid-dnd tr td {border-right-width: 1px; border-right-color: inherit; border-right-style: solid; height:20px}
|
||||
/* RTL Support */
|
||||
.ui-jqgrid .ui-jqgrid-caption-rtl {text-align: right;}
|
||||
.ui-jqgrid .ui-jqgrid-hbox-rtl {float: right; padding-left: 20px;}
|
||||
.ui-jqgrid .ui-jqgrid-resize-ltr {float: right;margin: -2px -2px -2px 0;}
|
||||
.ui-jqgrid .ui-jqgrid-resize-rtl {float: left;margin: -2px 0 -1px -3px;}
|
||||
.ui-jqgrid .ui-sort-rtl {left:0;}
|
||||
.ui-jqgrid .tree-wrap-ltr {float: left;}
|
||||
.ui-jqgrid .tree-wrap-rtl {float: right;}
|
||||
.ui-jqgrid .ui-ellipsis {-moz-text-overflow:ellipsis;text-overflow:ellipsis;}
|
||||
|
||||
/* Toolbar Search Menu , Nav menu*/
|
||||
.ui-search-menu,
|
||||
.ui-nav-menu {
|
||||
position: absolute;
|
||||
padding: 2px 5px;
|
||||
z-index:99999;
|
||||
-webkit-box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
|
||||
-moz-box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
|
||||
box-shadow: 7px 7px 5px 0px rgba(50, 50, 50, 0.75);
|
||||
}
|
||||
.ui-search-menu.ui-menu .ui-menu-item,
|
||||
.ui-nav-menu.ui-menu .ui-menu-item
|
||||
{
|
||||
list-style-image: none;
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
.ui-search-menu.ui-menu .ui-menu-item a,
|
||||
.ui-nav-menu.ui-menu .ui-menu-item a
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
.ui-search-menu.ui-menu .ui-menu-item a.g-menu-item:hover,
|
||||
.ui-nav-menu.ui-menu .ui-menu-item a.g-menu-item:hover
|
||||
{
|
||||
margin: -1px;
|
||||
font-weight: normal;
|
||||
}
|
||||
.ui-jqgrid .ui-search-table { padding: 0; border: 0 none; height:20px; width:100%;}
|
||||
.ui-jqgrid .ui-search-table .ui-search-oper { width:20px; }
|
||||
a.g-menu-item, a.soptclass, a.clearsearchclass { cursor: pointer; }
|
||||
.ui-jqgrid .ui-jqgrid-view input,
|
||||
.ui-jqgrid .ui-jqgrid-view select,
|
||||
.ui-jqgrid .ui-jqgrid-view textarea,
|
||||
.ui-jqgrid .ui-jqgrid-view button {
|
||||
font-size: 11px;
|
||||
}
|
||||
.ui-jqgrid .ui-scroll-popup {width: 95px;}
|
||||
.ui-search-table select,
|
||||
.ui-search-table input
|
||||
{
|
||||
padding: 4px 3px;
|
||||
}
|
||||
|
||||
.ui-jqgrid .ui-pg-table .ui-pg-button.ui-state-disabled:hover > .ui-separator {
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.ui-jqgrid .ui-pg-table .ui-pg-button.ui-state-disabled:hover > .ui-pg-div > .ui-icon {
|
||||
margin-left: 3px;
|
||||
margin-right: 3px;
|
||||
}
|
||||
/* Column menu */
|
||||
.ui-jqgrid .ui-jqgrid-htable .colmenu {
|
||||
position:absolute;
|
||||
right:1px;
|
||||
height:100%;
|
||||
color : black;
|
||||
}
|
||||
.ui-jqgrid .ui-jqgrid-htable .colmenuspan {
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.ui-jqgrid .ui-jqgrid-htable .ui-th-div {
|
||||
height:17px;
|
||||
margin-top:5px;
|
||||
display:inine-block;
|
||||
}
|
||||
.column-menu, .ui-search-menu {
|
||||
padding: 10px 10px;
|
||||
}
|
||||
.column-menu .divider {
|
||||
background-color: #e5e5e5;
|
||||
height: 1px;
|
||||
padding:0 0;
|
||||
margin: 5px 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.ui-menu-item .ui-common-table .menu_icon {
|
||||
white-space: pre;
|
||||
padding-right: 8px;
|
||||
width : auto;
|
||||
}
|
||||
.ui-menu-item .ui-common-table .menu_icon .ui-icon {
|
||||
display : inline-block;
|
||||
position: relative;
|
||||
}
|
||||
td.menu_text {
|
||||
width: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.ui-search-menu .ui-menu-item {
|
||||
padding : 0 0;
|
||||
}
|
||||
.ui-col-menu .ui-menu-item td.menu_text{
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-left : 1px;
|
||||
}
|
||||
.ui-col-menu .ui-menu-item td.menu_icon{
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.ui-col-menu .ui-menu-item td.menu_icon input{
|
||||
margin: 2px 0;
|
||||
|
||||
}
|
||||
#search_menu .ui-menu-item div {
|
||||
margin: 3px 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#search_menu .ui-menu-item div input,
|
||||
#search_menu .ui-menu-item div select
|
||||
{
|
||||
padding: 3px 2px;
|
||||
}
|
||||
#search_menu .search_buttons {
|
||||
display:inline-block;
|
||||
width:50%;
|
||||
}
|
||||
#column_menu.ui-menu .ui-menu-item {
|
||||
position :static;
|
||||
}
|
|
@ -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; }
|
|
@ -0,0 +1,47 @@
|
|||
#!/mod/bin/jimsh
|
||||
######
|
||||
# FlexView - Delete flexview cofig
|
||||
# Author: MymsMan, 2016
|
||||
######
|
||||
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class settings.class
|
||||
|
||||
# logging options
|
||||
if {[lindex $argv 0] eq "-d"} {
|
||||
set argv [lrange $argv 1 end]
|
||||
set loglevel 2
|
||||
} else {
|
||||
# Use same logging option as auto log
|
||||
set settings [settings]
|
||||
set loglevel [$settings _nval_setting "autolog"]
|
||||
}
|
||||
|
||||
|
||||
proc log {msg {level 2}} {
|
||||
if {$level > $::loglevel} return
|
||||
system plog flexview $msg
|
||||
}
|
||||
|
||||
httpheader
|
||||
|
||||
set start [clock milliseconds]
|
||||
set name [cgi_get name "default"]
|
||||
|
||||
set fname "/mod/etc/fvConfig_$name.json"
|
||||
if {[catch {exec rm $fname
|
||||
puts "Deleted configuration- $name<br>"} msg opts] } {
|
||||
log "Config file error caught: $msg $opts" 0
|
||||
puts "<b>File delete error $msg</b><br>"
|
||||
}
|
||||
|
||||
|
||||
source /mod/webif/plugin/flexview/configlist.jim
|
||||
genConfigList
|
||||
set end [clock milliseconds]
|
||||
set elapse $(double($end-$start)/1000.0)
|
||||
log "Delete | $elapse | $fname" 0
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* http://jsfiddle.net/7xwf1ysL/15/
|
||||
(c) 2015 by DBJ.ORG, GPL/MIT applies
|
||||
|
||||
expr argument is any legal jQuery selector.
|
||||
returns array of { element: , events: } objects
|
||||
events: is jQuery events structure attached (as data)
|
||||
to the element:
|
||||
return is null if no events are found
|
||||
*/
|
||||
jQuery.events = function(expr) {
|
||||
var rez = [],
|
||||
evo;
|
||||
jQuery(expr).each(
|
||||
function() {
|
||||
if (evo = jQuery._data(this, "events"))
|
||||
rez.push({
|
||||
element: this,
|
||||
events: evo
|
||||
});
|
||||
});
|
||||
return rez.length > 0 ? rez : null;
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/* plugin style file to support column formatters and context menu actions */
|
||||
|
||||
.contextMenu li.new_dir a
|
||||
{
|
||||
background-image: url(/img/folder.png);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.contextMenu li.dedupdir a
|
||||
{
|
||||
background-image: url(/img/dedup.png);
|
||||
}
|
||||
|
||||
.contextMenu li.theTVDB a
|
||||
{
|
||||
background-image: url(/img/tvdb-sm.png);
|
||||
background-size: 16px 20px;
|
||||
}
|
||||
|
||||
.contextMenu li.view a
|
||||
{
|
||||
background-image: url(/img/info.png);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.contextMenu li.view_file a ,
|
||||
.contextMenu li.view_node a
|
||||
{
|
||||
background-image: url(/plugin/flexview/img/view.gif);
|
||||
}
|
||||
|
||||
.contextMenu li.play a
|
||||
{
|
||||
background-image: url(/img/media/play.png);
|
||||
background-size: 16px 16px;
|
||||
}
|
||||
|
||||
.contextMenu li.reload_node a ,
|
||||
.contextMenu li.reload_fdir a ,
|
||||
.contextMenu li.reload_dir a
|
||||
{
|
||||
background-image: url(/plugin/flexview/img/refresh02.png);
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
|
||||
# plugin jim code to define column formatters and context menu actions for flexview
|
||||
# NB menu actions common to flexview and browse go in browse.hook
|
||||
|
||||
# Javascript and stylesheets for plugins
|
||||
jscss /plugin/flexview/flexview.js /plugin/flexview/flexview.css
|
||||
|
||||
# Context menu items for video recordings
|
||||
lappend plugins(menu) {view {desc "File Details"}}
|
||||
lappend plugins(menu) {view_file {desc "View details"}}
|
||||
lappend plugins(menu) {reload_fdir {desc "Reload folder"}}
|
||||
lappend plugins(menu) {play {desc "Play"}}
|
||||
|
||||
# Context menu items for other file types
|
||||
lappend plugins(omenu) {view_file {desc "View details"}}
|
||||
lappend plugins(omenu) {reload_fdir {desc "Reload folder content"}}
|
||||
|
||||
# Context menu items for directories
|
||||
lappend plugins(dmenu) {view_node {desc "View details"}}
|
||||
lappend plugins(dmenu) {reload_node {desc "Reload tree node"}}
|
||||
lappend plugins(dmenu) {reload_dir {desc "Reload folder"}}
|
||||
lappend plugins(dmenu) {dedupdir {desc "De-duplicate folder"}}
|
||||
lappend plugins(dmenu) {new_dir {desc "New sub-folder"}}
|
||||
|
||||
if {[system has tvdb]} {
|
||||
lappend plugins(menu) {theTVDB {desc " change episode"}}
|
||||
lappend plugins(dmenu) {theTVDB {desc " Add/change TVDB series"}}
|
||||
}
|
||||
|
||||
## Bottom button definitions
|
||||
#lappend plugins(buttons) "flexview {
|
||||
# desc {<img src=/plugin/flexview/img/icon16.png>flexview Rules}
|
||||
# link {/plugin/flexview/edit.jim?dir=[cgi_quote_url $dir]}
|
||||
#}"
|
||||
#
|
||||
#
|
||||
## Map browse context menu attributes to flexview column
|
||||
#lappend plugins(dmenuattr) "forceflatview" "flatview"
|
||||
#lappend plugins(dmenuattr) "noflat" "noflatten"
|
||||
#lappend plugins(omenuattr) "detads" "Addetection"
|
||||
#
|
||||
#
|
||||
## Icon name / icon
|
||||
#lappend plugins(icons) "detectads"
|
||||
#lappend plugins(icons) [_addicon "/plugin/detectads/img/detectads.png" "Ad Detection"]
|
||||
#
|
||||
#lappend plugins(icons) "flatview"
|
||||
#lappend plugins(icons) [_addicon "/plugin/flatview/steamroller.png" "Force-flatview" "fvIcon"]
|
||||
#
|
||||
#lappend plugins(icons) "noflatten"
|
||||
#lappend plugins(icons) [_addicon "/plugin/flatview/tyre.png" "No-flatten" "fvIcon"]
|
||||
#
|
||||
#
|
||||
## File list column - see jqGrid documentation for column options
|
||||
#lappend plugins(flcolumn) {
|
||||
#{ name:'Addetection',
|
||||
# hidden:false, width:22,
|
||||
# stype: 'select',
|
||||
# searchoptions: {value: {1:"Ad Detection",0:"No Ad Detection",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
# label: icons.detectads + ' Ad Detection',
|
||||
# formatter: fmtIcon, formatoptions: {img: icons.detectads}
|
||||
# },
|
||||
#}
|
||||
#
|
||||
## Directory tree column - see jqGrid documentation for column options
|
||||
#lappend plugins(dircolumn) {
|
||||
#{ name:'flatview',
|
||||
# hidden:false, width:22,
|
||||
# stype: 'select',
|
||||
# searchoptions: {value: {1:"Force-FlatView",0:"No Force-FlatView",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
# label: icons.flatview + ' Force-FlatView',
|
||||
# formatter: fmtIcon, formatoptions: {img: icons.flatview}
|
||||
# },
|
||||
#}
|
||||
#
|
||||
#lappend plugins(dircolumn) {
|
||||
#{ name:'noflatten',
|
||||
# hidden:false, width:22,
|
||||
# stype: 'select',
|
||||
# searchoptions: {value: {1:"No-Flatten",0:"Allow Flatten",'':"- All"}, searchOperMenu: false, clearSearch: false},
|
||||
# label: icons.noflatten + ' No-Flatten',
|
||||
# formatter: fmtIcon, formatoptions: {img: icons.noflatten}
|
||||
# },
|
||||
#}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
// plugin javascript code to support column formatters and context menu actions
|
||||
|
||||
plugins.menu.view_file = function(file) {
|
||||
var rowid= getRowId(decodeURI(file));
|
||||
viewRow('#filelist',rowid);
|
||||
};
|
||||
|
||||
plugins.menu.reload_fdir = function(file1) {
|
||||
var file =decodeURI(file1);
|
||||
var dir = file.substr(0,file.lastIndexOf("/"));
|
||||
reloadDir(dir);
|
||||
};
|
||||
|
||||
plugins.dmenu.reload_dir = function(dir1) {
|
||||
var dir = decodeURI(dir1);
|
||||
reloadDir(dir);
|
||||
};
|
||||
|
||||
plugins.dmenu.reload_node = function(dir) {
|
||||
var rowid= getRowId(decodeURI(dir));
|
||||
reloadNode(rowid);
|
||||
};
|
||||
|
||||
plugins.dmenu.view_node = function(dir) {
|
||||
var rowid= getRowId(decodeURI(dir));
|
||||
viewRow('#dirlist',rowid);
|
||||
};
|
||||
|
||||
plugins.menu.view = function(file) {
|
||||
var rowid= getRowId(decodeURI(file));
|
||||
viewFile(rowid);
|
||||
};
|
||||
|
||||
plugins.menu.play = function(file) {
|
||||
window.location = '/play/play.jim?file=' + file;
|
||||
};
|
||||
|
||||
plugins.menu.theTVDB = function(file) {
|
||||
window.location = '/browse/tvdb/episode.jim?file=' + file;
|
||||
};
|
||||
|
||||
plugins.dmenu.dedupdir = function(dir) {
|
||||
window.location = '/dedup/dedup.jim?dir=' + dir;
|
||||
};
|
||||
|
||||
plugins.dmenu.new_dir = function(dir) {
|
||||
// set dir field in form, no id :-(
|
||||
var cdir = $("form#newdirform_form input:first").val();
|
||||
|
||||
$('form#newdirform_form input:first').val(decodeURI(dir));
|
||||
|
||||
$('#newdirform').dialog({
|
||||
autoOpen: true,
|
||||
height: 'auto', width: 'auto',
|
||||
modal: true,
|
||||
buttons: {
|
||||
"Create": newdir_submit,
|
||||
"Cancel": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
close: function() { $('#newdirname').val(''); }
|
||||
});
|
||||
};
|
||||
|
||||
plugins.dmenu.theTVDB = function(dir) {
|
||||
var cdir = window.dir;
|
||||
window.dir = decodeURI(dir); // Set global var
|
||||
$('#tvdbsetseries').show().enable().trigger('click').hide();
|
||||
//window.dir = cdir; // Set global var
|
||||
};
|
||||
|
||||
|
|
@ -0,0 +1,358 @@
|
|||
#!/mod/bin/jimsh
|
||||
######
|
||||
# FlexView - Generate directory tree in jqGrid JSON format
|
||||
# Author: MymsMan, 2015/16
|
||||
######
|
||||
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require ts.class pretty_size system.class settings.class escape browse.class \
|
||||
plugin epg.class classdump
|
||||
|
||||
set dustbin [system dustbin 1]
|
||||
set root [system mediaroot]
|
||||
set nicesplice [system pkginst nicesplice]
|
||||
set model [system model]
|
||||
set dlnaok [system dlnastatus]
|
||||
|
||||
set ignore {.nts .thm .hmi}
|
||||
set include {.ts .avi .mpg .mpeg .wmv .mkv .mp3 .mp4 .mov .hmt .m4v .m4a}
|
||||
|
||||
# logging options
|
||||
if {[lindex $argv 0] eq "-d"} {
|
||||
set argv [lrange $argv 1 end]
|
||||
set loglevel 2
|
||||
} else {
|
||||
# Use same logging option as auto log
|
||||
set settings [settings]
|
||||
set loglevel [$settings _nval_setting "autolog"]
|
||||
}
|
||||
|
||||
|
||||
proc log {msg {level 2}} {
|
||||
if {$level > $::loglevel} return
|
||||
system plog flexview $msg
|
||||
}
|
||||
######
|
||||
# Common JSON code.
|
||||
# Author: Martin Wink, 2014.
|
||||
######
|
||||
|
||||
#
|
||||
# Initialize a map from control characters to JSON escaped characters.
|
||||
# Initially all non-null control characters to \u00xx sequences.
|
||||
for {set i 1} {$i < 32} {incr i} {
|
||||
set json_escape_map([format %c $i]) \\u[format %04x $i]
|
||||
}
|
||||
# Then overwrite certain well known control characters with shorter versions.
|
||||
set json_escape_map([format %c 8]) \\b; # backspace
|
||||
set json_escape_map([format %c 9]) \\t; # tab
|
||||
set json_escape_map([format %c 10]) \\n; # lf
|
||||
set json_escape_map([format %c 12]) \\f; # ff
|
||||
set json_escape_map([format %c 13]) \\r; # cr
|
||||
# Other special sequences
|
||||
set json_escape_map(\") {\"}
|
||||
set json_escape_map(\\) {\\}
|
||||
set json_escape_map(/) {\/}
|
||||
|
||||
#
|
||||
# Escape a string for inclusion in JSON output.
|
||||
#
|
||||
proc escape_json_string { in } {
|
||||
return [string map $::json_escape_map $in]
|
||||
}
|
||||
###### end Common JSON code.
|
||||
|
||||
set lbrc "\{"
|
||||
set rbrc "\}"
|
||||
set lbrk "\["
|
||||
set rbrk "\]"
|
||||
set quot "\""
|
||||
set nul ""
|
||||
set comma ","
|
||||
|
||||
# id's are used as html id so shouldn't contain space, dot etc to avoid confusing jquery
|
||||
# convert most specials to -
|
||||
for {set i 1} {$i < 48} {incr i} {
|
||||
set id_escape_map([format %c $i]) {-}
|
||||
}
|
||||
for {set i 58} {$i < 65} {incr i} {
|
||||
set id_escape_map([format %c $i]) {-}
|
||||
}
|
||||
for {set i 91} {$i < 95} {incr i} {
|
||||
set id_escape_map([format %c $i]) {-}
|
||||
}
|
||||
for {set i 123} {$i < 128} {incr i} {
|
||||
set id_escape_map([format %c $i]) {-}
|
||||
}
|
||||
|
||||
proc idQstring {str} {
|
||||
# Return quoted and escaped id string
|
||||
global quot
|
||||
return "$quot[string map $::id_escape_map $str]$quot"
|
||||
}
|
||||
|
||||
proc Qstring {str} {
|
||||
# Return quoted and escaped string
|
||||
global quot
|
||||
return "$quot[escape_json_string $str]$quot"
|
||||
}
|
||||
|
||||
proc json-key {key value {sep ","}} {
|
||||
global quot
|
||||
set jkey "$sep $quot$key$quot: $value"
|
||||
return $jkey
|
||||
}
|
||||
|
||||
proc p1l {str} {
|
||||
puts -nonewline $str
|
||||
}
|
||||
|
||||
proc pnl {str} {
|
||||
puts $str
|
||||
}
|
||||
|
||||
proc genDirList {dir ddir {depth 0} {expand 0} {i 0} {mode "children"}} {
|
||||
global lbrc rbrc lbrk rbrk quot nul comma
|
||||
|
||||
if {[catch {set dsize [exec /mod/bin/busybox/du -s "$dir/"]} msg]} {
|
||||
puts "Error, $dir, $msg"
|
||||
return
|
||||
}
|
||||
lassign $dsize dsize
|
||||
set psize [pretty_size $($dsize * 1024)]
|
||||
|
||||
|
||||
|
||||
set alist {}
|
||||
set dlist {}
|
||||
set flist {}
|
||||
foreach entry [lsort [readdir -nocomplain $dir]] {
|
||||
if {[string index $entry 0] eq "."} {
|
||||
lappend alist $entry
|
||||
continue
|
||||
}
|
||||
if {[file isdirectory "$dir/$entry"]} {
|
||||
lappend dlist $entry
|
||||
if {$depth <= 0} {
|
||||
# quit if not loading
|
||||
break
|
||||
}
|
||||
} else {
|
||||
lappend flist $entry
|
||||
}
|
||||
}
|
||||
|
||||
set ssep $nul
|
||||
if {$mode eq "parent"} {
|
||||
# Basic fields for all directories
|
||||
p1l [json-key title [Qstring $ddir] $lbrc]
|
||||
set ssep $comma
|
||||
|
||||
p1l [json-key id [idQstring $dir] ]
|
||||
p1l [json-key dir [Qstring $dir] ]
|
||||
p1l [json-key level $i]
|
||||
if {$i} {
|
||||
p1l [json-key parent [idQstring [file dirname $dir]] ]
|
||||
} else {
|
||||
p1l [json-key parent null ]
|
||||
}
|
||||
p1l [json-key listloaded 0]
|
||||
p1l [json-key opt [Qstring dopt] ]
|
||||
p1l [json-key dsize $dsize ]
|
||||
p1l [json-key psize [Qstring $psize] ]
|
||||
|
||||
# If subdirectories exist show whether node expanded or not
|
||||
if {[llength $dlist]} {
|
||||
p1l [json-key isLeaf false ]
|
||||
if {$expand >0} {
|
||||
p1l [json-key expanded true ]
|
||||
} else {
|
||||
p1l [json-key expanded false ]
|
||||
}
|
||||
} else {
|
||||
p1l [json-key isLeaf true ]
|
||||
}
|
||||
|
||||
# For each hidden file (dir attribute) create a flag (and content?) column
|
||||
foreach attr $alist {
|
||||
p1l [json-key [string range $attr 1 end] 1]
|
||||
}
|
||||
|
||||
|
||||
pnl "$rbrc"
|
||||
}
|
||||
|
||||
# Recurse into subdirectories if they are to be expanded
|
||||
if {[llength $dlist] && $depth > 0} {
|
||||
incr depth -1
|
||||
incr expand -1
|
||||
incr i
|
||||
|
||||
foreach subd $dlist {
|
||||
p1l $ssep
|
||||
genDirList "$dir/$subd" $subd $depth $expand $i parent
|
||||
set ssep $comma
|
||||
}
|
||||
|
||||
# if {[llength $flist]} {
|
||||
# p1l "$ssep [json-key title [Qstring -Files-] $lbrc]"
|
||||
# pnl "[json-key folder false $comma] $rbrc"
|
||||
# }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc genFileDetails {dir file} {
|
||||
global lbrc rbrc lbrk rbrk quot nul comma dinuse
|
||||
|
||||
set ext [string tolower [file extension $file]]
|
||||
set base [file rootname $file]
|
||||
|
||||
set fsize [file size "$dir/$file"]
|
||||
set psize [pretty_size $fsize]
|
||||
|
||||
# Basic attributes for all file types
|
||||
p1l [json-key id [idQstring "$dir/$file"] $lbrc ]
|
||||
p1l [json-key fname [Qstring $file] ]
|
||||
p1l [json-key dir [Qstring "$dir"] ]
|
||||
p1l [json-key sel false]
|
||||
p1l [json-key showrow true]
|
||||
p1l [json-key fsize $fsize ]
|
||||
p1l [json-key psize [Qstring $psize] ]
|
||||
|
||||
if {$ext eq ".ts"} {
|
||||
set omenu opt
|
||||
set type ts
|
||||
} else {
|
||||
set omenu oopt
|
||||
set type gen
|
||||
}
|
||||
|
||||
p1l [json-key ftype [Qstring $type] ]
|
||||
pnl [json-key opt [Qstring $omenu] ]
|
||||
|
||||
if {[file exists "$dir/$base.hmt"]} {
|
||||
# Generate hmt related attributes
|
||||
# Use HMT utility rather than TS class so we can handle orphaned HMT (and write less code)
|
||||
set line [exec hmt -p "$dir/$file"]
|
||||
set vars [split $line "\t"]
|
||||
|
||||
set vnames {title synopsis definition channel_num channel_name
|
||||
start end flags_list guidance bookmarks schedstart scheddur
|
||||
genre resume status seriesnum episodenum episodetot}
|
||||
|
||||
set ix 0
|
||||
foreach vn $vnames {
|
||||
p1l [json-key $vn [Qstring [lindex $vars $ix]] ]
|
||||
set $vn [lindex $vars $ix]
|
||||
incr ix
|
||||
}
|
||||
|
||||
if {[string is integer -strict $end]} {
|
||||
# calc duration
|
||||
set duration $($end-$start)
|
||||
p1l [json-key duration $duration ]
|
||||
}
|
||||
|
||||
if {$flags_list != ""} {
|
||||
# Individual Flag entries
|
||||
set flags [split [string range $flags_list 0 end-1] ,]
|
||||
foreach flag $flags {
|
||||
if {$flag in {HD SD {Unlimited Copies}}} {continue}
|
||||
p1l [json-key $flag 1]
|
||||
}
|
||||
# Need to special case Decrypt since it is the absence of ODE flag
|
||||
if {"ODEncrypted" ni $flags} {p1l [json-key Decrypted 1]}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if {[file exists "$dir/$base.thm"]} {
|
||||
# Generate thumbnail related attributes
|
||||
p1l [json-key thmok 1]
|
||||
}
|
||||
|
||||
# Possibly use SQL call to retrieve all DLNA for directory?
|
||||
set dlnaIndex [system dlnaurl [file normalize $dir/$file]]
|
||||
if {$dlnaIndex != ""} {
|
||||
p1l [json-key dlna 1]
|
||||
p1l [json-key dlnaIndex [Qstring $dlnaIndex] ]
|
||||
}
|
||||
|
||||
# Check for file inuse
|
||||
if {$file in $dinuse} {
|
||||
p1l [json-key inuse 1]
|
||||
}
|
||||
|
||||
pnl "$rbrc"
|
||||
|
||||
}
|
||||
|
||||
proc genFileList {dirlist } {
|
||||
global lbrc rbrc lbrk rbrk quot nul comma dinuse
|
||||
set ssep " "
|
||||
set dirl [split $dirlist {,}]
|
||||
|
||||
foreach dir $dirl {
|
||||
set alist {}
|
||||
set dlist {}
|
||||
set flist {}
|
||||
set dinuse [system dirinuse $dir]
|
||||
|
||||
foreach entry [lsort [readdir -nocomplain $dir]] {
|
||||
if {[string index $entry 0] eq "."} {
|
||||
lappend alist $entry
|
||||
continue
|
||||
}
|
||||
if {[file isdirectory "$dir/$entry"]} {
|
||||
lappend dlist $entry
|
||||
} else {
|
||||
set ext [string tolower [file extension $entry]]
|
||||
if {$ext ni $::include} { continue }
|
||||
set base [file rootname $entry]
|
||||
if {$ext eq ".hmt"} {
|
||||
if {[file exists "$dir/$base.ts"]} { continue }
|
||||
}
|
||||
lappend flist $entry
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if {[llength $flist]} {
|
||||
|
||||
foreach file $flist {
|
||||
p1l $ssep
|
||||
genFileDetails $dir $file
|
||||
set ssep $comma
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
httpheader "application/json"
|
||||
|
||||
set dir [cgi_get dir "/media"]
|
||||
set dir [cgi_get dir $root]
|
||||
set level [cgi_get n_level 0]
|
||||
set mode [cgi_get mode "parent"]
|
||||
set mode [cgi_get mode "filelist"]
|
||||
|
||||
pnl "[json-key rows $lbrk $lbrc]"
|
||||
|
||||
set start [clock milliseconds]
|
||||
if {$mode == "filelist"} {
|
||||
genFileList $dir
|
||||
} else {
|
||||
genDirList $dir [file tail $dir] 1 1 $level $mode
|
||||
}
|
||||
set end [clock milliseconds]
|
||||
set elapse $(double($end-$start)/1000.0)
|
||||
log "$mode | $elapse | $dir" 0
|
||||
|
||||
pnl "$rbrk $rbrc"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
register_module "flexview" "/plugin/flexview/"
|
||||
#system plog flexview "gohook mod $module last $lastmodule"
|
||||
|
||||
if {$module eq "browse" && $lastmodule eq "flexview"} {
|
||||
override_module "flexview"
|
||||
}
|
||||
|
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
Binary file not shown.
After Width: | Height: | Size: 69 KiB |
Binary file not shown.
After Width: | Height: | Size: 566 B |
Binary file not shown.
After Width: | Height: | Size: 225 B |
|
@ -0,0 +1,403 @@
|
|||
#!/mod/bin/jimsh
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require ts.class pretty_size system.class settings.class escape browse.class \
|
||||
plugin epg.class classdump
|
||||
|
||||
|
||||
set mroot [system mediaroot]
|
||||
set dir [cgi_get topdir $mroot]
|
||||
set model [system model]
|
||||
set dustbin [system dustbin 1]
|
||||
set nicesplice [system pkginst nicesplice]
|
||||
set settings [settings]
|
||||
set curconfig [$settings _tval_setting "fvConfig"]
|
||||
set curconfig [cgi_get config $curconfig]
|
||||
if {$curconfig == 0} {set curconfig "default"}
|
||||
|
||||
jqplugin contextMenu bar enadis blockui dialogue
|
||||
|
||||
header
|
||||
|
||||
jscss js/i18n/grid.locale-en.js
|
||||
puts {
|
||||
<script type="text/javascript">
|
||||
jQuery.jgrid.no_legacy_api = true;
|
||||
</script>
|
||||
}
|
||||
#jscss js/jquery.jqGrid.min.js css/ui.jqgrid.css
|
||||
jscss js/jquery.jqGrid.js css/ui.jqgrid.css
|
||||
jscss plugins/ui.multiselect.js plugins/ui.multiselect.css
|
||||
|
||||
jscss /browse/script.js /browse/style.css
|
||||
jscss contextmenu.js
|
||||
jscss script.js style.css
|
||||
if {[system has tvdb]} { jscss /browse/tvdb/script.js /browse/tvdb/style.css }
|
||||
|
||||
set plugins { dmenu {} menu {} omenu {} buttons {} dircolumn {} flcolumn {} icons {} dmenuattr {} menuattr {} omenuattr {} }
|
||||
eval_plugins browse
|
||||
eval_plugins flexview
|
||||
|
||||
|
||||
puts "
|
||||
<script type=text/javascript>
|
||||
var dir = '[string map {' {\'}} $dir]';
|
||||
var mediaroot = '$mroot';
|
||||
"
|
||||
|
||||
# Table column models & default config
|
||||
puts {
|
||||
|
||||
var plugin = {};
|
||||
|
||||
// Default config
|
||||
var fvConfig = {};
|
||||
fvConfig.name = 'basic';
|
||||
fvConfig.curdirsel = null;
|
||||
fvConfig.tablewidth =0;
|
||||
fvConfig.tabledepth =0;
|
||||
fvConfig.dircolwidth =0;
|
||||
fvConfig.flcolwidth =0
|
||||
fvConfig.dircolhidden = false;
|
||||
fvConfig.dirshrinktofit = false;
|
||||
fvConfig.flshrinktofit = false;
|
||||
fvConfig.datefmt = "d M y";
|
||||
fvConfig.datetimefmt = "d M y H:i";
|
||||
fvConfig.timefmt = "H:i:s";
|
||||
fvConfig.dirColChg={};
|
||||
fvConfig.flColChg={};
|
||||
fvConfig.sel={};
|
||||
fvConfig.excl={};
|
||||
fvConfig.exp={};
|
||||
fvConfig.exp['-media']=true;
|
||||
fvConfig.exp['-media-My-Video']=true;
|
||||
fvConfig.saveInt=15000;
|
||||
fvConfig.reloadInt=60;
|
||||
}
|
||||
|
||||
set fname "/mod/etc/fvConfig_$curconfig.json"
|
||||
if {[catch {set fd [open $fname r]
|
||||
set fvconfig [read $fd ]
|
||||
#puts "Object.assign(fvConfig,$fvconfig);"
|
||||
puts "\$.extend(fvConfig,$fvconfig);"
|
||||
puts "fvConfig.name = '$curconfig';"
|
||||
close $fd} msg opts]} {
|
||||
puts "console.error('Config file error caught: $msg');"
|
||||
}
|
||||
|
||||
puts {
|
||||
// Icons
|
||||
var icons = {};
|
||||
}
|
||||
|
||||
set icon [_addicon "/img/compressr.png" "Recursive Auto-shrink"]
|
||||
puts "icons.autoshrinkr = '$icon';"
|
||||
set icon [_addicon "/img/compress.png" "Auto-shrink"]
|
||||
puts "icons.autoshrink = '$icon';"
|
||||
set icon [_addicon "/img/dedup.png" "Auto-dedup"]
|
||||
puts "icons.autodedup = '$icon';"
|
||||
set icon [_addicon "/img/decryptr.png" "Recursive Auto-decrypt"]
|
||||
puts "icons.autodecryptr = '$icon';"
|
||||
set icon [_addicon "/img/decrypt.png" "Auto-decrypt"]
|
||||
puts "icons.autodecrypt = '$icon';"
|
||||
set icon [_addicon "/img/mpg.png" "Auto-MPG Extract"]
|
||||
puts "icons.autompg = '$icon';"
|
||||
set icon [_addicon "/img/mp3.png" "Auto-Audio Extract"]
|
||||
puts "icons.automp3 = '$icon';"
|
||||
set icon [_addicon "/img/clock.png" "Auto-Expire"]
|
||||
puts "icons.autoexpire = '$icon';"
|
||||
set icon [_addicon "/img/tvdb-sm.png" "TheTVDB"]
|
||||
puts "icons.tvdb = '$icon';"
|
||||
set icon [_addicon "/images/175_1_11_Series_Record.png" "Series"]
|
||||
puts "icons.series = '$icon';"
|
||||
|
||||
set icon [_addicon "/images/172_1_00_HD.png" "High Definition"]
|
||||
puts "icons.HD = '$icon';"
|
||||
set icon [_addicon "/images/172_1_26_SD.png" "Standard Definition"]
|
||||
puts "icons.SD = '$icon';"
|
||||
set icon [_addicon "/images/178_1_00_Icon_Lock.png" "Locked"]
|
||||
puts "icons.Locked = '$icon';"
|
||||
set icon [_addicon "/images/749_1_26_Video_Encryption.png" "Protected"]
|
||||
puts "icons.ENC = '$icon';"
|
||||
set icon [_addicon "/img/Decrypted.png" "Decrypted"]
|
||||
puts "icons.DEC = '$icon';"
|
||||
set icon [_addicon "/plugin/flexview/img/NotDecrypted.png" "On disk encrypted"]
|
||||
puts "icons.ODE = '$icon';"
|
||||
#set icon [_addicon "/img/Guidance_purple.png" "Guidance"]
|
||||
set icon [_addicon "/img/Guidance_purple.png"]
|
||||
puts "icons.guidance = '$icon';"
|
||||
#set icon [_addicon "/img/Guidance_blue.png" "General Guidance"]
|
||||
set icon [_addicon "/img/Guidance_blue.png"]
|
||||
puts "icons.Gguidance = '$icon';"
|
||||
set icon [_addicon "/img/compress.png" "Shrunk"]
|
||||
puts "icons.Shrunk = '$icon';"
|
||||
set icon [_addicon "/img/dedup.png" "De-duped"]
|
||||
puts "icons.Deduped = '$icon';"
|
||||
set icon [_addicon "/img/dlna.png" "Indexed by DLNA Server"]
|
||||
puts "icons.DLNA = '$icon';"
|
||||
set icon [_addicon "/images/743_1_10_Video_New.png" "New (unwatched)"]
|
||||
puts "icons.new = '$icon';"
|
||||
set icon [_addicon "/img/context/thumb.png" "Thumbnail"]
|
||||
puts "icons.thumb = '$icon';"
|
||||
set icon [_addicon "/img/context/bookmark.png" "Bookmark"]
|
||||
puts "icons.bookmark = '$icon';"
|
||||
set icon [_addicon "/img/inuse.png" "In Use"]
|
||||
puts "icons.inuse = '$icon';"
|
||||
set icon [_addicon "/img/radio.png" "Radio Programme"]
|
||||
puts "icons.Radio = '$icon';"
|
||||
|
||||
foreach {icon image} $plugins(icons) {
|
||||
# plugin icons
|
||||
puts "icons.$icon = '$image';"
|
||||
}
|
||||
|
||||
# opt+ menu attr values to table column mapping
|
||||
# browse Opt+ menus use a set of addon keywords in HTML element to pass values to menu
|
||||
# Define mapping with table rows to allow element to be built correctly
|
||||
# plugins can extend the list
|
||||
puts {var dirmenuattr = {
|
||||
autoshrink: 'autoshrink',
|
||||
autoshrinkR: 'autoshrinkR',
|
||||
autodedup: 'autodedup',
|
||||
autodecrypt: 'autodecrypt',
|
||||
autodecryptR: 'autodecryptR',
|
||||
autompg: 'autompg',
|
||||
automp3: 'automp3',
|
||||
autoexpire: 'autoexpire',
|
||||
tvdbseriesid: 'tvdb'};
|
||||
}
|
||||
foreach {attr column} $plugins(dmenuattr) {
|
||||
# plugin attribute
|
||||
puts "dirmenuattr.$attr = '$column';"
|
||||
}
|
||||
|
||||
|
||||
puts {var optmenuattr = {
|
||||
def: 'definition',
|
||||
locked: 'Locked',
|
||||
encd: 'Encrypted',
|
||||
odencd: 'ODEncrypted',
|
||||
shrunk: 'Shrunk',
|
||||
bx: 'bookmarks',
|
||||
type: 'ftype',
|
||||
rsize: 'fsize',
|
||||
dlna: 'dlna',
|
||||
thmok: 'thmok',
|
||||
new: 'New'};
|
||||
}
|
||||
foreach {attr column} $plugins(omenuattr) {
|
||||
# plugin attribute
|
||||
puts "optmenuattr.$attr = '$column';"
|
||||
}
|
||||
|
||||
|
||||
# Genre icon list
|
||||
set glist [ts genrelist]
|
||||
puts "var genrelist = {"
|
||||
foreach {gcode genreval} $glist {
|
||||
lassign $genreval txt img
|
||||
if {$img eq "Unclassified"} {
|
||||
set icon [_addicon "/images/173_3_26_G3_$img.png" $txt "fvICON va genre"]
|
||||
} else {
|
||||
set icon [_addicon "/images/173_3_00_G3_$img.png" $txt "fvICON va genre"]
|
||||
}
|
||||
puts "$gcode: '$icon $txt',"
|
||||
}
|
||||
puts "'':'- All'};"
|
||||
|
||||
puts {
|
||||
|
||||
// Table column models
|
||||
var dirColModel= [
|
||||
}
|
||||
set fd [open "DirColModel.json" r] ; # std columns
|
||||
set data [read $fd]
|
||||
puts $data
|
||||
close $fd
|
||||
#puts "// $plugins "
|
||||
foreach plugin $plugins(dircolumn) {
|
||||
# plugin columns
|
||||
puts $plugin
|
||||
}
|
||||
puts {
|
||||
];
|
||||
var flColModel= [
|
||||
}
|
||||
set fd [open "FlColModel.json" r] ; # std columns
|
||||
set data [read $fd]
|
||||
puts $data
|
||||
close $fd
|
||||
#puts "// $plugins "
|
||||
foreach plugin $plugins(flcolumn) {
|
||||
# plugin columns
|
||||
puts $plugin
|
||||
}
|
||||
puts {
|
||||
];
|
||||
|
||||
var flData = [];
|
||||
var flLoaded = {};
|
||||
var flLoadTime = {};
|
||||
var dirstart;
|
||||
|
||||
</script>
|
||||
}
|
||||
|
||||
|
||||
source /mod/webif/html/browse/assets.jim
|
||||
if {[system has tvdb]} { source /mod/webif/html/browse/tvdb/assets.jim }
|
||||
puts "<button style=\"display:none\" id=tvdbsetseries>TVDB</button>"
|
||||
|
||||
puts "<span style=\"display:none\" id=dir>$dir</span>"
|
||||
puts "<span style=\"display:none\" id=mediaroot>$mroot</span>"
|
||||
|
||||
# Top option buttons
|
||||
puts "<div class=brow>"
|
||||
puts {
|
||||
<button id=reload><img src=/plugin/flexview/img/refresh02.png>Reload grids</button>
|
||||
<button id=load>Load</button>
|
||||
<button id=save>Save</button>
|
||||
<div id="topspin" class=spinner style="float: right"><img border=0 src=/img/loading.gif>
|
||||
Loading... Please wait...</div>
|
||||
<div id="topmsg" class=blood style="float: right"></div>
|
||||
</div>
|
||||
|
||||
<div id=configload title="Load configuration" style="display: none">
|
||||
<select id=configllist class="ui-widget ui-corner-all">
|
||||
}
|
||||
source /mod/webif/plugin/flexview/configlist.jim
|
||||
genConfigList
|
||||
|
||||
puts {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id=configsave title="Save configuration as" style="display: none">
|
||||
<datalist id=configslist>
|
||||
}
|
||||
|
||||
genConfigList
|
||||
|
||||
puts "
|
||||
</datalist>
|
||||
<input id=configname type=text list=configslist value=\"$curconfig\" size=50 class=\"ui-widget ui-corner-all\">
|
||||
</div>
|
||||
"
|
||||
|
||||
# Directory and filelist grids
|
||||
puts {
|
||||
<div style="clear: both" >
|
||||
<table id="fvtable" border="1" class="ui-widget ui-corner-all">
|
||||
<col id=dircol> <col id=flcol>
|
||||
<thead border="1" class="ui-widget-header">
|
||||
<tr>
|
||||
<th id="dirhead" class="ui-widget ui-corner-all">Directory tree view
|
||||
<div id="dirspin" class=spinner style="float: left"><img border=0 src=/img/loading.gif>
|
||||
Loading... Please wait...</div>
|
||||
<span style="float: right">
|
||||
<button id=dircolumn>Columns</button>
|
||||
<button id=hide>Hide Tree</button>
|
||||
</span>
|
||||
</th>
|
||||
<th id="flhead" class="ui-widget ui-corner-all">File list view
|
||||
<div id="flspin" class=spinner style="float: left"><img border=0 src=/img/loading.gif>
|
||||
Loading... Please wait...</div>
|
||||
<span style="float: right">
|
||||
<button id=flcolumn>Columns</button>
|
||||
<button id=show>Show Tree</button>
|
||||
</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr id="dirrow">
|
||||
<td id="dircell">
|
||||
<!-- Add a <table> element where the tree should appear: -->
|
||||
<table id="dirlist">
|
||||
<tr> <td></td> </tr>
|
||||
</table>
|
||||
</td>
|
||||
<td id="flcell">
|
||||
<!-- Add a <table> element where the file list should appear: -->
|
||||
<table id="filelist">
|
||||
<tr> <td></td> </tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
# Bottom browse action buttons
|
||||
puts "<div class=brow>"
|
||||
puts {
|
||||
<button id=copy class=onesel>Copy</button>
|
||||
<button id=cut class=onesel>Cut</button>
|
||||
<button id=delete class=onesel>Delete</button>
|
||||
<div id=deletewait class=blood style="display: none">
|
||||
<img src=/img/loading.gif>Deleting may take some time, please be patient...
|
||||
</div>
|
||||
}
|
||||
|
||||
# Join
|
||||
if {$nicesplice} {
|
||||
puts { <button id=join class=tstwosel>Join</button> }
|
||||
}
|
||||
|
||||
# Queue
|
||||
set queueactions(decrypt) "Decryption"
|
||||
set queueactions(shrink) "Shrink"
|
||||
set queueactions(mp2) "Audio-Extraction (mp2, fast)"
|
||||
set queueactions(mp3) "Audio-Extraction (mp3, slow)"
|
||||
set queueactions(mpg) "Conversion to MPG"
|
||||
eval_plugins queueactions
|
||||
|
||||
puts {
|
||||
<button id=so_queue class=tsonesel><img src=/img/queueps.png class=qb>
|
||||
Queue for</button>
|
||||
<select id=so_queueactions
|
||||
class="tsonesel text ui-widget-content ui-corner-all">
|
||||
}
|
||||
set rqueueactions [lreverse $queueactions]
|
||||
foreach v [lsort [dict keys $rqueueactions]] {
|
||||
set k $rqueueactions($v)
|
||||
puts "<option value=$k>$v</option>"
|
||||
}
|
||||
puts {
|
||||
</select>
|
||||
}
|
||||
|
||||
puts {
|
||||
<button id=queue><img src=/img/queueps.png class=qb> View Queue</button>
|
||||
}
|
||||
|
||||
# Plugin buttons
|
||||
|
||||
if {[llength $plugins(buttons)]} {
|
||||
puts "</div><div class=buttonrow>"
|
||||
foreach plugin $plugins(buttons) {
|
||||
lassign $plugin tag options
|
||||
puts "
|
||||
<button class=plugin act=\"$options(link)\">$options(desc)</button>
|
||||
"
|
||||
}
|
||||
}
|
||||
|
||||
puts "</div>"
|
||||
|
||||
|
||||
# clipboard
|
||||
puts {
|
||||
<fieldset class=left style="margin: 0 1em 1em 1em; float: right">
|
||||
<legend style="font-size: 1.5em; padding: 0 0.5em 0.5em 0.5em; color: #1e5bbd;">
|
||||
File Clipboard
|
||||
</legend>
|
||||
<div id=clipboard>
|
||||
<img src=/img/loading.gif> <i>Loading...</i>
|
||||
</div>
|
||||
</fieldset>
|
||||
}
|
||||
footer
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,220 @@
|
|||
/**
|
||||
* jqGrid English Translation
|
||||
* 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.html
|
||||
**/
|
||||
/*global jQuery, define */
|
||||
(function( factory ) {
|
||||
"use strict";
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([
|
||||
"jquery",
|
||||
"../grid.base"
|
||||
], factory );
|
||||
} else {
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( $ ) {
|
||||
|
||||
$.jgrid = $.jgrid || {};
|
||||
if(!$.jgrid.hasOwnProperty("regional")) {
|
||||
$.jgrid.regional = [];
|
||||
}
|
||||
$.jgrid.regional["en"] = {
|
||||
defaults : {
|
||||
recordtext: "View {0} - {1} of {2}",
|
||||
emptyrecords: "No records to view",
|
||||
loadtext: "Loading...",
|
||||
savetext: "Saving...",
|
||||
pgtext : "Page {0} of {1}",
|
||||
pgfirst : "First Page",
|
||||
pglast : "Last Page",
|
||||
pgnext : "Next Page",
|
||||
pgprev : "Previous Page",
|
||||
pgrecs : "Records per Page",
|
||||
showhide: "Toggle Expand Collapse Grid",
|
||||
// mobile
|
||||
pagerCaption : "Grid::Page Settings",
|
||||
pageText : "Page:",
|
||||
recordPage : "Records per Page",
|
||||
nomorerecs : "No more records...",
|
||||
scrollPullup: "Pull up to load more...",
|
||||
scrollPulldown : "Pull down to refresh...",
|
||||
scrollRefresh : "Release to refresh..."
|
||||
},
|
||||
search : {
|
||||
caption: "Search...",
|
||||
Find: "Find",
|
||||
Reset: "Reset",
|
||||
odata: [{ oper:'eq', text:'equal'},{ oper:'ne', text:'not equal'},{ oper:'lt', text:'less'},{ oper:'le', text:'less or equal'},{ oper:'gt', text:'greater'},{ oper:'ge', text:'greater or equal'},{ oper:'bw', text:'begins with'},{ oper:'bn', text:'does not begin with'},{ oper:'in', text:'is in'},{ oper:'ni', text:'is not in'},{ oper:'ew', text:'ends with'},{ oper:'en', text:'does not end with'},{ oper:'cn', text:'contains'},{ oper:'nc', text:'does not contain'},{ oper:'nu', text:'is null'},{ oper:'nn', text:'is not null'}, {oper:'bt', text:'between'}],
|
||||
groupOps: [{ op: "AND", text: "all" },{ op: "OR", text: "any" }],
|
||||
operandTitle : "Click to select search operation.",
|
||||
resetTitle : "Reset Search Value"
|
||||
},
|
||||
edit : {
|
||||
addCaption: "Add Record",
|
||||
editCaption: "Edit Record",
|
||||
bSubmit: "Submit",
|
||||
bCancel: "Cancel",
|
||||
bClose: "Close",
|
||||
saveData: "Data has been changed! Save changes?",
|
||||
bYes : "Yes",
|
||||
bNo : "No",
|
||||
bExit : "Cancel",
|
||||
msg: {
|
||||
required:"Field is required",
|
||||
number:"Please, enter valid number",
|
||||
minValue:"value must be greater than or equal to ",
|
||||
maxValue:"value must be less than or equal to",
|
||||
email: "is not a valid e-mail",
|
||||
integer: "Please, enter valid integer value",
|
||||
date: "Please, enter valid date value",
|
||||
url: "is not a valid URL. Prefix required ('http://' or 'https://')",
|
||||
nodefined : " is not defined!",
|
||||
novalue : " return value is required!",
|
||||
customarray : "Custom function should return array!",
|
||||
customfcheck : "Custom function should be present in case of custom checking!"
|
||||
|
||||
}
|
||||
},
|
||||
view : {
|
||||
caption: "View Record",
|
||||
bClose: "Close"
|
||||
},
|
||||
del : {
|
||||
caption: "Delete",
|
||||
msg: "Delete selected record(s)?",
|
||||
bSubmit: "Delete",
|
||||
bCancel: "Cancel"
|
||||
},
|
||||
nav : {
|
||||
edittext: "",
|
||||
edittitle: "Edit selected row",
|
||||
addtext:"",
|
||||
addtitle: "Add new row",
|
||||
deltext: "",
|
||||
deltitle: "Delete selected row",
|
||||
searchtext: "",
|
||||
searchtitle: "Find records",
|
||||
refreshtext: "",
|
||||
refreshtitle: "Reload Grid",
|
||||
alertcap: "Warning",
|
||||
alerttext: "Please, select row",
|
||||
viewtext: "",
|
||||
viewtitle: "View selected row",
|
||||
savetext: "",
|
||||
savetitle: "Save row",
|
||||
canceltext: "",
|
||||
canceltitle : "Cancel row editing",
|
||||
selectcaption : "Actions..."
|
||||
},
|
||||
col : {
|
||||
caption: "Select columns",
|
||||
bSubmit: "Ok",
|
||||
bCancel: "Cancel"
|
||||
},
|
||||
errors : {
|
||||
errcap : "Error",
|
||||
nourl : "No url is set",
|
||||
norecords: "No records to process",
|
||||
model : "Length of colNames <> colModel!"
|
||||
},
|
||||
formatter : {
|
||||
integer : {thousandsSeparator: ",", defaultValue: '0'},
|
||||
number : {decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 2, defaultValue: '0.00'},
|
||||
currency : {decimalSeparator:".", thousandsSeparator: ",", decimalPlaces: 2, prefix: "", suffix:"", defaultValue: '0.00'},
|
||||
date : {
|
||||
dayNames: [
|
||||
"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat",
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
|
||||
],
|
||||
monthNames: [
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
|
||||
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
|
||||
],
|
||||
AmPm : ["am","pm","AM","PM"],
|
||||
S: function (j) {return j < 11 || j > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((j - 1) % 10, 3)] : 'th';},
|
||||
srcformat: 'Y-m-d',
|
||||
newformat: 'n/j/Y',
|
||||
parseRe : /[#%\\\/:_;.,\t\s-]/,
|
||||
masks : {
|
||||
// see http://php.net/manual/en/function.date.php for PHP format used in jqGrid
|
||||
// and see http://docs.jquery.com/UI/Datepicker/formatDate
|
||||
// and https://github.com/jquery/globalize#dates for alternative formats used frequently
|
||||
// one can find on https://github.com/jquery/globalize/tree/master/lib/cultures many
|
||||
// information about date, time, numbers and currency formats used in different countries
|
||||
// one should just convert the information in PHP format
|
||||
ISO8601Long:"Y-m-d H:i:s",
|
||||
ISO8601Short:"Y-m-d",
|
||||
// short date:
|
||||
// n - Numeric representation of a month, without leading zeros
|
||||
// j - Day of the month without leading zeros
|
||||
// Y - A full numeric representation of a year, 4 digits
|
||||
// example: 3/1/2012 which means 1 March 2012
|
||||
ShortDate: "n/j/Y", // in jQuery UI Datepicker: "M/d/yyyy"
|
||||
// long date:
|
||||
// l - A full textual representation of the day of the week
|
||||
// F - A full textual representation of a month
|
||||
// d - Day of the month, 2 digits with leading zeros
|
||||
// Y - A full numeric representation of a year, 4 digits
|
||||
LongDate: "l, F d, Y", // in jQuery UI Datepicker: "dddd, MMMM dd, yyyy"
|
||||
// long date with long time:
|
||||
// l - A full textual representation of the day of the week
|
||||
// F - A full textual representation of a month
|
||||
// d - Day of the month, 2 digits with leading zeros
|
||||
// Y - A full numeric representation of a year, 4 digits
|
||||
// g - 12-hour format of an hour without leading zeros
|
||||
// i - Minutes with leading zeros
|
||||
// s - Seconds, with leading zeros
|
||||
// A - Uppercase Ante meridiem and Post meridiem (AM or PM)
|
||||
FullDateTime: "l, F d, Y g:i:s A", // in jQuery UI Datepicker: "dddd, MMMM dd, yyyy h:mm:ss tt"
|
||||
// month day:
|
||||
// F - A full textual representation of a month
|
||||
// d - Day of the month, 2 digits with leading zeros
|
||||
MonthDay: "F d", // in jQuery UI Datepicker: "MMMM dd"
|
||||
// short time (without seconds)
|
||||
// g - 12-hour format of an hour without leading zeros
|
||||
// i - Minutes with leading zeros
|
||||
// A - Uppercase Ante meridiem and Post meridiem (AM or PM)
|
||||
ShortTime: "g:i A", // in jQuery UI Datepicker: "h:mm tt"
|
||||
// long time (with seconds)
|
||||
// g - 12-hour format of an hour without leading zeros
|
||||
// i - Minutes with leading zeros
|
||||
// s - Seconds, with leading zeros
|
||||
// A - Uppercase Ante meridiem and Post meridiem (AM or PM)
|
||||
LongTime: "g:i:s A", // in jQuery UI Datepicker: "h:mm:ss tt"
|
||||
SortableDateTime: "Y-m-d\\TH:i:s",
|
||||
UniversalSortableDateTime: "Y-m-d H:i:sO",
|
||||
// month with year
|
||||
// Y - A full numeric representation of a year, 4 digits
|
||||
// F - A full textual representation of a month
|
||||
YearMonth: "F, Y" // in jQuery UI Datepicker: "MMMM, yyyy"
|
||||
},
|
||||
reformatAfterEdit : false,
|
||||
userLocalTime : false
|
||||
},
|
||||
baseLinkUrl: '',
|
||||
showAction: '',
|
||||
target: '',
|
||||
checkbox : {disabled:true},
|
||||
idName : 'id'
|
||||
},
|
||||
colmenu : {
|
||||
sortasc : "Sort Ascending",
|
||||
sortdesc : "Sort Descending",
|
||||
columns : "Columns",
|
||||
filter : "Filter",
|
||||
grouping : "Group By",
|
||||
ungrouping : "Ungroup",
|
||||
searchTitle : "Get items with value that:",
|
||||
freeze : "Freeze",
|
||||
unfreeze : "Unfreeze",
|
||||
reorder : "Move to reorder"
|
||||
}
|
||||
};
|
||||
}));
|
|
@ -0,0 +1,43 @@
|
|||
Installation
|
||||
|
||||
Download the jqGrid package from the www.trirand/blog site section downloads.
|
||||
Note the new download manager where you can choose which modules you want to
|
||||
include in the download.
|
||||
|
||||
In order to use jqGrid 3.5, first a UI theme css file should be loaded.
|
||||
Download the desired theme (or build a custom one) from jQueryUI site
|
||||
(www.jqueryui.com) and point in your link tag in head section the path to the
|
||||
theme css
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="path_to_ui_css_file/jquery-ui-1.7.1.custom.css" />
|
||||
|
||||
where the path_to_ui_css_file is a valid path to the ui theme file
|
||||
|
||||
Extract the jqGrid package and copy the ui.jqgrid.css from css directory to
|
||||
your webserver directory. It is not necessary that the jqgrid css file is in
|
||||
the same directory as those of the jquery ui css.
|
||||
|
||||
<link rel="stylesheet" type="text/css" media="screen" href="path_to_jqgrid_css_file/ui.jqgrid.css" />
|
||||
|
||||
Starting with this version, jqGrid does not use a loader (which loads the
|
||||
needed files one by one), but all the needed code is contained in one file.
|
||||
The desired modules can be built using the jqGrid download manager from the
|
||||
site pointed above. In order to use this, first a language file should be
|
||||
loaded and then the jqgrid file.
|
||||
|
||||
Copy the desired language file from js/i18n directory to your web server
|
||||
directory where you store the java script files. Every language file is
|
||||
named grid.locale-XX.js, where XX is a two-letter code for the language.
|
||||
Copy the jquery.jqGid.min.js file to the same or other valid directory in
|
||||
your web server
|
||||
|
||||
Include both the files in script tags in the head section
|
||||
|
||||
<script src="path_to_js_files/grid.locale-en.js" type="text/javascript"></script>
|
||||
<script src="path_to_js_files/jquery.jqGrid.min.js" type="text/javascript"></script>
|
||||
|
||||
For debugging purposes, I have created a grid.loader.js which does the same
|
||||
loading of the files as in previous versions. The location of the file is in
|
||||
src directory of the package. In order to use this, the variable pathojsfiles
|
||||
should be adjusted to point to the appropriate folder - see 3.4.x docs.
|
||||
|
|
@ -0,0 +1,485 @@
|
|||
/*
|
||||
**
|
||||
* formatter for values but most of the values if for jqGrid
|
||||
* Some of this was inspired and based on how YUI does the table datagrid but in jQuery fashion
|
||||
* we are trying to keep it as light as possible
|
||||
* Joshua Burnett josh@9ci.com
|
||||
* http://www.greenbill.com
|
||||
*
|
||||
* Changes from Tony Tomov tony@trirand.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
|
||||
*
|
||||
**/
|
||||
/*jshint eqeqeq:false */
|
||||
/*global jQuery, define */
|
||||
|
||||
(function( factory ) {
|
||||
"use strict";
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define([
|
||||
"jquery",
|
||||
"./grid.base"
|
||||
], factory );
|
||||
} else {
|
||||
// Browser globals
|
||||
factory( jQuery );
|
||||
}
|
||||
}(function( $ ) {
|
||||
"use strict";
|
||||
//module begin
|
||||
$.fmatter = {};
|
||||
//opts can be id:row id for the row, rowdata:the data for the row, colmodel:the column model for this column
|
||||
//example {id:1234,}
|
||||
$.extend($.fmatter,{
|
||||
isBoolean : function(o) {
|
||||
return typeof o === 'boolean';
|
||||
},
|
||||
isObject : function(o) {
|
||||
return (o && (typeof o === 'object' || $.isFunction(o))) || false;
|
||||
},
|
||||
isString : function(o) {
|
||||
return typeof o === 'string';
|
||||
},
|
||||
isNumber : function(o) {
|
||||
return typeof o === 'number' && isFinite(o);
|
||||
},
|
||||
isValue : function (o) {
|
||||
return (this.isObject(o) || this.isString(o) || this.isNumber(o) || this.isBoolean(o));
|
||||
},
|
||||
isEmpty : function(o) {
|
||||
if(!this.isString(o) && this.isValue(o)) {
|
||||
return false;
|
||||
}
|
||||
if (!this.isValue(o)){
|
||||
return true;
|
||||
}
|
||||
o = $.trim(o).replace(/\ \;/ig,'').replace(/\ \;/ig,'');
|
||||
return o==="";
|
||||
}
|
||||
});
|
||||
$.fn.fmatter = function(formatType, cellval, opts, rwd, act) {
|
||||
// build main options before element iteration
|
||||
var v=cellval;
|
||||
opts = $.extend({}, $.jgrid.getRegional(this, 'formatter') , opts);
|
||||
|
||||
try {
|
||||
v = $.fn.fmatter[formatType].call(this, cellval, opts, rwd, act);
|
||||
} catch(fe){}
|
||||
return v;
|
||||
};
|
||||
$.fmatter.util = {
|
||||
// Taken from YAHOO utils
|
||||
NumberFormat : function(nData,opts) {
|
||||
if(!$.fmatter.isNumber(nData)) {
|
||||
nData *= 1;
|
||||
}
|
||||
if($.fmatter.isNumber(nData)) {
|
||||
var bNegative = (nData < 0);
|
||||
var sOutput = String(nData);
|
||||
var sDecimalSeparator = opts.decimalSeparator || ".";
|
||||
var nDotIndex;
|
||||
if($.fmatter.isNumber(opts.decimalPlaces)) {
|
||||
// Round to the correct decimal place
|
||||
var nDecimalPlaces = opts.decimalPlaces;
|
||||
var nDecimal = Math.pow(10, nDecimalPlaces);
|
||||
sOutput = String(Math.round(nData*nDecimal)/nDecimal);
|
||||
nDotIndex = sOutput.lastIndexOf(".");
|
||||
if(nDecimalPlaces > 0) {
|
||||
// Add the decimal separator
|
||||
if(nDotIndex < 0) {
|
||||
sOutput += sDecimalSeparator;
|
||||
nDotIndex = sOutput.length-1;
|
||||
}
|
||||
// Replace the "."
|
||||
else if(sDecimalSeparator !== "."){
|
||||
sOutput = sOutput.replace(".",sDecimalSeparator);
|
||||
}
|
||||
// Add missing zeros
|
||||
while((sOutput.length - 1 - nDotIndex) < nDecimalPlaces) {
|
||||
sOutput += "0";
|
||||
}
|
||||
}
|
||||
}
|
||||
if(opts.thousandsSeparator) {
|
||||
var sThousandsSeparator = opts.thousandsSeparator;
|
||||
nDotIndex = sOutput.lastIndexOf(sDecimalSeparator);
|
||||
nDotIndex = (nDotIndex > -1) ? nDotIndex : sOutput.length;
|
||||
var sNewOutput = sOutput.substring(nDotIndex);
|
||||
var nCount = -1, i;
|
||||
for (i=nDotIndex; i>0; i--) {
|
||||
nCount++;
|
||||
if ((nCount%3 === 0) && (i !== nDotIndex) && (!bNegative || (i > 1))) {
|
||||
sNewOutput = sThousandsSeparator + sNewOutput;
|
||||
}
|
||||
sNewOutput = sOutput.charAt(i-1) + sNewOutput;
|
||||
}
|
||||
sOutput = sNewOutput;
|
||||
}
|
||||
// Prepend prefix
|
||||
sOutput = (opts.prefix) ? opts.prefix + sOutput : sOutput;
|
||||
// Append suffix
|
||||
sOutput = (opts.suffix) ? sOutput + opts.suffix : sOutput;
|
||||
return sOutput;
|
||||
|
||||
}
|
||||
return nData;
|
||||
}
|
||||
};
|
||||
$.fn.fmatter.defaultFormat = function(cellval, opts) {
|
||||
return ($.fmatter.isValue(cellval) && cellval!=="" ) ? cellval : opts.defaultValue || " ";
|
||||
};
|
||||
$.fn.fmatter.email = function(cellval, opts) {
|
||||
if(!$.fmatter.isEmpty(cellval)) {
|
||||
return "<a href=\"mailto:" + cellval + "\">" + cellval + "</a>";
|
||||
}
|
||||
return $.fn.fmatter.defaultFormat(cellval,opts );
|
||||
};
|
||||
$.fn.fmatter.checkbox =function(cval, opts) {
|
||||
var op = $.extend({},opts.checkbox), ds;
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if(op.disabled===true) {ds = "disabled=\"disabled\"";} else {ds="";}
|
||||
if($.fmatter.isEmpty(cval) || cval === undefined ) {cval = $.fn.fmatter.defaultFormat(cval,op);}
|
||||
cval=String(cval);
|
||||
cval=(cval+"").toLowerCase();
|
||||
var bchk = cval.search(/(false|f|0|no|n|off|undefined)/i)<0 ? " checked='checked' " : "";
|
||||
return "<input type=\"checkbox\" " + bchk + " value=\""+ cval+"\" offval=\"no\" "+ds+ "/>";
|
||||
};
|
||||
$.fn.fmatter.link = function(cellval, opts) {
|
||||
var op = {target:opts.target};
|
||||
var target = "";
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if(op.target) {target = 'target=' + op.target;}
|
||||
if(!$.fmatter.isEmpty(cellval)) {
|
||||
return "<a "+target+" href=\"" + cellval + "\">" + cellval + "</a>";
|
||||
}
|
||||
return $.fn.fmatter.defaultFormat(cellval,opts);
|
||||
};
|
||||
$.fn.fmatter.showlink = function(cellval, opts) {
|
||||
var op = {baseLinkUrl: opts.baseLinkUrl,showAction:opts.showAction, addParam: opts.addParam || "", target: opts.target, idName: opts.idName},
|
||||
target = "", idUrl;
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if(op.target) {target = 'target=' + op.target;}
|
||||
idUrl = op.baseLinkUrl+op.showAction + '?'+ op.idName+'='+opts.rowId+op.addParam;
|
||||
if($.fmatter.isString(cellval) || $.fmatter.isNumber(cellval)) { //add this one even if its blank string
|
||||
return "<a "+target+" href=\"" + idUrl + "\">" + cellval + "</a>";
|
||||
}
|
||||
return $.fn.fmatter.defaultFormat(cellval,opts);
|
||||
};
|
||||
$.fn.fmatter.integer = function(cellval, opts) {
|
||||
var op = $.extend({},opts.integer);
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if($.fmatter.isEmpty(cellval)) {
|
||||
return op.defaultValue;
|
||||
}
|
||||
return $.fmatter.util.NumberFormat(cellval,op);
|
||||
};
|
||||
$.fn.fmatter.number = function (cellval, opts) {
|
||||
var op = $.extend({},opts.number);
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if($.fmatter.isEmpty(cellval)) {
|
||||
return op.defaultValue;
|
||||
}
|
||||
return $.fmatter.util.NumberFormat(cellval,op);
|
||||
};
|
||||
$.fn.fmatter.currency = function (cellval, opts) {
|
||||
var op = $.extend({},opts.currency);
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if($.fmatter.isEmpty(cellval)) {
|
||||
return op.defaultValue;
|
||||
}
|
||||
return $.fmatter.util.NumberFormat(cellval,op);
|
||||
};
|
||||
$.fn.fmatter.date = function (cellval, opts, rwd, act) {
|
||||
var op = $.extend({},opts.date);
|
||||
if(opts.colModel !== undefined && opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.colModel.formatoptions);
|
||||
}
|
||||
if(!op.reformatAfterEdit && act === 'edit'){
|
||||
return $.fn.fmatter.defaultFormat(cellval, opts);
|
||||
}
|
||||
if(!$.fmatter.isEmpty(cellval)) {
|
||||
return $.jgrid.parseDate.call(this, op.srcformat,cellval,op.newformat,op);
|
||||
}
|
||||
return $.fn.fmatter.defaultFormat(cellval, opts);
|
||||
};
|
||||
$.fn.fmatter.select = function (cellval,opts) {
|
||||
// jqGrid specific
|
||||
cellval = String(cellval);
|
||||
var oSelect = false, ret=[], sep, delim;
|
||||
if(opts.colModel.formatoptions !== undefined){
|
||||
oSelect= opts.colModel.formatoptions.value;
|
||||
sep = opts.colModel.formatoptions.separator === undefined ? ":" : opts.colModel.formatoptions.separator;
|
||||
delim = opts.colModel.formatoptions.delimiter === undefined ? ";" : opts.colModel.formatoptions.delimiter;
|
||||
} else if(opts.colModel.editoptions !== undefined){
|
||||
oSelect= opts.colModel.editoptions.value;
|
||||
sep = opts.colModel.editoptions.separator === undefined ? ":" : opts.colModel.editoptions.separator;
|
||||
delim = opts.colModel.editoptions.delimiter === undefined ? ";" : opts.colModel.editoptions.delimiter;
|
||||
}
|
||||
if (oSelect) {
|
||||
var msl = (opts.colModel.editoptions != null && opts.colModel.editoptions.multiple === true) === true ? true : false,
|
||||
scell = [], sv;
|
||||
if(msl) {scell = cellval.split(",");scell = $.map(scell,function(n){return $.trim(n);});}
|
||||
if ($.fmatter.isString(oSelect)) {
|
||||
// mybe here we can use some caching with care ????
|
||||
var so = oSelect.split(delim), j=0, i;
|
||||
for(i=0; i<so.length;i++){
|
||||
sv = so[i].split(sep);
|
||||
if(sv.length > 2 ) {
|
||||
sv[1] = $.map(sv,function(n,i){if(i>0) {return n;}}).join(sep);
|
||||
}
|
||||
if(msl) {
|
||||
if($.inArray(sv[0],scell)>-1) {
|
||||
ret[j] = sv[1];
|
||||
j++;
|
||||
}
|
||||
} else if($.trim(sv[0]) === $.trim(cellval)) {
|
||||
ret[0] = sv[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if($.fmatter.isObject(oSelect)) {
|
||||
// this is quicker
|
||||
if(msl) {
|
||||
ret = $.map(scell, function(n){
|
||||
return oSelect[n];
|
||||
});
|
||||
} else {
|
||||
ret[0] = oSelect[cellval] || "";
|
||||
}
|
||||
}
|
||||
}
|
||||
cellval = ret.join(", ");
|
||||
return cellval === "" ? $.fn.fmatter.defaultFormat(cellval,opts) : cellval;
|
||||
};
|
||||
$.fn.fmatter.rowactions = function(act) {
|
||||
var $tr = $(this).closest("tr.jqgrow"),
|
||||
rid = $tr.attr("id"),
|
||||
$id = $(this).closest("table.ui-jqgrid-btable").attr('id').replace(/_frozen([^_]*)$/,'$1'),
|
||||
$grid = $("#"+$id),
|
||||
$t = $grid[0],
|
||||
p = $t.p,
|
||||
cm = p.colModel[$.jgrid.getCellIndex(this)],
|
||||
$actionsDiv = cm.frozen ? $("tr#"+rid+" td:eq("+$.jgrid.getCellIndex(this)+") > div",$grid) :$(this).parent(),
|
||||
op = {
|
||||
extraparam: {}
|
||||
},
|
||||
saverow = function(rowid, res) {
|
||||
if($.isFunction(op.afterSave)) { op.afterSave.call($t, rowid, res); }
|
||||
$actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
|
||||
$actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
|
||||
},
|
||||
restorerow = function(rowid) {
|
||||
if($.isFunction(op.afterRestore)) { op.afterRestore.call($t, rowid); }
|
||||
$actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
|
||||
$actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
|
||||
};
|
||||
|
||||
if (cm.formatoptions !== undefined) {
|
||||
op = $.extend(op,cm.formatoptions);
|
||||
}
|
||||
if (p.editOptions !== undefined) {
|
||||
op.editOptions = p.editOptions;
|
||||
}
|
||||
if (p.delOptions !== undefined) {
|
||||
op.delOptions = p.delOptions;
|
||||
}
|
||||
if ($tr.hasClass("jqgrid-new-row")){
|
||||
op.extraparam[p.prmNames.oper] = p.prmNames.addoper;
|
||||
}
|
||||
var actop = {
|
||||
keys: op.keys,
|
||||
oneditfunc: op.onEdit,
|
||||
successfunc: op.onSuccess,
|
||||
url: op.url,
|
||||
extraparam: op.extraparam,
|
||||
aftersavefunc: saverow,
|
||||
errorfunc: op.onError,
|
||||
afterrestorefunc: restorerow,
|
||||
restoreAfterError: op.restoreAfterError,
|
||||
mtype: op.mtype
|
||||
};
|
||||
switch(act)
|
||||
{
|
||||
case 'edit':
|
||||
$grid.jqGrid('editRow', rid, actop);
|
||||
$actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").hide();
|
||||
$actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").show();
|
||||
$grid.triggerHandler("jqGridAfterGridComplete");
|
||||
break;
|
||||
case 'save':
|
||||
if ($grid.jqGrid('saveRow', rid, actop)) {
|
||||
$actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
|
||||
$actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
|
||||
$grid.triggerHandler("jqGridAfterGridComplete");
|
||||
}
|
||||
break;
|
||||
case 'cancel' :
|
||||
$grid.jqGrid('restoreRow', rid, restorerow);
|
||||
$actionsDiv.find("div.ui-inline-edit,div.ui-inline-del").show();
|
||||
$actionsDiv.find("div.ui-inline-save,div.ui-inline-cancel").hide();
|
||||
$grid.triggerHandler("jqGridAfterGridComplete");
|
||||
break;
|
||||
case 'del':
|
||||
$grid.jqGrid('delGridRow', rid, op.delOptions);
|
||||
break;
|
||||
case 'formedit':
|
||||
$grid.jqGrid('setSelection', rid);
|
||||
$grid.jqGrid('editGridRow', rid, op.editOptions);
|
||||
break;
|
||||
}
|
||||
};
|
||||
$.fn.fmatter.actions = function(cellval,opts) {
|
||||
var op={keys:false, editbutton:true, delbutton:true, editformbutton: false},
|
||||
rowid=opts.rowId, str="",ocl,
|
||||
nav = $.jgrid.getRegional(this, 'nav'),
|
||||
classes = $.jgrid.styleUI[(opts.styleUI || 'jQueryUI')].fmatter,
|
||||
common = $.jgrid.styleUI[(opts.styleUI || 'jQueryUI')].common;
|
||||
if(opts.colModel.formatoptions !== undefined) {
|
||||
op = $.extend(op,opts.colModel.formatoptions);
|
||||
}
|
||||
if(rowid === undefined || $.fmatter.isEmpty(rowid)) {return "";}
|
||||
var hover = "onmouseover=jQuery(this).addClass('" + common.hover +"'); onmouseout=jQuery(this).removeClass('" + common.hover +"'); ";
|
||||
if(op.editformbutton){
|
||||
ocl = "id='jEditButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'formedit'); " + hover;
|
||||
str += "<div title='"+nav.edittitle+"' style='float:left;cursor:pointer;' class='ui-pg-div ui-inline-edit' "+ocl+"><span class='" + common.icon_base +" "+classes.icon_edit +"'></span></div>";
|
||||
} else if(op.editbutton){
|
||||
ocl = "id='jEditButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'edit'); " + hover;
|
||||
str += "<div title='"+nav.edittitle+"' style='float:left;cursor:pointer;' class='ui-pg-div ui-inline-edit' "+ocl+"><span class='" + common.icon_base +" "+classes.icon_edit +"'></span></div>";
|
||||
}
|
||||
if(op.delbutton) {
|
||||
ocl = "id='jDeleteButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'del'); " + hover;
|
||||
str += "<div title='"+nav.deltitle+"' style='float:left;' class='ui-pg-div ui-inline-del' "+ocl+"><span class='" + common.icon_base +" "+classes.icon_del +"'></span></div>";
|
||||
}
|
||||
ocl = "id='jSaveButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'save'); " + hover;
|
||||
str += "<div title='"+nav.savetitle+"' style='float:left;display:none' class='ui-pg-div ui-inline-save' "+ocl+"><span class='" + common.icon_base +" "+classes.icon_save +"'></span></div>";
|
||||
ocl = "id='jCancelButton_"+rowid+"' onclick=jQuery.fn.fmatter.rowactions.call(this,'cancel'); " + hover;
|
||||
str += "<div title='"+nav.canceltitle+"' style='float:left;display:none;' class='ui-pg-div ui-inline-cancel' "+ocl+"><span class='" + common.icon_base +" "+classes.icon_cancel +"'></span></div>";
|
||||
return "<div style='margin-left:8px;'>" + str + "</div>";
|
||||
};
|
||||
$.unformat = function (cellval,options,pos,cnt) {
|
||||
// specific for jqGrid only
|
||||
var ret, formatType = options.colModel.formatter,
|
||||
op =options.colModel.formatoptions || {}, sep,
|
||||
re = /([\.\*\_\'\(\)\{\}\+\?\\])/g,
|
||||
unformatFunc = options.colModel.unformat||($.fn.fmatter[formatType] && $.fn.fmatter[formatType].unformat);
|
||||
if(unformatFunc !== undefined && $.isFunction(unformatFunc) ) {
|
||||
ret = unformatFunc.call(this, $(cellval).text(), options, cellval);
|
||||
} else if(formatType !== undefined && $.fmatter.isString(formatType) ) {
|
||||
var opts = $.jgrid.getRegional(this, 'formatter') || {}, stripTag;
|
||||
switch(formatType) {
|
||||
case 'integer' :
|
||||
op = $.extend({},opts.integer,op);
|
||||
sep = op.thousandsSeparator.replace(re,"\\$1");
|
||||
stripTag = new RegExp(sep, "g");
|
||||
ret = $(cellval).text().replace(stripTag,'');
|
||||
break;
|
||||
case 'number' :
|
||||
op = $.extend({},opts.number,op);
|
||||
sep = op.thousandsSeparator.replace(re,"\\$1");
|
||||
stripTag = new RegExp(sep, "g");
|
||||
ret = $(cellval).text().replace(stripTag,"").replace(op.decimalSeparator,'.');
|
||||
break;
|
||||
case 'currency':
|
||||
op = $.extend({},opts.currency,op);
|
||||
sep = op.thousandsSeparator.replace(re,"\\$1");
|
||||
stripTag = new RegExp(sep, "g");
|
||||
ret = $(cellval).text();
|
||||
if (op.prefix && op.prefix.length) {
|
||||
ret = ret.substr(op.prefix.length);
|
||||
}
|
||||
if (op.suffix && op.suffix.length) {
|
||||
ret = ret.substr(0, ret.length - op.suffix.length);
|
||||
}
|
||||
ret = ret.replace(stripTag,'').replace(op.decimalSeparator,'.');
|
||||
break;
|
||||
case 'checkbox':
|
||||
var cbv = (options.colModel.editoptions) ? options.colModel.editoptions.value.split(":") : ["Yes","No"];
|
||||
ret = $('input',cellval).is(":checked") ? cbv[0] : cbv[1];
|
||||
break;
|
||||
case 'select' :
|
||||
ret = $.unformat.select(cellval,options,pos,cnt);
|
||||
break;
|
||||
case 'actions':
|
||||
return "";
|
||||
default:
|
||||
ret= $(cellval).text();
|
||||
}
|
||||
}
|
||||
return ret !== undefined ? ret : cnt===true ? $(cellval).text() : $.jgrid.htmlDecode($(cellval).html());
|
||||
};
|
||||
$.unformat.select = function (cellval,options,pos,cnt) {
|
||||
// Spacial case when we have local data and perform a sort
|
||||
// cnt is set to true only in sortDataArray
|
||||
var ret = [];
|
||||
var cell = $(cellval).text();
|
||||
if(cnt===true) {return cell;}
|
||||
var op = $.extend({}, options.colModel.formatoptions !== undefined ? options.colModel.formatoptions: options.colModel.editoptions),
|
||||
sep = op.separator === undefined ? ":" : op.separator,
|
||||
delim = op.delimiter === undefined ? ";" : op.delimiter;
|
||||
|
||||
if(op.value){
|
||||
var oSelect = op.value,
|
||||
msl = op.multiple === true ? true : false,
|
||||
scell = [], sv;
|
||||
if(msl) {scell = cell.split(",");scell = $.map(scell,function(n){return $.trim(n);});}
|
||||
if ($.fmatter.isString(oSelect)) {
|
||||
var so = oSelect.split(delim), j=0, i;
|
||||
for(i=0; i<so.length;i++){
|
||||
sv = so[i].split(sep);
|
||||
if(sv.length > 2 ) {
|
||||
sv[1] = $.map(sv,function(n,i){if(i>0) {return n;}}).join(sep);
|
||||
}
|
||||
if(msl) {
|
||||
if($.inArray($.trim(sv[1]),scell)>-1) {
|
||||
ret[j] = sv[0];
|
||||
j++;
|
||||
}
|
||||
} else if($.trim(sv[1]) === $.trim(cell)) {
|
||||
ret[0] = sv[0];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if($.fmatter.isObject(oSelect) || $.isArray(oSelect) ){
|
||||
if(!msl) {scell[0] = cell;}
|
||||
ret = $.map(scell, function(n){
|
||||
var rv;
|
||||
$.each(oSelect, function(i,val){
|
||||
if (val === n) {
|
||||
rv = i;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if( rv !== undefined ) {return rv;}
|
||||
});
|
||||
}
|
||||
return ret.join(", ");
|
||||
}
|
||||
return cell || "";
|
||||
};
|
||||
$.unformat.date = function (cellval, opts) {
|
||||
var op = $.jgrid.getRegional(this, 'formatter.date') || {};
|
||||
if(opts.formatoptions !== undefined) {
|
||||
op = $.extend({},op,opts.formatoptions);
|
||||
}
|
||||
if(!$.fmatter.isEmpty(cellval)) {
|
||||
return $.jgrid.parseDate.call(this, op.newformat,cellval,op.srcformat,op);
|
||||
}
|
||||
return $.fn.fmatter.defaultFormat(cellval, opts);
|
||||
};
|
||||
//module end
|
||||
}));
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,48 @@
|
|||
#!/mod/bin/jimsh
|
||||
######
|
||||
# FlexView - Load flexview cofig in jqGrid JSON format
|
||||
# Author: MymsMan, 2016
|
||||
######
|
||||
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class settings.class
|
||||
|
||||
# logging options
|
||||
if {[lindex $argv 0] eq "-d"} {
|
||||
set argv [lrange $argv 1 end]
|
||||
set loglevel 2
|
||||
} else {
|
||||
# Use same logging option as auto log
|
||||
set settings [settings]
|
||||
set loglevel [$settings _nval_setting "autolog"]
|
||||
}
|
||||
|
||||
|
||||
proc log {msg {level 2}} {
|
||||
if {$level > $::loglevel} return
|
||||
system plog flexview $msg
|
||||
}
|
||||
|
||||
httpheader "application/json"
|
||||
|
||||
set start [clock milliseconds]
|
||||
set name [cgi_get name "default"]
|
||||
|
||||
set fname "/mod/etc/fvConfig_$name.json"
|
||||
if {[catch {set fd [open $fname r]
|
||||
set fvconfig [read $fd]
|
||||
puts $fvconfig
|
||||
$fd close} msg opts]} {
|
||||
log "Config file error caught: $msg $opts" 0
|
||||
puts "{\"errmsg\": \"File load error $msg\"}"
|
||||
}
|
||||
|
||||
[settings new] _tval_setting "fvConfig" $name
|
||||
|
||||
set end [clock milliseconds]
|
||||
set elapse $(double($end-$start)/1000.0)
|
||||
log "Load | $elapse | $fname" 0
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
menuitem \
|
||||
"Flexible View" \
|
||||
"/plugin/flexview/img/flexview.png" \
|
||||
"/go/flexview"
|
||||
# "/plugin/flexview/index.jim"
|
||||
|
|
@ -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);
|
|
@ -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);
|
|
@ -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);
|
|
@ -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();
|
||||
});
|
|
@ -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 */
|
|
@ -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
|
||||
}
|
||||
);
|
|
@ -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; }
|
|
@ -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; }
|
|
@ -0,0 +1,342 @@
|
|||
/*
|
||||
* 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", {
|
||||
options: {
|
||||
sortable: true,
|
||||
searchable: true,
|
||||
doubleClickable: true,
|
||||
animated: 'fast',
|
||||
show: 'slideDown',
|
||||
hide: 'slideUp',
|
||||
dividerLocation: 0.6,
|
||||
availableFirst: false,
|
||||
nodeComparator: function(node1,node2) {
|
||||
var text1 = node1.text(),
|
||||
text2 = node2.text();
|
||||
return text1 == text2 ? 0 : (text1 < text2 ? -1 : 1);
|
||||
}
|
||||
},
|
||||
_create: 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>')[this.options.availableFirst?'prependTo': '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';
|
||||
}
|
||||
this.useProp = !!$.fn.prop;
|
||||
// init lists
|
||||
this._populateLists(this.element.find('option'));
|
||||
|
||||
// make selection sortable
|
||||
if (this.options.sortable) {
|
||||
this.selectedList.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')[ this.useProp ? 'prop' : '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
|
||||
this.container.find(".remove-all").click(function() {
|
||||
that._populateLists(that.element.find('option').removeAttr('selected'));
|
||||
return false;
|
||||
});
|
||||
|
||||
this.container.find(".add-all").click(function() {
|
||||
var options = that.element.find('option').not(":selected");
|
||||
if (that.availableList.children('li:hidden').length > 1) {
|
||||
that.availableList.children('li').each(function(i) {
|
||||
if ($(this).is(":visible")) $(options[i-1])[ that.useProp ? 'prop' : 'attr' ]('selected', true);
|
||||
});
|
||||
} else {
|
||||
options[ that.useProp ? 'prop' : 'attr' ]('selected', true);
|
||||
}
|
||||
that._populateLists(that.element.find('option'));
|
||||
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();
|
||||
that._filter.apply(this.availableContainer.find('input.search'), [that.availableList]);
|
||||
},
|
||||
_updateCount: function() {
|
||||
this.element.trigger('change');
|
||||
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(false,false);
|
||||
clone.data('optionLink', clonee.data('optionLink'));
|
||||
clone.data('idx', clonee.data('idx'));
|
||||
return clone;
|
||||
},
|
||||
_setSelected: function(item, selected) {
|
||||
item.data('optionLink')[ this.useProp ? 'prop' : '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._registerDoubleClickEvents(item);
|
||||
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();
|
||||
});
|
||||
}
|
||||
},
|
||||
_registerDoubleClickEvents: function(elements) {
|
||||
if (!this.options.doubleClickable) return;
|
||||
elements.dblclick(function(ev) {
|
||||
if ($(ev.target).closest('.action').length === 0) {
|
||||
// This may be triggered with rapid clicks on actions as well. In that
|
||||
// case don't trigger an additional click.
|
||||
elements.find('a.action').click();
|
||||
}
|
||||
});
|
||||
},
|
||||
_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
|
||||
if (this.options.sortable) {
|
||||
elements.each(function() {
|
||||
$(this).parent().draggable({
|
||||
connectToSortable: that.selectedList,
|
||||
helper: function() {
|
||||
var selectedItem = that._cloneWithData($(this)).width($(this).width() - 50);
|
||||
selectedItem.width($(this).width());
|
||||
return selectedItem;
|
||||
},
|
||||
appendTo: that.container,
|
||||
containment: that.container,
|
||||
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, {
|
||||
locale: {
|
||||
addAll:'Add all',
|
||||
removeAll:'Remove all',
|
||||
itemsCount:'items selected'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})(jQuery);
|
|
@ -0,0 +1,50 @@
|
|||
#!/mod/bin/jimsh
|
||||
######
|
||||
# FlexView - Save flexview cofig in jqGrid JSON format
|
||||
# Author: MymsMan, 2016
|
||||
######
|
||||
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class settings.class
|
||||
|
||||
# logging options
|
||||
if {[lindex $argv 0] eq "-d"} {
|
||||
set argv [lrange $argv 1 end]
|
||||
set loglevel 2
|
||||
} else {
|
||||
# Use same logging option as auto log
|
||||
set settings [settings]
|
||||
set loglevel [$settings _nval_setting "autolog"]
|
||||
}
|
||||
|
||||
|
||||
proc log {msg {level 2}} {
|
||||
if {$level > $::loglevel} return
|
||||
system plog flexview $msg
|
||||
}
|
||||
|
||||
httpheader
|
||||
|
||||
set start [clock milliseconds]
|
||||
set name [cgi_get name "default"]
|
||||
set fvconfig [cgi_get fvconfig "{}"]
|
||||
|
||||
set fname "/mod/etc/fvConfig_$name.json"
|
||||
if {[catch {set fd [open $fname w]
|
||||
puts $fd $fvconfig
|
||||
close $fd
|
||||
puts "Saved configuration- $name<br>"} msg opts] } {
|
||||
log "Config file error caught: $msg $opts" 0
|
||||
puts "<b>File save error $msg</b><br>"
|
||||
}
|
||||
|
||||
source /mod/webif/plugin/flexview/configlist.jim
|
||||
genConfigList
|
||||
[settings new] _tval_setting "fvConfig" $name
|
||||
set end [clock milliseconds]
|
||||
set elapse $(double($end-$start)/1000.0)
|
||||
log "Save | $elapse | $fname" 0
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,106 @@
|
|||
.fvIcon {
|
||||
vertical-align: center;
|
||||
height: 21px;
|
||||
}
|
||||
#flcell {
|
||||
vertical-align: top;
|
||||
}
|
||||
#dircell {
|
||||
vertical-align: top;
|
||||
}
|
||||
.ui-resizable-helper {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
#resize {
|
||||
background-color: #ccc;
|
||||
}
|
||||
#paste {
|
||||
display: none
|
||||
}
|
||||
|
||||
/* change grid z-index so it is lower than top menu pull downs */
|
||||
.ui-jqgrid {
|
||||
z-index: 20;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
/* stop text bottom being cut off */
|
||||
.ui-jqgrid .ui-jqgrid-sortable { height:24px !important; }
|
||||
|
||||
/* stop filter boxes overflowing */
|
||||
.ui-search-table select, .ui-search-table input {
|
||||
width: 90% !important;
|
||||
}
|
||||
.ui-jqgrid .ui-search-table .ui-search-oper {
|
||||
width: 10px;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Zebra stripe table in common with other webif displays */
|
||||
/*
|
||||
.ui-jqgrid tr.jqgrow:nth-child(even) {
|
||||
background: #ffffcc;
|
||||
}
|
||||
.ui-jqgrid tr.jqgrow:nth-child(odd) {
|
||||
background: #ccff99;
|
||||
}
|
||||
*/
|
||||
|
||||
#tabcontent
|
||||
{
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.spinner
|
||||
{
|
||||
width: 50%;
|
||||
margin: 10px;
|
||||
height: 20px
|
||||
}
|
||||
|
||||
/* Minimal tabs */
|
||||
/*
|
||||
#tabbar
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
#tabbar .ui-widget-header
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 1px solid #c0c0c0;
|
||||
-moz-border-radius: 0px;
|
||||
-webkit-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#tabbar .ui-tabs-nav .ui-state-default
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#tabbar .ui-tabs-nav .ui-state-active
|
||||
{
|
||||
background: transparent url(img/uiTabsArrow.png) no-repeat bottom center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#tabbar .ui-tabs-nav .ui-state-default a
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#tabbar .ui-tabs-nav .ui-state-active a
|
||||
{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#tabbar .ui-tabs-panel
|
||||
{
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
tb "/plugin/flexview/img/flexview.png" "Flex View" "/go/flexview"
|
||||
#tb "/plugin/flexview/icon.png" "Flex View" "/plugin/flexview/index.jim"
|
||||
|
Loading…
Reference in New Issue