This is just some static backup of the original site, don't expect every link to work!

source: content/vI_rdfDataTree.js @ 509348

ng_0.9
Last change on this file since 509348 was 509348, checked in by rene <rene@…>, 8 years ago

code formatting (no code changes)

  • Property mode set to 100644
File size: 22.9 KB
Line 
1/* ***** BEGIN LICENSE BLOCK *****
2    This program is free software; you can redistribute it and/or modify
3    it under the terms of the GNU General Public License as published by
4    the Free Software Foundation; either version 2 of the License, or
5    (at your option) any later version.
6
7    This program is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU General Public License for more details.
11
12    You should have received a copy of the GNU General Public License
13    along with this program; if not, write to the Free Software
14    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
15
16    The Original Code is the Virtual Identity Extension.
17
18    The Initial Developer of the Original Code is Rene Ejury.
19    Portions created by the Initial Developer are Copyright (C) 2007
20    the Initial Developer. All Rights Reserved.
21
22    Contributor(s):
23 * ***** END LICENSE BLOCK ***** */
24
25/*  Parts of this code taken from
26    http://developer.mozilla.org/en/docs/Sorting_and_filtering_a_custom_tree_view
27    under MIT license
28    http://www.ibiblio.org/pub/Linux/LICENSES/mit.license
29*/
30
31Components.utils.import("resource://v_identity/vI_nameSpaceWrapper.js");
32virtualIdentityExtension.ns(function () {
33  with(virtualIdentityExtension.LIB) {
34
35    let Log = vI.setupLogging("virtualIdentity.rdfDataTree");
36
37    Components.utils.import("resource://v_identity/vI_identityData.js", virtualIdentityExtension);
38    Components.utils.import("resource://v_identity/vI_rdfDatasource.js", virtualIdentityExtension);
39    Components.utils.import("resource://v_identity/vI_prefs.js", virtualIdentityExtension);
40
41    //prepares an object for easy comparison against another. for strings, lowercases them
42    var prepareForComparison = function (element, field) {
43      if (field == "changedCol") {
44        field = "changed"
45      }
46      if (field == "usedCol") {
47        field = "used"
48      }
49      var o = element[field];
50      if (typeof o == "string") {
51        return o.toLowerCase().replace(/\"/g, "");
52      }
53      return "";
54    };
55
56
57    var rdfDataTree = function (treeType, rdfDatasource) {
58      this.treeType = treeType;
59      this._rdfDatasource = rdfDatasource;
60      this.filterText = "";
61      this.loadTable();
62    };
63
64    rdfDataTree.prototype = {
65      idTable: null,
66      idData: null,
67      filterText: null,
68      treeType: null,
69      _rdfDatasource: null,
70
71      get treeElem() {
72        return document.getElementById("rdfDataTree_" + this.treeType);
73      },
74      get tabElem() {
75        return document.getElementById(this.treeType + "Tab");
76      },
77
78      //this function is called every time the tree is sorted, filtered, or reloaded
79      loadTable: function () {
80        //         Log.debug("loadTable.");
81        //remember scroll position. this is useful if this is an editable table
82        //to prevent the user from losing the row they edited
83        var topVisibleRow = null;
84        if (this.idTable)
85          topVisibleRow = this.treeElem.treeBoxObject.getFirstVisibleRow();
86        if (this.idData == null) {
87          this.idData = [];
88          this._rdfDatasource.readAllEntriesFromRDF(this.addNewDatum, this.treeType, this.idData);
89        }
90        if (this.filterText == "") {
91          //show all of them
92          this.idTable = this.idData;
93        } else {
94          //filter out the ones we want to display
95          var curTable = [];
96          var curFilterText = this.filterText;
97          this.idData.forEach(function (element) {
98            //we'll match on every property
99            for (var i in element) {
100              if (prepareForComparison(element, i).indexOf(curFilterText) != -1) {
101                curTable.push(element);
102                break;
103              }
104            }
105          });
106          this.idTable = curTable;
107        }
108
109        this.sort();
110
111        //restore scroll position
112        if (topVisibleRow && topVisibleRow <= this.idTable.length) {
113          this.treeElem.treeBoxObject.scrollToRow(topVisibleRow);
114        }
115
116        // set Tab label
117        this.tabElem.setAttribute("label", this.treeType + " (" + this.idTable.length + ")");
118        //         Log.debug("loadTable done.");
119      },
120
121      addNewDatum: function (resource, name, localIdentityData, idData, used, changed) {
122        var usedDate = "",
123          changedDate = "";
124        var format = vI.prefroot.getCharPref("extensions.virtualIdentity.storage_timeFormat")
125        if (format != "") {
126          if (used) usedDate = new Date(parseFloat(used)).toLocaleFormat(format);
127          if (changed) changedDate = new Date(parseFloat(changed)).toLocaleFormat(format);
128        } else {
129          if (used) usedDate = new Date(parseFloat(used)).toLocaleString();
130          if (changed) changedDate = new Date(parseFloat(changed)).toLocaleString();
131        }
132        var pref = {
133            recipientCol: name,
134            indexCol: idData.length + 1 + ".",
135            senderCol: localIdentityData.combinedName,
136            smtpCol: localIdentityData.smtp.value,
137            //              smtpKey : localIdentityData.smtp.key,
138            idCol: localIdentityData.id.value,
139            usedCol: usedDate,
140            used: used,
141            changedCol: changedDate,
142            changed: changed,
143            //              idKey : localIdentityData.id.key,
144            resource: resource,
145            identityData: localIdentityData
146          }
147          //        Log.debug("addNewDatum.");
148        localIdentityData.extras.addPrefs(pref);
149        idData.push(pref);
150      },
151      sort: function (columnName) {
152        //      Log.debug("sort: " + columnName);
153        var order = this.treeElem.getAttribute("sortDirection") == "ascending" ? 1 : -1;
154        // if the column is passed and it's already sorted by that column, reverse sort
155        if (columnName && (this.treeElem.getAttribute("sortResource") == columnName)) {
156          order *= -1;
157        }
158
159        function columnSort(a, b) {
160          try {
161            if (prepareForComparison(a, columnName) >
162              prepareForComparison(b, columnName)) return 1 * order;
163            if (prepareForComparison(a, columnName) <
164              prepareForComparison(b, columnName)) return -1 * order;
165          } catch (e) {};
166          return 0;
167        }
168
169        if (!columnName)
170          columnName = this.treeElem.getAttribute("sortResource")
171
172        this.idTable.sort(columnSort);
173
174        //setting these will make the sort option persist
175        this.treeElem.setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
176        this.treeElem.setAttribute("sortResource", columnName);
177
178        this.treeElem.view = new rdfDataTreeCollection.treeView(this.idTable);
179
180        //set the appropriate attributes to show to indicator
181        var cols = this.treeElem.getElementsByTagName("treecol");
182        for (var i = 0; i < cols.length; i++) {
183          cols[i].removeAttribute("sortDirection");
184          if (cols[i].id.match(columnName))
185            cols[i].setAttribute("sortDirection", order == 1 ? "ascending" : "descending");
186        }
187      }
188    };
189
190    var rdfDataTreeCollection = {
191      promptService: Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
192        .getService(Components.interfaces.nsIPromptService),
193
194      treeTypes: Array("email", "maillist", "newsgroup", "filter"),
195
196      trees: {},
197      tabbox: null,
198
199      _strings: null,
200      _rdfDatasource: null,
201
202      onTabSelect: function () {
203        rdfDataTreeCollection.hideInfoBox();
204        if (rdfDataTreeCollection.tabbox) {
205          rdfDataTreeCollection.moveConstraints();
206          rdfDataTreeCollection.updateButtonMenu();
207        }
208      },
209
210      onselect: function () {
211        rdfDataTreeCollection.moveConstraints();
212        rdfDataTreeCollection.updateButtonMenu();
213
214        var tree = rdfDataTreeCollection.trees[rdfDataTreeCollection.tabbox.selectedPanel.id];
215        var htmlBox = document.getElementById("rdfDataTreeCollectionInfoBox")
216        if (tree.treeElem.view.selection.count != 1) {
217          rdfDataTreeCollection.hideInfoBox();
218          return;
219        }
220
221        var identityData = tree.idTable[tree.treeElem.currentIndex]["identityData"];
222        var _identityInfo =
223          "<div id='recipientLabel'>" +
224          tree.idTable[tree.treeElem.currentIndex]["recipientCol"].replace(/>/g, "&gt;").replace(/</g, "&lt;") +
225          "</div><div id='vICard'>" +
226          "<table><tr>" +
227          "<td class='image'><img src='chrome://v_identity/skin/vi-info.png' /></td>" +
228          "<td class='identityTable'>" +
229          "<div class='name'>" + identityData.combinedNameHtml + "</div>" +
230          "<table><tbody>" + identityData.getMatrix() + "</tbody></table>" +
231          "</td>" +
232          "</tr></table></div>"
233
234        htmlBox.outputString = _identityInfo;
235        rdfDataTreeCollection.infoBoxHidden = false;
236        htmlBox.setAttribute("style", "height:" + htmlBox.contentDocument.lastChild.scrollHeight + "px");
237        rdfDataTreeCollection.overflow(); // better resize one time too much, mozilla is still magic  :)
238      },
239
240      init: function () {
241        rdfDataTreeCollection.tabbox = document.getElementById("TreeTabbox");
242        rdfDataTreeCollection._strings = Components.classes["@mozilla.org/intl/stringbundle;1"]
243          .getService(Components.interfaces.nsIStringBundleService)
244          .createBundle("chrome://v_identity/locale/vI_rdfDataEditor.properties");
245
246        rdfDataTreeCollection._rdfDatasource = new vI.rdfDatasource("virtualIdentity.rdf");
247
248        for each(var treeType in rdfDataTreeCollection.treeTypes)
249        rdfDataTreeCollection.trees[treeType] = new rdfDataTree(treeType, rdfDataTreeCollection._rdfDatasource);
250      },
251
252      clean: function () {
253        if (rdfDataTreeCollection._rdfDatasource) rdfDataTreeCollection._rdfDatasource.clean();
254      },
255
256      get _braille() {
257        var braille = false;
258        try {
259          braille = (vI.prefroot.getCharPref("accessibility.usebrailledisplay") ||
260            vI.prefroot.getCharPref("accessibility.usetexttospeech"));
261        } catch (e) {};
262        return braille;
263      },
264
265      // generic custom tree view stuff
266      treeView: function (table) {
267        this.rowCount = table.length;
268        this.getCellText = function (row, col) {
269          var retValue = table[row][col.id.substr(0, col.id.indexOf("_"))];
270          if (!rdfDataTreeCollection._braille && (retValue == "no" || retValue == "yes"))
271            return ""; // image will be used as indicator
272          else return retValue;
273        };
274        this.getCellValue = function (row, col) {
275          return this.getCellText(row, col);
276        };
277        this.setTree = function (treebox) {
278          this.treebox = treebox;
279        };
280        this.isEditable = function (row, col) {
281          return col.editable;
282        };
283        this.isContainer = function (row) {
284          return false;
285        };
286        this.isSeparator = function (row) {
287          return false;
288        };
289        this.isSorted = function () {
290          return false;
291        };
292        this.getLevel = function (row) {
293          return 0;
294        };
295        this.getImageSrc = function (row, col) {
296          return null;
297        };
298        this.getRowProperties = function (row, props) {};
299        this.getCellProperties = function (row, col, props) {};
300        this.getColumnProperties = function (colid, col, props) {};
301        this.cycleHeader = function (col, elem) {
302          var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
303          if (treeType != "filter")
304            rdfDataTreeCollection.trees[treeType].sort(col.id.substr(0, col.id.indexOf("_")));
305        };
306        this.getCellProperties = function (row, col, props) {
307          var returnValue = null;
308          if (!rdfDataTreeCollection._braille) {
309            var aserv = Components.classes["@mozilla.org/atom-service;1"].
310            getService(Components.interfaces.nsIAtomService);
311            if (typeof props == 'undefined') {
312              // Requires Gecko 22
313              switch (table[row][col.id.substr(0, col.id.indexOf("_"))]) {
314              case "yes":
315                returnValue = aserv.getAtom("yes");
316                break;
317              case "no":
318                returnValue = aserv.getAtom("no");
319                break;
320              }
321            } else {
322              // Obsolete since Gecko 22
323              switch (table[row][col.id.substr(0, col.id.indexOf("_"))]) {
324              case "yes":
325                props.AppendElement(aserv.getAtom("yes"));
326                break;
327              case "no":
328                props.AppendElement(aserv.getAtom("no"));
329                break;
330              }
331            }
332          }
333          return returnValue;
334        };
335      },
336
337
338      __setFilter: function (text) {
339        // loop trough all trees
340        for each(var treeType in rdfDataTreeCollection.treeTypes) {
341          var tree = rdfDataTreeCollection.trees[treeType];
342          tree.filterText = text;
343          tree.loadTable();
344        }
345      },
346
347      inputFilter: function (event) {
348        var value = "";
349        if (typeof event.target.value == "string") {
350          value = event.target.value.toLowerCase().replace(/\"/g, "");
351        }
352        rdfDataTreeCollection.__setFilter(value);
353        document.getElementById("clearFilter").disabled = value.length == 0;
354      },
355
356      clearFilter: function () {
357        document.getElementById("clearFilter").disabled = true;
358        var filterElement = document.getElementById("filter");
359        filterElement.focus();
360        filterElement.value = "";
361        rdfDataTreeCollection.__setFilter("");
362      },
363
364      __updateMenu: function (modifySelected, removeSelected) {
365        var tree = rdfDataTreeCollection.trees[rdfDataTreeCollection.tabbox.selectedPanel.id];
366        var noSelections = (tree.treeElem.view.selection.count == 0)
367        modifySelected.setAttribute("disabled", noSelections)
368        removeSelected.setAttribute("disabled", noSelections)
369      },
370
371      updateButtonMenu: function () {
372        rdfDataTreeCollection.__updateMenu(
373          document.getElementById("editButton_" + rdfDataTreeCollection.tabbox.selectedPanel.id),
374          document.getElementById("deleteButton_" + rdfDataTreeCollection.tabbox.selectedPanel.id))
375      },
376
377      updateContextMenu: function () {
378        rdfDataTreeCollection.__updateMenu(
379          document.getElementById("context_modifySelected"),
380          document.getElementById("context_removeSelected"))
381      },
382
383      updateMenu: function () {
384        rdfDataTreeCollection.__updateMenu(
385          document.getElementById("menu_modifySelected"),
386          document.getElementById("menu_removeSelected"))
387      },
388
389      modifySelected: function () {
390        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
391        var tree = rdfDataTreeCollection.trees[treeType];
392        if (tree.treeElem.view.selection.count == 0) return;
393        if (tree.treeElem.view.selection.count > 5) {
394          var warning = rdfDataTreeCollection._strings.GetStringFromName("vI_rdfDataTree.modify.Warning1") + " " +
395            tree.treeElem.view.selection.count + " " +
396            rdfDataTreeCollection._strings.GetStringFromName("vI_rdfDataTree.modify.Warning2")
397          if (!rdfDataTreeCollection.promptService.confirm(window, "Warning", warning)) return;
398        }
399
400        var start = new Object();
401        var end = new Object();
402        var numRanges = tree.treeElem.view.selection.getRangeCount();
403
404        var retVar = {
405          treeType: null
406        };
407        for (var t = 0; t < numRanges; t++) {
408          tree.treeElem.view.selection.getRangeAt(t, start, end);
409          for (var v = start.value; v <= end.value; v++)
410            window.openDialog("chrome://v_identity/content/vI_rdfDataEditor.xul", 0,
411              "chrome, dialog, modal, alwaysRaised, resizable=yes",
412              tree.idTable[v], treeType,
413              rdfDataTreeCollection._rdfDatasource, retVar).focus();
414        }
415
416        // reload all trees (multiple types might have changed)
417        for each(var treeType in rdfDataTreeCollection.treeTypes) {
418          rdfDataTreeCollection.trees[treeType].idData = null;
419          rdfDataTreeCollection.trees[treeType].loadTable()
420        }
421        rdfDataTreeCollection.tabbox.selectedTab = document.getElementById(retVar.treeType + "Tab");
422        rdfDataTreeCollection.hideInfoBox();
423      },
424
425      removeSelected: function () {
426        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
427        var tree = rdfDataTreeCollection.trees[treeType];
428        if (tree.treeElem.view.selection.count == 0) return;
429        var warning = rdfDataTreeCollection._strings.GetStringFromName("vI_rdfDataTree.remove.Warning1") + " " +
430          tree.treeElem.view.selection.count + " " +
431          rdfDataTreeCollection._strings.GetStringFromName("vI_rdfDataTree.remove.Warning2")
432
433        if (!rdfDataTreeCollection.promptService.confirm(window, "Warning", warning)) return;
434
435        var start = new Object();
436        var end = new Object();
437        var numRanges = tree.treeElem.view.selection.getRangeCount();
438
439        for (var t = 0; t < numRanges; t++) {
440          tree.treeElem.view.selection.getRangeAt(t, start, end);
441          for (var v = start.value; v <= end.value; v++) {
442            rdfDataTreeCollection._rdfDatasource.removeVIdentityFromRDF(tree.idTable[v]["resource"], treeType)
443          }
444        }
445
446        tree.idData = null;
447        tree.idTable = null;
448        tree.loadTable();
449        rdfDataTreeCollection.hideInfoBox();
450      },
451
452      moveConstraints: function () {
453        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
454        if (treeType != "filter") return;
455        var tree = rdfDataTreeCollection.trees[treeType];
456        if (tree.treeElem.view.selection.count == 0) {
457          document.getElementById("reorderUpButton_filter").setAttribute("disabled", "true");
458          document.getElementById("reorderDownButton_filter").setAttribute("disabled", "true");
459          return;
460        };
461        var start = new Object();
462        var end = new Object();
463        var numRanges = tree.treeElem.view.selection.getRangeCount();
464        if (numRanges > 1) {
465          document.getElementById("reorderUpButton_filter").setAttribute("disabled", "true");
466          document.getElementById("reorderDownButton_filter").setAttribute("disabled", "true");
467          return;
468        }
469        tree.treeElem.view.selection.getRangeAt(0, start, end);
470        if (start.value > 0)
471          document.getElementById("reorderUpButton_filter").removeAttribute("disabled");
472        else document.getElementById("reorderUpButton_filter").setAttribute("disabled", "true");
473        if (end.value < tree.idTable.length - 1)
474          document.getElementById("reorderDownButton_filter").removeAttribute("disabled");
475        else document.getElementById("reorderDownButton_filter").setAttribute("disabled", "true");
476      },
477
478      moveUpSelected: function () {
479        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
480        if (treeType != "filter") return; // just to be safe, button should be disabled
481        var tree = rdfDataTreeCollection.trees[treeType];
482        if (tree.treeElem.view.selection.count == 0) return; // just to be safe, button should be disabled
483
484        var start = new Object();
485        var end = new Object();
486        var numRanges = tree.treeElem.view.selection.getRangeCount();
487        if (numRanges > 1) return; // just to be safe, button should be disabled
488
489        tree.treeElem.view.selection.getRangeAt(0, start, end);
490        for (var v = start.value; v <= end.value; v++) {
491          var resource = rdfDataTreeCollection._rdfDatasource.filterContainer.RemoveElementAt(v + 1, true);
492          rdfDataTreeCollection._rdfDatasource.filterContainer.InsertElementAt(resource, v, true);
493        }
494        tree.idData = null;
495        tree.idTable = null;
496        tree.loadTable();
497        tree.treeElem.view.selection.rangedSelect(start.value - 1, end.value - 1, false);
498      },
499
500      moveDownSelected: function () {
501        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
502        if (treeType != "filter") return; // just to be safe, button should be disabled
503        var tree = rdfDataTreeCollection.trees[treeType];
504        if (tree.treeElem.view.selection.count == 0) return; // just to be safe, button should be disabled
505
506        var start = new Object();
507        var end = new Object();
508        var numRanges = tree.treeElem.view.selection.getRangeCount();
509        if (numRanges > 1) return; // just to be safe, button should be disabled
510
511        tree.treeElem.view.selection.getRangeAt(0, start, end);
512        for (var v = end.value; v >= start.value; v--) {
513          var resource = rdfDataTreeCollection._rdfDatasource.filterContainer.RemoveElementAt(v + 1, true);
514          rdfDataTreeCollection._rdfDatasource.filterContainer.InsertElementAt(resource, v + 2, true);
515        }
516        tree.idData = null;
517        tree.idTable = null;
518        tree.loadTable();
519        tree.treeElem.view.selection.rangedSelect(start.value + 1, end.value + 1, false);
520      },
521
522      infoBoxHidden: true,
523      overflow: function () {
524        if (rdfDataTreeCollection.infoBoxHidden) return;
525        var htmlBox = document.getElementById("rdfDataTreeCollectionInfoBox")
526        htmlBox.setAttribute("style", "height:" + htmlBox.contentDocument.lastChild.scrollHeight + "px");
527      },
528
529      hideInfoBox: function () {
530        rdfDataTreeCollection.infoBoxHidden = true;
531        document.getElementById("rdfDataTreeCollectionInfoBox").setAttribute("style", "height:0px");
532        for each(var treeType in rdfDataTreeCollection.treeTypes) {
533          try {
534            if (rdfDataTreeCollection.trees[treeType])
535              rdfDataTreeCollection.trees[treeType].treeElem.view.selection.selectNone()
536          } catch (e) {}
537        }
538      },
539
540      selectAll: function () {
541        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
542        var tree = rdfDataTreeCollection.trees[treeType];
543        tree.treeElem.view.selection.selectAll();
544      },
545
546      newItem: function () {
547        var treeType = rdfDataTreeCollection.tabbox.selectedPanel.id;
548        var newItemPreset = {
549          identityData: new vI.identityData("", null, null, vI.NO_SMTP_TAG, null, null)
550        };
551        var retVar = {
552          treeType: null
553        };
554
555        window.openDialog("chrome://v_identity/content/vI_rdfDataEditor.xul", 0,
556          "chrome, dialog, modal, alwaysRaised, resizable=yes",
557          newItemPreset, treeType,
558          rdfDataTreeCollection._rdfDatasource, retVar).focus();
559
560        // reload all trees (multiple types might have changed)
561        for each(var treeType in rdfDataTreeCollection.treeTypes) {
562          rdfDataTreeCollection.trees[treeType].idData = null;
563          rdfDataTreeCollection.trees[treeType].idTable = null;
564          rdfDataTreeCollection.trees[treeType].loadTable()
565        }
566        rdfDataTreeCollection.tabbox.selectedTab = document.getElementById(retVar.treeType + "Tab");
567        rdfDataTreeCollection.hideInfoBox();
568      }
569    };
570
571    vI.rdfDataTreeCollection = rdfDataTreeCollection;
572    vI.rdfDataTree = rdfDataTree;
573  }
574});
Note: See TracBrowser for help on using the repository browser.