source: Dev/branches/rest-dojo-ui/client/dojox/atom/widget/FeedViewer.js @ 256

Last change on this file since 256 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 23.8 KB
Line 
1define([
2        "dojo/_base/kernel",
3        "dojo/_base/lang",
4        "dojo/_base/array",
5        "dojo/_base/connect",
6        "dojo/dom-class",
7        "dijit/_Widget",
8        "dijit/_Templated",
9        "dijit/_Container",
10        "../io/Connection",
11        "dojo/text!./templates/FeedViewer.html",
12        "dojo/text!./templates/FeedViewerEntry.html",
13        "dojo/text!./templates/FeedViewerGrouping.html",
14        "dojo/i18n!./nls/FeedViewerEntry",
15        "dojo/_base/declare"
16], function (dojo, lang, arrayUtil, connect, domClass, _Widget, _Templated, _Container, Connection, template, entryTemplate, groupingTemplate, i18nViewer) {
17dojo.experimental("dojox.atom.widget.FeedViewer");
18
19var widget = dojo.getObject("dojox.atom.widget", true);
20
21widget.FeedViewer = dojo.declare(/*===== "dojox.atom.widget.FeedViewer", =====*/ [_Widget, _Templated, _Container],{
22        //      summary:
23        //              An ATOM feed viewer that allows for viewing a feed, deleting entries, and editing entries.
24        //      description:
25        //              An ATOM feed viewer that allows for viewing a feed, deleting entries, and editing entries.
26        feedViewerTableBody: null,      //The body of the feed viewer table so we can access it and populate it.  Will be assigned via template.
27        feedViewerTable: null,          //The overal table container which contains the feed viewer table.  Will be assigned via template.
28        entrySelectionTopic: "",        //The topic to broadcast when any entry is clicked so that a listener can pick up it and display it.
29        url: "",                                        //The URL to which to connect to initially on creation.
30        xmethod: false,
31        localSaveOnly: false,
32
33        //Templates for the HTML rendering.  Need to figure these out better, admittedly.
34        templateString: template,
35
36        _feed: null,
37        _currentSelection: null, // Currently selected entry
38
39        _includeFilters: null,
40
41        alertsEnabled: false,
42
43        postCreate: function(){
44                //      summary:
45                //              The postCreate function.
46                //      description:
47                //              The postCreate function.  Creates our AtomIO object for future interactions and subscribes to the
48                //              event given in markup/creation.
49                this._includeFilters = [];
50
51                if(this.entrySelectionTopic !== ""){
52                        this._subscriptions = [dojo.subscribe(this.entrySelectionTopic, this, "_handleEvent")];
53                }
54                this.atomIO = new Connection();
55                this.childWidgets = [];
56        },
57       
58        startup: function(){
59                //      summary:
60                //              The startup function.
61                //      description:
62                //              The startup function.  Parses the filters and sets the feed based on the given url.
63                this.containerNode = this.feedViewerTableBody;
64                var children = this.getDescendants();
65                for(var i in children){
66                        var child = children[i];
67                        if(child && child.isFilter){
68                                this._includeFilters.push(new widget.FeedViewer.CategoryIncludeFilter(child.scheme, child.term, child.label));
69                                child.destroy();
70                        }
71                }
72               
73                if(this.url !== ""){
74                        this.setFeedFromUrl(this.url);
75                }
76        },
77
78        clear: function(){
79                //      summary:
80                //              Function clearing all current entries in the feed view.
81                //      description:
82                //              Function clearing all current entries in the feed view.
83                //
84                //      returns:
85                //              Nothing.
86                this.destroyDescendants();
87        },
88
89        setFeedFromUrl: function(/*string*/url){
90                //      summary:
91                //              Function setting the feed from a URL which to get the feed.
92                //      description:
93                //              Function setting the dojox.atom.io.model.Feed data into the view.
94                //
95                //      url:
96                //              The URL to the feed to load.
97                //
98                //      returns:
99                //              Nothing.
100                if(url !== ""){
101                        if(this._isRelativeURL(url)){
102                                var baseUrl = "";
103                                if(url.charAt(0) !== '/'){
104                                        baseUrl = this._calculateBaseURL(window.location.href, true);
105                                }else{
106                                        baseUrl = this._calculateBaseURL(window.location.href, false);
107                                }
108                                this.url = baseUrl + url;
109                        }
110
111                        this.atomIO.getFeed(url,lang.hitch(this,this.setFeed));
112                }
113        },
114
115
116        setFeed: function(/*object*/feed){
117                //      summary:
118                //              Function setting the dojox.atom.io.model.Feed data into the view.
119                //      description:
120                //              Function setting the dojox.atom.io.model.Feed data into the view.
121                //
122                //      entry:
123                //              The dojox.atom.io.model.Feed object to process
124                //
125                //      returns:
126                //              Nothing.
127                this._feed = feed;
128                this.clear();
129                var entrySorter=function(a,b){
130                        var dispA = this._displayDateForEntry(a);
131                        var dispB = this._displayDateForEntry(b);
132                        if(dispA > dispB){return -1;}
133                        if(dispA < dispB){return 1;}
134                        return 0;
135                };
136
137                // This function may not be safe in different locales.
138                var groupingStr = function(dateStr){
139                        var dpts = dateStr.split(',');
140                       
141                        dpts.pop(); // remove year and time
142                        return dpts.join(",");
143                };
144                var sortedEntries = feed.entries.sort(lang.hitch(this,entrySorter));
145                if(feed){
146                        var lastSectionTitle = null;
147                        for(var i=0;i<sortedEntries.length;i++){
148                               
149                                var entry = sortedEntries[i];
150
151                                if(this._isFilterAccepted(entry)){
152                                        var time = this._displayDateForEntry(entry);
153                                        var sectionTitle = "";
154
155                                        if(time !== null){
156                                                sectionTitle = groupingStr(time.toLocaleString());
157
158                                                if(sectionTitle === "" ){
159                                                        //Generally an issue on Opera with how its toLocaleString() works, so do a quick and dirty date construction M/D/Y
160                                                        sectionTitle = "" + (time.getMonth() + 1) + "/" + time.getDate() + "/" + time.getFullYear();
161                                                }
162                                        }
163                                        if((lastSectionTitle === null) || (lastSectionTitle != sectionTitle)){
164                                                this.appendGrouping(sectionTitle);
165                                                lastSectionTitle = sectionTitle;
166                                        }
167                                        this.appendEntry(entry);
168                                }
169                        }
170                }
171        },
172
173        _displayDateForEntry: function(/*object*/entry){
174                //      summary:
175                //              Internal function for determining the appropriate date to display.
176                //              description: Internal function for determining of a particular entry is editable.
177                //
178                //      entry:
179                //              The dojox.atom.io.model.Entry object to examine.
180                //
181                //      returns:
182                //              An appropriate date for the feed viewer display.
183                if(entry.updated){return entry.updated;}
184                if(entry.modified){return entry.modified;}
185                if(entry.issued){return entry.issued;}
186                return new Date();
187        },
188
189        appendGrouping: function(/*string*/titleText){
190                //      summary:
191                //              Function for appending a new grouping of entries to the feed view.
192                //      description:
193                //              Function for appending a grouping of entries to the feed view.
194                //
195                //      entry:
196                //              The title of the new grouping to create on the view.
197                //
198                //      returns:
199                //              Nothing.
200                var entryWidget = new widget.FeedViewerGrouping({});
201                entryWidget.setText(titleText);
202                this.addChild(entryWidget);
203                this.childWidgets.push(entryWidget);
204        },
205
206        appendEntry: function(/*object*/entry){
207                //      summary:
208                //              Function for appending an entry to the feed view.
209                //      description:
210                //              Function for appending an entry to the feed view.
211                //
212                //      entry:
213                //              The dojox.atom.io.model.Entry object to append
214                //
215                //      returns:
216                //              Nothing.
217                var entryWidget = new widget.FeedViewerEntry({"xmethod": this.xmethod});
218                entryWidget.setTitle(entry.title.value);
219                entryWidget.setTime(this._displayDateForEntry(entry).toLocaleTimeString());
220                entryWidget.entrySelectionTopic = this.entrySelectionTopic;
221                entryWidget.feed = this;
222                this.addChild(entryWidget);
223                this.childWidgets.push(entryWidget);
224                this.connect(entryWidget, "onClick", "_rowSelected");
225                entry.domNode = entryWidget.entryNode;
226               
227                //Need to set up a bi-directional reference here to control events between the two.
228                entry._entryWidget = entryWidget;
229                entryWidget.entry = entry;
230        },
231       
232        deleteEntry: function(/*object*/entryRow){
233                //      summary:
234                //              Function for deleting a row from the view
235                //      description:
236                //              Function for deleting a row from the view
237                if(!this.localSaveOnly){
238                        this.atomIO.deleteEntry(entryRow.entry, lang.hitch(this, this._removeEntry, entryRow), null, this.xmethod);
239                }else{
240                        this._removeEntry(entryRow, true);
241                }
242                dojo.publish(this.entrySelectionTopic, [{ action: "delete", source: this, entry: entryRow.entry }]);
243        },
244
245        _removeEntry: function(/*FeedViewerEntry*/ entry, /* boolean */success){
246                //      summary:
247                //              callback for when an entry is deleted from a feed.
248                //      description:
249                //              callback for when an entry is deleted from a feed.
250                if(success){
251                        /* Check if this is the last Entry beneath the given date */
252                        var idx = arrayUtil.indexOf(this.childWidgets, entry);
253                        var before = this.childWidgets[idx-1];
254                        var after = this.childWidgets[idx+1];
255                        if( before.isInstanceOf(widget.FeedViewerGrouping) &&
256                                (after === undefined || after.isInstanceOf(widget.FeedViewerGrouping))){
257                                before.destroy();
258                        }
259                       
260                        /* Destroy the FeedViewerEntry to remove it from the view */
261                        entry.destroy();
262                }else{}
263        },
264       
265        _rowSelected: function(/*object*/evt){
266                //      summary:
267                //              Internal function for handling the selection of feed entries.
268                //      description:
269                //              Internal function for handling the selection of feed entries.
270                //
271                //      evt:
272                //              The click event that triggered a selection.
273                //
274                //      returns:
275                //              Nothing.
276                var selectedNode = evt.target;
277                while(selectedNode){
278                        if(domClass.contains(selectedNode, 'feedViewerEntry')) {
279                                break;
280                        }
281                        selectedNode = selectedNode.parentNode;
282                }
283
284                for(var i=0;i<this._feed.entries.length;i++){
285                        var entry = this._feed.entries[i];
286                        if( (selectedNode === entry.domNode) && (this._currentSelection !== entry) ){
287                                //Found it and it isn't already selected.
288                                domClass.add(entry.domNode, "feedViewerEntrySelected");
289                                domClass.remove(entry._entryWidget.timeNode, "feedViewerEntryUpdated");
290                                domClass.add(entry._entryWidget.timeNode, "feedViewerEntryUpdatedSelected");
291
292                                this.onEntrySelected(entry);
293                                if(this.entrySelectionTopic !== ""){
294                                        dojo.publish(this.entrySelectionTopic, [{ action: "set", source: this, feed: this._feed, entry: entry }]);
295                                }
296                                if(this._isEditable(entry)){
297                                        entry._entryWidget.enableDelete();
298                                }
299
300                                this._deselectCurrentSelection();
301                                this._currentSelection = entry;
302                                break;
303                        }else if( (selectedNode === entry.domNode) && (this._currentSelection === entry) ){
304                                //Found it and it is the current selection, we just want to de-select it so users can 'unselect rows' if they want.
305                                dojo.publish(this.entrySelectionTopic, [{ action: "delete", source: this, entry: entry }]);
306                                this._deselectCurrentSelection();
307                                break;
308                        }
309                }
310        },
311
312        _deselectCurrentSelection: function(){
313                //      summary:
314                //              Internal function for unselecting the current selection.
315                //      description:
316                //              Internal function for unselecting the current selection.
317                //
318                //      returns:
319                //              Nothing.
320                if(this._currentSelection){
321                        domClass.add(this._currentSelection._entryWidget.timeNode, "feedViewerEntryUpdated");
322                        domClass.remove(this._currentSelection.domNode, "feedViewerEntrySelected");
323                        domClass.remove(this._currentSelection._entryWidget.timeNode, "feedViewerEntryUpdatedSelected");
324                        this._currentSelection._entryWidget.disableDelete();
325                        this._currentSelection = null;
326                }
327        },
328
329
330        _isEditable: function(/*object*/entry){
331                //      summary:
332                //              Internal function for determining of a particular entry is editable.
333                //      description:
334                //              Internal function for determining of a particular entry is editable.
335                //              This is used for determining if the delete action should be displayed or not.
336                //
337                //      entry:
338                //              The dojox.atom.io.model.Entry object to examine
339                //
340                //      returns:
341                //              Boolean denoting if the entry seems editable or not..
342                var retVal = false;
343                if(entry && entry !== null && entry.links && entry.links !== null){
344                        for(var x in entry.links){
345                                if(entry.links[x].rel && entry.links[x].rel == "edit"){
346                                        retVal = true;
347                                        break;
348                                }
349                        }
350                }
351                return retVal;
352        },
353
354        onEntrySelected: function(/*object*/entry){
355                //      summary:
356                //              Function intended for over-riding/replacement as an attachpoint to for other items to recieve
357                //              selection notification.
358                //      description: Function intended for over0-riding/replacement as an attachpoint to for other items to recieve
359                //              selection notification.
360                //
361                //      entry:
362                //              The dojox.atom.io.model.Entry object selected.
363                //
364                //      returns:
365                //              Nothing.
366        },
367
368        _isRelativeURL: function(/*string*/url){
369                //      summary:
370                //              Method to determine if the URL is relative or absolute.
371                //      description:
372                //              Method to determine if the URL is relative or absolute.  Basic assumption is if it doesn't start
373                //              with http:// or file://, it's relative to the current document.
374                //
375                //      url:
376                //              The URL to inspect.
377                //
378                //      returns:
379                //              boolean indicating whether it's a relative url or not.
380                var isFileURL = function(url){
381                        var retVal = false;
382                        if(url.indexOf("file://") === 0){
383                                retVal = true;
384                        }
385                        return retVal;
386                }
387
388                var isHttpURL = function(url){
389                        var retVal = false;
390                        if(url.indexOf("http://") === 0){
391                                retVal = true;
392                        }
393                        return retVal;
394                }
395
396                var retVal = false;
397                if(url !== null){
398                        if(!isFileURL(url) && !isHttpURL(url)){
399                                retVal = true;
400                        }
401                }
402                return retVal;
403        },
404
405        _calculateBaseURL: function(/*string*/fullURL, /*boolean*/currentPageRelative){
406                //      summary:
407                //              Internal function to calculate a baseline URL from the provided full URL.
408                //      description:
409                //              Internal function to calculate a baseline URL from the provided full URL.
410                //
411                //      fullURL:
412                //              The full URL as a string.
413                //      currentPageRelative:
414                //              Flag to denote of the base URL should be calculated as just the server base, or relative to the current page/location in the URL.
415                //
416                //      returns:
417                //              String of the baseline URL
418                var baseURL = null;
419                if(fullURL !== null){
420                        //Check to see if we need to strip off any query parameters from the URL.
421                        var index = fullURL.indexOf("?");
422                        if(index != -1){
423                                fullURL = fullURL.substring(0,index);
424                                //console.debug("Removed query parameters.  URL now: " + fullURL);
425                        }
426
427                        if(currentPageRelative){
428                                //Relative to the 'current page' in the URL, so we need to trim that off.
429                                //Now we need to trim if necessary.  If it ends in /, then we don't have a filename to trim off
430                                //so we can return.
431                                index = fullURL.lastIndexOf("/");
432                                if((index > 0) && (index < fullURL.length) && (index !== (fullURL.length -1))){
433                                        //We want to include the terminating /
434                                        baseURL = fullURL.substring(0,(index + 1));
435                                }else{
436                                        baseURL = fullURL;
437                                }
438                        }else{
439                                //We want to find the first occurance of / after the <protocol>://
440                                index = fullURL.indexOf("://");
441                                if(index > 0){
442                                        index = index + 3;
443                                        var protocol = fullURL.substring(0,index);
444                                        var fragmentURL = fullURL.substring(index, fullURL.length);
445                                        index = fragmentURL.indexOf("/");
446                                        if((index < fragmentURL.length) && (index > 0) ){
447                                                baseURL = protocol + fragmentURL.substring(0,index);
448                                        }else{
449                                                baseURL = protocol + fragmentURL;
450                                        }
451                                }
452                        }
453                }
454                return baseURL;
455        },
456
457        _isFilterAccepted: function(/*object*/entry) {
458                //      summary:
459                //              Internal function to do matching of category filters to widgets.
460                //      description:
461                //              Internal function to do matching of category filters to widgets.
462                //
463                //      returns:
464                //              boolean denoting if this entry matched one of the accept filters.
465                var accepted = false;
466                if (this._includeFilters && (this._includeFilters.length > 0)) {
467                        for (var i = 0; i < this._includeFilters.length; i++) {
468                                var filter = this._includeFilters[i];
469                                if (filter.match(entry)) {
470                                        accepted = true;
471                                        break;
472                                }
473                        }
474                }
475                else {
476                        accepted = true;
477                }
478                return accepted;
479        },
480
481        addCategoryIncludeFilter: function(/*object*/filter) {
482                //      summary:
483                //              Function to add a filter for entry inclusion in the feed view.
484                //      description:
485                //              Function to add a filter for entry inclusion in the feed view.
486                //
487                //      filter:
488                //              The basic items to filter on and the values.
489                //              Should be of format: {scheme: <some text or null>, term: <some text or null>, label: <some text or null>}
490                //
491                //      returns:
492                //              Nothing.
493                if (filter) {
494                        var scheme = filter.scheme;
495                        var term = filter.term;
496                        var label = filter.label;
497                        var addIt = true;
498
499                        if (!scheme) {
500                                scheme = null;
501                        }
502                        if (!term) {
503                                scheme = null;
504                        }
505                        if (!label) {
506                                scheme = null;
507                        }
508                       
509                        if (this._includeFilters && this._includeFilters.length > 0) {
510                                for (var i = 0; i < this._includeFilters.length; i++) {
511                                        var eFilter = this._includeFilters[i];
512                                        if ((eFilter.term === term) && (eFilter.scheme === scheme) && (eFilter.label === label)) {
513                                                //Verify we don't have this filter already.
514                                                addIt = false;
515                                                break;
516                                        }
517                                }
518                        }
519
520                        if (addIt) {
521                                this._includeFilters.push(widget.FeedViewer.CategoryIncludeFilter(scheme, term, label));
522                        }
523                }
524        },
525
526        removeCategoryIncludeFilter: function(/*object*/filter) {
527                //      summary:
528                //              Function to remove a filter for entry inclusion in the feed view.
529                //      description:
530                //              Function to remove a filter for entry inclusion in the feed view.
531                //
532                //      filter:
533                //              The basic items to identify the filter that is present.
534                //              Should be of format: {scheme: <some text or null>, term: <some text or null>, label: <some text or null>}
535                //
536                //      returns:
537                //              Nothing.
538                if (filter) {
539                        var scheme = filter.scheme;
540                        var term = filter.term;
541                        var label = filter.label;
542
543                        if (!scheme) {
544                                scheme = null;
545                        }
546                        if (!term) {
547                                scheme = null;
548                        }
549                        if (!label) {
550                                scheme = null;
551                        }
552                       
553                        var newFilters = [];
554                        if (this._includeFilters && this._includeFilters.length > 0) {
555                                for (var i = 0; i < this._includeFilters.length; i++) {
556                                        var eFilter = this._includeFilters[i];
557                                        if (!((eFilter.term === term) && (eFilter.scheme === scheme) && (eFilter.label === label))) {
558                                                //Keep only filters that do not match
559                                                newFilters.push(eFilter);
560                                        }
561                                }
562                                this._includeFilters = newFilters;
563                        }
564                }
565        },
566
567        _handleEvent: function(/*object*/entrySelectionEvent) {
568                //      summary:
569                //              Internal function for listening to a topic that will handle entry notification.
570                //      description:
571                //              Internal function for listening to a topic that will handle entry notification.
572                //
573                //      entrySelectionEvent:
574                //              The topic message containing the entry that was selected for view.
575                //
576                //      returns:
577                //              Nothing.
578                if(entrySelectionEvent.source != this) {
579                        if(entrySelectionEvent.action == "update" && entrySelectionEvent.entry) {
580                var evt = entrySelectionEvent;
581                                if(!this.localSaveOnly){
582                                        this.atomIO.updateEntry(evt.entry, lang.hitch(evt.source,evt.callback), null, true);
583                                }
584                                this._currentSelection._entryWidget.setTime(this._displayDateForEntry(evt.entry).toLocaleTimeString());
585                                this._currentSelection._entryWidget.setTitle(evt.entry.title.value);
586                        } else if(entrySelectionEvent.action == "post" && entrySelectionEvent.entry) {
587                                if(!this.localSaveOnly){
588                                        this.atomIO.addEntry(entrySelectionEvent.entry, this.url, lang.hitch(this,this._addEntry));
589                                }else{
590                                        this._addEntry(entrySelectionEvent.entry);
591                                }
592                        }
593                }
594        },
595       
596        _addEntry: function(/*object*/entry) {
597                //      summary:
598                //              callback function used when adding an entry to the feed.
599                //      description:
600                //              callback function used when adding an entry to the feed.  After the entry has been posted to the feed,
601                //              we add it to our feed representation (to show it on the page) and publish an event to update any entry viewers.
602                this._feed.addEntry(entry);
603                this.setFeed(this._feed);
604                dojo.publish(this.entrySelectionTopic, [{ action: "set", source: this, feed: this._feed, entry: entry }]);
605        },
606
607        destroy: function(){
608                //      summary:
609                //              Destroys this widget, including all descendants and subscriptions.
610                //      description:
611                //              Destroys this widget, including all descendants and subscriptions.
612                this.clear();
613                arrayUtil.forEach(this._subscriptions, dojo.unsubscribe);
614        }
615});
616
617widget.FeedViewerEntry = dojo.declare(/*===== "dojox.atom.widget.FeedViewerEntry", =====*/ [_Widget, _Templated],{
618        //      summary:
619        //              Widget for handling the display of an entry and specific events associated with it.
620        //              description: Widget for handling the display of an entry and specific events associated with it.
621
622        templateString: entryTemplate,
623
624        entryNode: null,
625        timeNode: null,
626        deleteButton: null,
627        entry: null,
628        feed: null,
629
630        postCreate: function(){
631                var _nlsResources = i18nViewer;
632                this.deleteButton.innerHTML = _nlsResources.deleteButton;
633        },
634
635        setTitle: function(/*string*/text){
636                //      summary:
637                //              Function to set the title of the entry.
638                //      description:
639                //              Function to set the title of the entry.
640                //
641                //      text:
642                //              The title.
643                //
644                //      returns:
645                //              Nothing.
646                if (this.titleNode.lastChild){this.titleNode.removeChild(this.titleNode.lastChild);}
647               
648                var titleTextNode = document.createElement("div");
649                titleTextNode.innerHTML = text;
650                this.titleNode.appendChild(titleTextNode);
651        },
652
653        setTime: function(/*string*/timeText){
654                //      summary:
655                //              Function to set the time of the entry.
656                //      description:
657                //              Function to set the time of the entry.
658                //
659                //      timeText:
660                //              The string form of the date.
661                //
662                //      returns:
663                //              Nothing.
664                if (this.timeNode.lastChild){this.timeNode.removeChild(this.timeNode.lastChild);}
665                var timeTextNode = document.createTextNode(timeText);
666                this.timeNode.appendChild(timeTextNode);
667        },
668
669        enableDelete: function(){
670                //      summary:
671                //              Function to enable the delete action on this entry.
672                //      description:
673                //              Function to enable the delete action on this entry.
674                //
675                //      returns:
676                //              Nothing.
677                if (this.deleteButton !== null) {
678                        //TODO Fix this
679                        this.deleteButton.style.display = 'inline';
680                }
681        },
682
683        disableDelete: function(){
684                //      summary:
685                //              Function to disable the delete action on this entry.
686                //      description:
687                //              Function to disable the delete action on this entry.
688                //
689                //      returns:
690                //              Nothing.
691                if (this.deleteButton !== null) {
692                        this.deleteButton.style.display = 'none';
693                }
694        },
695
696        deleteEntry: function(/*object*/event) {
697                //      summary:
698                //              Function to handle the delete event and delete the entry.
699                //      description:
700                //              Function to handle the delete event and delete the entry.
701                //
702                //      returns:
703                //              Nothing.
704                event.preventDefault();
705                event.stopPropagation();
706                this.feed.deleteEntry(this);
707        },
708
709        onClick: function(/*object*/e){
710                //      summary:
711                //              Attach point for when a row is clicked on.
712                //      description:
713                //              Attach point for when a row is clicked on.
714                //
715                //      e:
716                //              The event generated by the click.
717        }
718});
719
720widget.FeedViewerGrouping = dojo.declare(/*===== "dojox.atom.widget.FeedViewerGrouping", =====*/ [_Widget, _Templated],{
721        //      summary:
722        //              Grouping of feed entries.
723        //      description:
724        //              Grouping of feed entries.
725        templateString: groupingTemplate,
726       
727        groupingNode: null,
728        titleNode: null,
729
730        setText: function(text){
731                //      summary:
732                //              Sets the text to be shown above this grouping.
733                //      description:
734                //              Sets the text to be shown above this grouping.
735                //
736                //      text:
737                //              The text to show.
738                if (this.titleNode.lastChild){this.titleNode.removeChild(this.titleNode.lastChild);}
739                var textNode = document.createTextNode(text);
740                this.titleNode.appendChild(textNode);
741        }
742});
743
744widget.AtomEntryCategoryFilter = dojo.declare(/*===== "dojox.atom.widget.AtomEntryCategoryFilter", =====*/ [_Widget, _Templated],{
745        //      summary:
746        //              A filter to be applied to the list of entries.
747        //      description:
748        //              A filter to be applied to the list of entries.
749        scheme: "",
750        term: "",
751        label: "",
752        isFilter: true
753});
754
755widget.FeedViewer.CategoryIncludeFilter = dojo.declare(/*===== "dojox.atom.widget.FeedViewer.CategoryIncludeFilter", =====*/ null,{
756        constructor: function(scheme, term, label){
757                //      summary:
758                //              The initializer function.
759                //      description:
760                //              The initializer function.
761                this.scheme = scheme;
762                this.term = term;
763                this.label = label;
764        },
765
766        match: function(entry) {
767                //      summary:
768                //              Function to determine if this category filter matches against a category on an atom entry
769                //      description:
770                //              Function to determine if this category filter matches against a category on an atom entry
771                //
772                //      returns:
773                //              boolean denoting if this category filter matched to this entry.
774                var matched = false;
775                if (entry !== null) {
776                        var categories = entry.categories;
777                        if (categories !== null) {
778                                for (var i = 0; i < categories.length; i++) {
779                                        var category = categories[i];
780
781                                        if (this.scheme !== "") {
782                                                if (this.scheme !== category.scheme) {
783                                                        break;
784                                                }
785                                        }
786                                       
787                                        if (this.term !== "") {
788                                                if (this.term !== category.term) {
789                                                        break;
790                                                }
791                                        }
792
793                                        if (this.label !== "") {
794                                                if (this.label !== category.label) {
795                                                        break;
796                                                }
797                                        }
798                                        //Made it this far, everything matched.
799                                        matched = true;
800                                }
801                        }
802                }
803                return matched;
804        }
805});
806return widget.FeedViewer;
807});
Note: See TracBrowser for help on using the repository browser.