blob: 2053f39ccf62a41cb3c3ccb3b21d5c63933c1d0d [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001(function () {
2 // Private function
3 function getColumnsForScaffolding(data) {
4 if ((typeof data.length !== 'number') || data.length === 0) {
5 return [];
6 }
7 var columns = [];
8 for (var propertyName in data[0]) {
9 columns.push({ headerText:propertyName, headerTextTrans:propertyName, rowText:propertyName, columnType:propertyName, width:propertyName, sortable:propertyName });
10 }
11 return columns;
12 }
13
14 ko.simpleGrid = {
15 // Defines a view model class you can use to populate a grid
16 viewModel:function (configuration) {
17 var self = this;
18 self.sideNumber = 3; //当前页面左右页码数
19 self.midNumber = 1 + 2 * self.sideNumber; //中间要显示的页码
20 self.allNumber = self.midNumber + 2; //显示完整页码的最大页码
21
22 self.showMenu = false;
23
24 self.className = "table table-striped table-hover ko-grid colorHoverTable " + (configuration.tableClass ? configuration.tableClass : "");
25
26 self.ellipsisLength = 16;
27 self.searchInitStatus = ko.observable();
28 self.searchKey = ko.observable();
29 self.searchColumns = configuration.searchColumns;
30 self.primaryColumn = configuration.primaryColumn;
31 self.showPager = !!configuration.showPager;
32 self.sortField = ko.observable(configuration.defaultSortField);
33 self.sortDirection = ko.observable(configuration.defaultSortDirection);
34 self.data = ko.observableArray(configuration.data);
35 self.pageToGo = ko.observable();
36 self.sortedData = ko.computed(function () {
37 var exp = self.sortField();
38 var dir = self.sortDirection();
39 if (exp && dir) {
40 return self.data().sort(function (a, b) {
41 return dir == "ASC" ? a[exp].localeCompare(b[exp]) : b[exp].localeCompare(a[exp]);
42 });
43 } else {
44 return self.data();
45 }
46 });
47 self.checkedCount = ko.observable(0);
48 self.translate = function () {
49 $(".ko-grid").translate();
50 if ($("#pblist tr").length >0 ){
51 $("#pblist-checkall").removeClass("disable");
52 }else{
53 $("#pblist-checkall").addClass("disable");
54 }
55 };
56
57 self.clearCheck = function () {
58 $("#ko_grid_checkAll").removeAttr("checked");
59 $("#pblist-checkall").removeClass("checkbox_selected");
60 $("p:checkbox[target='pblist-checkall']").removeAttr("checked");
61 $("p[id^='chk__'] ").removeClass("checkbox_selected");
62 $("p[id^='chk__'] :checkbox").removeAttr("checked");
63 self.checkedCount(0);
64 self.translate();
65 };
66
67 self.searchText = ko.computed(function () {
68 self.clearCheck();
69 var text = "";
70 if (!self.searchInitStatus()) {
71 text = $.trim(self.searchKey());
72 }
73 return text;
74 });
75
76 self.afterSearchData = ko.computed(function () {
77 var key = $.trim(self.searchText()).toLowerCase();
78 if (key == "") {
79 return self.sortedData();
80 }
81 else {
82 return _.filter(self.sortedData(), function (item) {
83 for (var i = 0; i < self.searchColumns.length; i++) {
84 var col = self.searchColumns[i];
85 if (item[col].toLowerCase().indexOf(key) != -1) {
86 return true;
87 }
88 }
89 return false;
90 });
91 }
92 });
93 self.currentPageIndex = ko.observable(0);
94 self.pageSize = configuration.pageSize || 5;
95 // If you don't specify columns configuration, we'll use scaffolding
96 self.columns = configuration.columns || getColumnsForScaffolding(ko.utils.unwrapObservable(self.afterSearchData()));
97 self.rowClickHandler = configuration.rowClickHandler;
98 self.hasRowClickHandler = !!configuration.rowClickHandler;
99 self.deleteHandler = configuration.deleteHandler;
100 self.idName = configuration.idName;
101 self.tmplType = configuration.tmplType;
102 self.changeTemplateHandler = configuration.changeTemplateHandler;
103 self.maxPageIndex = ko.computed(function () {
104 return Math.ceil(ko.utils.unwrapObservable(self.afterSearchData()).length / self.pageSize) - 1;
105 });
106 self.radioClickExtend = configuration.radioClickHandler;
107 self.radioChecked4Column = configuration.radioChecked4Column;
108 self.radioChecked4Value = configuration.radioChecked4Value;
109
110 self.fixCurrentPageIndex = function (oldIndex) {
111 if (oldIndex < 0) return 0;
112 var maxIndex = self.maxPageIndex();
113 return oldIndex > maxIndex ? maxIndex : oldIndex;
114 };
115
116 self.pagerStart = ko.computed(function () {
117 var index = self.fixCurrentPageIndex(self.currentPageIndex());
118 var maxIndex = self.maxPageIndex();
119 var retIndex = 0;
120 if (index < self.midNumber || maxIndex <= self.allNumber) {
121 retIndex = 1;
122 } else if (index + self.sideNumber >= maxIndex) {
123 retIndex = maxIndex - self.midNumber;
124 } else {
125 retIndex = index - self.sideNumber;
126 }
127 return retIndex;
128 });
129
130 self.pagerEnd = ko.computed(function () {
131 var index = self.fixCurrentPageIndex(self.currentPageIndex());
132 var maxIndex = self.maxPageIndex();
133 var retIndex = 0;
134 if (index + self.sideNumber >= maxIndex || maxIndex <= self.allNumber) {
135 retIndex = maxIndex - 1;
136 } else if (index < self.midNumber) {
137 retIndex = self.midNumber;
138 } else {
139 retIndex = index + self.sideNumber;
140 }
141 if (maxIndex - retIndex == 2) {
142 retIndex = maxIndex -1;
143 }
144 return retIndex;
145 });
146
147 self.itemsOnCurrentPage = ko.computed(function () {
148 self.translate();
149 var pageIndex = self.fixCurrentPageIndex(self.currentPageIndex());
150 var startIndex = self.pageSize * pageIndex;
151 return self.afterSearchData().slice(startIndex, startIndex + self.pageSize);
152 });
153
154 self.changePage = function (pageIndex) {
155 var pageIndex = self.fixCurrentPageIndex(pageIndex);
156 self.currentPageIndex(pageIndex);
157 self.clearCheck();
158 };
159
160 self.nextPage = function () {
161 var pageIndex = self.fixCurrentPageIndex(self.currentPageIndex() + 1);
162 self.currentPageIndex(pageIndex);
163 self.clearCheck();
164 };
165
166 self.previousPage = function () {
167 var pageIndex = self.fixCurrentPageIndex(self.currentPageIndex() - 1);
168 self.currentPageIndex(pageIndex);
169 self.clearCheck();
170 };
171
172 self.clearAllChecked = function () {
173 $("#pblist-checkall").trigger("click");
174 if ($("#pblist-checkall").hasClass("checkbox_selected")) {
175 $("#pblist-checkall").trigger("click");
176 }
177 }
178
179 self.clickCheckAll = function () {
180 if ($("#pblist-checkall").hasClass("checkbox_selected")) {
181 self.checkedCount(0);
182 } else {
183 var checked = $("#pblist :checkbox").length;
184 self.checkedCount(checked);
185 }
186 };
187
188 self.clickCheck = function (index) {
189 var checkbox = $("#chk__" + index+" :checkbox");
190 if (checkbox.attr("checked")) {
191 checkbox.removeAttr("checked");
192 } else {
193 checkbox.attr("checked", "checked");
194 }
195 checkCheckbox(checkbox);
196
197 var checked = $("#pblist p.checkbox_selected :checkbox").length;
198 self.checkedCount(checked);
199 };
200
201 self.selectedItems = function (type) {
202 var checks;
203 /*if (self.tmplType == 'card') { cov_2
204 checks = $("#pblist :checkbox[checked='checked']");
205 }
206 else {
207 checks = $("#pblist :checkbox[checked='checked']");
208 }*/
209 checks = $("#pblist :checkbox[checked='checked']");
210 var items = [];
211 if (type == "primary") {
212 checks.each(function () {
213 items.push($(this).attr("primaryValue"));
214 });
215 } else {
216 checks.each(function () {
217 items.push($(this).val());
218 });
219 }
220 return items;
221 };
222
223 self.selectedIds = function () {
224 return self.selectedItems("id");
225 };
226
227 self.selectedPrimaryValue = function () {
228 return self.selectedItems("primary");
229 };
230
231 self.radioSelectValue = function () {
232 if ($.browser.msie && event && event.srcElement && event.srcElement.type == "radio") {
233 return event.srcElement.value;
234 }
235 return $("#pblist [name='ko_grid_radio']:checked").val();
236 }
237
238 self.radioSelectedPrimaryValue = function () {
239 if ($.browser.msie && event && event.srcElement && event.srcElement.type == "radio") {
240 return event.srcElement.attribute("primaryValue");
241 }
242 return $("#pblist [name='ko_grid_radio']:checked").attr("primaryValue");
243 }
244
245 self.radioClick = function () {
246 self.checkedCount(self.checkedCount() + 1);
247 }
248
249 self.clearRadioSelect = function () {
250 $("#pblist [name='ko_grid_radio']:checked").removeAttr("checked");
251 self.checkedCount(0);
252 }
253
254 self.setRadioSelect = function (val) {
255 $("#pblist [name='ko_grid_radio'][value='" + val + "']").attr("checked", "checked");
256 self.checkedCount(1);
257 }
258
259 self.sort = function (exp) {
260 if (exp == undefined) {
261 return;
262 }
263 var sortExp = self.sortField();
264 var dir = "ASC";
265 if (exp == sortExp) {
266 dir = (self.sortDirection() == "ASC") ? "DESC" : "ASC";
267 }
268 self.sortField(exp);
269 self.sortDirection(dir);
270
271 self.data(self.data().sort(function (a, b) {
272 return dir == "ASC" ? a[exp].localeCompare(b[exp]) : b[exp].localeCompare(a[exp]);
273 }));
274
275 self.currentPageIndex(0);
276 self.clearCheck();
277
278 $(".ko-grid thead th.ko-grid-th-asc").removeClass("ko-grid-th-asc").addClass("ko-grid-th-sortable");
279 $(".ko-grid thead th.ko-grid-th-desc").removeClass("ko-grid-th-desc").addClass("ko-grid-th-sortable");
280 if (dir == "ASC") {
281 $("#ko_grid_th_" + exp).removeClass().addClass("ko-grid-th-asc");
282 } else {
283 $("#ko_grid_th_" + exp).removeClass().addClass("ko-grid-th-desc");
284 }
285 };
286
287 self.ellipsisText = function (txt) {
288 if (!txt) return "";
289 if ((txt.length * 2) < self.ellipsisLength) {
290 return txt;
291 }
292 var len = 0;
293 for (var i = 0; i < txt.length; i++) {
294 if (txt.charCodeAt(i) > 256) {
295 len += 2;
296 } else {
297 len++;
298 }
299 if (len >= self.ellipsisLength) {
300 return txt.substring(0, i) + "...";
301 }
302 }
303 return txt;
304 };
305 }
306 };
307
308 // Templates used to render the grid
309 var templateEngine = new ko.nativeTemplateEngine();
310
311 templateEngine.addTemplate = function (templateName, templateMarkup) {
312 if ($('#' + templateName)[0]) {
313 $('#' + templateName).remove();
314 }
315 $('#container').append("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "<" + "/script>");
316 };
317
318 // The "simpleGrid" binding
319 ko.bindingHandlers.simpleGrid = {
320 init:function (element, viewModelAccessor) {
321
322 var viewModel = viewModelAccessor();
323 if (viewModel.rowClickHandler == undefined) {
324 viewModel.rowClickHandler = function () {
325 };
326 }
327 if (viewModel.deleteHandler == undefined) {
328 viewModel.deleteHandler = function () {
329 };
330 }
331 if (viewModel.radioClickExtend == undefined) {
332 viewModel.radioClickHandler = function(){
333 viewModel.radioClick();
334 return true;
335 }
336 } else {
337 viewModel.radioClickHandler = function () {
338 viewModel.radioClick();
339 viewModel.radioClickExtend();
340 return true;
341 }
342 }
343
344
345 ko.utils.arrayMap(viewModel.columns, function (item) {
346 if (item.columnType == undefined) {
347 item.columnType = 'text';
348 }
349 if (item.sortable == undefined) {
350 item.sortable = false;
351 }
352 if (item.headerTextTrans == undefined) {
353 item.headerTextTrans = '';
354 }
355 if (item.display == undefined) {
356 item.display = true;
357 }
358 if (item.needTrans == undefined) {
359 item.needTrans = false;
360 }
361 });
362
363 if (viewModel.tmplType == 'card') {
364 templateEngine.addTemplate("ko_simpleGrid_grid", "\
365 <div class='ko-grid-container'>\
366 <div class='ko-grid-menu' data-bind='visible:showMenu'>\
367 <div class='ko-grid-option'>\
368 <img id='ko_grid_layout' class='cursor-pointer' src='pic/res_list.png' data-bind='click:changeTemplateHandler'/>\
369 <p id=\"pblist-checkall\" target=\"pblist\" class=\"checkbox checkboxToggle\">\
370 <input type='checkbox' id='ko_grid_checkAll' data-bind='visible: tmplType==\"card\"&&data().length>0,click: clickCheckAll' />\
371 </p>\
372 </div>\
373 <div class='clean'></div>\
374 </div>\
375 <div id=\"pblist\" class=\"ko-grid\" data-bind=\"foreach: itemsOnCurrentPage\">\
376 <div class=\"ko-grid-card\" >\
377 <div class=\"ko-grid-card-content\" data-bind=\"foreach: $parent.columns ,click:function(){$root.rowClickHandler($data[$root.idName])}\">\
378 <!-- ko if: display==true -->\
379 <p data-bind=\"attr:{title:typeof rowText == 'function' ? rowText($parent) : $parent[rowText]},text: $root.ellipsisText(typeof rowText == 'function' ? rowText($parent) : $parent[rowText])\"></p>\
380 <!-- /ko -->\
381 </div>\
382 <div class=\"ko-grid-card-delete\" data-bind=\"click:function(){$root.deleteHandler($data[$root.idName]);}\" >×</div>\
383 <div class=\"ko-grid-card-check\" ><p class=\"checkbox\"><input type='checkbox' data-bind='value: $data[$root.idName],attr:{primaryValue:$data[$root.primaryColumn]}' target=\"pblist-checkall\"/></p></div>\
384 </div>\
385 <div>\
386 </div>");
387 } else {
388 templateEngine.addTemplate("ko_simpleGrid_grid", "\
389 <div class='ko-grid-container'>\
390 <div class='ko-grid-menu' data-bind='visible:showMenu'>\
391 <div class='ko-grid-option'>\
392 <img id='ko_grid_layout' class='cursor-pointer' src='pic/res_card.png' data-bind='click:changeTemplateHandler'/>\
393 </div>\
394 <div class='clean'></div>\
395 </div>\
396 <table data-bind=\"attr:{'class':className}\" cellspacing=\"0\" cellspadding='0'>\
397 <thead>\
398 <tr data-bind=\"foreach: columns\" >\
399 <!-- ko if: columnType=='checkbox' -->\
400 <th data-bind='attr:{width:width}, visible: display'>\
401 <p id=\"pblist-checkall\" target=\"pblist\" class=\"checkbox checkboxToggle\" data-bind='click:$root.clickCheckAll'>\
402 <input type='checkbox' id='ko_grid_checkAll'/>\
403 </p>\
404 </th>\
405 <!-- /ko --> \
406 <!-- ko if: columnType=='text' || columnType=='image' -->\
407 <!-- ko if: sortable==true -->\
408 <th data-bind=\"visible: display, css: {'ko-grid-th-sortable':rowText!=$root.sortField(),'ko-grid-th-desc':(rowText==$root.sortField() && 'DESC'==$root.sortDirection()),'ko-grid-th-asc': (rowText==$root.sortField() && 'ASC'==$root.sortDirection())},attr:{id:'ko_grid_th_'+rowText,width:width},click:function(event,data){$root.sort(rowText)}\"><a href='#' data-bind=\"attr:{\'data-trans\': headerTextTrans}\"></a></th>\
409 <!-- /ko --> \
410 <!-- ko if: sortable==false -->\
411 <th nowrap='nowrap' data-bind=\"visible: display, attr:{width:width,\'data-trans\': headerTextTrans}\"></th>\
412 <!-- /ko --> \
413 <!-- /ko --> \
414 <!-- ko if: columnType=='radio' -->\
415 <th nowrap='nowrap' data-bind=\"visible: display, attr:{width:width,\'data-trans\': headerTextTrans}\"></th>\
416 <!-- /ko --> \
417 <!-- ko if: columnType=='button' -->\
418 <th nowrap='nowrap' data-bind=\"visible: display, attr:{width:width,\'data-trans\': headerTextTrans}\"></th>\
419 <!-- /ko --> \
420 </tr>\
421 </thead>\
422 <tbody id=\"pblist\" data-bind=\"foreach: itemsOnCurrentPage\">\
423 <tr data-bind=\"foreach: $parent.columns,css:{'odd': $index() % 2==1,'even':$index()%2==0 } \">\
424 <!-- ko if: columnType=='checkbox' -->\
425 <td class = 'ko-grid-center'><p class=\"checkbox\" manualControl='true' data-bind='attr:{id:\"chk__\"+ $parent[rowText]},click:function(){$root.clickCheck($parent[rowText])}'><input type='checkbox' data-bind='value: $parent[rowText],attr:{primaryValue:$parent[$root.primaryColumn]}' target=\"pblist-checkall\"/></p></td>\
426 <!-- /ko --> \
427 <!-- ko if: columnType=='radio' -->\
428 <td class = 'ko-grid-center'><input type='radio' name='ko_grid_radio' data-bind='click:$root.radioClickHandler,value: $parent[rowText],attr:{primaryValue:$parent[$root.primaryColumn]}'/></td>\
429 <!-- /ko --> \
430 <!-- ko if: columnType=='text' && !needTrans -->\
431 <td class = 'ko-grid-center' data-bind=\"visible: display, css:{'cursor-pointer':$root.hasRowClickHandler },text: typeof rowText == 'function' ? rowText($parent) : $parent[rowText], click:function(){$root.rowClickHandler($parent[$root.idName])}\"></td>\
432 <!-- /ko --> \
433 <!-- ko if: columnType=='text' && needTrans -->\
434 <td class = 'ko-grid-center' data-bind=\"visible: display, css:{'cursor-pointer':$root.hasRowClickHandler },click:function(){$root.rowClickHandler($parent[$root.idName])}\">\
435 <span data-bind=\"attr: {\'data-trans\': $parent[rowText]}\"></span>\
436 </td>\
437 <!-- /ko -->\
438 <!-- ko if: columnType=='image' -->\
439 <td class = 'ko-grid-center' data-bind=\"visible: display, css:{'cursor-pointer':$root.hasRowClickHandler },click:function(){$root.rowClickHandler($parent[$root.idName])}\">\
440 <img data-bind=\"attr: {src: $parent[rowText]}\"/>\
441 </td>\
442 <!-- /ko --> \
443 <!-- ko if: columnType=='button' -->\
444 <td class = 'ko-grid-center' data-bind=\"visible: display\"><input type=\"button\" class=\"btn-1 btn-ex\" data-bind=\"visible:$parent[\'btnDisplay\'],enable:$parent[\'enabled\'],attr:{\'data-trans\':$parent[\'actionTrans\']},click:$parent['action']\"/></td>\
445 <!-- /ko --> \
446 </tr>\
447 </tbody>\
448 </table>\
449 </div>");
450 }
451 templateEngine.addTemplate("ko_simpleGrid_pageLinks", "\
452 <div class=\"ko-grid-pageLinks\">\
453 <a class='ko-grid-pager' href='javascript:void(0)' data-bind=\"click:previousPage,enable:$root.fixCurrentPageIndex($root.currentPageIndex())>0,visible:$root.afterSearchData().length>0,css:{'ko-grid-pager-disabled': $root.fixCurrentPageIndex($root.currentPageIndex())==0}\">&lt;&lt;</a>\
454 <a href='javascript:void(0)' data-bind=\"visible:$root.afterSearchData().length>0,text: 1, click: function() { $root.changePage(0); }, css: {'ko-grid-pager-selected': 0 == $root.fixCurrentPageIndex($root.currentPageIndex()),'ko-grid-pager':0 != $root.fixCurrentPageIndex($root.currentPageIndex()) }\"></a>\
455 <span data-bind='visible:pagerStart()>2'>...</span>\
456 <!-- ko foreach: ko.utils.range(pagerStart,pagerEnd) -->\
457 <a href='javascript:void(0)' data-bind=\"text: $data + 1, click: function() { $root.changePage($data); }, disable:$data == $root.fixCurrentPageIndex($root.currentPageIndex()) ,css: {'ko-grid-pager-selected': $data == $root.fixCurrentPageIndex($root.currentPageIndex()),'ko-grid-pager':$data != $root.fixCurrentPageIndex($root.currentPageIndex()) }\"></a>\
458 <!-- /ko -->\
459 <span data-bind='visible:pagerEnd()<maxPageIndex()-2'>...</span>\
460 <a href='javascript:void(0)' data-bind=\"visible:maxPageIndex()>0,text: maxPageIndex()+1, click: function() { $root.changePage(maxPageIndex());}, css: {'ko-grid-pager-selected': maxPageIndex() == $root.fixCurrentPageIndex($root.currentPageIndex()),'ko-grid-pager': maxPageIndex() != $root.fixCurrentPageIndex($root.currentPageIndex()) }\"></a>\
461 <a class='ko-grid-pager' href='javascript:void(0)' data-bind=\"click:nextPage,enable:$root.fixCurrentPageIndex($root.currentPageIndex())<maxPageIndex(),visible:$root.afterSearchData().length>0,css:{'ko-grid-pager-disabled': $root.fixCurrentPageIndex($root.currentPageIndex())==maxPageIndex()}\">&gt;&gt;</a>\
462 <span style='display:none;'><span>(</span><span id='ko_simpleGrid_recordCount' data-bind='text:$root.afterSearchData().length'></span><span>)</span></span>\
463 <div class=\"input-group margin-left-10\" data-bind=\"visible:$root.afterSearchData().length>0\" style='width: 170px;'><label class=\"input-group-addon\" data-trans=\"page\"></label>\
464 <input id=\"ko-grid-input-page\" type=\"text\" data-bind=\"value:pageToGo,valueUpdate: 'afterkeydown'\" class=\"form-control\"/>\
465 <label class=\"input-group-addon cursorhand\" data-trans=\"go\" data-bind=\"click:function() { if(/^[0-9]+$/.test(pageToGo()) && (parseInt(pageToGo())-1) <= maxPageIndex() && (parseInt(pageToGo())-1) >= 0){$root.changePage(parseInt(pageToGo())-1); pageToGo(''); }} \"></label></div>\
466 </div>");
467
468 return { 'controlsDescendantBindings':true };
469 },
470 // This method is called to initialize the node, and will also be called again if you change what the grid is bound to
471 update:function (element, viewModelAccessor, allBindingsAccessor) {
472 var viewModel = viewModelAccessor(), allBindings = allBindingsAccessor();
473
474 // Empty the element
475 while (element.firstChild)
476 ko.removeNode(element.firstChild);
477
478 // Allow the default templates to be overridden
479 var gridTemplateName = allBindings.simpleGridTemplate || "ko_simpleGrid_grid",
480 pageLinksTemplateName = allBindings.simpleGridPagerTemplate || "ko_simpleGrid_pageLinks";
481
482 // Render the main grid
483 var gridContainer = element.appendChild(document.createElement("DIV"));
484 ko.renderTemplate(gridTemplateName, viewModel, { templateEngine:templateEngine }, gridContainer, "replaceNode");
485
486 // Render the page links
487 if (viewModel.showPager) {
488 var pageLinksContainer = element.appendChild(document.createElement("DIV"));
489 ko.renderTemplate(pageLinksTemplateName, viewModel, { templateEngine:templateEngine }, pageLinksContainer, "replaceNode");
490 }
491 }
492 };
493})();