📄 sel.js
字号:
/* sel.js{{IS_NOTE Purpose: zk.Selectable Description: History: Fri Aug 26 08:45:55 2005, Created by tomyeh}}IS_NOTECopyright (C) 2005 Potix Corporation. All Rights Reserved.{{IS_RIGHT This program is distributed under GPL Version 2.0 in the hope that it will be useful, but WITHOUT ANY WARRANTY.}}IS_RIGHT*/zk.load("zul.zul");//////Customization/** Returns the background color for a list item or tree item. * Developer can override this method by providing a different background. */if (!window.Selectable_effect) { //define it only if not customized window.Selectable_effect = function (row, undo) { if (undo) { zk.rmClass(row, "overseld"); zk.rmClass(row, "overd"); } else zk.addClass(row, zk.hasClass(row, "seld") ? "overseld": "overd"); };}////// Seletable //zk.Selectable = Class.create();zk.Selectable.prototype = { initialize: function (cmp) { this.id = cmp.id; zkau.setMeta(cmp, this); this.qcells = []; this.init(); }, init: function (isLater) { this.element = $e(this.id); if (!this.element) return; if (getZKAttr(this.element, "vflex") == "true") { if (zk.ie) this.element.style.overflow = "hidden"; // added by Jumper for IE to get a correct offsetHeight so we need // to add this command faster than the this._calcSize() function. var hgh = this.element.style.height; if (!hgh || hgh == "auto") this.element.style.height = "99%"; // avoid border 1px; } //_headtbl might be null, while other must be NOT null this.body = $e(this.id + "!body"); if (this.body) { this.bodytbl = zk.firstChild(this.body, "TABLE", true); if (this.bodytbl) { var bds = this.bodytbl.tBodies; if (!bds || !bds.length) this.bodytbl.appendChild(document.createElement("TBODY")); this.bodyrows = bds[0].rows; } this.head = $e(this.id + "!head"); if (this.head) this.headtbl = zk.firstChild(this.head, "TABLE", true); this.foot = $e(this.id + "!foot"); if (this.foot) this.foottbl = zk.firstChild(this.foot, "TABLE", true); } else { this.paging = true; this.body = $e(this.id + "!paging"); this.bodytbl = zk.firstChild(this.body, "TABLE", true); var bs = this.bodytbl.tBodies; for (var j = 0; j < bs.length; ++j) if (bs[j].id) { this.bodyrows = bs[j].rows; break; } } if (!zk.isRealVisible(this.element)) return; if (!this.bodyrows) { alert(mesg.INVALID_STRUCTURE + this.id); return; } var meta = this; //the nested function only see local var if (!this._inited) { this._inited = true; //If Mozilla, we have to eat keystrokes, or the page //will scroll when UP/DOWN is pressed if (zk.gecko) { this.element.onkeydown = this.element.onkeyup = this.element.onkeypress = function (evt) { var target = Event.element(evt); if (zkSel._shallIgnoreEvent(target)) return true; if (evt) { switch (evt.keyCode) { case 33: //PgUp case 34: //PgDn case 38: //UP case 40: //DOWN case 37: //LEFT case 39: //RIGHT case 32: //SPACE case 36: //Home case 35: //End Event.stop(evt); return false; } } return true; }; } if (!this.paging) { this.fnResize = function () {meta.recalcSize(true);}; zk.addOnResize(this.fnResize); } this.form = zk.formOf(this.element); if (this.form) { this.fnSubmit = function () { meta.onsubmit(); }; zk.listen(this.form, "submit", this.fnSubmit); } } if (!this.paging) { //FF: a small fragment is shown //IE: Bug 1775014 if (this.headtbl && this.headtbl.rows.length) { var empty = true; l_out: for (var j = this.headtbl.rows.length; j;) { var headrow = this.headtbl.rows[--j]; for (var k = headrow.cells.length; k;) { var n = $e(headrow.cells[--k].id + "!cave"); // Bug #1819037 for (n = n ? n.firstChild: n; n; n = n.nextSibling) if (!n.id || !n.id.endsWith("!hint")) { empty = false; break l_out; } } } if (empty) this.head.style.height = "0px"; // Bug #1819037 //we have to hide if empty (otherwise, a small block is shown) } this.body.onscroll = function () { if (meta.head) meta.head.scrollLeft = meta.body.scrollLeft; if (meta.foot) meta.foot.scrollLeft = meta.body.scrollLeft; meta._render(zk.gecko ? 200: 60); //Moz has a bug to send the request out if we don't wait long enough //How long is enough is unknown, but 200 seems fine }; } if (isLater && this.qcells.length && this.headtbl && this.headtbl.rows.length && this.bodytbl && this.bodytbl.rows.length > 1) { //recalc is only a few lines zk.cpCellArrayWidth(this.headtbl.rows[0], this.qcells); } else { setTimeout("zkSel._calcSize('"+this.id+"')", 150); // Bug #1813722 this.stripe(); } this.qcells.length = 0; this._render(155); //prolong a bit since calSize might not be ready }, putCellQue: function (cell) {/** no need to check replication, since the server generates one for each for (var j = this.qcells.length; j;) if (this.qcells[--j] == cell) return; //replicate*/ this.qcells.push(cell); }, cleanup: function () { if (this.fnResize) zk.rmOnResize(this.fnResize); if (this.fnSubmit) zk.unlisten(this.form, "submit", this.fnSubmit); this.element = this.body = this.head = this.bodytbl = this.headtbl this.foot = this.foottbl = this.fnSubmit = this.qcells = null; //in case: GC not works properly }, /** Stripes the rows. */ stripe: function () { var scOdd = getZKAttr(this.element, "scOddRow"); if (!scOdd || !this.bodyrows) return; for (var j = 0, even = true; j < this.bodyrows.length; ++j) { var row = this.bodyrows[j]; if ($visible(row)) { zk.addClass(row, scOdd, !even); even = !even; } } }, /** Handles keydown sent to the body. */ dobodykeydown: function (evt, target) { if (zkSel._shallIgnoreEvent(target)) return true; // Note: We don't intercept body's onfocus to gain focus back to anchor. // Otherwise, it cause scroll problem on IE: // When user clicks on the scrollbar, it scrolls first and call onfocus, // then it will scroll back to the focus because _focusToAnc is called switch (evt.keyCode) { case 33: //PgUp case 34: //PgDn case 38: //UP case 40: //DOWN case 37: //LEFT case 39: //RIGHT case 32: //SPACE case 36: //Home case 35: //End if ($tag(target) != "A") this._refocus(); Event.stop(evt); return false; } return true; }, /** Handles the keydown sent to the row. */ dokeydown: function (evt, target) { if (zkSel._shallIgnoreEvent(target)) return true; var row = $tag(target) == "TR" ? target: zk.parentNode(target, "TR"); if (!row) return true; var shift = evt.shiftKey, ctrl = evt.ctrlKey; if (shift && !this._isMultiple()) shift = false; //OK to var endless = false, step, lastrow; switch (evt.keyCode) { case 33: //PgUp case 34: //PgDn step = this.realsize(); if (step == 0) step = 20; if (evt.keyCode == 33) step = -step; break; case 38: //UP case 40: //DOWN step = evt.keyCode == 40 ? 1: -1; break; case 32: //SPACE if (this._isMultiple()) this.toggleSelect(row, !this._isSelected(row)); else this.select(row); break; case 36: //Home case 35: //End step = evt.keyCode == 35 ? 1: -1; endless = true; break; case 37: //LEFT this._doLeft(row); break; case 39: //RIGHT this._doRight(row); break; } if (step) { if (shift) this.toggleSelect(row, true); for (; (row = step > 0 ? row.nextSibling: row.previousSibling) != null;) { if ($tag(row) == "TR" && this._isValid(row)) { if (shift) this.toggleSelect(row, true); if ($visible(row)) { if (!shift) lastrow = row; if (!endless) { if (step > 0) --step; else ++step; if (step == 0) break; } } } } } if (lastrow) { if (ctrl) this.focus(lastrow); else this.select(lastrow); } switch (evt.keyCode) { case 33: //PgUp case 34: //PgDn case 38: //UP case 40: //DOWN case 37: //LEFT case 39: //RIGHT case 32: //SPACE case 36: //Home case 35: //End Event.stop(evt); return false; } return true; }, /** Do when the left key is pressed. */ _doLeft: function (row) { }, /** Do when the right key is pressed. */ _doRight: function (row) { }, /** Returns the type of the row. */ _rowType: function () { return "Lit"; }, doclick: function (evt, target) { if (zkSel._shallIgnoreEvent(target)) return; var tn = $tag(target); if((tn != "TR" && target.onclick) || (tn == "A" && !target.id.endsWith("!sel")) || getZKAttr(target, "lfclk") || getZKAttr(target, "dbclk")) return; var checkmark = target.id && target.id.endsWith("!cm"); var row = tn == "TR" ? target: zk.parentNode(target, "TR"); if (!row || $type(row) != this._rowType()) return; //incomplete structure or grid in listbox... //It is better not to change selection only if dragging selected //(like Windows does) //However, FF won't fire onclick if dragging, so the spec is //not to change selection if dragging (selected or not) if (zk.dragging /*&& this._isSelected(row)*/) return; if (checkmark) { if (this._isMultiple()) { this.toggleSelect(row, target.checked); } else { this.select(row); } } else { //Bug 1650540: double click as select again //Note: we don't handle if clicking on checkmark, since FF always //toggle and it causes incosistency if ((zk.gecko || zk.safari) && getZKAttr(row, "dbclk")) { var now = $now(), last = row._last; row._last = now; if (last && now - last < 900) return; //ignore double-click } if (this._isMultiple()) { if (evt && evt.shiftKey) { this.selectUpto(row); } else if (evt && evt.ctrlKey) { this.toggleSelect(row, !this._isSelected(row)); } else { //Note: onclick means toggle if checkmark is enabled //Otherwise, we mimic Windows if checkmark is disabled var el = $e(row.id + "!cm"); if (el) this.toggleSelect(row, !el.checked); else this.select(row); } } else { this.select(row); } //since row might was selected, we always enfoce focus here this._focusToAnc(row); //if (evt) Event.stop(evt); //No much reason to eat the event. //Oppositely, it disabled popup (bug 1578659) } }, /** Returns # of rows allowed. */ size: function () { var sz = getZKAttr(this.element, "size"); return sz ? $int(sz): 0; }, /** Returns the real # of rows (aka., real size). */ realsize: function (v) { if ("number" == typeof v) { this.element.setAttribute("zk_realsize", v); } else { var sz = this.size(); if (sz) return sz; sz = this.element.getAttribute("zk_realsize"); return sz ? $int(sz): 0; } }, /** Re-setfocus to the anchor who shall be in focus. */ _refocus: function () { for (var j = 0; j < this.bodyrows.length; ++j) { var r = this.bodyrows[j]; if (this._isFocus(r)) this._focusToAnc(r); } }, /** Process the setAttr command sent from the server. */ setAttr: function (nm, val) { switch (nm) { case "z.innerWidth": if (this.headtbl) this.headtbl.style.width = val; if (this.bodytbl) this.headtbl.style.width = val; if (this.foottbl) this.headtbl.style.width = val; return true; case "select": //select by uuid var row = $e(val); this._selectOne(row, false); zk.scrollIntoView(this.body, row); return true; case "selectAll": this._selectAll(); return true; //no more processing case "z.multiple": //whether to support multiple this._setMultiple("true" == val); return true; case "chgSel": //val: a list of uuid to select var sels = {}; for (var j = 0;;) { var k = val.indexOf(',', j); var s = (k >= 0 ? val.substring(j, k): val.substring(j)).trim(); if (s) sels[s] = true; if (k < 0) break; j = k + 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -