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

source: chrome/content/v_identity/vI_rdfDataTree.js @ 1b97b4

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

backported fixes from 11bcb7373760 - sorting and filter view

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