source: Dev/trunk/src/client/dojox/mobile/IconItem.js @ 532

Last change on this file since 532 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

File size: 11.9 KB
Line 
1define([
2        "dojo/_base/declare",
3        "dojo/_base/event",
4        "dojo/_base/lang",
5        "dojo/sniff",
6        "dojo/_base/window",
7        "dojo/dom-class",
8        "dojo/dom-construct",
9        "dojo/dom-geometry",
10        "dojo/dom-style",
11        "./_ItemBase",
12        "./Badge",
13        "./TransitionEvent",
14        "./iconUtils",
15        "./lazyLoadUtils",
16        "./viewRegistry",
17        "./_css3",
18        "dojo/has!dojo-bidi?dojox/mobile/bidi/IconItem"
19], function(declare, event, lang, has, win, domClass, domConstruct, domGeometry, domStyle, ItemBase, Badge, TransitionEvent, iconUtils, lazyLoadUtils, viewRegistry, css3, BidiIconItem){
20
21        // module:
22        //              dojox/mobile/IconItem
23
24        var IconItem = declare(has("dojo-bidi") ? "dojox.mobile.NonBidiIconItem" : "dojox.mobile.IconItem", ItemBase, {
25                // summary:
26                //              An icon item widget.
27                // description:
28                //              IconItem represents an item that has an application component
29                //              and its icon image. You can tap the icon to open the
30                //              corresponding application component. You can also use the icon
31                //              to move to a different view by specifying either of the moveTo,
32                //              href or url parameters.
33
34                // lazy: String
35                //              If true, the content of the widget, which includes dojo markup,
36                //              is instantiated lazily. That is, only when the widget is opened
37                //              by the user, the required modules are loaded and the content
38                //              widgets are instantiated.
39                //              This option works both in the sync and async loader mode.
40                lazy: false,
41
42                // requires: String
43                //              Comma-separated required module names to be lazily loaded. This
44                //              property is effective only when lazy=true. All the modules
45                //              specified with data-dojo-type and their depending modules are
46                //              automatically loaded by the IconItem when it is opened.
47                //              However, if you need other extra modules to be loaded, use this parameter.
48                //              This option works both in the sync and async loader mode.
49                requires: "",
50
51                // timeout: String
52                //              Duration of highlight in seconds.
53                timeout: 10,
54
55                // content: String
56                //              An HTML fragment to embed as icon content.
57                content: "",
58
59                // badge: String
60                //              A text to show in a badge (ex. "55").
61                badge: "",
62
63                // badgeClass: String
64                //              A class name of a DOM button for a badge.
65                badgeClass: "mblDomButtonRedBadge",
66
67                // deletable: Boolean
68                //              If true, you can delete this IconItem by clicking on the delete
69                //              icon during edit mode.
70                //              If false, the delete icon is not displayed during edit mode so
71                //              that it cannot be deleted.
72                deletable: true,
73
74                // deleteIcon: String
75                //              A delete icon to display at the top-left corner of the item
76                //              during edit mode. The value can be either a path for an image
77                //              file or a class name of a DOM button.
78                deleteIcon: "",
79
80                // tag: String
81                //              A name of the HTML tag to create as domNode.
82                tag: "li",
83
84                /* internal properties */       
85                // Note these are overrides for similar properties defined in _ItemBase.
86                paramsToInherit: "transition,icon,deleteIcon,badgeClass,deleteIconTitle,deleteIconRole",
87                baseClass: "mblIconItem",
88                _selStartMethod: "touch",
89                _selEndMethod: "none",
90
91                destroy: function(){
92                        if(this.badgeObj){
93                                delete this.badgeObj;
94                        }
95                        this.inherited(arguments);
96                },
97
98                buildRendering: function(){
99                        this.domNode = this.srcNodeRef || domConstruct.create(this.tag);
100
101                        if(this.srcNodeRef){
102                                // reparent
103                                this._tmpNode = domConstruct.create("div");
104                                for(var i = 0, len = this.srcNodeRef.childNodes.length; i < len; i++){
105                                        this._tmpNode.appendChild(this.srcNodeRef.firstChild);
106                                }
107                        }
108
109                        this.iconDivNode = domConstruct.create("div", {className:"mblIconArea"}, this.domNode);
110                        this.iconParentNode = domConstruct.create("div", {className:"mblIconAreaInner"}, this.iconDivNode);
111                        this.labelNode = domConstruct.create("span", {className:"mblIconAreaTitle"}, this.iconDivNode);
112
113                        this.inherited(arguments);
114                },
115
116                startup: function(){
117                        if(this._started){ return; }
118
119                        var p = this.getParent();
120                        require([p.iconItemPaneClass], lang.hitch(this, function(module){
121                                var w = this.paneWidget = new module(p.iconItemPaneProps);
122                                this.containerNode = w.containerNode;
123                                if(this._tmpNode){
124                                        // reparent
125                                        for(var i = 0, len = this._tmpNode.childNodes.length; i < len; i++){
126                                                w.containerNode.appendChild(this._tmpNode.firstChild);
127                                        }
128                                        this._tmpNode = null;
129                                }
130                                p.paneContainerWidget.addChild(w, this.getIndexInParent());
131                                w.set("label", this.label);
132                                this._clickCloseHandle = this.connect(w.closeIconNode, "onclick", "_closeIconClicked");
133                                this._keydownCloseHandle = this.connect(w.closeIconNode, "onkeydown", "_closeIconClicked"); // for desktop browsers
134                        }));
135
136                        this.inherited(arguments);
137                        if(!this._isOnLine){
138                                this._isOnLine = true;
139                                // retry applying the attribute for which the custom setter delays the actual
140                                // work until _isOnLine is true.
141                                this.set("icon", this._pendingIcon !== undefined ? this._pendingIcon : this.icon);
142                                // Not needed anymore (this code executes only once per life cycle):
143                                delete this._pendingIcon;
144                        }
145                        if(!this.icon && p.defaultIcon){
146                                this.set("icon", p.defaultIcon);
147                        }
148
149                        this._dragstartHandle = this.connect(this.domNode, "ondragstart", event.stop);
150                        this.connect(this.domNode, "onkeydown", "_onClick"); // for desktop browsers
151                },
152
153                highlight: function(/*Number?*/timeout){
154                        // summary:
155                        //              Shakes the icon 10 seconds.
156                        domClass.add(this.iconDivNode, "mblVibrate");
157                        timeout = (timeout !== undefined) ? timeout : this.timeout;
158                        if(timeout > 0){
159                                var _this = this;
160                                _this.defer(function(){
161                                        _this.unhighlight();
162                                }, timeout*1000);
163                        }
164                },
165
166                unhighlight: function(){
167                        // summary:
168                        //              Stops shaking the icon.
169                        if(!has("ie") && has("trident") === 7){
170                                // Workaround on IE11: if just removing the style, the icon continues to shake
171                                domStyle.set(this.iconDivNode, "animation-name", "");
172                        }
173                        domClass.remove(this.iconDivNode, "mblVibrate");
174                },
175
176                isOpen: function(e){
177                        // summary:
178                        //              Returns true if the icon is open.
179                        return this.paneWidget.isOpen();
180                },
181
182                _onClick: function(e){
183                        // summary:
184                        //              Internal handler for click events.
185                        // tags:
186                        //              private
187                        if(this.getParent().isEditing || e && e.type === "keydown" && e.keyCode !== 13){ return; }
188                        if(this.onClick(e) === false){ return; } // user's click action
189                        this.defaultClickAction(e);
190                },
191
192                onClick: function(/*Event*/ /*===== e =====*/){
193                        // summary:
194                        //              User-defined function to handle clicks.
195                        // tags:
196                        //              callback
197                },
198
199                _onNewWindowOpened: function(e){
200                        // Override from _ItemBase
201                        this.set("selected", false);
202                },
203
204                _prepareForTransition: function(e, transOpts){
205                        // Override from _ItemBase
206                        if(transOpts){
207                                this.defer(function(d){
208                                        this.set("selected", false);
209                                }, 1500);
210                                return true;
211                        }else{
212                                if(this.getParent().transition === "below" && this.isOpen()){
213                                        this.close();
214                                }else{
215                                        this.open(e);
216                                }
217                                return false;
218                        }
219                },
220
221                _closeIconClicked: function(e){
222                        // summary:
223                        //              Internal handler for click events.
224                        // tags:
225                        //              private
226                        if(e){
227                                if(e.type === "keydown" && e.keyCode !== 13){ return; }
228                                if(this.closeIconClicked(e) === false){ return; } // user's click action
229                                this.defer(function(d){ this._closeIconClicked(); });
230                                return;
231                        }
232                        this.close();
233                },
234
235                closeIconClicked: function(/*Event*/ /*===== e =====*/){
236                        // summary:
237                        //              User-defined function to handle clicks for the close icon.
238                        // tags:
239                        //              callback
240                },
241
242                open: function(e){
243                        // summary:
244                        //              Opens the icon content, or makes a transition.
245                        var parent = this.getParent(); // IconContainer
246                        if(this.transition === "below"){
247                                if(parent.single){
248                                        parent.closeAll();
249                                }
250                                this._open_1();
251                        }else{
252                                parent._opening = this;
253                                if(parent.single){
254                                        this.paneWidget.closeHeaderNode.style.display = "none";
255                                        if(!this.isOpen()){
256                                                parent.closeAll();
257                                        }
258                                        parent.appView._heading.set("label", this.label);
259                                }
260                                this.moveTo = parent.id + "_mblApplView";
261                                new TransitionEvent(this.domNode, this.getTransOpts(), e).dispatch();
262                        }
263                },
264
265                _open_1: function(){
266                        // summary:
267                        //              Opens the icon content for the 'below' transition.
268                        // tags:
269                        //              private
270                        this.paneWidget.show();
271                        this.unhighlight();
272                        if(this.lazy){
273                                lazyLoadUtils.instantiateLazyWidgets(this.containerNode, this.requires);
274                                this.lazy = false;
275                        }
276                        this.scrollIntoView(this.paneWidget.domNode);
277                        this.onOpen();
278                },
279
280                scrollIntoView: function(/*DomNode*/node){
281                        // summary:
282                        //              Scrolls until the given node is in the view.
283                        var s = viewRegistry.getEnclosingScrollable(node);
284                        if(s){ // this node is placed inside scrollable
285                                var dim = s.getDim();
286                                if(dim.c.h >= dim.d.h){ // #16306: only if the content is larger than the display area
287                                        s.scrollIntoView(node, true);
288                                }
289                        }else{
290                                win.global.scrollBy(0, domGeometry.position(node, false).y);
291                        }
292                },
293
294                close: function(/*Boolean?*/noAnimation){
295                        // summary:
296                        //              Closes the icon content.
297                        if(!this.isOpen()){ return; }
298                        this.set("selected", false);
299                        if(has("css3-animations") && !noAnimation){
300                                var contentNode = this.paneWidget.domNode;
301                                if(this.getParent().transition == "below"){
302                                        domClass.add(contentNode, "mblCloseContent mblShrink");
303                                        var nodePos = domGeometry.position(contentNode, true);
304                                        var targetPos = domGeometry.position(this.domNode, true);
305                                        var origin = (targetPos.x + targetPos.w/2 - nodePos.x) + "px " + (targetPos.y + targetPos.h/2 - nodePos.y) + "px";
306                                        domStyle.set(contentNode, css3.add({}, { transformOrigin:origin }));
307                                }else{
308                                        domClass.add(contentNode, "mblCloseContent mblShrink0");
309                                }
310                        }else{
311                                this.paneWidget.hide();
312                        }
313                        this.onClose();
314                },
315
316                onOpen: function(){
317                        // summary:
318                        //              Stub method to allow the application to connect.
319                },
320
321                onClose: function(){
322                        // summary:
323                        //              Stub method to allow the application to connect.
324                },
325
326                _setLabelAttr: function(/*String*/text){
327                        // tags:
328                        //              private
329                        this.label = text;
330                        var s = this._cv ? this._cv(text) : text;
331                        this.labelNode.innerHTML = s;
332                        if(this.paneWidget){
333                                this.paneWidget.set("label", text);
334                        }
335                },
336
337                _getBadgeAttr: function(){
338                        // tags:
339                        //              private
340                        return this.badgeObj ? this.badgeObj.getValue() : null;
341                },
342
343                _setBadgeAttr: function(/*String*/value){
344                        // tags:
345                        //              private
346                        if(!this.badgeObj){
347                                this.badgeObj = new Badge({fontSize:14, className:this.badgeClass});
348                                domStyle.set(this.badgeObj.domNode, {
349                                        position: "absolute",
350                                        top: "-2px",
351                                        right: "2px"
352                                });
353                        }
354                        this.badgeObj.setValue(value);
355                        if(value){
356                                this.iconDivNode.appendChild(this.badgeObj.domNode);
357                        }else{
358                                this.iconDivNode.removeChild(this.badgeObj.domNode);
359                        }
360                },
361
362                _setDeleteIconAttr: function(icon){
363                        // tags:
364                        //              private
365                        if(!this.getParent()){ return; } // icon may be invalid because inheritParams is not called yet
366
367                        this._set("deleteIcon", icon);
368                        icon = this.deletable ? icon : "";
369                        this.deleteIconNode = iconUtils.setIcon(icon, this.deleteIconPos, this.deleteIconNode,
370                                        this.deleteIconTitle || this.alt, this.iconDivNode);
371                        if(this.deleteIconNode){
372                                domClass.add(this.deleteIconNode, "mblIconItemDeleteIcon");
373                                if(this.deleteIconRole){
374                                        this.deleteIconNode.setAttribute("role", this.deleteIconRole);
375                                }
376                        }
377                },
378
379                _setContentAttr: function(/*String|DomNode*/data){
380                        // tags:
381                        //              private
382                        var root;
383                        if(!this.paneWidget){
384                                if(!this._tmpNode){
385                                        this._tmpNode = domConstruct.create("div");
386                                }
387                                root = this._tmpNode;
388                        }else{
389                                root = this.paneWidget.containerNode;
390                        }
391
392                        if(typeof data === "object"){
393                                domConstruct.empty(root);
394                                root.appendChild(data);
395                        }else{
396                                root.innerHTML = data;
397                        }
398                },
399
400                _setSelectedAttr: function(/*Boolean*/selected){
401                        // summary:
402                        //              Makes this widget in the selected or unselected state.
403                        // tags:
404                        //              private
405                        this.inherited(arguments);
406                        domStyle.set(this.iconNode, "opacity",
407                                                 selected ? this.getParent().pressedIconOpacity : 1);
408                }
409        });
410
411        return has("dojo-bidi") ? declare("dojox.mobile.IconItem", [IconItem, BidiIconItem]) : IconItem;
412});
Note: See TracBrowser for help on using the repository browser.