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

source: content/vI_rdfDataTree.js

ng_0.9 0.10.3
Last change on this file was 9168c4, checked in by rene <rene@…>, 4 years ago

use extra strftime implementation

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