/[transports]/trunk/web/static/js/protoGrowl.js
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/web/static/js/protoGrowl.js

Parent Directory Parent Directory | Revision Log Revision Log


Revision 101 - (show annotations)
Sat Jun 24 16:14:18 2006 UTC (17 years, 9 months ago) by dpavlin
File MIME type: application/javascript
File size: 24862 byte(s)
better way to include javascript, moved protoGrowl CSS into app-base.css
1 /*
2 Class: protoGrowl
3 Version: 1.0b (Work in progress)
4 License: GNU LGPL
5
6 Jerry Jalava, jerry.jalava@incognito.fi
7 2006
8
9 --------------------------
10 To create a growl:
11 var growl = new protoGrowl({type: 'info', title: 'title', content: 'content'});
12 --------------------------
13
14 --------------------------
15 Hint: if you have html coded growls
16 do this on body onLoad:
17 new BodyReader( {} );
18
19 It reads the whole document and transforms every element
20 with attribute id="midcom-service-uimessages-protogrowl"
21 to growl windows (read more from BodyReader description)
22 --------------------------
23
24 Updated documentation will reside in:
25 http://www.midgard-project.org/documentation/protogrowl
26
27 ** Warning **
28 This is still a big work in progress.
29 */
30
31 var protoGrowl = Class.create();
32 protoGrowl.prototype = {
33
34 /*
35 Initializes protoGrowl Class.
36 This is where we'll set some defaults and parse all user input
37 to creation process.
38
39 Available parameters:
40 id: growl id (this you don't need to set, but can be overrided if wanted)
41 type: growl type (notfication, warning, error, message)
42 title: growls title (this gets populated to div with class $className+'-title')
43 content: growls content (Can be html or just plain text. $className+'-content')
44
45 width: growl width (defaults to 350 (px))
46 height: growl height (defaults to 80 (px))
47 minWidth: minimum width (defaults to 350 (px))
48 minHeight: minimum height (defaults to 80 (px))
49 maxWidth: maximum width
50 maxHeight: maximum height
51
52 - You can adjust the effect growls are revealed/hidden
53 showEffect: not yet in use
54 showEffectOptions: not yet in use
55 hideEffect: not yet in use
56 hideEffectOptions: not yet in use
57
58 maxprotoGrowls: this sets the maximum for how many growl can be displayed at once,
59 if the count is exceeded it will hide the oldest automatically
60
61 lifeTime: sets growls lifeTime in seconds (default to 3600 seconds)
62
63 closable: true/false (does he growl have the close button on it...)
64
65 className: defaults to 'midcom-service-uimessages-protogrowl'
66
67 padding: array of growl padding. Defaults to [10,0,0,0] (top,right,bottom,left)
68
69 */
70 initialize: function(parameters)
71 {
72 this.id = parameters.id || this.nextID();
73 this.type = parameters.type || 'info';
74 this.title = parameters.title;
75 this.content = parameters.message;
76
77 this.minWidth = parameters.minWidth || 350;
78 this.minHeight = parameters.minHeight || 80;
79 this.maxWidth = parameters.maxWidth;
80 this.maxHeight = parameters.maxHeight;
81
82 this.hasEffectLib = String.prototype.parseColor != null;
83 this.showEffectOptions = parameters.showEffectOptions || (parameters.effectOptions || { duration:0.50 });
84 this.hideEffectOptions = parameters.hideEffectOptions || (parameters.effectOptions || { duration:0.80, afterFinish: function(){ this.destroy(); }.bind(this) } );
85 //afterFinish: .bind(this)
86
87 this.showEffect = parameters.showEffect || (this.hasEffectLib ? Effect.Appear : Element.show);
88 this.hideEffect = parameters.hideEffect || (this.hasEffectLib ? Effect.Fade : Element.hide);
89
90 var maxprotoGrowls = parameters.maxprotoGrowls || 3;
91 protoGrowls.setMaxprotoGrowls( maxprotoGrowls );
92 this.lifetime = parameters.lifeTime || 3600;
93
94 this.closable = parameters.closable != null ? parameters.closable : true;
95 this.destroyOnClose = true;
96
97 var className = parameters.className != null ? parameters.className : "midcom-service-uimessages-protogrowl";
98 this.className = className;
99
100 var parent = parameters.parent || document.getElementsByTagName("body")[0];//.item(0);
101
102 if(parameters.element != null && parameters.element != undefined) {
103 this.element = this.collectElement( parameters.element, parent );
104 } else {
105 this.element = this.create( parent );
106 }
107
108 for(var k in this.element) {
109 // debug("k: "+k+" val:"+this.element[k]);
110 }
111
112
113 this.eventMouseUp = this.hide.bindAsEventListener(this);
114 this.eventOnLoad = this.getWindowMeasurements.bindAsEventListener(this);
115 var closeBtnClass = this.className + "-closebutton";
116 this.closeBtn = document.getElementsByClassName(closeBtnClass);
117 //debug("this.closeBtn "+this.closeBtn);
118 //debug("this.element "+this.element);
119 Event.observe(this.closeBtn, "mouseup", this.eventMouseUp);
120 Event.observe(window, "load", this.eventOnLoad);
121
122 var offset = [0,0];
123 this.padding = parameters.padding || [10,0,0,0];
124 var width = parseFloat(parameters.width) || 350;
125 var height = parseFloat(parameters.height) || 80;
126
127 if (parameters.left != null) {
128 this.setStyle({left: parseFloat(parameters.left) + offset[0] + 'px'});
129 this.useLeft = true;
130 }
131 if (parameters.right != null) {
132 this.setStyle({right: parseFloat(parameters.right) + 'px'});
133 this.useLeft = false;
134 }
135 if (parameters.top != null) {
136 this.setStyle({top: parseFloat(parameters.top) + 'px'});
137 this.useTop = true;
138 }
139 if (parameters.bottom != null) {
140 this.setStyle({bottom: parseFloat(parameters.bottom) + 'px'});
141 this.useTop = false;
142 }
143 if (parameters.zIndex) {
144 this.setZIndex(parameters.zIndex);
145 }
146
147 this.getWindowMeasurements();
148
149 this.setSize(width, height);
150 //this.placeprotoGrowl();
151
152 if(this.content != null && this.content != undefined) {
153 this.getContent().innerHTML = this.content;
154 }
155
156 protoGrowls.register(this);
157 this.destroyed = false;
158
159 if(parameters.dontShow == false || parameters.dontShow == undefined) {
160 this.show();
161 }
162 },
163
164 create: function( parent )
165 {
166 var growl_div = document.createElement("div");
167 var growl_id = this.id;
168
169 growl_div.setAttribute('id', growl_id);
170 growl_div.className = this.className + ' ' + this.className + '-type-' + this.type;
171
172 if(!this.title) {
173 this.title = " ";
174 }
175 //debug("id: "+growl_id);
176 growl_div.innerHTML = "\
177 <div class='"+ this.className +"-contenthelper-type-"+this.type+"'>\
178 <div class='"+ this.className +"-closebutton' id='"+ this.className +"-closebutton' onclick='protoGrowls.close(\""+ growl_id +"\");'>X</div>\
179 <div class='"+ this.className +"-title' id='"+ this.className +"-title'>"+ this.title +"</div>\
180 <div class='"+ this.className +"-content' id='"+ this.className +"-content-" + this.id +"'> </div>\
181 </div>\
182 ";
183 Element.hide(growl_div);
184
185 parent.insertBefore(growl_div, parent.firstChild);
186
187 if(!this.closable) {
188 Element.hide(this.className + "-closebutton");
189 }
190
191 //debug(growl_div.innerHTML);
192
193 return growl_div;
194 },
195
196 collectElement: function( elmId, def_parent )
197 {
198 var growl_div = document.getElementById(elmId);
199 var growl_id = this.id;
200 //debug('collect elmid: '+elmId);
201 //debug('collect id: '+growl_id);
202 if(!growl_div) {
203 //debug( 'element not found!' );
204 this.create( def_parent );
205 }
206
207 //var growl_div_content = document.getElementById(elmId+'-content');
208 //growl_div_content.setAttribute('id', elmId+'-content-'+growl_id);
209
210 growl_div.setAttribute('id', growl_id);
211 var growl_div_real = document.getElementById(growl_id);
212
213 //debug('collect afterid: '+growl_div_real.id);
214
215 //if(this.title != '') {
216 //this.setTitle(this.title);
217 //}
218
219 Element.hide(growl_div_real);
220 return growl_div_real;
221 },
222
223 placeprotoGrowl: function()
224 {
225 var element = this.element;
226 if(element == undefined || isNull(element)) {
227 return false;
228 }
229
230 var windowScroll = WindowUtilities.getWindowScroll();
231 var pageSize = WindowUtilities.getPageSize();
232
233 var X = 0;
234 var Y = 0;
235 var middle = getViewportSize()[0]/2 + getScrollXY()[0] - this.width/2;
236 //var growlCnt = activeprotoGrowlList.length-1;
237
238 Y = ((getViewportSize()[1] + getScrollXY()[1]) - this.padding[0] - this.height);
239 // - (growlCnt*gH) - (growlCnt*gPadding);
240 X = windowScroll.left + (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2;//middle;
241
242 //debug('x:'+X+' y:'+Y);
243
244 this.setStyle({position: 'absolute'});
245 this.setLocation( Y, X );
246 },
247
248 moveUp: function()
249 {
250 //debug('move up: '+this.id);
251 var Y = 0;
252 Y = this.top - this.height - this.padding[0];
253 this.setLocation( Y );
254 },
255
256 setLocation: function(top, left, bottom, right)
257 {
258 if(top == null || top == undefined) {
259 var top = '';
260 }
261 if(left == null || left == undefined) {
262 var left = '';
263 }
264 if(right == null || right == undefined) {
265 var right = '';
266 }
267 if(bottom == null || bottom == undefined) {
268 var bottom = '';
269 }
270
271 if(top != '') {
272 this.top = top;
273 this.setStyle({top: top + 'px'});
274 this.useTop = true;
275 this.useBottom = false;
276 } else if(bottom != '') {
277 this.bottom = bottom;
278 this.setStyle({bottom: bottom + 'px'});
279 this.useTop = false;
280 this.useBottom = true;
281 }
282
283 if(left != '') {
284 this.left = left;
285 this.setStyle({left: left + 'px'});
286 this.useLeft = true;
287 this.useRight = false;
288 } else if(right != '') {
289 this.right = right;
290 this.setStyle({right: right + 'px'});
291 this.useLeft = false;
292 this.useRight = true;
293 }
294
295 },
296
297 setSize: function(width, height)
298 {
299 if(width < this.minWidth) {
300 width = this.minWidth;
301 }
302
303 if(height < this.minHeight) {
304 height = this.minHeight;
305 }
306
307 if(this.maxHeight && height > this.maxHeight) {
308 height = this.maxHeight;
309 }
310
311 if(this.maxWidth && width > this.maxWidth) {
312 width = this.maxWidth;
313 }
314
315 this.width = width;
316 this.height = height;
317
318 this.setStyle({width: width + this.widthW + this.widthE + "px"});
319 this.setStyle({height: height + this.heightN + this.heightS + "px"});
320 },
321
322 show: function()
323 {
324 //debug('show: '+this.id);
325 //debug('show x:'+this.element.style.left+' y:'+this.element.style.top);
326 this.placeprotoGrowl();
327 this.setSize(this.width, this.height);
328
329 if(this.showEffect != Element.show && this.showEffectOptions ) {
330 //debug('this.showEffect: '+this.showEffect);
331 this.showEffect(this.element, this.showEffectOptions);
332 } else {
333 //debug('this.showEffect (no options): '+this.showEffect);
334 this.showEffect(this.element);
335 }
336 },
337
338 hide: function( id )
339 {
340 //debug('hide: '+this.id);
341 if(this.hideEffectOptions) {
342 this.hideEffect(this.element, this.hideEffectOptions);
343 } else {
344 this.hideEffect(this.element);
345 }
346
347 //if(this.iefix)
348 // this.iefix.hide();
349 },
350
351 center: function()
352 {
353 var windowScroll = WindowUtilities.getWindowScroll();
354 var pageSize = WindowUtilities.getPageSize();
355
356 this.setLocation(windowScroll.top + (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2, windowScroll.left + (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2);
357 },
358
359 destroy: function( id )
360 {
361 if(this.destroyed) {
362 return false;
363 }
364 protoGrowls.notify("onDestroy", this);
365
366 Event.stopObserving(this.closeBtn, "mouseup", this.eventMouseUp);
367 Event.stopObserving(window, "load", this.eventOnLoad);
368
369 if(this.iefix) {
370 Element.hide(this.iefix);
371 }
372
373 var objBody = document.getElementsByTagName("body").item(0);
374 objBody.removeChild(this.element);
375 this.destroyed = true;
376 protoGrowls.unregister(this);
377 },
378
379 setDelegate: function(delegate)
380 {
381 this.delegate = delegate;
382 },
383
384 getDelegate: function()
385 {
386 return this.delegate;
387 },
388
389 getContent: function ()
390 {
391 //alert(document.getElementById(this.id).innerHTML);
392 //var elid = this.className + "-content-" + this.id;
393 //alert(elid);
394 //alert(document.getElementById(elid));
395 //alert(document.getElementsByClassName(this.className + "-content-" + this.id));
396 return document.getElementById(this.className + "-content-" + this.id);
397 },
398
399 setContent: function(id, autoposition)
400 {
401 var d = null;
402 var p = null;
403
404 if(autoposition) {
405 p = Position.cumulativeOffset($(id));
406 }
407
408 var content = this.getContent()
409 content.appendChild($(id));
410
411 if(autoposition) {
412 this.setLocation(p[1] - this.heightN, p[0] - this.widthW);
413 }
414 },
415
416 setStyle: function(style)
417 {
418 for (name in style) {
419 this.element.style[name.camelize()] = style[name];
420 }
421 },
422
423 getId: function()
424 {
425 return this.element.id;
426 },
427
428 closeObject: function()
429 {
430 if(this.closeBtn) {
431 return;
432 }
433 },
434
435 getWindowMeasurements: function(event)
436 {
437 var div = this.createHiddenDiv(this.className + "_n")
438 this.heightN = Element.getDimensions(div).height;
439 div.parentNode.removeChild(div)
440
441 var div = this.createHiddenDiv(this.className + "_s")
442 this.heightS = Element.getDimensions(div).height;
443 div.parentNode.removeChild(div)
444
445 var div = this.createHiddenDiv(this.className + "_e")
446 this.widthE = Element.getDimensions(div).width;
447 div.parentNode.removeChild(div)
448
449 var div = this.createHiddenDiv(this.className + "_w")
450 this.widthW = Element.getDimensions(div).width;
451 div.parentNode.removeChild(div);
452 },
453
454 createHiddenDiv: function(className)
455 {
456 var objBody = document.getElementsByTagName("body").item(0);
457
458 var growl_hidden_div = document.createElement("div");
459 growl_hidden_div.setAttribute('id', this.id + "-tmp");
460 growl_hidden_div.className = className;
461 growl_hidden_div.style.display = 'none';
462 growl_hidden_div.innerHTML = '';
463
464 objBody.insertBefore(growl_hidden_div, objBody.firstChild)
465
466 return growl_hidden_div;
467 },
468
469 nextID: function()
470 {
471 return protoGrowls.getNextId();
472 },
473
474 setZIndex: function(zindex)
475 {
476 this.setStyle({zIndex: zindex});
477 protoGrowls.updateZindex(zindex, this);
478 },
479
480 setTitle: function(newTitle)
481 {
482 if(!newTitle) {
483 newTitle = "&nbsp;";
484 Element.update(this.className + '-title', newTitle);
485 }
486 }
487
488 };
489
490 var protoGrowls = {
491 growls: [],
492 observers: [],
493 focusedWindow: null,
494 maxZIndex: 0,
495 maxprotoGrowls: 3,
496 listenFrequency: 0.8,
497 nextid: 1,
498
499 addObserver: function(observer) {
500 this.observers.push(observer);
501 },
502
503 removeObserver: function(observer) {
504 this.observers = this.observers.reject( function(o) { return o==observer });
505 },
506
507 notify: function(eventName, growl) {
508 this.observers.each( function(o) {if(o[eventName]) o[eventName](eventName, growl);});
509 },
510
511 growlExists: function(id)
512 {
513 return this.growls.detect(function(d) { return d.getId() ==id });
514 },
515
516 getprotoGrowl: function(id)
517 {
518 return this.growls.detect(function(d) { if(d.getId()==id){return d;} });
519 },
520
521 setMaxprotoGrowls: function( max )
522 {
523 this.maxprotoGrowls = max;
524 },
525
526 getNextId: function()
527 {
528 return this.nextid;
529 },
530
531 register: function(growl) {
532 var growlCnt = this.growls.length;
533 this.nextid = growl.id+1;
534 if(growlCnt < this.maxprotoGrowls) {
535 this.moveUp();
536 growl.registered = new Date().getTime();
537 this.growls.push(growl);
538 } else {
539 this.removeFirst();
540 this.moveUp();
541 growl.registered = new Date().getTime();
542 this.growls.push(growl);
543 }
544 },
545
546 removeFirst: function()
547 {
548 var oldest = this.growls[0];
549 //debug('oldest id: '+oldest.id);
550 this.close(oldest.id);
551 },
552
553 unregister: function(growl) {
554 this.growls = this.growls.reject(function(d) { return d==growl });
555 },
556
557 close: function(id) {
558 growl = this.growlExists(id);
559 if (growl) {
560 if(growl.getDelegate() && ! growl.getDelegate().canClose(growl)) {
561 return;
562 }
563
564 this.notify("onClose", growl);
565 growl.hide();
566 }
567 },
568
569 isExpired: function( id )
570 {
571 var growl = this.getprotoGrowl(id);
572 var timestamp = new Date().getTime();
573 var expires = growl.registered + growl.lifetime;
574 if(expires <= timestamp) {
575 return true;
576 }
577 return false;
578 },
579
580 moveUp: function() {
581 this.growls.each( function(g) {g.moveUp()} );
582 },
583
584 closeAll: function() {
585 this.growls.each( function(g) {protoGrowls.close(g.getId())} );
586 },
587
588 updateZindex: function(zindex, growl) {
589 if(zindex > this.maxZIndex) {
590 this.maxZIndex = zindex;
591 }
592 this.focusedWindow = growl;
593 }
594 };
595
596 var BodyReader = Class.create();
597 BodyReader.prototype = {
598
599 initialize: function( params ) {
600 this.deftype = 'class';
601
602 this.start = params.body || 'body';
603 this.autotransform = params.autotransf || true;
604
605 this.name = params.name || 'midcom-service-uimessages-protogrowl';
606 this.growl_type = params.type || 'info';
607
608 if(!params.type) {
609 this.collect( this.name, this.deftype );
610 }
611 },
612 collect: function( p_var, p_type ) {
613 var element = '';
614 var elements = '';
615
616 if(p_type == 'id') {
617 element = document.getElementById(p_var);
618 var growl_type = this.growl_type || 'info';
619 if(this.autotransform && element) {
620 this.transform( p_var, growl_type );
621 }
622 }
623 if(p_type == 'class') {
624 elements = document.getElementsByClassName(p_var);
625 if(elements.length>0) {
626 for(var i=0;i<elements.length;i++) {
627 var growl_type = this.growl_type || 'info';
628 if(this.autotransform && elements[i]) {
629 var tempid = 'midcom-service-uimessages-protogrowl_tmp_obj_'+i;
630 elements[i].setAttribute('id', tempid);
631 this.transform( tempid, growl_type );
632 }
633 }
634 }
635 }
636 },
637 transform: function( p_name, p_type, p_readtype ) {
638 new protoGrowl({type: p_type, element: p_name});
639 }
640 };
641 //var BodyReader = new BodyReader( {} );
642
643 var LifeWatcher = Class.create();
644 LifeWatcher.prototype = {
645 initialize: function() {
646 this.defaultLifetime = 8;
647
648 //this.execute();
649 },
650
651 execute: function() {
652 var growlCnt = protoGrowls.growls.length;
653 //debug('lw execute: '+new Date().getTime());
654 if(growlCnt>=1) {
655 protoGrowls.growls.each( function(g) {
656 var gID = g.getId();
657 if(protoGrowls.isExpired(gID)) {
658 protoGrowls.close(gID);
659 }
660 } );
661 }
662 }
663 };
664 var LifeGuard = new LifeWatcher();
665 new PeriodicalExecuter(LifeGuard.execute,protoGrowls.listenFrequency);
666
667
668
669
670 var isIE = navigator.appVersion.match(/MSIE/) == "MSIE";
671
672 var WindowUtilities = {
673
674 getWindowScroll: function() {
675 var w = window;
676 var T, L, W, H;
677 with (w.document) {
678 if (w.document.documentElement && documentElement.scrollTop) {
679 T = documentElement.scrollTop;
680 L = documentElement.scrollLeft;
681 } else if (w.document.body) {
682 T = body.scrollTop;
683 L = body.scrollLeft;
684 }
685 if (w.innerWidth) {
686 W = w.innerWidth;
687 H = w.innerHeight;
688 } else if (w.document.documentElement && documentElement.clientWidth) {
689 W = documentElement.clientWidth;
690 H = documentElement.clientHeight;
691 } else {
692 W = body.offsetWidth;
693 H = body.offsetHeight
694 }
695 }
696 return { top: T, left: L, width: W, height: H };
697
698 },
699
700 getPageSize: function(){
701 var xScroll, yScroll;
702
703 if (window.innerHeight && window.scrollMaxY) {
704 xScroll = document.body.scrollWidth;
705 yScroll = window.innerHeight + window.scrollMaxY;
706 } else if (document.body.scrollHeight > document.body.offsetHeight){
707 xScroll = document.body.scrollWidth;
708 yScroll = document.body.scrollHeight;
709 } else {
710 xScroll = document.body.offsetWidth;
711 yScroll = document.body.offsetHeight;
712 }
713
714 var windowWidth, windowHeight;
715
716 if (self.innerHeight) {
717 windowWidth = self.innerWidth;
718 windowHeight = self.innerHeight;
719 } else if (document.documentElement && document.documentElement.clientHeight) {
720 windowWidth = document.documentElement.clientWidth;
721 windowHeight = document.documentElement.clientHeight;
722 } else if (document.body) {
723 windowWidth = document.body.clientWidth;
724 windowHeight = document.body.clientHeight;
725 }
726 var pageHeight, pageWidth;
727
728 if(yScroll < windowHeight){
729 pageHeight = windowHeight;
730 } else {
731 pageHeight = yScroll;
732 }
733
734 if(xScroll < windowWidth){
735 pageWidth = windowWidth;
736 } else {
737 pageWidth = xScroll;
738 }
739
740 return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight};
741 }
742
743 };
744
745 /* Midgard common */
746
747 function isNull(a) {
748 return typeof a == 'object' && !a;
749 }
750
751 function getScrollXY() {
752 var scrOfX = 0, scrOfY = 0;
753
754 if(typeof(window.pageYOffset) == 'number') {
755 //Netscape compliant
756 scrOfY = window.pageYOffset;
757 scrOfX = window.pageXOffset;
758
759 } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) {
760 //DOM compliant
761 scrOfY = document.body.scrollTop;
762 scrOfX = document.body.scrollLeft;
763
764 } else if (document.documentElement &&
765 (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
766 //IE6 standards compliant mode
767 scrOfY = document.documentElement.scrollTop;
768 scrOfX = document.documentElement.scrollLeft;
769 }
770
771 return [scrOfX, scrOfY];
772 }
773
774 function getViewportSize() {
775 var myWidth = 0, myHeight = 0;
776
777 if (typeof(window.innerWidth ) == 'number') {
778 //Non-IE
779 myWidth = window.innerWidth;
780 myHeight = window.innerHeight;
781
782 } else if (document.documentElement &&
783 (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
784 //IE 6+ in 'standards compliant mode'
785 myWidth = document.documentElement.clientWidth;
786 myHeight = document.documentElement.clientHeight;
787
788 } else if (document.body && (document.body.clientWidth || document.body.clientHeight)) {
789 //IE 4 compatible
790 myWidth = document.body.clientWidth;
791 myHeight = document.body.clientHeight;
792 }
793
794 return [myWidth, myHeight];
795 }

  ViewVC Help
Powered by ViewVC 1.1.26