r24958: This is the final text, and the final version. I'll send the release
[jelmer/samba4-debian.git] / webapps / qooxdoo-0.6.5-sdk / frontend / framework / source / class / qx / client / NativeWindow.js
1 /* ************************************************************************
2
3    qooxdoo - the new era of web development
4
5    http://qooxdoo.org
6
7    Copyright:
8      2004-2007 1&1 Internet AG, Germany, http://www.1and1.org
9
10    License:
11      LGPL: http://www.gnu.org/licenses/lgpl.html
12      EPL: http://www.eclipse.org/org/documents/epl-v10.php
13      See the LICENSE file in the project's top-level directory for details.
14
15    Authors:
16      * Sebastian Werner (wpbasti)
17      * Andreas Ecker (ecker)
18
19 ************************************************************************ */
20
21 /* ************************************************************************
22
23 #require(qx.html.Window)
24
25 ************************************************************************ */
26
27 qx.OO.defineClass("qx.client.NativeWindow", qx.core.Target,
28 function(vUrl, vName)
29 {
30   qx.core.Target.call(this);
31
32
33   // ************************************************************************
34   //   TIMER
35   // ************************************************************************
36
37   this._timer = new qx.client.Timer(100);
38   this._timer.addEventListener("interval", this._oninterval, this);
39
40
41   // ************************************************************************
42   //   INITIAL PROPERTIES
43   // ************************************************************************
44
45   if (vUrl != null) {
46     this.setUrl(vUrl);
47   }
48
49   if (vName != null) {
50     this.setName(vName);
51   }
52 });
53
54
55
56
57
58 /*
59 ---------------------------------------------------------------------------
60   PROPERTIES
61 ---------------------------------------------------------------------------
62 */
63
64 /*!
65   If the window is open or closed
66 */
67 qx.OO.addProperty({ name : "open", type : "boolean", defaultValue : false });
68
69 /*!
70   The outer width of the window.
71 */
72 qx.OO.addProperty({ name : "width", type : "number", defaultValue : 400, impl : "dimension" });
73
74 /*!
75   The outer height of the window.
76 */
77 qx.OO.addProperty({ name : "height", type : "number", defaultValue : 250, impl : "dimension" });
78
79 /*!
80   The left screen coordinate of the window.
81 */
82 qx.OO.addProperty({ name : "left", type : "number", defaultValue : 100, impl : "position" });
83
84 /*!
85   The top screen coordinate of the window.
86 */
87 qx.OO.addProperty({ name : "top", type : "number", defaultValue : 200, impl : "position" });
88
89 /*!
90   Should be window be modal
91 */
92 qx.OO.addProperty({ name : "modal", type : "boolean", defaultValue : false });
93
94 /*!
95   Should be window be dependent on this application window
96 */
97 qx.OO.addProperty({ name : "dependent", type : "boolean", defaultValue : true });
98
99 /*!
100   The url
101 */
102 qx.OO.addProperty({ name : "url", type : "string" });
103
104 /*!
105   The window name
106 */
107 qx.OO.addProperty({ name : "name", type : "string" });
108
109 /*!
110   The text of the statusbar
111 */
112 qx.OO.addProperty({ name : "status", type : "string", defaultValue : "Ready" });
113
114 /*!
115   Should the statusbar be shown
116 */
117 qx.OO.addProperty({ name : "showStatusbar", type : "boolean", defaultValue : false });
118
119 /*!
120   Should the menubar be shown
121 */
122 qx.OO.addProperty({ name : "showMenubar", type : "boolean", defaultValue : false });
123
124 /*!
125   Should the location(bar) be shown
126 */
127 qx.OO.addProperty({ name : "showLocation", type : "boolean", defaultValue : false });
128
129 /*!
130   Should the toolbar be shown
131 */
132 qx.OO.addProperty({ name : "showToolbar", type : "boolean", defaultValue : false });
133
134 /*!
135   If the window is resizeable
136 */
137 qx.OO.addProperty({ name : "resizeable", type : "boolean", defaultValue : true });
138
139 /*!
140   If the window is able to scroll and has visible scrollbars if needed
141 */
142 qx.OO.addProperty({ name : "allowScrollbars", type : "boolean", defaultValue : true });
143
144
145
146 /*
147 ---------------------------------------------------------------------------
148   STATE
149 ---------------------------------------------------------------------------
150 */
151
152 qx.Proto._loaded = false;
153
154
155
156
157 /*
158 ---------------------------------------------------------------------------
159   PROPERTY GROUPS
160 ---------------------------------------------------------------------------
161 */
162
163 qx.OO.addPropertyGroup({ name : "location", members : [ "left", "top" ]});
164 qx.OO.addPropertyGroup({ name : "dimension", members : [ "width", "height" ]});
165
166
167
168
169 /*
170 ---------------------------------------------------------------------------
171   MODIFIERS
172 ---------------------------------------------------------------------------
173 */
174
175 qx.Proto._modifyPosition = function(propValue, propOldValue, propName)
176 {
177   /*
178     http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx
179     Changes to Functionality in Microsoft Windows XP Service Pack 2
180     Part 5: Enhanced Browsing Security
181     URLACTION_FEATURE_WINDOW_RESTRICTIONS
182     Allow script-initiated windows without size or position constraints
183     Code: 2102
184   */
185
186   if (!this.isClosed())
187   {
188     try
189     {
190       this._window.moveTo(this.getLeft(), this.getTop());
191     }
192     catch(ex)
193     {
194       this.error("Cross-Domain Scripting problem: Could not move window!", ex);
195     }
196   }
197
198   return true;
199 }
200
201 qx.Proto._modifyDimension = function(propValue, propOldValue, propName)
202 {
203   /*
204     http://www.microsoft.com/technet/prodtechnol/winxppro/maintain/sp2brows.mspx
205     Changes to Functionality in Microsoft Windows XP Service Pack 2
206     Part 5: Enhanced Browsing Security
207     URLACTION_FEATURE_WINDOW_RESTRICTIONS
208     Allow script-initiated windows without size or position constraints
209     Code: 2102
210   */
211
212   if (!this.isClosed())
213   {
214     try
215     {
216       this._window.resizeTo(this.getWidth(), this.getHeight());
217     }
218     catch(ex)
219     {
220       this.error("Cross-Domain Scripting problem: Could not resize window!", ex);
221     }
222   }
223
224   return true;
225 }
226
227 qx.Proto._modifyName = function(propValue, propOldValue, propName)
228 {
229   if (!this.isClosed()) {
230     this._window.name = propValue;
231   }
232
233   return true;
234 }
235
236 qx.Proto._modifyUrl = function(propValue, propOldValue, propName)
237 {
238   // String hack needed for old compressor (compile.py)
239   if(!this.isClosed()) {
240     this._window.location.replace(propValue != null ? propValue : ("javascript:/" + "/"));
241   }
242
243   return true;
244 }
245
246 qx.Proto._modifyOpen = function(propValue, propOldValue, propData)
247 {
248   propValue ? this._open() : this._close();
249   return true;
250 }
251
252
253
254
255
256
257 /*
258 ---------------------------------------------------------------------------
259   NAME
260 ---------------------------------------------------------------------------
261 */
262
263 qx.Proto.getName = function()
264 {
265   if (!this.isClosed())
266   {
267     try
268     {
269       var vName = this._window.name;
270     }
271     catch(ex)
272     {
273       return this._valueName;
274     }
275
276     if (vName == this._valueName)
277     {
278       return vName;
279     }
280     else
281     {
282       throw new Error("window name and name property are not identical");
283     }
284   }
285   else
286   {
287     return this._valueName;
288   }
289 }
290
291
292
293
294
295
296 /*
297 ---------------------------------------------------------------------------
298   UTILITY
299 ---------------------------------------------------------------------------
300 */
301
302 qx.Proto.isClosed = function()
303 {
304   var vClosed = true;
305
306   if (this._window)
307   {
308     try {
309       vClosed = this._window.closed;
310     } catch(ex) {}
311   }
312
313   return vClosed;
314 }
315
316 qx.Proto.open = function() {
317   this.setOpen(true);
318 }
319
320 qx.Proto.close = function() {
321   this.setOpen(false);
322 }
323
324 qx.Proto.isLoaded = function() {
325   return this._loaded;
326 }
327
328
329
330
331
332
333
334 /*
335 ---------------------------------------------------------------------------
336   OPEN METHOD
337 ---------------------------------------------------------------------------
338 */
339
340 qx.Proto._open = function()
341 {
342   var vConf = [];
343
344
345   /*
346   ------------------------------------------------------------------------------
347     PRE CONFIGURE WINDOW
348   ------------------------------------------------------------------------------
349   */
350
351   if (this.getWidth() != null)
352   {
353     vConf.push("width");
354     vConf.push("=");
355     vConf.push(this.getWidth());
356     vConf.push(",");
357   }
358
359   if (this.getHeight() != null)
360   {
361     vConf.push("height");
362     vConf.push("=");
363     vConf.push(this.getHeight());
364     vConf.push(",");
365   }
366
367   if (this.getLeft() != null)
368   {
369     vConf.push("left");
370     vConf.push("=");
371     vConf.push(this.getLeft());
372     vConf.push(",");
373   }
374
375   if (this.getTop() != null)
376   {
377     vConf.push("top");
378     vConf.push("=");
379     vConf.push(this.getTop());
380     vConf.push(",");
381   }
382
383
384
385   vConf.push("dependent");
386   vConf.push("=");
387   vConf.push(this.getDependent() ? "yes" : "no");
388   vConf.push(",");
389
390   vConf.push("resizable");
391   vConf.push("=");
392   vConf.push(this.getResizeable() ? "yes" : "no");
393   vConf.push(",");
394
395   vConf.push("status");
396   vConf.push("=");
397   vConf.push(this.getShowStatusbar() ? "yes" : "no");
398   vConf.push(",");
399
400   vConf.push("location");
401   vConf.push("=");
402   vConf.push(this.getShowLocation() ? "yes" : "no");
403   vConf.push(",");
404
405   vConf.push("menubar");
406   vConf.push("=");
407   vConf.push(this.getShowMenubar() ? "yes" : "no");
408   vConf.push(",");
409
410   vConf.push("toolbar");
411   vConf.push("=");
412   vConf.push(this.getShowToolbar() ? "yes" : "no");
413   vConf.push(",");
414
415   vConf.push("scrollbars");
416   vConf.push("=");
417   vConf.push(this.getAllowScrollbars() ? "yes" : "no");
418   vConf.push(",");
419
420   vConf.push("modal");
421   vConf.push("=");
422   vConf.push(this.getModal() ? "yes" : "no");
423   vConf.push(",");
424
425
426
427
428
429
430   /*
431   ------------------------------------------------------------------------------
432     OPEN WINDOW
433   ------------------------------------------------------------------------------
434   */
435
436   if (this.getName() != null) {
437     this.setName("qx_NativeWindow" + this.toHashCode());
438   }
439
440   this._window = window.open(this.getUrl(), this.getName(), vConf.join(""));
441
442   if (this.isClosed())
443   {
444     this.error("Window could not be opened. It seems, there is a popup blocker active!");
445   }
446   else
447   {
448     // This try-catch is needed because of cross domain issues (access rights)
449     try
450     {
451       this._window._native = this;
452       this._window.onload = this._onload;
453     }
454     catch(ex) {}
455
456     // start timer for close detection
457     this._timer.start();
458
459     // block original document
460     if (this.getModal()) {
461       qx.ui.core.ClientDocument.getInstance().block(this);
462     }
463   }
464 }
465
466 qx.Proto._close = function()
467 {
468   if (!this._window) {
469     return;
470   }
471
472   // stop timer for close detection
473   this._timer.stop();
474
475   // release window again
476   if (this.getModal()){
477     qx.ui.core.ClientDocument.getInstance().release(this);
478   }
479
480   // finally close window
481   if (!this.isClosed()) {
482     this._window.close();
483   }
484
485   try
486   {
487     this._window._native = null;
488     this._window.onload = null;
489   }
490   catch(ex) {};
491
492   this._window = null;
493   this._loaded = false;
494
495   this.createDispatchEvent("close");
496 }
497
498
499
500
501
502
503 /*
504 ---------------------------------------------------------------------------
505   CENTER SUPPORT
506 ---------------------------------------------------------------------------
507 */
508
509 qx.Proto.centerToScreen = function() {
510   return this._centerHelper((screen.width - this.getWidth()) / 2, (screen.height - this.getHeight()) / 2);
511 }
512
513 qx.Proto.centerToScreenArea = function() {
514   return this._centerHelper((screen.availWidth - this.getWidth()) / 2, (screen.availHeight - this.getHeight()) / 2);
515 }
516
517 qx.Proto.centerToOpener = function() {
518   return this._centerHelper(((qx.html.Window.getInnerWidth(window) - this.getWidth()) / 2) + qx.html.Location.getScreenBoxLeft(window.document.body), ((qx.html.Window.getInnerHeight(window) - this.getHeight()) / 2) + qx.html.Location.getScreenBoxTop(window.document.body));
519 }
520
521 qx.Proto._centerHelper = function(l, t)
522 {
523   // set new values
524   this.setLeft(l);
525   this.setTop(t);
526
527   // focus window if opened
528   if (!this.isClosed()) {
529     this.focus();
530   }
531 }
532
533
534
535
536
537
538 /*
539 ---------------------------------------------------------------------------
540   FOCUS HANDLING
541 ---------------------------------------------------------------------------
542 */
543
544 qx.Proto.focus = function()
545 {
546   if (!this.isClosed()) {
547     this._window.focus();
548   }
549 }
550
551 qx.Proto.blur = function()
552 {
553   if (!this.isClosed()) {
554     this._window.blur();
555   }
556 }
557
558
559
560
561
562
563
564 /*
565 ---------------------------------------------------------------------------
566   EVENT HANDLING
567 ---------------------------------------------------------------------------
568 */
569
570 qx.Proto._oninterval = function(e)
571 {
572   if (this.isClosed()) {
573     this.setOpen(false);
574   }
575   else if (!this._loaded)
576   {
577     // This try-catch is needed because of cross domain issues (access rights)
578     try
579     {
580       if (this._window.document && this._window.document.readyState == "complete")
581       {
582         this._loaded = true;
583         this.createDispatchEvent("load");
584       }
585     }
586     catch(ex) {};
587   }
588 }
589
590 qx.Proto._onload = function(e)
591 {
592   var obj = this._native;
593
594   if (!obj._loaded)
595   {
596     obj._loaded = true;
597     obj.createDispatchEvent("load");
598   }
599 }
600
601
602
603
604
605
606 /*
607 ---------------------------------------------------------------------------
608   DISPOSER
609 ---------------------------------------------------------------------------
610 */
611
612 qx.Proto.dispose = function()
613 {
614   if (this.getDisposed()) {
615     return;
616   }
617
618   if (this.getDependent()) {
619     this.close();
620   }
621
622   if (this._timer)
623   {
624     this._timer.stop();
625     this._timer = null;
626   }
627
628   if (this._window)
629   {
630     try
631     {
632       this._window._native = null;
633       this._window.onload = null;
634     }
635     catch(ex) {};
636
637     this._window = null;
638   }
639
640   return qx.core.Target.prototype.dispose.call(this);
641 }