Upgrade to ExtJS 3.0.0 - Released 07/06/2009
[extjs.git] / docs / source / prototype-bridge.html
1 <html>\r
2 <head>\r
3   <title>The source code</title>\r
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />\r
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>\r
6 </head>\r
7 <body  onload="prettyPrint();">\r
8     <pre class="prettyprint lang-js">(function(){
9
10 var libFlyweight,
11     version = Prototype.Version.split('.'),
12     mouseEnterSupported = (parseInt(version[0]) >= 2) || (parseInt(version[1]) >= 7) || (parseInt(version[2]) >= 1),
13     mouseCache = {},
14     isXUL = Ext.isGecko ? function(node){ 
15         return Object.prototype.toString.call(node) == '[object XULElement]';
16     } : function(){},
17     isTextNode = Ext.isGecko ? function(node){
18         try{
19             return node.nodeType == 3;
20         }catch(e) {
21             return false;
22         }
23
24     } : function(node){
25         return node.nodeType == 3;
26     },
27     elContains = function(parent, child) {
28        if(parent && parent.firstChild){  
29          while(child) {
30             if(child === parent) {
31                 return true;
32             }
33             try {
34                 child = child.parentNode;
35             } catch(e) {
36                 // In FF if you mouseout an text input element
37                 // thats inside a div sometimes it randomly throws
38                 // Permission denied to get property HTMLDivElement.parentNode
39                 // See https://bugzilla.mozilla.org/show_bug.cgi?id=208427
40                 return false;
41             }                
42             if(child && (child.nodeType != 1)) {
43                 child = null;
44             }
45           }
46         }
47         return false;
48     },
49     checkRelatedTarget = function(e) {
50         var related = Ext.lib.Event.getRelatedTarget(e);
51         return !(isXUL(related) || elContains(e.currentTarget,related));
52     };
53
54 Ext.lib.Dom = {
55     getViewWidth : function(full){
56         return full ? this.getDocumentWidth() : this.getViewportWidth();
57     },
58
59     getViewHeight : function(full){
60         return full ? this.getDocumentHeight() : this.getViewportHeight();
61     },
62
63     getDocumentHeight: function() { // missing from prototype?
64         var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
65         return Math.max(scrollHeight, this.getViewportHeight());
66     },
67
68     getDocumentWidth: function() { // missing from prototype?
69         var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
70         return Math.max(scrollWidth, this.getViewportWidth());
71     },
72
73     getViewportHeight: function() { // missing from prototype?
74         var height = self.innerHeight;
75         var mode = document.compatMode;
76
77         if ( (mode || Ext.isIE) && !Ext.isOpera ) {
78             height = (mode == "CSS1Compat") ?
79                     document.documentElement.clientHeight : // Standards
80                     document.body.clientHeight; // Quirks
81         }
82
83         return height;
84     },
85
86     getViewportWidth: function() { // missing from prototype?
87         var width = self.innerWidth;  // Safari
88         var mode = document.compatMode;
89
90         if (mode || Ext.isIE) { // IE, Gecko, Opera
91             width = (mode == "CSS1Compat") ?
92                     document.documentElement.clientWidth : // Standards
93                     document.body.clientWidth; // Quirks
94         }
95         return width;
96     },
97
98     isAncestor : function(p, c){ // missing from prototype?
99         p = Ext.getDom(p);
100         c = Ext.getDom(c);
101         if (!p || !c) {return false;}
102
103         if(p.contains && !Ext.isSafari) {
104             return p.contains(c);
105         }else if(p.compareDocumentPosition) {
106             return !!(p.compareDocumentPosition(c) & 16);
107         }else{
108             var parent = c.parentNode;
109             while (parent) {
110                 if (parent == p) {
111                     return true;
112                 }
113                 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
114                     return false;
115                 }
116                 parent = parent.parentNode;
117             }
118             return false;
119         }
120     },
121
122     getRegion : function(el){
123         return Ext.lib.Region.getRegion(el);
124     },
125
126     getY : function(el){
127         return this.getXY(el)[1];
128     },
129
130     getX : function(el){
131         return this.getXY(el)[0];
132     },
133
134     getXY : function(el){ // this initially used Position.cumulativeOffset but it is not accurate enough
135         var p, pe, b, scroll, bd = (document.body || document.documentElement);
136         el = Ext.getDom(el);
137
138         if(el == bd){
139             return [0, 0];
140         }
141
142         if (el.getBoundingClientRect) {
143             b = el.getBoundingClientRect();
144             scroll = fly(document).getScroll();
145             return [Math.round(b.left + scroll.left), Math.round(b.top + scroll.top)];
146         }
147         var x = 0, y = 0;
148
149         p = el;
150
151         var hasAbsolute = fly(el).getStyle("position") == "absolute";
152
153         while (p) {
154
155             x += p.offsetLeft;
156             y += p.offsetTop;
157
158             if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
159                 hasAbsolute = true;
160             }
161
162             if (Ext.isGecko) {
163                 pe = fly(p);
164
165                 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
166                 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
167
168
169                 x += bl;
170                 y += bt;
171
172
173                 if (p != el && pe.getStyle('overflow') != 'visible') {
174                     x += bl;
175                     y += bt;
176                 }
177             }
178             p = p.offsetParent;
179         }
180
181         if (Ext.isSafari && hasAbsolute) {
182             x -= bd.offsetLeft;
183             y -= bd.offsetTop;
184         }
185
186         if (Ext.isGecko && !hasAbsolute) {
187             var dbd = fly(bd);
188             x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
189             y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
190         }
191
192         p = el.parentNode;
193         while (p && p != bd) {
194             if (!Ext.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
195                 x -= p.scrollLeft;
196                 y -= p.scrollTop;
197             }
198             p = p.parentNode;
199         }
200         return [x, y];
201     },
202
203     setXY : function(el, xy){ // this initially used Position.cumulativeOffset but it is not accurate enough
204         el = Ext.fly(el, '_setXY');
205         el.position();
206         var pts = el.translatePoints(xy);
207         if(xy[0] !== false){
208             el.dom.style.left = pts.left + "px";
209         }
210         if(xy[1] !== false){
211             el.dom.style.top = pts.top + "px";
212         }
213     },
214
215     setX : function(el, x){
216         this.setXY(el, [x, false]);
217     },
218
219     setY : function(el, y){
220         this.setXY(el, [false, y]);
221     }
222 };
223
224 Ext.lib.Event = {
225     getPageX : function(e){
226         return Event.pointerX(e.browserEvent || e);
227     },
228
229     getPageY : function(e){
230         return Event.pointerY(e.browserEvent || e);
231     },
232
233     getXY : function(e){
234         e = e.browserEvent || e;
235         return [Event.pointerX(e), Event.pointerY(e)];
236     },
237
238     getTarget : function(e){
239         return Event.element(e.browserEvent || e);
240     },
241
242     resolveTextNode: function(node) {
243         return node && !isXUL(node) && isTextNode(node) ? node.parentNode : node;
244     },
245
246     getRelatedTarget: function(ev) { // missing from prototype?
247         ev = ev.browserEvent || ev;
248         var t = ev.relatedTarget;
249         if (!t) {
250             if (ev.type == "mouseout") {
251                 t = ev.toElement;
252             } else if (ev.type == "mouseover") {
253                 t = ev.fromElement;
254             }
255         }
256
257         return this.resolveTextNode(t);
258     },
259
260     on : function(el, eventName, fn){
261         if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
262             var item = mouseCache[el.id] || (mouseCache[el.id] = {});
263             item[eventName] = fn;
264             fn = fn.createInterceptor(checkRelatedTarget);
265             eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
266         }
267         Event.observe(el, eventName, fn, false);
268     },
269
270     un : function(el, eventName, fn){
271         if((eventName == 'mouseenter' || eventName == 'mouseleave') && !mouseEnterSupported){
272             var item = mouseCache[el.id], 
273                 ev = item && item[eventName];
274
275             if(ev){
276                 fn = ev.fn;
277                 delete item[eventName];
278                 eventName = (eventName == 'mouseenter') ? 'mouseover' : 'mouseout';
279             }
280         }
281         Event.stopObserving(el, eventName, fn, false);
282     },
283
284     purgeElement : function(el){
285         // no equiv?
286     },
287
288     preventDefault : function(e){   // missing from prototype?
289         e = e.browserEvent || e;
290         if(e.preventDefault) {
291             e.preventDefault();
292         } else {
293             e.returnValue = false;
294         }
295     },
296
297     stopPropagation : function(e){   // missing from prototype?
298         e = e.browserEvent || e;
299         if(e.stopPropagation) {
300             e.stopPropagation();
301         } else {
302             e.cancelBubble = true;
303         }
304     },
305
306     stopEvent : function(e){
307         Event.stop(e.browserEvent || e);
308     },
309
310     onAvailable : function(id, fn, scope){  // no equiv
311         var start = new Date(), iid;
312         var f = function(){
313             if(start.getElapsed() > 10000){
314                 clearInterval(iid);
315             }
316             var el = document.getElementById(id);
317             if(el){
318                 clearInterval(iid);
319                 fn.call(scope||window, el);
320             }
321         };
322         iid = setInterval(f, 50);
323     }
324 };
325
326 Ext.lib.Ajax = function(){
327     var createSuccess = function(cb){
328          return cb.success ? function(xhr){
329             cb.success.call(cb.scope||window, {
330                 responseText: xhr.responseText,
331                 responseXML : xhr.responseXML,
332                 argument: cb.argument
333             });
334          } : Ext.emptyFn;
335     };
336     var createFailure = function(cb){
337          return cb.failure ? function(xhr){
338             cb.failure.call(cb.scope||window, {
339                 responseText: xhr.responseText,
340                 responseXML : xhr.responseXML,
341                 argument: cb.argument
342             });
343          } : Ext.emptyFn;
344     };
345     return {
346         request : function(method, uri, cb, data, options){
347             var o = {
348                 method: method,
349                 parameters: data || '',
350                 timeout: cb.timeout,
351                 onSuccess: createSuccess(cb),
352                 onFailure: createFailure(cb)
353             };
354             if(options){
355                 var hs = options.headers;
356                 if(hs){
357                     o.requestHeaders = hs;
358                 }
359                 if(options.xmlData){
360                     method = (method ? method : (options.method ? options.method : 'POST'));
361                     if (!hs || !hs['Content-Type']){
362                         o.contentType = 'text/xml';
363                     }
364                     o.postBody = options.xmlData;
365                     delete o.parameters;
366                 }
367                 if(options.jsonData){
368                     method = (method ? method : (options.method ? options.method : 'POST'));
369                     if (!hs || !hs['Content-Type']){
370                         o.contentType = 'application/json';
371                     }
372                     o.postBody = typeof options.jsonData == 'object' ? Ext.encode(options.jsonData) : options.jsonData;
373                     delete o.parameters;
374                 }
375             }
376             new Ajax.Request(uri, o);
377         },
378
379         formRequest : function(form, uri, cb, data, isUpload, sslUri){
380             new Ajax.Request(uri, {
381                 method: Ext.getDom(form).method ||'POST',
382                 parameters: Form.serialize(form)+(data?'&'+data:''),
383                 timeout: cb.timeout,
384                 onSuccess: createSuccess(cb),
385                 onFailure: createFailure(cb)
386             });
387         },
388
389         isCallInProgress : function(trans){
390             return false;
391         },
392
393         abort : function(trans){
394             return false;
395         },
396         
397         serializeForm : function(form){
398             return Form.serialize(form.dom||form);
399         }
400     };
401 }();
402
403
404 Ext.lib.Anim = function(){
405     
406     var easings = {
407         easeOut: function(pos) {
408             return 1-Math.pow(1-pos,2);
409         },
410         easeIn: function(pos) {
411             return 1-Math.pow(1-pos,2);
412         }
413     };
414     var createAnim = function(cb, scope){
415         return {
416             stop : function(skipToLast){
417                 this.effect.cancel();
418             },
419
420             isAnimated : function(){
421                 return this.effect.state == 'running';
422             },
423
424             proxyCallback : function(){
425                 Ext.callback(cb, scope);
426             }
427         };
428     };
429     return {
430         scroll : function(el, args, duration, easing, cb, scope){
431             // not supported so scroll immediately?
432             var anim = createAnim(cb, scope);
433             el = Ext.getDom(el);
434             if(typeof args.scroll.to[0] == 'number'){
435                 el.scrollLeft = args.scroll.to[0];
436             }
437             if(typeof args.scroll.to[1] == 'number'){
438                 el.scrollTop = args.scroll.to[1];
439             }
440             anim.proxyCallback();
441             return anim;
442         },
443
444         motion : function(el, args, duration, easing, cb, scope){
445             return this.run(el, args, duration, easing, cb, scope);
446         },
447
448         color : function(el, args, duration, easing, cb, scope){
449             return this.run(el, args, duration, easing, cb, scope);
450         },
451
452         run : function(el, args, duration, easing, cb, scope, type){
453             var o = {};
454             for(var k in args){
455                 switch(k){   // scriptaculous doesn't support, so convert these
456                     case 'points':
457                         var by, pts, e = Ext.fly(el, '_animrun');
458                         e.position();
459                         if(by = args.points.by){
460                             var xy = e.getXY();
461                             pts = e.translatePoints([xy[0]+by[0], xy[1]+by[1]]);
462                         }else{
463                             pts = e.translatePoints(args.points.to);
464                         }
465                         o.left = pts.left+'px';
466                         o.top = pts.top+'px';
467                     break;
468                     case 'width':
469                         o.width = args.width.to+'px';
470                     break;
471                     case 'height':
472                         o.height = args.height.to+'px';
473                     break;
474                     case 'opacity':
475                         o.opacity = String(args.opacity.to);
476                     break;
477                     default:
478                         o[k] = String(args[k].to);
479                     break;
480                 }
481             }
482             var anim = createAnim(cb, scope);
483             anim.effect = new Effect.Morph(Ext.id(el), {
484                 duration: duration,
485                 afterFinish: anim.proxyCallback,
486                 transition: easings[easing] || Effect.Transitions.linear,
487                 style: o
488             });
489             return anim;
490         }
491     };
492 }();
493
494
495 // all lib flyweight calls use their own flyweight to prevent collisions with developer flyweights
496 function fly(el){
497     if(!libFlyweight){
498         libFlyweight = new Ext.Element.Flyweight();
499     }
500     libFlyweight.dom = el;
501     return libFlyweight;
502 }
503     
504 Ext.lib.Region = function(t, r, b, l) {
505     this.top = t;
506     this[1] = t;
507     this.right = r;
508     this.bottom = b;
509     this.left = l;
510     this[0] = l;
511 };
512
513 Ext.lib.Region.prototype = {
514     contains : function(region) {
515         return ( region.left   >= this.left   &&
516                  region.right  <= this.right  &&
517                  region.top    >= this.top    &&
518                  region.bottom <= this.bottom    );
519
520     },
521
522     getArea : function() {
523         return ( (this.bottom - this.top) * (this.right - this.left) );
524     },
525
526     intersect : function(region) {
527         var t = Math.max( this.top,    region.top    );
528         var r = Math.min( this.right,  region.right  );
529         var b = Math.min( this.bottom, region.bottom );
530         var l = Math.max( this.left,   region.left   );
531
532         if (b >= t && r >= l) {
533             return new Ext.lib.Region(t, r, b, l);
534         } else {
535             return null;
536         }
537     },
538     union : function(region) {
539         var t = Math.min( this.top,    region.top    );
540         var r = Math.max( this.right,  region.right  );
541         var b = Math.max( this.bottom, region.bottom );
542         var l = Math.min( this.left,   region.left   );
543
544         return new Ext.lib.Region(t, r, b, l);
545     },
546
547     constrainTo : function(r) {
548             this.top = this.top.constrain(r.top, r.bottom);
549             this.bottom = this.bottom.constrain(r.top, r.bottom);
550             this.left = this.left.constrain(r.left, r.right);
551             this.right = this.right.constrain(r.left, r.right);
552             return this;
553     },
554
555     adjust : function(t, l, b, r){
556         this.top += t;
557         this.left += l;
558         this.right += r;
559         this.bottom += b;
560         return this;
561     }
562 };
563
564 Ext.lib.Region.getRegion = function(el) {
565     var p = Ext.lib.Dom.getXY(el);
566
567     var t = p[1];
568     var r = p[0] + el.offsetWidth;
569     var b = p[1] + el.offsetHeight;
570     var l = p[0];
571
572     return new Ext.lib.Region(t, r, b, l);
573 };
574
575 Ext.lib.Point = function(x, y) {
576    if (Ext.isArray(x)) {
577       y = x[1];
578       x = x[0];
579    }
580     this.x = this.right = this.left = this[0] = x;
581     this.y = this.top = this.bottom = this[1] = y;
582 };
583
584 Ext.lib.Point.prototype = new Ext.lib.Region();
585
586
587 // prevent IE leaks
588 if(Ext.isIE) {
589     function fnCleanUp() {
590         var p = Function.prototype;
591         delete p.createSequence;
592         delete p.defer;
593         delete p.createDelegate;
594         delete p.createCallback;
595         delete p.createInterceptor;
596
597         window.detachEvent("onunload", fnCleanUp);
598     }
599     window.attachEvent("onunload", fnCleanUp);
600 }
601 })();</pre>    \r
602 </body>\r
603 </html>