Bienvenue sur PostGIS.fr

Bienvenue sur PostGIS.fr , le site de la communauté des utilisateurs francophones de PostGIS.

PostGIS ajoute le support d'objets géographique à la base de données PostgreSQL. En effet, PostGIS "spatialise" le serverur PostgreSQL, ce qui permet de l'utiliser comme une base de données SIG.

Maintenu à jour, en fonction de nos disponibilités et des diverses sorties des outils que nous testons, nous vous proposons l'ensemble de nos travaux publiés en langue française.

source: trunk/workshop-routing-foss4g/web/OpenLayers/lib/OpenLayers/Popup.js @ 76

Revision 76, 34.0 KB checked in by djay, 12 years ago (diff)

Ajout du répertoire web

  • Property svn:executable set to *
Line 
1/* Copyright (c) 2006-2010 by OpenLayers Contributors (see authors.txt for
2 * full list of contributors). Published under the Clear BSD license. 
3 * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
4 * full text of the license. */
5
6
7/**
8 * Class: OpenLayers.Popup
9 * A popup is a small div that can opened and closed on the map.
10 * Typically opened in response to clicking on a marker. 
11 * See <OpenLayers.Marker>.  Popup's don't require their own
12 * layer and are added the the map using the <OpenLayers.Map.addPopup>
13 * method.
14 *
15 * Example:
16 * (code)
17 * popup = new OpenLayers.Popup("chicken",
18 *                    new OpenLayers.LonLat(5,40),
19 *                    new OpenLayers.Size(200,200),
20 *                    "example popup",
21 *                    true);
22 *       
23 * map.addPopup(popup);
24 * (end)
25 */
26OpenLayers.Popup = OpenLayers.Class({
27
28    /**
29     * Property: events 
30     * {<OpenLayers.Events>} custom event manager
31     */
32    events: null,
33   
34    /** Property: id
35     * {String} the unique identifier assigned to this popup.
36     */
37    id: "",
38
39    /**
40     * Property: lonlat
41     * {<OpenLayers.LonLat>} the position of this popup on the map
42     */
43    lonlat: null,
44
45    /**
46     * Property: div
47     * {DOMElement} the div that contains this popup.
48     */
49    div: null,
50
51    /**
52     * Property: contentSize
53     * {<OpenLayers.Size>} the width and height of the content.
54     */
55    contentSize: null,   
56
57    /**
58     * Property: size
59     * {<OpenLayers.Size>} the width and height of the popup.
60     */
61    size: null,   
62
63    /**
64     * Property: contentHTML
65     * {String} An HTML string for this popup to display.
66     */
67    contentHTML: null,
68   
69    /**
70     * Property: backgroundColor
71     * {String} the background color used by the popup.
72     */
73    backgroundColor: "",
74   
75    /**
76     * Property: opacity
77     * {float} the opacity of this popup (between 0.0 and 1.0)
78     */
79    opacity: "",
80
81    /**
82     * Property: border
83     * {String} the border size of the popup.  (eg 2px)
84     */
85    border: "",
86   
87    /**
88     * Property: contentDiv
89     * {DOMElement} a reference to the element that holds the content of
90     *              the div.
91     */
92    contentDiv: null,
93   
94    /**
95     * Property: groupDiv
96     * {DOMElement} First and only child of 'div'. The group Div contains the
97     *     'contentDiv' and the 'closeDiv'.
98     */
99    groupDiv: null,
100
101    /**
102     * Property: closeDiv
103     * {DOMElement} the optional closer image
104     */
105    closeDiv: null,
106
107    /**
108     * APIProperty: autoSize
109     * {Boolean} Resize the popup to auto-fit the contents.
110     *     Default is false.
111     */
112    autoSize: false,
113
114    /**
115     * APIProperty: minSize
116     * {<OpenLayers.Size>} Minimum size allowed for the popup's contents.
117     */
118    minSize: null,
119
120    /**
121     * APIProperty: maxSize
122     * {<OpenLayers.Size>} Maximum size allowed for the popup's contents.
123     */
124    maxSize: null,
125
126    /**
127     * Property: displayClass
128     * {String} The CSS class of the popup.
129     */
130    displayClass: "olPopup",
131
132    /**
133     * Property: contentDisplayClass
134     * {String} The CSS class of the popup content div.
135     */
136    contentDisplayClass: "olPopupContent",
137
138    /**
139     * Property: padding
140     * {int or <OpenLayers.Bounds>} An extra opportunity to specify internal
141     *     padding of the content div inside the popup. This was originally
142     *     confused with the css padding as specified in style.css's
143     *     'olPopupContent' class. We would like to get rid of this altogether,
144     *     except that it does come in handy for the framed and anchoredbubble
145     *     popups, who need to maintain yet another barrier between their
146     *     content and the outer border of the popup itself.
147     *
148     *     Note that in order to not break API, we must continue to support
149     *     this property being set as an integer. Really, though, we'd like to
150     *     have this specified as a Bounds object so that user can specify
151     *     distinct left, top, right, bottom paddings. With the 3.0 release
152     *     we can make this only a bounds.
153     */
154    padding: 0,
155
156    /**
157     * Property: disableFirefoxOverflowHack
158     * {Boolean} The hack for overflow in Firefox causes all elements
159     *     to be re-drawn, which causes Flash elements to be
160     *     re-initialized, which is troublesome.
161     *     With this property the hack can be disabled.
162     */
163    disableFirefoxOverflowHack: false,
164
165    /**
166     * Method: fixPadding
167     * To be removed in 3.0, this function merely helps us to deal with the
168     *     case where the user may have set an integer value for padding,
169     *     instead of an <OpenLayers.Bounds> object.
170     */
171    fixPadding: function() {
172        if (typeof this.padding == "number") {
173            this.padding = new OpenLayers.Bounds(
174                this.padding, this.padding, this.padding, this.padding
175            );
176        }
177    },
178
179    /**
180     * APIProperty: panMapIfOutOfView
181     * {Boolean} When drawn, pan map such that the entire popup is visible in
182     *     the current viewport (if necessary).
183     *     Default is false.
184     */
185    panMapIfOutOfView: false,
186   
187    /**
188     * APIProperty: keepInMap
189     * {Boolean} If panMapIfOutOfView is false, and this property is true,
190     *     contrain the popup such that it always fits in the available map
191     *     space. By default, this is not set on the base class. If you are
192     *     creating popups that are near map edges and not allowing pannning,
193     *     and especially if you have a popup which has a
194     *     fixedRelativePosition, setting this to false may be a smart thing to
195     *     do. Subclasses may want to override this setting.
196     *   
197     *     Default is false.
198     */
199    keepInMap: false,
200
201    /**
202     * APIProperty: closeOnMove
203     * {Boolean} When map pans, close the popup.
204     *     Default is false.
205     */
206    closeOnMove: false,
207   
208    /**
209     * Property: map
210     * {<OpenLayers.Map>} this gets set in Map.js when the popup is added to the map
211     */
212    map: null,
213
214    /**
215    * Constructor: OpenLayers.Popup
216    * Create a popup.
217    *
218    * Parameters:
219    * id - {String} a unqiue identifier for this popup.  If null is passed
220    *               an identifier will be automatically generated.
221    * lonlat - {<OpenLayers.LonLat>}  The position on the map the popup will
222    *                                 be shown.
223    * contentSize - {<OpenLayers.Size>} The size of the content.
224    * contentHTML - {String}          An HTML string to display inside the   
225    *                                 popup.
226    * closeBox - {Boolean}            Whether to display a close box inside
227    *                                 the popup.
228    * closeBoxCallback - {Function}   Function to be called on closeBox click.
229    */
230    initialize:function(id, lonlat, contentSize, contentHTML, closeBox, closeBoxCallback) {
231        if (id == null) {
232            id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
233        }
234
235        this.id = id;
236        this.lonlat = lonlat;
237
238        this.contentSize = (contentSize != null) ? contentSize 
239                                  : new OpenLayers.Size(
240                                                   OpenLayers.Popup.WIDTH,
241                                                   OpenLayers.Popup.HEIGHT);
242        if (contentHTML != null) { 
243             this.contentHTML = contentHTML;
244        }
245        this.backgroundColor = OpenLayers.Popup.COLOR;
246        this.opacity = OpenLayers.Popup.OPACITY;
247        this.border = OpenLayers.Popup.BORDER;
248
249        this.div = OpenLayers.Util.createDiv(this.id, null, null, 
250                                             null, null, null, "hidden");
251        this.div.className = this.displayClass;
252       
253        var groupDivId = this.id + "_GroupDiv";
254        this.groupDiv = OpenLayers.Util.createDiv(groupDivId, null, null, 
255                                                    null, "relative", null,
256                                                    "hidden");
257
258        var id = this.div.id + "_contentDiv";
259        this.contentDiv = OpenLayers.Util.createDiv(id, null, this.contentSize.clone(), 
260                                                    null, "relative");
261        this.contentDiv.className = this.contentDisplayClass;
262        this.groupDiv.appendChild(this.contentDiv);
263        this.div.appendChild(this.groupDiv);
264
265        if (closeBox) {
266            this.addCloseBox(closeBoxCallback);
267        } 
268
269        this.registerEvents();
270    },
271
272    /**
273     * Method: destroy
274     * nullify references to prevent circular references and memory leaks
275     */
276    destroy: function() {
277
278        this.id = null;
279        this.lonlat = null;
280        this.size = null;
281        this.contentHTML = null;
282       
283        this.backgroundColor = null;
284        this.opacity = null;
285        this.border = null;
286       
287        if (this.closeOnMove && this.map) {
288            this.map.events.unregister("movestart", this, this.hide);
289        }
290
291        this.events.destroy();
292        this.events = null;
293       
294        if (this.closeDiv) {
295            OpenLayers.Event.stopObservingElement(this.closeDiv); 
296            this.groupDiv.removeChild(this.closeDiv);
297        }
298        this.closeDiv = null;
299       
300        this.div.removeChild(this.groupDiv);
301        this.groupDiv = null;
302
303        if (this.map != null) {
304            this.map.removePopup(this);
305        }
306        this.map = null;
307        this.div = null;
308       
309        this.autoSize = null;
310        this.minSize = null;
311        this.maxSize = null;
312        this.padding = null;
313        this.panMapIfOutOfView = null;
314    },
315
316    /**
317    * Method: draw
318    * Constructs the elements that make up the popup.
319    *
320    * Parameters:
321    * px - {<OpenLayers.Pixel>} the position the popup in pixels.
322    *
323    * Returns:
324    * {DOMElement} Reference to a div that contains the drawn popup
325    */
326    draw: function(px) {
327        if (px == null) {
328            if ((this.lonlat != null) && (this.map != null)) {
329                px = this.map.getLayerPxFromLonLat(this.lonlat);
330            }
331        }
332
333        // this assumes that this.map already exists, which is okay because
334        // this.draw is only called once the popup has been added to the map.
335        if (this.closeOnMove) {
336            this.map.events.register("movestart", this, this.hide);
337        }
338       
339        //listen to movestart, moveend to disable overflow (FF bug)
340        if (!this.disableFirefoxOverflowHack && OpenLayers.Util.getBrowserName() == 'firefox') {
341            this.map.events.register("movestart", this, function() {
342                var style = document.defaultView.getComputedStyle(
343                    this.contentDiv, null
344                );
345                var currentOverflow = style.getPropertyValue("overflow");
346                if (currentOverflow != "hidden") {
347                    this.contentDiv._oldOverflow = currentOverflow;
348                    this.contentDiv.style.overflow = "hidden";
349                }
350            });
351            this.map.events.register("moveend", this, function() {
352                var oldOverflow = this.contentDiv._oldOverflow;
353                if (oldOverflow) {
354                    this.contentDiv.style.overflow = oldOverflow;
355                    this.contentDiv._oldOverflow = null;
356                }
357            });
358        }
359
360        this.moveTo(px);
361        if (!this.autoSize && !this.size) {
362            this.setSize(this.contentSize);
363        }
364        this.setBackgroundColor();
365        this.setOpacity();
366        this.setBorder();
367        this.setContentHTML();
368       
369        if (this.panMapIfOutOfView) {
370            this.panIntoView();
371        }   
372
373        return this.div;
374    },
375
376    /**
377     * Method: updatePosition
378     * if the popup has a lonlat and its map members set,
379     * then have it move itself to its proper position
380     */
381    updatePosition: function() {
382        if ((this.lonlat) && (this.map)) {
383            var px = this.map.getLayerPxFromLonLat(this.lonlat);
384            if (px) {
385                this.moveTo(px);           
386            }   
387        }
388    },
389
390    /**
391     * Method: moveTo
392     *
393     * Parameters:
394     * px - {<OpenLayers.Pixel>} the top and left position of the popup div.
395     */
396    moveTo: function(px) {
397        if ((px != null) && (this.div != null)) {
398            this.div.style.left = px.x + "px";
399            this.div.style.top = px.y + "px";
400        }
401    },
402
403    /**
404     * Method: visible
405     *
406     * Returns:     
407     * {Boolean} Boolean indicating whether or not the popup is visible
408     */
409    visible: function() {
410        return OpenLayers.Element.visible(this.div);
411    },
412
413    /**
414     * Method: toggle
415     * Toggles visibility of the popup.
416     */
417    toggle: function() {
418        if (this.visible()) {
419            this.hide();
420        } else {
421            this.show();
422        }
423    },
424
425    /**
426     * Method: show
427     * Makes the popup visible.
428     */
429    show: function() {
430        OpenLayers.Element.show(this.div);
431
432        if (this.panMapIfOutOfView) {
433            this.panIntoView();
434        }   
435    },
436
437    /**
438     * Method: hide
439     * Makes the popup invisible.
440     */
441    hide: function() {
442        OpenLayers.Element.hide(this.div);
443    },
444
445    /**
446     * Method: setSize
447     * Used to adjust the size of the popup.
448     *
449     * Parameters:
450     * contentSize - {<OpenLayers.Size>} the new size for the popup's
451     *     contents div (in pixels).
452     */
453    setSize:function(contentSize) { 
454        this.size = contentSize.clone(); 
455       
456        // if our contentDiv has a css 'padding' set on it by a stylesheet, we
457        //  must add that to the desired "size".
458        var contentDivPadding = this.getContentDivPadding();
459        var wPadding = contentDivPadding.left + contentDivPadding.right;
460        var hPadding = contentDivPadding.top + contentDivPadding.bottom;
461
462        // take into account the popup's 'padding' property
463        this.fixPadding();
464        wPadding += this.padding.left + this.padding.right;
465        hPadding += this.padding.top + this.padding.bottom;
466
467        // make extra space for the close div
468        if (this.closeDiv) {
469            var closeDivWidth = parseInt(this.closeDiv.style.width);
470            wPadding += closeDivWidth + contentDivPadding.right;
471        }
472
473        //increase size of the main popup div to take into account the
474        // users's desired padding and close div.       
475        this.size.w += wPadding;
476        this.size.h += hPadding;
477
478        //now if our browser is IE, we need to actually make the contents
479        // div itself bigger to take its own padding into effect. this makes
480        // me want to shoot someone, but so it goes.
481        if (OpenLayers.Util.getBrowserName() == "msie") {
482            this.contentSize.w += 
483                contentDivPadding.left + contentDivPadding.right;
484            this.contentSize.h += 
485                contentDivPadding.bottom + contentDivPadding.top;
486        }
487
488        if (this.div != null) {
489            this.div.style.width = this.size.w + "px";
490            this.div.style.height = this.size.h + "px";
491        }
492        if (this.contentDiv != null){
493            this.contentDiv.style.width = contentSize.w + "px";
494            this.contentDiv.style.height = contentSize.h + "px";
495        }
496    }, 
497
498    /**
499     * APIMethod: updateSize
500     * Auto size the popup so that it precisely fits its contents (as
501     *     determined by this.contentDiv.innerHTML). Popup size will, of
502     *     course, be limited by the available space on the current map
503     */
504    updateSize: function() {
505       
506        // determine actual render dimensions of the contents by putting its
507        // contents into a fake contentDiv (for the CSS) and then measuring it
508        var preparedHTML = "<div class='" + this.contentDisplayClass+ "'>" + 
509            this.contentDiv.innerHTML + 
510            "</div>";
511 
512        var containerElement = (this.map) ? this.map.layerContainerDiv
513                                                                          : document.body;
514        var realSize = OpenLayers.Util.getRenderedDimensions(
515            preparedHTML, null, {
516                displayClass: this.displayClass,
517                containerElement: containerElement
518            }
519        );
520
521        // is the "real" size of the div is safe to display in our map?
522        var safeSize = this.getSafeContentSize(realSize);
523
524        var newSize = null;
525        if (safeSize.equals(realSize)) {
526            //real size of content is small enough to fit on the map,
527            // so we use real size.
528            newSize = realSize;
529
530        } else {
531
532            //make a new OL.Size object with the clipped dimensions
533            // set or null if not clipped.
534            var fixedSize = new OpenLayers.Size();
535            fixedSize.w = (safeSize.w < realSize.w) ? safeSize.w : null;
536            fixedSize.h = (safeSize.h < realSize.h) ? safeSize.h : null;
537       
538            if (fixedSize.w && fixedSize.h) {
539                //content is too big in both directions, so we will use
540                // max popup size (safeSize), knowing well that it will
541                // overflow both ways.               
542                newSize = safeSize;
543            } else {
544                //content is clipped in only one direction, so we need to
545                // run getRenderedDimensions() again with a fixed dimension
546                var clippedSize = OpenLayers.Util.getRenderedDimensions(
547                    preparedHTML, fixedSize, {
548                        displayClass: this.contentDisplayClass,
549                        containerElement: containerElement
550                    }
551                );
552               
553                //if the clipped size is still the same as the safeSize,
554                // that means that our content must be fixed in the
555                // offending direction. If overflow is 'auto', this means
556                // we are going to have a scrollbar for sure, so we must
557                // adjust for that.
558                //
559                var currentOverflow = OpenLayers.Element.getStyle(
560                    this.contentDiv, "overflow"
561                );
562                if ( (currentOverflow != "hidden") && 
563                     (clippedSize.equals(safeSize)) ) {
564                    var scrollBar = OpenLayers.Util.getScrollbarWidth();
565                    if (fixedSize.w) {
566                        clippedSize.h += scrollBar;
567                    } else {
568                        clippedSize.w += scrollBar;
569                    }
570                }
571               
572                newSize = this.getSafeContentSize(clippedSize);
573            }
574        }                       
575        this.setSize(newSize);     
576    },   
577
578    /**
579     * Method: setBackgroundColor
580     * Sets the background color of the popup.
581     *
582     * Parameters:
583     * color - {String} the background color.  eg "#FFBBBB"
584     */
585    setBackgroundColor:function(color) { 
586        if (color != undefined) {
587            this.backgroundColor = color; 
588        }
589       
590        if (this.div != null) {
591            this.div.style.backgroundColor = this.backgroundColor;
592        }
593    }, 
594   
595    /**
596     * Method: setOpacity
597     * Sets the opacity of the popup.
598     *
599     * Parameters:
600     * opacity - {float} A value between 0.0 (transparent) and 1.0 (solid).   
601     */
602    setOpacity:function(opacity) { 
603        if (opacity != undefined) {
604            this.opacity = opacity; 
605        }
606       
607        if (this.div != null) {
608            // for Mozilla and Safari
609            this.div.style.opacity = this.opacity;
610
611            // for IE
612            this.div.style.filter = 'alpha(opacity=' + this.opacity*100 + ')';
613        }
614    }, 
615   
616    /**
617     * Method: setBorder
618     * Sets the border style of the popup.
619     *
620     * Parameters:
621     * border - {String} The border style value. eg 2px
622     */
623    setBorder:function(border) { 
624        if (border != undefined) {
625            this.border = border;
626        }
627       
628        if (this.div != null) {
629            this.div.style.border = this.border;
630        }
631    },     
632   
633    /**
634     * Method: setContentHTML
635     * Allows the user to set the HTML content of the popup.
636     *
637     * Parameters:
638     * contentHTML - {String} HTML for the div.
639     */
640    setContentHTML:function(contentHTML) {
641
642        if (contentHTML != null) {
643            this.contentHTML = contentHTML;
644        }
645       
646        if ((this.contentDiv != null) && 
647            (this.contentHTML != null) &&
648            (this.contentHTML != this.contentDiv.innerHTML)) {
649       
650            this.contentDiv.innerHTML = this.contentHTML;
651       
652            if (this.autoSize) {
653               
654                //if popup has images, listen for when they finish
655                // loading and resize accordingly
656                this.registerImageListeners();
657
658                //auto size the popup to its current contents
659                this.updateSize();
660            }
661        }   
662
663    },
664   
665    /**
666     * Method: registerImageListeners
667     * Called when an image contained by the popup loaded. this function
668     *     updates the popup size, then unregisters the image load listener.
669     */   
670    registerImageListeners: function() { 
671
672        // As the images load, this function will call updateSize() to
673        // resize the popup to fit the content div (which presumably is now
674        // bigger than when the image was not loaded).
675        //
676        // If the 'panMapIfOutOfView' property is set, we will pan the newly
677        // resized popup back into view.
678        //
679        // Note that this function, when called, will have 'popup' and
680        // 'img' properties in the context.
681        //
682        var onImgLoad = function() {
683           
684            this.popup.updateSize();
685     
686            if ( this.popup.visible() && this.popup.panMapIfOutOfView ) {
687                this.popup.panIntoView();
688            }
689
690            OpenLayers.Event.stopObserving(
691                this.img, "load", this.img._onImageLoad
692            );
693   
694        };
695
696        //cycle through the images and if their size is 0x0, that means that
697        // they haven't been loaded yet, so we attach the listener, which
698        // will fire when the images finish loading and will resize the
699        // popup accordingly to its new size.
700        var images = this.contentDiv.getElementsByTagName("img");
701        for (var i = 0, len = images.length; i < len; i++) {
702            var img = images[i];
703            if (img.width == 0 || img.height == 0) {
704
705                var context = {
706                    'popup': this,
707                    'img': img
708                };
709
710                //expando this function to the image itself before registering
711                // it. This way we can easily and properly unregister it.
712                img._onImgLoad = OpenLayers.Function.bind(onImgLoad, context);
713
714                OpenLayers.Event.observe(img, 'load', img._onImgLoad);
715            }   
716        } 
717    },
718
719    /**
720     * APIMethod: getSafeContentSize
721     *
722     * Parameters:
723     * size - {<OpenLayers.Size>} Desired size to make the popup.
724     *
725     * Returns:
726     * {<OpenLayers.Size>} A size to make the popup which is neither smaller
727     *     than the specified minimum size, nor bigger than the maximum
728     *     size (which is calculated relative to the size of the viewport).
729     */
730    getSafeContentSize: function(size) {
731
732        var safeContentSize = size.clone();
733
734        // if our contentDiv has a css 'padding' set on it by a stylesheet, we
735        //  must add that to the desired "size".
736        var contentDivPadding = this.getContentDivPadding();
737        var wPadding = contentDivPadding.left + contentDivPadding.right;
738        var hPadding = contentDivPadding.top + contentDivPadding.bottom;
739
740        // take into account the popup's 'padding' property
741        this.fixPadding();
742        wPadding += this.padding.left + this.padding.right;
743        hPadding += this.padding.top + this.padding.bottom;
744
745        if (this.closeDiv) {
746            var closeDivWidth = parseInt(this.closeDiv.style.width);
747            wPadding += closeDivWidth + contentDivPadding.right;
748        }
749
750        // prevent the popup from being smaller than a specified minimal size
751        if (this.minSize) {
752            safeContentSize.w = Math.max(safeContentSize.w, 
753                (this.minSize.w - wPadding));
754            safeContentSize.h = Math.max(safeContentSize.h, 
755                (this.minSize.h - hPadding));
756        }
757
758        // prevent the popup from being bigger than a specified maximum size
759        if (this.maxSize) {
760            safeContentSize.w = Math.min(safeContentSize.w, 
761                (this.maxSize.w - wPadding));
762            safeContentSize.h = Math.min(safeContentSize.h, 
763                (this.maxSize.h - hPadding));
764        }
765       
766        //make sure the desired size to set doesn't result in a popup that
767        // is bigger than the map's viewport.
768        //
769        if (this.map && this.map.size) {
770           
771            var extraX = 0, extraY = 0;
772            if (this.keepInMap && !this.panMapIfOutOfView) {
773                var px = this.map.getPixelFromLonLat(this.lonlat);
774                switch (this.relativePosition) {
775                    case "tr":
776                        extraX = px.x;
777                        extraY = this.map.size.h - px.y;
778                        break;
779                    case "tl":
780                        extraX = this.map.size.w - px.x;
781                        extraY = this.map.size.h - px.y;
782                        break;
783                    case "bl":
784                        extraX = this.map.size.w - px.x;
785                        extraY = px.y;
786                        break;
787                    case "br":
788                        extraX = px.x;
789                        extraY = px.y;
790                        break;
791                    default:   
792                        extraX = px.x;
793                        extraY = this.map.size.h - px.y;
794                        break;
795                }
796            }   
797         
798            var maxY = this.map.size.h - 
799                this.map.paddingForPopups.top - 
800                this.map.paddingForPopups.bottom - 
801                hPadding - extraY;
802           
803            var maxX = this.map.size.w - 
804                this.map.paddingForPopups.left - 
805                this.map.paddingForPopups.right - 
806                wPadding - extraX;
807           
808            safeContentSize.w = Math.min(safeContentSize.w, maxX);
809            safeContentSize.h = Math.min(safeContentSize.h, maxY);
810        }
811       
812        return safeContentSize;
813    },
814   
815    /**
816     * Method: getContentDivPadding
817     * Glorious, oh glorious hack in order to determine the css 'padding' of
818     *     the contentDiv. IE/Opera return null here unless we actually add the
819     *     popup's main 'div' element (which contains contentDiv) to the DOM.
820     *     So we make it invisible and then add it to the document temporarily.
821     *
822     *     Once we've taken the padding readings we need, we then remove it
823     *     from the DOM (it will actually get added to the DOM in
824     *     Map.js's addPopup)
825     *
826     * Returns:
827     * {<OpenLayers.Bounds>}
828     */
829    getContentDivPadding: function() {
830
831        //use cached value if we have it
832        var contentDivPadding = this._contentDivPadding;
833        if (!contentDivPadding) {
834
835                if (this.div.parentNode == null) {
836                        //make the div invisible and add it to the page       
837                    this.div.style.display = "none";
838                    document.body.appendChild(this.div);
839                }
840                   
841            //read the padding settings from css, put them in an OL.Bounds       
842            contentDivPadding = new OpenLayers.Bounds(
843                OpenLayers.Element.getStyle(this.contentDiv, "padding-left"),
844                OpenLayers.Element.getStyle(this.contentDiv, "padding-bottom"),
845                OpenLayers.Element.getStyle(this.contentDiv, "padding-right"),
846                OpenLayers.Element.getStyle(this.contentDiv, "padding-top")
847            );
848   
849            //cache the value
850            this._contentDivPadding = contentDivPadding;
851
852            if (this.div.parentNode == document.body) {
853                    //remove the div from the page and make it visible again
854                    document.body.removeChild(this.div);
855                    this.div.style.display = "";
856            }
857        }
858        return contentDivPadding;
859    },
860
861    /**
862     * Method: addCloseBox
863     *
864     * Parameters:
865     * callback - {Function} The callback to be called when the close button
866     *     is clicked.
867     */
868    addCloseBox: function(callback) {
869
870        this.closeDiv = OpenLayers.Util.createDiv(
871            this.id + "_close", null, new OpenLayers.Size(17, 17)
872        );
873        this.closeDiv.className = "olPopupCloseBox"; 
874       
875        // use the content div's css padding to determine if we should
876        //  padd the close div
877        var contentDivPadding = this.getContentDivPadding();
878         
879        this.closeDiv.style.right = contentDivPadding.right + "px";
880        this.closeDiv.style.top = contentDivPadding.top + "px";
881        this.groupDiv.appendChild(this.closeDiv);
882
883        var closePopup = callback || function(e) {
884            this.hide();
885            OpenLayers.Event.stop(e);
886        };
887        OpenLayers.Event.observe(this.closeDiv, "click", 
888                OpenLayers.Function.bindAsEventListener(closePopup, this));
889    },
890
891    /**
892     * Method: panIntoView
893     * Pans the map such that the popup is totaly viewable (if necessary)
894     */
895    panIntoView: function() {
896       
897        var mapSize = this.map.getSize();
898   
899        //start with the top left corner of the popup, in px,
900        // relative to the viewport
901        var origTL = this.map.getViewPortPxFromLayerPx( new OpenLayers.Pixel(
902            parseInt(this.div.style.left),
903            parseInt(this.div.style.top)
904        ));
905        var newTL = origTL.clone();
906   
907        //new left (compare to margins, using this.size to calculate right)
908        if (origTL.x < this.map.paddingForPopups.left) {
909            newTL.x = this.map.paddingForPopups.left;
910        } else 
911        if ( (origTL.x + this.size.w) > (mapSize.w - this.map.paddingForPopups.right)) {
912            newTL.x = mapSize.w - this.map.paddingForPopups.right - this.size.w;
913        }
914       
915        //new top (compare to margins, using this.size to calculate bottom)
916        if (origTL.y < this.map.paddingForPopups.top) {
917            newTL.y = this.map.paddingForPopups.top;
918        } else 
919        if ( (origTL.y + this.size.h) > (mapSize.h - this.map.paddingForPopups.bottom)) {
920            newTL.y = mapSize.h - this.map.paddingForPopups.bottom - this.size.h;
921        }
922       
923        var dx = origTL.x - newTL.x;
924        var dy = origTL.y - newTL.y;
925       
926        this.map.pan(dx, dy);
927    },
928
929    /**
930     * Method: registerEvents
931     * Registers events on the popup.
932     *
933     * Do this in a separate function so that subclasses can
934     *   choose to override it if they wish to deal differently
935     *   with mouse events
936     *
937     *   Note in the following handler functions that some special
938     *    care is needed to deal correctly with mousing and popups.
939     *   
940     *   Because the user might select the zoom-rectangle option and
941     *    then drag it over a popup, we need a safe way to allow the
942     *    mousemove and mouseup events to pass through the popup when
943     *    they are initiated from outside.
944     *
945     *   Otherwise, we want to essentially kill the event propagation
946     *    for all other events, though we have to do so carefully,
947     *    without disabling basic html functionality, like clicking on
948     *    hyperlinks or drag-selecting text.
949     */
950     registerEvents:function() {
951        this.events = new OpenLayers.Events(this, this.div, null, true);
952
953        this.events.on({
954            "mousedown": this.onmousedown,
955            "mousemove": this.onmousemove,
956            "mouseup": this.onmouseup,
957            "click": this.onclick,
958            "mouseout": this.onmouseout,
959            "dblclick": this.ondblclick,
960            scope: this
961        });
962       
963     },
964
965    /**
966     * Method: onmousedown
967     * When mouse goes down within the popup, make a note of
968     *   it locally, and then do not propagate the mousedown
969     *   (but do so safely so that user can select text inside)
970     *
971     * Parameters:
972     * evt - {Event}
973     */
974    onmousedown: function (evt) {
975        this.mousedown = true;
976        OpenLayers.Event.stop(evt, true);
977    },
978
979    /**
980     * Method: onmousemove
981     * If the drag was started within the popup, then
982     *   do not propagate the mousemove (but do so safely
983     *   so that user can select text inside)
984     *
985     * Parameters:
986     * evt - {Event}
987     */
988    onmousemove: function (evt) {
989        if (this.mousedown) {
990            OpenLayers.Event.stop(evt, true);
991        }
992    },
993
994    /**
995     * Method: onmouseup
996     * When mouse comes up within the popup, after going down
997     *   in it, reset the flag, and then (once again) do not
998     *   propagate the event, but do so safely so that user can
999     *   select text inside
1000     *
1001     * Parameters:
1002     * evt - {Event}
1003     */
1004    onmouseup: function (evt) {
1005        if (this.mousedown) {
1006            this.mousedown = false;
1007            OpenLayers.Event.stop(evt, true);
1008        }
1009    },
1010
1011    /**
1012     * Method: onclick
1013     * Ignore clicks, but allowing default browser handling
1014     *
1015     * Parameters:
1016     * evt - {Event}
1017     */
1018    onclick: function (evt) {
1019        OpenLayers.Event.stop(evt, true);
1020    },
1021
1022    /**
1023     * Method: onmouseout
1024     * When mouse goes out of the popup set the flag to false so that
1025     *   if they let go and then drag back in, we won't be confused.
1026     *
1027     * Parameters:
1028     * evt - {Event}
1029     */
1030    onmouseout: function (evt) {
1031        this.mousedown = false;
1032    },
1033   
1034    /**
1035     * Method: ondblclick
1036     * Ignore double-clicks, but allowing default browser handling
1037     *
1038     * Parameters:
1039     * evt - {Event}
1040     */
1041    ondblclick: function (evt) {
1042        OpenLayers.Event.stop(evt, true);
1043    },
1044
1045    CLASS_NAME: "OpenLayers.Popup"
1046});
1047
1048OpenLayers.Popup.WIDTH = 200;
1049OpenLayers.Popup.HEIGHT = 200;
1050OpenLayers.Popup.COLOR = "white";
1051OpenLayers.Popup.OPACITY = 1;
1052OpenLayers.Popup.BORDER = "0px";
Note: See TracBrowser for help on using the repository browser.