]> git.parisson.com Git - telemeta.git/commitdiff
popup class implemented (still work in progress)
authorriccardo <riccardo@parisson.com>
Mon, 2 May 2011 15:30:41 +0000 (17:30 +0200)
committerriccardo <riccardo@parisson.com>
Mon, 2 May 2011 15:30:41 +0000 (17:30 +0200)
telemeta/htdocs/js/application.js
telemeta/templates/telemeta_default/mediaitem_detail.html

index 6fa4fbdbef3a6022587bc30e38248a779bd70842..ab425336406effaf24ca34f668c5574d26c0fd85 100644 (file)
@@ -290,7 +290,6 @@ var popup={
     },\r
 \r
     show:function(content, optionalEvent){\r
-        consolelog("showing popup:"+optionalEvent);\r
         //if showing, hide\r
         if(this.isShowing()){\r
             this.hide();\r
@@ -423,8 +422,6 @@ var popup={
         div.show(300, function(){ //basically in between fast (200) and slow (600)\r
             //position div shadow:\r
             divShadow.show();\r
-            consolelog(div.outerHeight(true)+" "+div.outerHeight(false));\r
-            consolelog(divShadow.outerHeight(true)+" "+divShadow.outerHeight(false));\r
             \r
             //set focus to the first input component, if any. Otherwise try with anchors, otherwise do nothing\r
             var inputs = $J(div).find(':input');\r
@@ -642,14 +639,14 @@ function PopupUtils(){
      * The workaround is quite tricky and maybe not well formed, as it uses a timeout function. However, any other implementation was trickier\r
      * and with potential drawbacks. Note that any subelement of dialogDiv is assigned a "focus" attribute with the current time in millisecs\r
      */\r
-//    var setAsPopup = function(dialogDiv, removeOnHide){\r
-//        dialogDiv.setAsPopup(removeOnHide ? function(){dialogDiv.remove();} : function(){dialogDiv.hide();});\r
-//    };\r
+    //    var setAsPopup = function(dialogDiv, removeOnHide){\r
+    //        dialogDiv.setAsPopup(removeOnHide ? function(){dialogDiv.remove();} : function(){dialogDiv.hide();});\r
+    //    };\r
 \r
     this.bindClickToPopup = function(invokerAsJQueryObj, popupContent){\r
-     var p = new DivDialog(popupContent);\r
+        var p = new DivDialog(popupContent);\r
         var oldShow = p.show;\r
-       // var pint = parseInt;\r
+        // var pint = parseInt;\r
         p.show = function(){\r
 \r
             var rect = screenRect();\r
@@ -659,43 +656,55 @@ function PopupUtils(){
             var spaceAbove = offs.top - rect.y;\r
             var spaceBelow = rect.height - height - spaceAbove;\r
 \r
-            consolelog('wHeight:'+rect.height+ ' space above: '+spaceAbove + ' spacebelow: '+spaceBelow);\r
+           // consolelog('wHeight:'+rect.height+ ' space above: '+spaceAbove + ' spacebelow: '+spaceBelow);\r
 \r
             if(spaceAbove>spaceBelow){\r
-                p.css({'maxHeight':(spaceAbove-p.shadowoffset)+'px', 'top':rect.y+'px'});\r
+                p.css({\r
+                    'maxHeight':(spaceAbove-p.shadowoffset)+'px',\r
+                    'top':rect.y+'px'\r
+                    });\r
             }else{\r
-                p.css({'maxHeight':(spaceBelow-p.shadowoffset)+'px', 'top':(offs.top+height)+'px'});\r
+                p.css({\r
+                    'maxHeight':(spaceBelow-p.shadowoffset)+'px',\r
+                    'top':(offs.top+height)+'px'\r
+                    });\r
             }\r
-            p.css({'height':'auto','width' :'auto', 'maxWidth': (rect.x+rect.width-offs.left)+'px'});\r
+            p.css({\r
+                'height':'auto',\r
+                'width' :'auto',\r
+                'maxWidth': (rect.x+rect.width-offs.left)+'px'\r
+                });\r
 \r
-        //consolelog("size"); consolelog(size);\r
-//        p.offset({\r
-//            left: rect.x + pint((rect.width-size.width)/2),\r
-//            top: rect.y + pint((rect.height-size.height)/2)\r
-//        });\r
-        //consolelog("offset"); consolelog({\r
-        //    left: rect.x + pint((rect.width-size.width)/2),\r
-        //    top: rect.y + pint((rect.height-size.height)/2)\r
-       // });\r
+            //consolelog("size"); consolelog(size);\r
+            //        p.offset({\r
+            //            left: rect.x + pint((rect.width-size.width)/2),\r
+            //            top: rect.y + pint((rect.height-size.height)/2)\r
+            //        });\r
+            //consolelog("offset"); consolelog({\r
+            //    left: rect.x + pint((rect.width-size.width)/2),\r
+            //    top: rect.y + pint((rect.height-size.height)/2)\r
+            // });\r
 \r
             oldShow.apply(p,arguments);\r
             p.refreshShadowPosition();\r
             p.setFocus();\r
         };\r
-        consolelog(invokerAsJQueryObj);\r
+        //consolelog(invokerAsJQueryObj);\r
         p.css({\r
             'minWidth':invokerAsJQueryObj.outerWidth()+'px',\r
             'left':invokerAsJQueryObj.offset().left+'px'\r
         });\r
 \r
-        p.setPopupFocus(function(){p.hide();});\r
+        p.setPopupFocus(function(){\r
+            p.hide();\r
+        });\r
 \r
         invokerAsJQueryObj.unbind('click').click(function(evt){\r
-           p.show();\r
-           return false;\r
+            p.show();\r
+            return false;\r
         });\r
-        //p.show();\r
-        //p.setFocus();\r
+    //p.show();\r
+    //p.setFocus();\r
     }\r
     /**\r
      * Shows an info dialog centered in screeen. The dialog is a DivDialog with maxwidth and maxheight equals to the half of the\r
@@ -713,24 +722,24 @@ function PopupUtils(){
         p.show = function(){\r
             oldShow.apply(p,arguments);\r
             var rect = screenRect();\r
-//        var pint = parseInt;\r
-//        p.css({\r
-//            'maxWidth':pint(rect.width/2)+'px',\r
-//            'maxHeight':pint(rect.height/2)+'px'\r
-//        });\r
-//consolelog("screeenrect"); consolelog(rect);\r
-        var size = p.size();\r
-        //consolelog("size"); consolelog(size);\r
-        p.offset({\r
-            left: rect.x + pint((rect.width-size.width)/2),\r
-            top: rect.y + pint((rect.height-size.height)/2)\r
-        });\r
-        //consolelog("offset"); consolelog({\r
-        //    left: rect.x + pint((rect.width-size.width)/2),\r
-        //    top: rect.y + pint((rect.height-size.height)/2)\r
-       // });\r
+            //        var pint = parseInt;\r
+            //        p.css({\r
+            //            'maxWidth':pint(rect.width/2)+'px',\r
+            //            'maxHeight':pint(rect.height/2)+'px'\r
+            //        });\r
+            //consolelog("screeenrect"); consolelog(rect);\r
+            var size = p.size();\r
+            //consolelog("size"); consolelog(size);\r
+            p.offset({\r
+                left: rect.x + pint((rect.width-size.width)/2),\r
+                top: rect.y + pint((rect.height-size.height)/2)\r
+            });\r
+            //consolelog("offset"); consolelog({\r
+            //    left: rect.x + pint((rect.width-size.width)/2),\r
+            //    top: rect.y + pint((rect.height-size.height)/2)\r
+            // });\r
 \r
-        p.refreshShadowPosition();\r
+            p.refreshShadowPosition();\r
 \r
         };\r
         var rect = screenRect();\r
@@ -745,9 +754,13 @@ function PopupUtils(){
                 p=null;\r
             },timeInMsec);\r
         }else if(timeInMsec == 'hide'){ //is a boolean\r
-            p.setPopupFocus(function(){p.hide();});\r
+            p.setPopupFocus(function(){\r
+                p.hide();\r
+            });\r
         }else if(timeInMsec == 'remove'){ //is a boolean\r
-            p.setPopupFocus(function(){p.remove();});\r
+            p.setPopupFocus(function(){\r
+                p.remove();\r
+            });\r
         }\r
         p.show();\r
         p.setFocus();\r
@@ -796,23 +809,32 @@ function DivDialog(content){
 \r
 \r
 \r
-//    if(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') ||\r
-//    invoker.is('input[type=submit]')){\r
-//        var w = invoker.outerWidth();\r
-//        popup.css({'minWidth':w+'px'});\r
-//        this.show = show1();\r
-//    }else{\r
-//\r
-//    }\r
+    //    if(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') ||\r
+    //    invoker.is('input[type=submit]')){\r
+    //        var w = invoker.outerWidth();\r
+    //        popup.css({'minWidth':w+'px'});\r
+    //        this.show = show1();\r
+    //    }else{\r
+    //\r
+    //    }\r
 \r
     this.maxSize = function(size){\r
-        popup.css({'maxHeight':size.height,'maxWidth':size.width});\r
-        popupContent.css({'maxHeight':size.height-(popup.outerHeight()-popup.height()),'maxWidth':size.width-(popup.outerWidth()-popup.width())});\r
+        popup.css({\r
+            'maxHeight':size.height,\r
+            'maxWidth':size.width\r
+            });\r
+        popupContent.css({\r
+            'maxHeight':size.height-(popup.outerHeight()-popup.height()),\r
+            'maxWidth':size.width-(popup.outerWidth()-popup.width())\r
+            });\r
     };\r
     this.minsize = function(size){\r
-        popup.css({'minHeight':size.height,'minWidth':size.width});\r
+        popup.css({\r
+            'minHeight':size.height,\r
+            'minWidth':size.width\r
+            });\r
     };\r
-     this.offset = function(){\r
+    this.offset = function(){\r
         var ret = popup.offset.apply(popup,arguments);\r
         //refreshPosition();\r
         return me;\r
@@ -899,8 +921,8 @@ function DivDialog(content){
                     }\r
                 }\r
                 arg = [a];\r
-//                consolelog('css');\r
-//                consolelog(arg);\r
+            //                consolelog('css');\r
+            //                consolelog(arg);\r
             }\r
         }else{\r
             return me;\r
@@ -912,17 +934,17 @@ function DivDialog(content){
 \r
 \r
 \r
-//    this.bindAsPopupFor = function(jQueryAnchorElement){\r
-//        if(!jQueryAnchorElement.attr('id')){\r
-//            jQueryAnchorElement.attr('id','popup_'+new Date().getTime());\r
-//        }\r
-//        var id = jQueryAnchorElement.attr('id');\r
-//\r
-//        anchorElement.click(function(){\r
-//\r
-//        })\r
-//\r
-//    }\r
+    //    this.bindAsPopupFor = function(jQueryAnchorElement){\r
+    //        if(!jQueryAnchorElement.attr('id')){\r
+    //            jQueryAnchorElement.attr('id','popup_'+new Date().getTime());\r
+    //        }\r
+    //        var id = jQueryAnchorElement.attr('id');\r
+    //\r
+    //        anchorElement.click(function(){\r
+    //\r
+    //        })\r
+    //\r
+    //    }\r
    \r
     this.setPopupFocus = function(callbackOnFocusLost){\r
         \r
@@ -946,7 +968,7 @@ function DivDialog(content){
                 //otherwise execute callback\r
                 setTimeout(function(){\r
                     var v = document.activeElement;\r
-                    consolelog(v);\r
+                   // consolelog(v);\r
                     if(v && $J(v).attr(focusid)){\r
                         return;\r
                     }\r
@@ -980,3 +1002,832 @@ function DivDialog(content){
 }\r
 \r
 \r
+\r
+\r
+\r
+//var PopupManager={\r
+//\r
+//    //default properties:\r
+//    $J: jQuery,\r
+//    shadowOpacity: 0.4,\r
+//    shadowOffset: 5,\r
+//    zIndex: 1000,\r
+//    infoDialogMaxSizeInWindowPercent: 0.5,\r
+//    defaultClasses: 'control component',\r
+//    createPopupDiv: function(content){\r
+//        var $J = this.$J;\r
+//        var wdw = $J(window);\r
+//        var div  = $J('<div/>').addClass(this.defaultClasses).css({\r
+//            'position':'absolute',\r
+//            'zIndex':this.zIndex,\r
+//            'visibility':'hidden',\r
+//            'left':wdw.scrollLeft()+'px',\r
+//            'top':wdw.scrollTop()+'px',\r
+//            'overflow':'auto',\r
+//            'padding':'1ex'\r
+//        });\r
+//        div.appendTo('body'); //necessary to properly display the div size\r
+//        if(content instanceof $J){\r
+//            div.append(content);\r
+//        }else if(typeof content == 'string'){\r
+//            div.html(""+content);\r
+//        }else{\r
+//            div.css('overflow',''); //clear overflow\r
+//            var container = $J('<div/>').css('overflow','auto');\r
+//            var table = $J('<table/>');\r
+//            container.append(table);\r
+//            var insert = function(e1,e2){\r
+//                var t1 = $J('<td/>');\r
+//                var t2 = $J('<td/>');\r
+//                if(e1){\r
+//                    t1.append(e1);\r
+//                }\r
+//                if(e2){\r
+//                    t2.append(e2);\r
+//                }\r
+//                table.append($J('<tr/>').append(t1).append(t2));\r
+//            }\r
+//            var title, component;\r
+//            for(var k in content){\r
+//                var val = content[k];\r
+//                if(val instanceof Function){\r
+//                    component = $J('<a/>').html(k).attr('href','#').click(function(evt){\r
+//                        val();\r
+//                        return false;\r
+//                    });\r
+//                    insert(component);\r
+//                }else if(typeof val == 'string' || typeof val == 'number'){\r
+//                    title = $J('<span/>').html(k);\r
+//                    component = $('<input/>').attr('type','text').val(val).attr('name',k);\r
+//                    insert(title,component);\r
+//                }else if(val === true || val === false){\r
+//                    title = $J('<span/>').html(k);\r
+//                    component = $('<input/>').attr('type','checkbox').attr('name',k);\r
+//                    if(val){\r
+//                        component.attr('checked','checked');\r
+//                    }else{\r
+//                        component.removeAttr('checked');\r
+//                    }\r
+//                    insert(title,component);\r
+//                }\r
+//            }\r
+//        }\r
+//        this.getId(div); //actually, sets an id (see below)\r
+//        return div;\r
+//    },\r
+//\r
+//    showInfoDialog: function(content, timeInMSec){\r
+//        var remove = this.remove;\r
+//        var popup = this.createPopupDiv(content)\r
+//        this.setBounds(popup,this.infoDialogMaxSizeInWindowPercent);\r
+//        if(timeInMSec){\r
+//            this.show(popup, function(){\r
+//                setTimeout(function(){\r
+//                    remove(content)\r
+//                    },timeInMSec);\r
+//            })\r
+//        }else{\r
+//            var focus = this.setPopupBehaviourAndReturnFocusElement(popup, true); //remove on hide\r
+//            this.show(popup);\r
+//            focus.focus();\r
+//        }\r
+//    },\r
+//\r
+//    getId: function(div){\r
+//        if(!(div.attr('id'))){\r
+//            div.attr('id','popup_'+(new Date().getTime()));\r
+//        }\r
+//        return div.attr('id');\r
+//    },\r
+//    /**\r
+//     * sets dialogDiv (a jQuery object or a DivDialog, see below) as popup mode. In other words,\r
+//     * scans each sub-element of dialogDiv and assigns to it a onblur event: when the subselemnt looses the focus and the focus\r
+//     * is NOT given to another dialogDiv subelement, hides or removes (depending on removeOnHide param) dialogDiv.\r
+//     * The workaround is quite tricky and maybe not well formed, as it uses a timeout function. However, any other implementation was trickier\r
+//     * and with potential drawbacks. Note that any subelement of dialogDiv is assigned a "focus" attribute with the current time in millisecs\r
+//     */\r
+//    bindPopupClick: function(invoker, popupDiv, removeOnBlur){\r
+//        if(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') ||\r
+//            invoker.is('input[type=submit]')){\r
+//            var $J = this.$J;\r
+//            var focusElm = this.setPopupBehaviourAndReturnFocusElement(popupDiv, removeOnBlur ? this.remove(popupDiv) : this.hide(popupDiv));\r
+//            var id = this.getId(popupDiv);\r
+//            var me = this;\r
+//            invoker.unbind('click').bind('click',function(evt){\r
+//                var pup = $J('#'+id); //dont do anything if the popup is already visible\r
+//                if(pup.length && pup.is(':visible')){\r
+//                    focusElm.focus();\r
+//                    return false;\r
+//                }\r
+////                me.setBounds.apply(me, [popupDiv,invoker]);\r
+////                me.show.apply(me,[popupDiv, function(){focusElm.focus();}]);\r
+//                me.show.apply(me,[popupDiv, function(){me.setBounds.apply(me, [popupDiv,invoker]);focusElm.focus();}]);\r
+//                return false;\r
+//            });\r
+//        }\r
+//    },\r
+//\r
+//    //binds every child of popup that is focusable to a blur event\r
+//    //TODO: TEST IT WITH OTHER BROWSERS!!!! if not working, manda tutto affanculo and use click events\r
+//    setPopupBehaviourAndReturnFocusElement: function(popup, callbackOnBlur){\r
+//        popup.attr('tabindex',0);\r
+//        var $J = this.$J;\r
+//        var elementsWithFocus = $J(popup).find('textarea,a,input');\r
+//        var doc = document;\r
+//        var ret = elementsWithFocus.length ? $J(elementsWithFocus[0]) : popup;\r
+//        elementsWithFocus = elementsWithFocus.add(popup);\r
+//        //build the attribute focus to recognize subelement of popup\r
+//        var focusid = 'popupfocus'+(new Date().getTime());\r
+//        var me = this;\r
+//        //bind the blur to each focusable element:\r
+//        elementsWithFocus.each(function(i,e){\r
+//            var ee = $J(e);\r
+//            ee.attr(focusid,'true');\r
+//            ee.attr('tabindex',i+1);\r
+//            ee.blur(function(){\r
+//                //wait 250msec to see if the focus has been given to another popup focusable element: if yes, do nothing\r
+//                //otherwise execute callback\r
+//                setTimeout(function(){\r
+//                    var v = doc.activeElement;\r
+//                    //consolelog(v);\r
+//                    if(v && $J(v).attr(focusid)){\r
+//                        return;\r
+//                    }\r
+//                    if(callbackOnBlur){\r
+//                        me.hide.apply(me,[popup,callbackOnBlur]);\r
+//                    }else{\r
+//                        me.hide.apply(me,[popup]);\r
+//                    }\r
+//                },200)\r
+//            }); //set here another time delay. 300 seems to be the good compromise between visual hide and safetiness that\r
+//        //meanwhile the focus has already been given to the next component\r
+//        });\r
+//        return ret;\r
+//    },\r
+//\r
+//\r
+//    hideAllPopups: function(){\r
+//        this.hide(this.$J('div[name^="popup_"]'));\r
+//    },\r
+//\r
+//    //show(div, argumentsAsInJQueryShow)\r
+//    //creates a shwdow and shows div and shadow\r
+//    show: function(){\r
+//        var div = arguments[0];\r
+//        div.css({\r
+//            'display':'none',\r
+//            'visibility':'visible'\r
+//        });\r
+//        var body = this.$J('body');\r
+//        if(!div.parent().length){\r
+//            div.appendTo('body');\r
+//        }\r
+//        //TODO: avoid clone and empty?\r
+//        var shadow = div.clone(true,true).empty().css({\r
+//            'backgroundColor':'#000',\r
+//            'borderColor':'#000',\r
+//            'zIndex':this.zIndex-1\r
+//            }).removeAttr('tabindex').fadeTo(0,this.shadowOpacity);\r
+//        var id = this.getId(div);\r
+//        shadow.attr('id',id+'_shadow'); //for use in hide\r
+//        body.append(shadow);\r
+//\r
+//        var both = div.add(shadow);\r
+//\r
+//        var me = this;\r
+//        var placeShadow = function(){\r
+//            var rect = me.getBounds.apply(me,[div]);\r
+//            shadow.css({\r
+//                'left':(rect.x + me.shadowOffset)+'px',\r
+//                'top':(rect.y + me.shadowOffset)+'px',\r
+//                'width':(rect.width)+'px',\r
+//                'height':(rect.height)+'px'\r
+//            });\r
+//        }\r
+//        //calling show with the specified arguments:\r
+//        var args = [];\r
+//        for(var i=1; i<arguments.length; i++){\r
+//            args.push(arguments[i]);\r
+//        }\r
+//        if(args.length==0 || !(args[args.length-1] instanceof Function)){\r
+//            args.push(placeShadow);\r
+//        }else{\r
+//            var fcn = args[args.length-1];\r
+//            args[args.length-1] = function(){\r
+//                placeShadow();\r
+//                fcn();\r
+//            }\r
+//        }\r
+//        both.show.apply(both,args);\r
+//    },\r
+//\r
+//    //hide(div, argumentsAsInJQueryShow)\r
+//    hide: function(){\r
+//        var $J = this.$J;\r
+//        var div = arguments[0];\r
+//        var shadow = $J([]);\r
+//        $J.each(div, function(i,e){\r
+//            shadow = shadow.add($J('#'+$J(e).attr('id')+'_shadow'));\r
+//        });\r
+//        var both = div.add(shadow);\r
+//        //calling hide with the specified arguments:\r
+//        var removeShadow = new function(){\r
+//            shadow.remove();\r
+//        };\r
+//        var args = [];\r
+//        for(var i=1; i<arguments.length; i++){\r
+//            args.push(arguments[i]);\r
+//        }\r
+//        if(args.length<1 || !(args[args.length-1] instanceof Function)){\r
+//            args.push(removeShadow);\r
+//        }else{\r
+//            var f = args[args.length-1];\r
+//            var newf = function(){\r
+//                removeShadow();\r
+//                f();\r
+//            }\r
+//            args[args.length-1] = newf;\r
+//        }\r
+//        both.hide.apply(both, args);\r
+//    },\r
+//\r
+//    remove: function(div){\r
+//        var shadow = $J('#'+div.attr('id')+'_shadow');\r
+//        var both = div.add(shadow);\r
+//        both.remove();\r
+//    },\r
+//\r
+//    setMaxSize: function(div, size){\r
+//        this.convertSize(div, size);\r
+//        var css = {};\r
+//        if('width' in size){\r
+//            css.maxWidth = size.width+'px';\r
+//        }\r
+//        if('height' in size){\r
+//            css.maxHeight = size.height+'px';\r
+//        }\r
+//        if(css){\r
+//            div.css(css);\r
+//        }\r
+//        return size;\r
+//    },\r
+//    setMinSize: function(div, size){\r
+//        this.convertSize(div, size);\r
+//        var css = {};\r
+//        if('width' in size){\r
+//            css.minWidth = size.width+'px';\r
+//        }\r
+//        if('height' in size){\r
+//            css.minHeight = size.height+'px';\r
+//        }\r
+//        if(css){\r
+//            div.css(css);\r
+//        }\r
+//        return size;\r
+//    },\r
+//    //div must be display!=hidden. size is a dict with at least one of the fields 'width' and 'height'\r
+//    convertSize: function(div, size){\r
+//        var eD = {\r
+//            'width': div.outerWidth(true)-div.width(),\r
+//            'height':div.outerHeight(true)-div.height()\r
+//            };\r
+//        if('width' in size){\r
+//            size.width -= (eD.width + this.shadowOffset);\r
+//        }\r
+//        if('height' in size){\r
+//            size.height -= (eD.height + this.shadowOffset);\r
+//        }\r
+//    },\r
+//\r
+//    setSize: function(div, size){ //does it works like that?\r
+//        this.setMaxSize(div, size);\r
+//        this.setMinSize(div, size);\r
+//    },\r
+//\r
+//    offset: function(div, offs){\r
+//        //if offs is a jquery element, size it as a popup.\r
+//        div.offset(offs);\r
+//    },\r
+//\r
+//    //div must be display!=hidden\r
+//    centerInParent: function(div, parent, maxPercentageSize){\r
+//        var bounds = this.getBounds(parent);\r
+//        var x=bounds.x;\r
+//        var y = bounds.y;\r
+//        var w = bounds.width\r
+//        var h = bounds.height;\r
+//        var pInt = parseInt;\r
+//        if(maxPercentageSize){\r
+//            this.setMaxSize(div,{\r
+//                'width':pInt(w*maxPercentageSize),\r
+//                'height':pInt(h*maxPercentageSize)\r
+//                });\r
+//        }\r
+//        var offs = {\r
+//            'left':x+pInt((w-div.outerWidth())/2),\r
+//            'top':y+pInt((h-div.outerHeight())/2)\r
+//            };\r
+//        div.offset(offs);\r
+//    },\r
+//    //setBounds(div, invokerAsjQueryElement): sets the maxsize, minwidth and offset relative ot invokerAs...\r
+//    //setBounds(div, 0.5) sets the maxsize and the offset relative to the window\r
+//    setBounds: function(popupDiv, argument){\r
+//        if(typeof invokerAsJQueryObj == 'number'){\r
+//            this.centerInParent(popupDiv, this.$J(window), argument);\r
+//            return;\r
+//        }\r
+//        var popupOffset = {\r
+//            'left':argument.offset().left,\r
+//            'top':0\r
+//        };\r
+//        var windowRectangle = this.getBounds(); //returns the window rectangle\r
+//        var invokerOffset = argument.offset();\r
+//        var invokerOuterHeight = argument.outerHeight();\r
+//\r
+//        var spaceAbove = invokerOffset.top - windowRectangle.y;\r
+//        var spaceBelow = windowRectangle.height - invokerOuterHeight - spaceAbove;\r
+//\r
+//        // consolelog('wHeight:'+rect.height+ ' space above: '+spaceAbove + ' spacebelow: '+spaceBelow);\r
+//\r
+//        var popupMaxSize={\r
+//            height:0,\r
+//            width:(windowRectangle.x+windowRectangle.width-invokerOffset.left)\r
+//        };\r
+//        if(spaceAbove>spaceBelow){\r
+//            popupMaxSize.height = (spaceAbove-popupDiv.shadowoffset);\r
+//            popupOffset.top = invokerOffset.top - popupDiv.outerHeight(true);\r
+//\r
+//        //p.css({'maxHeight':(spaceAbove-p.shadowoffset)+'px', 'top':rect.y+'px'});\r
+//        }else{\r
+//            popupMaxSize.height =(spaceBelow-popupDiv.shadowoffset);\r
+//            popupOffset.top = (invokerOffset.top+invokerOuterHeight);\r
+//        //p.css({'maxHeight':(spaceBelow-p.shadowoffset)+'px', 'top':(offs.top+height)+'px'});\r
+//        }\r
+//        this.setMaxSize(popupDiv, popupMaxSize);\r
+//        this.setMinSize(popupDiv, {\r
+//            width: argument.outerWidth()\r
+//            });\r
+//        this.offset(popupDiv, popupOffset);\r
+//\r
+//        consolelog('maxSize');\r
+//        consolelog(popupMaxSize);\r
+//        consolelog('minWidth');\r
+//        consolelog(argument.outerWidth());\r
+//        consolelog('offset');\r
+//        consolelog(popupOffset);\r
+//        consolelog('maxWidth: '+popupDiv.css('maxWidth')+' maxHeight: '+popupDiv.css('maxHeight')+\r
+//        ' width: '+popupDiv.css('width')+' height: '+popupDiv.css('height')+' left '+popupDiv.css('left')+' top '+popupDiv.css('top'));\r
+//    },\r
+//    //returns a dictionary with x,y,width and height keys representing the\r
+//    //rectangle where jQueryElement lies. width and height are jQuery.width() and jQuery.height() respectively\r
+//    //if jQueryElement is missing, jQuery(window) is used\r
+//    //jQueryElement must be display!=none\r
+//    getBounds: function(jQueryElement){\r
+//        var ret = {\r
+//            x:0,\r
+//            y:0,\r
+//            width:0,\r
+//            height:0\r
+//        };\r
+//        if(!jQueryElement){\r
+//            jQueryElement = this.$J(window);\r
+//        }\r
+//        if(jQueryElement[0] === window){\r
+//            ret.x = jQueryElement.scrollLeft();\r
+//            ret.y = jQueryElement.scrollTop();\r
+//        }else{\r
+//            var offs = jQueryElement.offset();\r
+//            ret.x = offs.left;\r
+//            ret.y = offs.top;\r
+//        }\r
+//        ret.width = jQueryElement.width();\r
+//        ret.height = jQueryElement.height();\r
+//        return ret;\r
+//    }\r
+//\r
+//\r
+//};\r
+\r
+function PopupDiv(content){\r
+    var $J = this.$J;\r
+    //var wdw = $J(window);\r
+    var div  = $J('<div/>').addClass(this.defaultClasses).css({\r
+        'position':'absolute',\r
+        'zIndex':this.zIndex,\r
+//        'display':'none',\r
+//        'left':wdw.scrollLeft()+'px',\r
+//        'top':wdw.scrollTop()+'px',\r
+        'overflow':'auto',\r
+        'padding':'1ex',\r
+        'border':'1px solid #666'\r
+    });\r
+    //div.appendTo('body'); //necessary to properly display the div size\r
+    if(content instanceof $J){\r
+        div.append(content);\r
+    }else if(typeof content == 'string'){\r
+        div.html(""+content);\r
+    }else{\r
+        div.css('overflow',''); //clear overflow\r
+        var container = $J('<div/>').css('overflow','auto');\r
+        var table = $J('<table/>');\r
+        container.append(table);\r
+        var insert = function(e1,e2){\r
+            var t1 = $J('<td/>');\r
+            var t2 = $J('<td/>');\r
+            if(e1){\r
+                t1.append(e1);\r
+            }\r
+            if(e2){\r
+                t2.append(e2);\r
+            }\r
+            table.append($J('<tr/>').append(t1).append(t2));\r
+        }\r
+        var title, component;\r
+        for(var k in content){\r
+            var val = content[k];\r
+            if(val instanceof Function){\r
+                component = $J('<a/>').html(k).attr('href','#').click(function(evt){\r
+                    val();\r
+                    return false;\r
+                });\r
+                insert(component);\r
+            }else if(typeof val == 'string' || typeof val == 'number'){\r
+                title = $J('<span/>').html(k);\r
+                component = $('<input/>').attr('type','text').val(val).attr('name',k);\r
+                insert(title,component);\r
+            }else if(val === true || val === false){\r
+                title = $J('<span/>').html(k);\r
+                component = $('<input/>').attr('type','checkbox').attr('name',k);\r
+                if(val){\r
+                    component.attr('checked','checked');\r
+                }else{\r
+                    component.removeAttr('checked');\r
+                }\r
+                insert(title,component);\r
+            }\r
+        }\r
+    }\r
+    div.attr('id',this.defaultId+"_"+(new Date().getTime()));\r
+    this.getFocusId = function(){\r
+        return this.defaultId+'_focus';\r
+    }\r
+    this.getDiv = function(){\r
+        return div;\r
+    }\r
+    \r
+    this.callbackPreShow = null;\r
+    this.callbackPostShow = null;\r
+}\r
+(function(p){\r
+    //populating the prototype:\r
+    //properties:\r
+    p.defaultFadeTime='fast',\r
+    p.$J = jQuery;\r
+    p.shadowOpacity = 0.4;\r
+    p.shadowOffset = 5;\r
+    p.zIndex = 1000;\r
+    p.defaultClasses = 'control component';\r
+    p.defaultId = 'popup_'+(new Date().getTime());\r
+    p.focusId = p.defaultId+'_focus';\r
+\r
+    //p.wdow = p.$J(window);\r
+    //methods:\r
+    p.getId = function(){\r
+        var div = this.getDiv();\r
+        if(!(div.attr('id'))){\r
+            div.attr('id',this.defaultId+'_'+(new Date().getTime()));\r
+        }\r
+        return div.attr('id');\r
+    };\r
+    //p.createButtons({'ok':function...,'cancel':function,...});\r
+   \r
+\r
+    p.setAsPopupOf = function(invoker,removeOnBlur){\r
+        if(!(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') ||\r
+            invoker.is('input[type=submit]'))){\r
+            return;\r
+        }\r
+        invoker.attr('tabindex',0).attr(this.focusId,'true');\r
+        //invoker.attr(this.getFocusId(),'true');\r
+        var me =this;\r
+        this.callbackPreShow = function(){\r
+            me.setBounds.apply(me,[invoker]);\r
+        };\r
+        this.callbackPostShow = function(){\r
+            var fcn = removeOnBlur ? me.remove : me.hide;\r
+            me.setFocusable.apply(me,[function(){\r
+                fcn.apply(me);\r
+            }]);\r
+            var elm = me.getFirstFocusableElement();\r
+            elm.focus();\r
+        };\r
+\r
+        var popupDiv = this.getDiv();\r
+        invoker.unbind('click').bind('click',function(evt){\r
+            if(popupDiv.length && popupDiv.is(':visible')){\r
+                me.getFirstFocusableElement().focus();\r
+                return false;\r
+            }\r
+            //                me.setBounds.apply(me, [popupDiv,invoker]);\r
+            //                me.show.apply(me,[popupDiv, function(){focusElm.focus();}]);\r
+            me.show.apply(me);\r
+            return false;\r
+        });\r
+    };\r
+\r
+    p.setAsWindowDialog = function(timeInMsec, windowPercentSize){\r
+\r
+        var me =this;\r
+        this.callbackPreShow = function(){\r
+            me.setBounds.apply(me,[windowPercentSize]);\r
+        }\r
+\r
+        if(timeInMsec){\r
+            this.callbackPostShow = function(){\r
+                setTimeout(timeInMsec, function(){\r
+                    me.remove.apply(me);\r
+                });\r
+            }\r
+        }else{\r
+            this.callbackPostShow = function(){\r
+                var elm = me.setFocusable.apply(me,function(){\r
+                    me.remove.apply(me);\r
+                });\r
+                elm.focus();\r
+            };\r
+        }\r
+    };\r
+    p.setFocusable = function(callbackOnBlur){\r
+        var popup = this.getDiv();\r
+        popup.attr('tabindex',0);\r
+        var $J = this.$J;\r
+        var elementsWithFocus = $J(popup).find('textarea,a,input');\r
+        var doc = document;\r
+        var ret = elementsWithFocus.length ? $J(elementsWithFocus[0]) : popup;\r
+        elementsWithFocus = elementsWithFocus.add(popup);\r
+        //build the attribute focus to recognize subelement of popup\r
+        var focusid =this.focusId;\r
+    \r
+        //bind the blur to each focusable element:\r
+        elementsWithFocus.each(function(i,e){\r
+            var ee = $J(e);\r
+            ee.removeAttr(focusid).attr(focusid,'true'); //makes sense?\r
+            ee.attr('tabindex',i+1);\r
+            ee.unbind('blur').blur(function(){\r
+                //wait 250msec to see if the focus has been given to another popup focusable element: if yes, do nothing\r
+                //otherwise execute callback\r
+                setTimeout(function(){\r
+                    var v = doc.activeElement;\r
+                    //consolelog(v);\r
+                    if(v && $J(v).attr(focusid)){\r
+                        return;\r
+                    }\r
+                    if(callbackOnBlur){\r
+                        callbackOnBlur();\r
+                    }\r
+                },200)\r
+            }); //set here another time delay. 300 seems to be the good compromise between visual hide and safetiness that\r
+        //meanwhile the focus has already been given to the next component\r
+        });\r
+        this.getFirstFocusableElement = function(){\r
+            return ret;\r
+        }\r
+    };\r
+\r
+    p.show = function(){\r
+        var div = this.getDiv();\r
+\r
+        if(!div.parent().length){\r
+            div.appendTo('body');\r
+        }\r
+        //set the div as opacity 0 but displayable\r
+        div.css({\r
+            'visibility':'visible'\r
+        }).fadeTo(0,0).show();\r
+\r
+        if(this.callbackPreShow){\r
+            this.callbackPreShow();\r
+        }\r
+\r
+       \r
+        //TODO: avoid clone and empty?\r
+        var shadow = div.clone(true,true).empty().css({\r
+            'backgroundColor':'#000',\r
+            'borderColor':'#000',\r
+            'zIndex':this.zIndex-1\r
+        }).removeAttr('tabindex').fadeTo(0,0);\r
+        var id = this.getId();\r
+        shadow.attr('id',id+'_shadow'); //for use in hide\r
+        shadow.insertAfter(div);\r
+\r
+        var me = this;\r
+        var postShowFcn = function(){\r
+            var rect = me.getBounds.apply(me);\r
+            shadow.css({\r
+                'left':(rect.x + me.shadowOffset)+'px',\r
+                'top':(rect.y + me.shadowOffset)+'px',\r
+                'width':(rect.width)+'px',\r
+                'height':(rect.height)+'px'\r
+            }).fadeTo(0,me.shadowOpacity);\r
+            if(me.callbackPostShow){\r
+                me.callbackPostShow.apply(me);\r
+            }\r
+        }\r
+\r
+        var arg1 = arguments.length && arguments[0] instanceof Function ? arguments[0] : this.defaultFadeTime;\r
+        var arg2 = arguments.length && arguments[arguments.length-1] instanceof Function ? arguments[arguments.length-1] : undefined;\r
+\r
+        div.fadeTo(arg1,1,function(){\r
+            postShowFcn();\r
+            if(arg2){\r
+                arg2();\r
+            }\r
+        });\r
+    };\r
+    //setBounds(0.5)\r
+    //setBounds(jQueryDisplayedElement)\r
+    p.setBounds = function(arg){\r
+        if(typeof arg == ' number'){\r
+            this.centerIn(this.$J(window), arg);\r
+            return;\r
+        }\r
+        var invoker = arg;\r
+        var popupDiv = this.getDiv();\r
+\r
+        var popupOffset = {\r
+            'left':invoker.offset().left,\r
+            'top':0\r
+        };\r
+        var windowRectangle = this.getBoundsOf(this.$J(window)); //returns the window rectangle\r
+        var invokerOffset = invoker.offset();\r
+        var invokerOuterHeight = invoker.outerHeight();\r
+\r
+        var spaceAbove = invokerOffset.top - windowRectangle.y;\r
+        var spaceBelow = windowRectangle.height - invokerOuterHeight - spaceAbove;\r
+\r
+        var popupMaxSize={\r
+            height:0,\r
+            width:(windowRectangle.x+windowRectangle.width-invokerOffset.left)\r
+        };\r
+        if(spaceAbove>spaceBelow){\r
+            popupMaxSize.height = spaceAbove;\r
+            popupOffset.top = invokerOffset.top - Math.min(spaceAbove, popupDiv.outerHeight(true));\r
+\r
+        //p.css({'maxHeight':(spaceAbove-p.shadowoffset)+'px', 'top':rect.y+'px'});\r
+        }else{\r
+            popupMaxSize.height = Math.min(spaceBelow, popupDiv.outerHeight(true));\r
+            popupOffset.top = (invokerOffset.top+invokerOuterHeight);\r
+        //p.css({'maxHeight':(spaceBelow-p.shadowoffset)+'px', 'top':(offs.top+height)+'px'});\r
+        }\r
+        this.setMaxSize(popupMaxSize);\r
+        this.setMinSize({\r
+            width: invoker.outerWidth()\r
+        });\r
+        this.offset(popupOffset);\r
+\r
+        consolelog('maxSize:');\r
+        consolelog(popupMaxSize);\r
+        consolelog('minWidth:'+ invoker.outerWidth());\r
+        consolelog('offset:');\r
+        consolelog(popupOffset);\r
+        consolelog('maxWidth: '+popupDiv.css('maxWidth')+' maxHeight: '+popupDiv.css('maxHeight')+\r
+            ' width: '+popupDiv.css('width')+' height: '+popupDiv.css('height')+' left '+popupDiv.css('left')+' top '+popupDiv.css('top'));\r
+    };\r
+\r
+    p.centerIn = function(parent, maxPercentageSize){\r
+        var div = this.getDiv();\r
+        var bounds = this._getBounds(parent);\r
+        var x=bounds.x;\r
+        var y = bounds.y;\r
+        var w = bounds.width\r
+        var h = bounds.height;\r
+        var pInt = parseInt;\r
+        if(maxPercentageSize){\r
+            this.setMaxSize(div,{\r
+                'width':pInt(w*maxPercentageSize),\r
+                'height':pInt(h*maxPercentageSize)\r
+            });\r
+        }\r
+        var offs = {\r
+            'left':x+pInt((w-div.outerWidth())/2),\r
+            'top':y+pInt((h-div.outerHeight())/2)\r
+        };\r
+        div.offset(offs);\r
+    };\r
+    p.getBounds = function(){\r
+        return this.getBoundsOf(this.getDiv());\r
+    },\r
+    //TODO: change argument\r
+    p.getBoundsOf = function(jQueryElement){\r
+        var ret = {\r
+            x:0,\r
+            y:0,\r
+            width:0,\r
+            height:0\r
+        };\r
+        if(!jQueryElement){\r
+            jQueryElement = this.$J(window);\r
+        }\r
+        if(jQueryElement[0] === window){\r
+            ret.x = jQueryElement.scrollLeft();\r
+            ret.y = jQueryElement.scrollTop();\r
+        }else{\r
+            var offs = jQueryElement.offset();\r
+            ret.x = offs.left;\r
+            ret.y = offs.top;\r
+        }\r
+        ret.width = jQueryElement.width();\r
+        ret.height = jQueryElement.height();\r
+        return ret;\r
+    }\r
+\r
+    p.setMaxSize = function(size){\r
+        var div = this.getDiv();\r
+        this._convertSize(div, size);\r
+        var css = {};\r
+        if('width' in size){\r
+            css.maxWidth = size.width+'px';\r
+        }\r
+        if('height' in size){\r
+            css.maxHeight = size.height+'px';\r
+        }\r
+        if(css){\r
+            div.css(css);\r
+        }\r
+        return size;\r
+    };\r
+    p.setMinSize = function(size){\r
+        var div = this.getDiv();\r
+        this._convertSize(div, size);\r
+        var css = {};\r
+        if('width' in size){\r
+            css.minWidth = size.width+'px';\r
+        }\r
+        if('height' in size){\r
+            css.minHeight = size.height+'px';\r
+        }\r
+        if(css){\r
+            div.css(css);\r
+        }\r
+        return size;\r
+    },\r
+    //div must be display!=hidden. size is a dict with at least one of the fields 'width' and 'height'\r
+    p._convertSize = function(div, size){\r
+        var eD = {\r
+            'width': div.outerWidth(true)-div.width(),\r
+            'height':div.outerHeight(true)-div.height()\r
+        };\r
+        if('width' in size){\r
+            size.width -= (eD.width + this.shadowOffset);\r
+        }\r
+        if('height' in size){\r
+            size.height -= (eD.height + this.shadowOffset);\r
+        }\r
+    },\r
+\r
+    p.setSize = function(div, size){ //does it works like that?\r
+        this.setMaxSize(div, size);\r
+        this.setMinSize(div, size);\r
+    };\r
+\r
+    p.offset = function(offs){\r
+        //if offs is a jquery element, size it as a popup.\r
+        this.getDiv().offset(offs);\r
+    };\r
+\r
+    p.hide = function(){\r
+        var div = this.getDiv();\r
+        var $J = this.$J;\r
+        var shadow = $J([]);\r
+        $J.each(div, function(i,e){\r
+            shadow = shadow.add($J('#'+$J(e).attr('id')+'_shadow'));\r
+        });\r
+        var both = div.add(shadow);\r
+        //calling hide with the specified arguments:\r
+        var removeShadow = new function(){\r
+            shadow.remove();\r
+        };\r
+        var args = [];\r
+        for(var i=1; i<arguments.length; i++){\r
+            args.push(arguments[i]);\r
+        }\r
+        if(args.length<1 || !(args[args.length-1] instanceof Function)){\r
+            args.push(removeShadow);\r
+        }else{\r
+            var f = args[args.length-1];\r
+            var newf = function(){\r
+                removeShadow();\r
+                f();\r
+            }\r
+            args[args.length-1] = newf;\r
+        }\r
+        both.hide.apply(both, args);\r
+    };\r
+\r
+    p.remove = function(){\r
+        var div = this.getDiv();\r
+        var shadow = $J('#'+div.attr('id')+'_shadow');\r
+        var both = div.add(shadow);\r
+        both.remove();\r
+    };\r
+})(PopupDiv.prototype);
\ No newline at end of file
index 1aa87ea721f19153a283aabe8c4711893467da9c..88e5eda16ba4546ccea0dfa1a243d92cb03d7b27 100644 (file)
         }
     });
 
+    jQuery(document).ready(function(){
+        var ar = [];
+        for(var i=0; i<1000; i++){
+            ar.push('<a href=#>'+i+'</a>');
+        }
+        var p = new PopupDiv(ar.join('<br/>'));
+         consolelog(p);
+            p.getDiv().find('a').each(function(i,aa){
+                jQuery(aa).click(function(){alert(jQuery(aa).html());p.hide();return false;});
+            });
+
+        var a = jQuery('<a/>').attr('href','#').html('clickme');
+       
+        p.setAsPopupOf(a);
+        jQuery('body').append(a);
+    });
 </script>
 <!--item.approx_duration-->