Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojox.widget.Toaster"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojox.widget.Toaster"] = true;
3
dojo.provide("dojox.widget.Toaster");
4
 
5
dojo.require("dojo.fx");
6
 
7
dojo.require("dijit._Widget");
8
dojo.require("dijit._Templated");
9
 
10
// This is mostly taken from Jesse Kuhnert's MessageNotifier.
11
// Modified by Bryan Forbes to support topics and a variable delay.
12
// Modified by Karl Tiedt to support 0 duration messages that require user interaction and message stacking
13
 
14
dojo.declare("dojox.widget.Toaster", [dijit._Widget, dijit._Templated], {
15
		// summary
16
		//		Message that slides in from the corner of the screen, used for notifications
17
		//		like "new email".
18
		templateString: '<div dojoAttachPoint="clipNode"><div dojoAttachPoint="containerNode" dojoAttachEvent="onclick:onSelect"><div dojoAttachPoint="contentNode"></div></div></div>',
19
 
20
		// messageTopic: String
21
		//		Name of topic; anything published to this topic will be displayed as a message.
22
		//		Message format is either String or an object like
23
		//		{message: "hello word", type: "error", duration: 500}
24
		messageTopic: "",
25
 
26
		_uniqueId: 0,
27
 
28
		// messageTypes: Enumeration
29
		//		Possible message types.
30
		messageTypes: {
31
			MESSAGE: "message",
32
			WARNING: "warning",
33
			ERROR: "error",
34
			FATAL: "fatal"
35
		},
36
 
37
		// defaultType: String
38
		//		If message type isn't specified (see "messageTopic" parameter),
39
		//		then display message as this type.
40
		//		Possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
41
		defaultType: "message",
42
 
43
		// positionDirection: String
44
		//		Position from which message slides into screen, one of
45
		//		["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"]
46
		positionDirection: "br-up",
47
 
48
		// positionDirectionTypes: Array
49
		//		Possible values for positionDirection parameter
50
		positionDirectionTypes: ["br-up", "br-left", "bl-up", "bl-right", "tr-down", "tr-left", "tl-down", "tl-right"],
51
 
52
		// duration: Integer
53
		//		Number of milliseconds to show message
54
		duration: "2000",
55
 
56
		//separator: String
57
		//		String used to separate messages if consecutive calls are made to setContent before previous messages go away
58
		separator: "<hr></hr>",
59
 
60
		postCreate: function(){
61
			dojox.widget.Toaster.superclass.postCreate.apply(this);
62
			this.hide();
63
 
64
			this.clipNode.className = "dijitToasterClip";
65
			this.containerNode.className += " dijitToasterContainer";
66
			this.contentNode.className = "dijitToasterContent";
67
			if(this.messageTopic){
68
				dojo.subscribe(this.messageTopic, this, "_handleMessage");
69
			}
70
		},
71
 
72
		_handleMessage: function(/*String|Object*/message){
73
			if(dojo.isString(message)){
74
				this.setContent(message);
75
			}else{
76
				this.setContent(message.message, message.type, message.duration);
77
			}
78
		},
79
 
80
		setContent: function(/*String*/message, /*String*/messageType, /*int?*/duration){
81
			// summary
82
			//		sets and displays the given message and show duration
83
			// message:
84
			//		the message
85
			// messageType:
86
			//		type of message; possible values in messageTypes enumeration ("message", "warning", "error", "fatal")
87
			// duration:
88
			//		duration in milliseconds to display message before removing it. Widget has default value.
89
			duration = duration||this.duration;
90
			// sync animations so there are no ghosted fades and such
91
			if(this.slideAnim){
92
				if(this.slideAnim.status() != "playing"){
93
					this.slideAnim.stop();
94
				}
95
				if(this.slideAnim.status() == "playing" || (this.fadeAnim && this.fadeAnim.status() == "playing")){
96
					setTimeout(dojo.hitch(this, function(){
97
						this.setContent(message, messageType);
98
					}), 50);
99
					return;
100
				}
101
			}
102
 
103
			var capitalize = function(word){
104
				return word.substring(0,1).toUpperCase() + word.substring(1);
105
			};
106
 
107
			// determine type of content and apply appropriately
108
			for(var type in this.messageTypes){
109
				dojo.removeClass(this.containerNode, "dijitToaster" + capitalize(this.messageTypes[type]));
110
			}
111
 
112
			dojo.style(this.containerNode, "opacity", 1);
113
 
114
			if(message && this.isVisible){
115
				message = this.contentNode.innerHTML + this.separator + message;
116
			}
117
			this.contentNode.innerHTML = message;
118
 
119
			dojo.addClass(this.containerNode, "dijitToaster" + capitalize(messageType || this.defaultType));
120
 
121
			// now do funky animation of widget appearing from
122
			// bottom right of page and up
123
			this.show();
124
			var nodeSize = dojo.marginBox(this.containerNode);
125
 
126
			if(this.isVisible){
127
				this._placeClip();
128
			}else{
129
				var style = this.containerNode.style;
130
				var pd = this.positionDirection;
131
				// sets up initial position of container node and slide-out direction
132
				if(pd.indexOf("-up") >= 0){
133
					style.left=0+"px";
134
					style.top=nodeSize.h + 10 + "px";
135
				}else if(pd.indexOf("-left") >= 0){
136
					style.left=nodeSize.w + 10 +"px";
137
					style.top=0+"px";
138
				}else if(pd.indexOf("-right") >= 0){
139
					style.left = 0 - nodeSize.w - 10 + "px";
140
					style.top = 0+"px";
141
				}else if(pd.indexOf("-down") >= 0){
142
					style.left = 0+"px";
143
					style.top = 0 - nodeSize.h - 10 + "px";
144
				}else{
145
					throw new Error(this.id + ".positionDirection is invalid: " + pd);
146
				}
147
 
148
				this.slideAnim = dojo.fx.slideTo({
149
					node: this.containerNode,
150
					top: 0, left: 0,
151
					duration: 450});
152
				dojo.connect(this.slideAnim, "onEnd", this, function(nodes, anim){
153
						//we build the fadeAnim here so we dont have to duplicate it later
154
						// can't do a fadeHide because we're fading the
155
						// inner node rather than the clipping node
156
						this.fadeAnim = dojo.fadeOut({
157
							node: this.containerNode,
158
							duration: 1000});
159
						dojo.connect(this.fadeAnim, "onEnd", this, function(evt){
160
							this.isVisible = false;
161
							this.hide();
162
						});
163
						//if duration == 0 we keep the message displayed until clicked
164
						//TODO: fix so that if a duration > 0 is displayed when a duration==0 is appended to it, the fadeOut is canceled
165
						if(duration>0){
166
							setTimeout(dojo.hitch(this, function(evt){
167
								// we must hide the iframe in order to fade
168
								// TODO: figure out how to fade with a BackgroundIframe
169
								if(this.bgIframe && this.bgIframe.iframe){
170
									this.bgIframe.iframe.style.display="none";
171
								}
172
								this.fadeAnim.play();
173
							}), duration);
174
						}else{
175
							dojo.connect(this, 'onSelect', this, function(evt){
176
								this.fadeAnim.play();
177
							});
178
						}
179
						this.isVisible = true;
180
					});
181
				this.slideAnim.play();
182
			}
183
		},
184
 
185
		_placeClip: function(){
186
			var view = dijit.getViewport();
187
 
188
			var nodeSize = dojo.marginBox(this.containerNode);
189
 
190
			var style = this.clipNode.style;
191
			// sets up the size of the clipping node
192
			style.height = nodeSize.h+"px";
193
			style.width = nodeSize.w+"px";
194
 
195
			// sets up the position of the clipping node
196
			var pd = this.positionDirection;
197
			if(pd.match(/^t/)){
198
				style.top = view.t+"px";
199
			}else if(pd.match(/^b/)){
200
				style.top = (view.h - nodeSize.h - 2 + view.t)+"px";
201
			}
202
			if(pd.match(/^[tb]r-/)){
203
				style.left = (view.w - nodeSize.w - 1 - view.l)+"px";
204
			}else if(pd.match(/^[tb]l-/)){
205
				style.left = 0 + "px";
206
			}
207
 
208
			style.clip = "rect(0px, " + nodeSize.w + "px, " + nodeSize.h + "px, 0px)";
209
			if(dojo.isIE){
210
				if(!this.bgIframe){
211
					this.clipNode.id = "__dojoXToaster_"+this._uniqueId++;
212
					this.bgIframe = new dijit.BackgroundIframe(this.clipNode);
213
//TODO					this.bgIframe.setZIndex(this.clipNode);
214
				}
215
//TODO				this.bgIframe.onResized();
216
				var iframe = this.bgIframe.iframe;
217
				iframe && (iframe.style.display="block");
218
			}
219
		},
220
 
221
		onSelect: function(/*Event*/e){
222
			// summary: callback for when user clicks the message
223
		},
224
 
225
		show: function(){
226
			// summary: show the Toaster
227
			dojo.style(this.containerNode, 'display', '');
228
 
229
			this._placeClip();
230
 
231
			if(!this._scrollConnected){
232
				this._scrollConnected = dojo.connect(window, "onscroll", this, this._placeClip);
233
			}
234
		},
235
 
236
		hide: function(){
237
			// summary: hide the Toaster
238
 
239
			//Q: ALP: I didn't port all the toggler stuff from d.w.HtmlWidget.  Is it needed? Ditto for show.
240
			dojo.style(this.containerNode, 'display', 'none');
241
 
242
			if(this._scrollConnected){
243
				dojo.disconnect(this._scrollConnected);
244
				this._scrollConnected = false;
245
			}
246
 
247
			dojo.style(this.containerNode, "opacity", 1);
248
		}
249
	}
250
);
251
 
252
}