]> git.parisson.com Git - telemeta.git/commitdiff
working on playlists popups and player...
authorriccardo <riccardo@parisson.com>
Thu, 5 May 2011 14:23:34 +0000 (16:23 +0200)
committerriccardo <riccardo@parisson.com>
Thu, 5 May 2011 14:23:34 +0000 (16:23 +0200)
telemeta/htdocs/js/application.js
telemeta/htdocs/timeside/src/playlist.js
telemeta/htdocs/timeside/src/timeside.js
telemeta/templates/telemeta_default/mediaitem_detail.html

index 333a2d915d14eb4c3b4a8ff0de3b214930e558b8..295405cd2093a7213e4559313e74ebba5ab5e8af 100644 (file)
@@ -1003,413 +1003,9 @@ function DivDialog(content){
 \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
+    \r
     //var wdw = $J(window);\r
     var div  = $J('<div/>').addClass(this.defaultClasses).css({\r
         'position':'absolute',\r
@@ -1421,186 +1017,374 @@ function PopupDiv(content){
         'padding':'1ex',\r
         'border':'1px solid #666'\r
     });\r
-    var header = $J('<div/>').css('float','right');\r
+    var header = $J('<div/>'); //.css('float','right');\r
     var container = $J('<div/>').css('overflow','auto');\r
     var footer = $J('<div/>');\r
     div.append(header).append(container).append(footer);\r
+    //defining immediately the method getDiv (because it is used below)\r
+    this.getDiv = function(){\r
+        return div;\r
+    }\r
 \r
     //div.appendTo('body'); //necessary to properly display the div size\r
     if(content instanceof $J){\r
         container.append(content);\r
     }else if(typeof content == 'string'){\r
         container.html(""+content);\r
-    }else{\r
-        div.css('overflow',''); //clear overflow\r
-        var table = $J('<table/>');\r
-        container.append(table);\r
+    }\r
+    //    else if(content instanceof Array){\r
+    //        for(var k=0; k<content.length;i++){\r
+    //            (function(value){container.append($J('<a/>').attr('href','#').html(value).click(\r
+    //            function(){\r
+    //                if(optionalCallbackOnClick){\r
+    //                    optionalCallbackOnClick(value);\r
+    //                }\r
+    //            }\r
+    //            ))})(content[k]);\r
+    //        }\r
+    //}\r
+    else{\r
+        var leftElements = $J([]);\r
+        var rightElements = $J([]);\r
+        var maxw = [0,0];\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
+            var lineDiv = $J('<div/>');\r
+            if(!e2){\r
+                e2=e1;\r
+                e1 = $J('<span/>');\r
+            } \r
+            rightElements = rightElements.add(e2);\r
+            leftElements = leftElements.add(e1);\r
+            container.append(lineDiv.append(e1).append(e2));\r
+            return lineDiv;\r
         }\r
         var title, component;\r
+        \r
+        var max = Math.max; //instantiate once\r
+        var lineDiv = undefined;\r
+        var needAlign = false;\r
+        var lineDivs = $J([]);\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
+            //alert(k);\r
+            //            if(val instanceof Function){\r
+            //                //alert('inserting anchor/function');\r
+            //                component = $J('<a/>').html(k).attr('href','#').click(function(evt){\r
+            //                    val();\r
+            //                    return false;\r
+            //                });\r
+            //                lineDivs = lineDivs.add(insert(component));\r
+            //                maxw[1] = max(maxw[1],k.length);\r
+            //            }else\r
+            if(typeof val == 'string' || typeof val == 'number'){\r
+                //alert('inserting string/number');\r
                 title = $J('<span/>').html(k);\r
+                maxw[0] = max(maxw[0],k.length);\r
+                maxw[1] = max(maxw[1],val.length);\r
                 component = $('<input/>').attr('type','text').val(val).attr('name',k);\r
-                insert(title,component);\r
+                lineDivs = lineDivs.add(insert(title,component));\r
+                needAlign = true;\r
             }else if(val === true || val === false){\r
-                title = $J('<span/>').html(k);\r
-                component = $('<input/>').attr('type','checkbox').attr('name',k);\r
+                //alert('inserting boolean');\r
+                var id = this.getId()+"_checkbox";\r
+                title = $('<input/>').attr('type','checkbox').attr('name',k).attr('id',id);\r
                 if(val){\r
-                    component.attr('checked','checked');\r
+                    title.attr('checked','checked');\r
                 }else{\r
-                    component.removeAttr('checked');\r
+                    title.removeAttr('checked');\r
+                }\r
+                component = $J('<label/>').attr('for',id).html(k);\r
+                maxw[1] = max(maxw[1],k.length);\r
+                lineDivs = lineDivs.add(insert($J('<span/>').append(title),component));\r
+                needAlign = true;\r
+            }else if(val instanceof Array){\r
+                //alert('inserting array');\r
+                title = $J('<span/>').html(k);\r
+                maxw[0] = max(maxw[0],k.length);\r
+                component = $J('<select/>').attr('size',1);\r
+                for(var i=0; i< val.length; i++){\r
+                    component.append($J('<option/>').val(val[i]).html(val[i]));\r
+                    maxw[1] = max(maxw[1],val[i].length);\r
                 }\r
-                insert(title,component);\r
+                lineDivs = lineDivs.add(insert(title,component));\r
+                needAlign = true;\r
+            }\r
+            if(lineDiv){\r
+                lineDiv.css('marginBottom','1ex');\r
             }\r
         }\r
+        lineDivs.css({\r
+            'white-space': 'nowrap',\r
+            'marginBottom':'0.5ex'\r
+        });\r
+        //last div erase marginBottom\r
+        $J(lineDivs[lineDivs.length-1]).css('marginBottom','');\r
+        \r
+        //as ex is aproximately 1/3 em, we use a measure in between:\r
+        if(needAlign){\r
+            //display: inline-block below assures that width are properly set\r
+            //IE 6/7 accepts the value only on elements with a natural display: inline.\r
+            //(see http://www.quirksmode.org/css/display.html#t03)\r
+            //span and anchors are among them\r
+            //(see http://www.maxdesign.com.au/articles/inline/)\r
+            leftElements.add(rightElements).css({\r
+                'display':'inline-block',\r
+                'margin':'0px',\r
+                'padding':'0px'\r
+            });\r
+            leftElements.css({\r
+                'textAlign':'right',\r
+                'marginRight':'0.5ex',\r
+                'width':Math.round((3/5)*maxw[0])+'em'\r
+            });\r
+            rightElements.css({\r
+                'width':Math.round((3/5)*maxw[1])+'em'\r
+            });\r
+        }\r
     }\r
\r
     \r
-    this.getFocusId = function(){\r
-        return this.defaultId+'_focus';\r
+    //callback to be called BEFORE showing the popupdiv.\r
+    //it is usually a function to place the div in the correct point and recalculate its size\r
+    //Note that when called, the popup div is NOT visible BUT has display!='none', so that width and height can be calculated safely\r
+    this.callbackPreShow = null;\r
+    //callback to be called AFTER the popup is shown, it is usually a function to set the focus in case of popups\r
+    this.callbackPostShow = null;\r
+    //setting functions:\r
+    var sizable = false;\r
+    var wdw = this.$J(window);\r
+    this.isSizable = function(){\r
+        return sizable;\r
     }\r
-    this.getDiv = function(){\r
-        return div;\r
+    this.setSizable = function(value){\r
+        //if false, just update the flag\r
+        if(!value){\r
+            sizable = false;\r
+            return undefined;\r
+        }\r
+        if(!div.parent().length){\r
+            div.appendTo('body');\r
+        }\r
+        var keys = ['display','visibility','left','top','maxWidth','maxHeight','minWidth','minHeight'];\r
+        var css = {};\r
+        for(var i=0; i<keys.length; i++){\r
+            css[keys[i]] = div.css(keys[i]);\r
+        }\r
+        div.offset({\r
+            'left':wdw.scrollLeft(),\r
+            'top':wdw.scrollTop()\r
+        });\r
+        //set the div invisible but displayable to calculate the size (callbackPreShow)\r
+        div.css({\r
+            'visibility':'hidden',\r
+            'maxWidth':'',\r
+            'maxHeight':'',\r
+            'minWidth':'',\r
+            'minHeight':'',\r
+            'height':'',\r
+            'width':''\r
+        }).show();\r
+        sizable = true;\r
+        return css;\r
+    }\r
+\r
+    var listeners = {};\r
+    this.getListeners = function(){\r
+        return listeners;\r
     }\r
     \r
-    this.callbackPreShow = null;\r
-    this.callbackPostShow = null;\r
+    var pding = this.defaultBounds;\r
+    this.setBoundsInInvoker = function(padding){\r
+        var newp = {};\r
+        var db = this.defaultBounds;\r
+        var keys = ['top','bottom','left','right'];\r
+        for(var i=0; i<keys.length; i++){\r
+            if(!(keys[i] in padding)){\r
+                newp[keys[i]] = db[keys[i]];\r
+            }\r
+        }\r
+        pding = newp;\r
+    }\r
+    this.getBoundsInInvoker = function(){\r
+        return pding;\r
+    }\r
+\r
+    var invk = this.defaultInvoker;\r
+    this.setInvoker = function(invoker){\r
+        var focusAttr = this.getFocusAttr();\r
+        consolelog(focusAttr);\r
+        if(this.isClickElement(invk)){\r
+            invk.unbind('click').removeAttr('tabindex').removeAttr(focusAttr);\r
+        }\r
+        \r
+        if(this.isClickElement(invoker)){\r
+            var me = this;\r
+            me.setFocusable(true);\r
+            invoker.unbind('click').bind('click',function(evt){\r
+                //let the invoker have focus and let it be recognized as an element which does not blur the popup:\r
+                invoker.attr('tabindex',0).attr(focusAttr,'true');\r
+                var popupDiv = me.getDiv();\r
+                if(popupDiv.length && popupDiv.is(':visible')){\r
+                    me.getFirstFocusableElement().focus();\r
+                    return false;\r
+                }\r
+                me.show.apply(me);\r
+                return false;\r
+            });\r
+        }\r
+        \r
+        invk = invoker;\r
+    }\r
+    this.getInvoker = function(){\r
+        return invk && invk instanceof this.$J ? invk : this.defaultInvoker;\r
+    }\r
+    \r
+    var co;\r
+    this.setCloseOperation = function(hideOrRemove){\r
+        if(hideOrRemove == 'remove'){\r
+            co = 'remove';\r
+        }else{\r
+            co = undefined;\r
+        }\r
+    }\r
+    this.getCloseOperation = function(){\r
+        return co ? co : this.defaultCloseOperation;\r
+    }\r
+\r
+    this.getShadowDivId = function(){\r
+        return this.getId()+"_shadow";\r
+    }\r
+\r
+    this.getFocusAttr = function(){\r
+        return this.getId()+"_focus";\r
+    }\r
+\r
 }\r
 (function(p){\r
+\r
+    p.isClickElement = function(element){\r
+return element && element.length && element instanceof this.$J && element[0] !== window && element[0] !== document &&\r
+        (element.is('a') || element.is('input[type=button]') || element.is('button') ||\r
+            element.is('input[type=submit]'));\r
+    }\r
+\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
+\r
     //populating the prototype:\r
     //properties:\r
-    p.defaultFadeTime='fast',\r
+    p.defaultFadeTime = 'fast',\r
+    p.defaultFadeOutTime = 0,\r
     p.$J = jQuery;\r
-    p.shadowOpacity = 0.4;\r
+    p.shadowOpacity = 0.3;\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.okButtonClass =  'component_icon button icon_ok';\r
     p.cancelButtonClass = 'component_icon button icon_cancel';\r
+    p.defaultCloseOperation = 'hide';\r
+    p.defaultInvoker = p.$J(window);\r
+    p.defaultBounds = {\r
+        'top':0.5,\r
+        'left':0.5,\r
+        'right':0.5,\r
+        'bottom':0.5\r
+    };\r
     //p.wdow = p.$J(window);\r
     //methods:\r
 \r
+    //    p.getFormData = function(){\r
+    //        var elms = this.getDiv().find\r
+    //    }\r
+\r
+    p.bind = function(eventName, callback){ //eventname: show, blur or ok\r
+        var listeners = this.getListeners();\r
+        if(eventName in listeners){\r
+            listeners[eventName].push(callback);\r
+        }else{\r
+            listeners[eventName] = [callback];\r
+        }\r
+    }\r
+    p.unbind = function(eventName){\r
+        var listeners = this.getListeners();\r
+        if(eventName in listeners){\r
+            delete listeners[eventName];\r
+        }\r
+    }\r
+    p.trigger = function(eventName, extraParameters){\r
+        var listeners = this.getListeners();\r
+        if(eventName in listeners){\r
+            var callbacks = listeners[eventName];\r
+            for(var i=0; i<callbacks.length; i++){\r
+                callbacks[i](extraParameters);\r
+            }\r
+        }\r
+    }\r
+\r
     p.addButton = function(onTop, caption, classNames, callback){\r
         var $J = this.$J;\r
         var div = $J($J(this.getDiv()).children()[onTop ? 0 : 2]);\r
-        var a = $J('<a/>').html(caption).addClass(classNames).attr('href','#').click(function(evt){callback(evt); return false;});\r
+        var a = $J('<a/>').html(caption).addClass(classNames).attr('href','#').click(function(evt){\r
+            callback(evt);\r
+            return false;\r
+        });\r
         div.append(a);\r
         return a;\r
-    },\r
-\r
+    }\r
+    //adds a cancel button to the bottom of the popupdiv\r
+    //addCancelButton(caption) adds a cancel button which HIDES the popup\r
+    //addCancelButton(caption, true) adds a cancel button which REMOVES the popup\r
     p.addCancelButton = function(caption, removeOnClick){\r
         var me = this;\r
-        addButton(false,caption,this.cancelButtonClass, removeOnClick ? function(){me.remove()} : function(){me.hide()});\r
-    },\r
-\r
-    p.addOkButton = function(caption, callbackOnClick){\r
-        addButton(false,caption,this.okButtonClass, callbackOnClick);\r
-    },\r
-\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
-   p.createButtons = function(jQueryElement){\r
-     var bottomDiv = this.$J(this.getDiv().children()[2]);\r
-     for(k in dict){\r
-         bottomDiv.append(this.$J('<a/>'))\r
-     }\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
+        addButton(false,caption,this.cancelButtonClass, removeOnClick ? function(){\r
+            me.remove()\r
+        } : function(){\r
+            me.hide()\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
+    //adds a ok button to the bottom of the popupdiv\r
+    //addOkButton(caption,callback) adds a cancel button which HIDES the popup AND EXECUTES\r
+    //addCancelButton(caption, true) adds a cancel button which REMOVES the popup\r
+    p.addOkButton = function(caption, callbackOnClick, removeOnClick){\r
+        addButton(false,caption,this.okButtonClass, callbackOnClick);\r
+    }\r
+    p.find = function(argumentAsInJQueryFind){\r
+        return this.$J(this.getDiv().children[1]).find(argumentAsInJQueryFind);\r
+    }\r
+    \r
+    p.setFocusable = function(value){\r
+        var popup = this.getDiv();\r
+        var $J = this.$J;\r
+        var focusAttr =this.getFocusAttr();\r
+        if(!value){\r
+            popup = popup.add($J(popup).find('*'));\r
+            popup.each(function(i,elm){\r
+                $J(elm).removeAttr('tabindex').removeAttr(focudid);\r
+            });\r
+            this.getFirstFocusableElement = function(){\r
+                return undefined;\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
+            return;\r
         }\r
-    };\r
-    p.setFocusable = function(callbackOnBlur){\r
-        var popup = this.getDiv();\r
+        \r
         popup.attr('tabindex',0);\r
-        var $J = this.$J;\r
-        var elementsWithFocus = $J(popup).find('textarea,a,input');\r
+        var elementsWithFocus = $J(popup).find('textarea,a,input,select');\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
+        \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.removeAttr(focusid).attr(focusid,'true'); //makes sense?\r
+            ee.attr(focusAttr,'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
@@ -1608,12 +1392,11 @@ function PopupDiv(content){
                 setTimeout(function(){\r
                     var v = doc.activeElement;\r
                     //consolelog(v);\r
-                    if(v && $J(v).attr(focusid)){\r
+                    if(v && $J(v).attr(focusAttr)){\r
                         return;\r
                     }\r
-                    if(callbackOnBlur){\r
-                        callbackOnBlur();\r
-                    }\r
+                    me.trigger('blur');\r
+                    me.close();\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
@@ -1622,40 +1405,59 @@ function PopupDiv(content){
             return ret;\r
         }\r
     };\r
-\r
+    p.getFirstFocusableElement = function(){\r
+        return undefined;\r
+    }\r
     p.show = function(){\r
         var div = this.getDiv();\r
         var me = this;\r
 \r
-        if(!div.parent().length){\r
-            div.appendTo('body');\r
-        }\r
-        //set the div invisible but displayable to calculate the size (callbackPreShow)\r
-        div.css({\r
-            'visibility':'hidden'\r
-        }).show();\r
+        this.setSizable(true);\r
 \r
-        if(this.callbackPreShow){\r
-            this.callbackPreShow();\r
-\r
-            //set all subdivs to same width. Must be done when the element is full showing\r
-            //apparently, even opacity is considered not fully showing\r
-            var subdiv = div.children();\r
-            consolelog(subdiv);\r
-            var maxw = 0;\r
-            var $J= me.$J;\r
-            var max = Math.max;\r
-            subdiv.each(function(i,d){\r
-                //consolelog(i);\r
-                maxw = max(maxw,$J(d).width());\r
-            });\r
-            subdiv.each(function(i,d){\r
-                $J(d).css('minWidth',maxw+'px');\r
-            });\r
-            $J(subdiv[1]).css('maxHeight',(div.height()-$J(subdiv[0]).outerHeight()-$J(subdiv[2]).outerHeight()-\r
-                ($J(subdiv[1]).outerHeight(true)-$J(subdiv[1]).height()))+'px');\r
-            //done\r
+       \r
+        var subdiv = div.children();\r
+        var $J= me.$J;\r
+        //reset properties of the central div\r
+        $J(subdiv[1]).css({\r
+            'maxHeight':'',\r
+            'maxWidth':'',\r
+            'minHeight':'',\r
+            'minWidth':'',\r
+            'height':'',\r
+            'width':''\r
+        });\r
+\r
+        var invoker = this.getInvoker();\r
+            \r
+        if(this.isClickElement(invoker)){\r
+            this.setBoundsAsPopup(invoker);\r
+            consolelog('sbap');\r
+        }else{\r
+            this.setBoundsInside(invoker, this.getBoundsOfInvoker());\r
+        }\r
+        //this.callbackPreShow();\r
+\r
+        //            consolelog('maxHeight: '+ (div.height()-$J(subdiv[0]).outerHeight()-$J(subdiv[2]).outerHeight()-\r
+        //                ($J(subdiv[1]).outerHeight(true)-$J(subdiv[1]).height())));\r
+        //            consolelog('height: '+$J(subdiv[1]).height());\r
+\r
+        //set central div max height ONLY IF NECESSARY:\r
+        var maxHeight = (div.height()-$J(subdiv[0]).outerHeight()-$J(subdiv[2]).outerHeight()-\r
+            ($J(subdiv[1]).outerHeight(true)-$J(subdiv[1]).height()));\r
+        var height = $J(subdiv[1]).height();\r
+        if(maxHeight<height){\r
+            //alert('setting height');\r
+            $J(subdiv[1]).css('maxHeight',maxHeight+'px');\r
         }\r
+            \r
+        //set central div max width ONLY IF NECESSARY:\r
+        var maxWidth = div.width();\r
+        var width = $J(subdiv[1]).outerWidth(true);\r
+        if(maxWidth<width){\r
+            //alert('setting width');\r
+            $J(subdiv[1]).css('maxHeight',maxHeight+'px');\r
+        }\r
+      \r
 \r
        \r
         //TODO: avoid clone and empty?\r
@@ -1664,10 +1466,9 @@ function PopupDiv(content){
             'borderColor':'#000',\r
             'visibility':'visible',\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
+        }).removeAttr('tabindex').fadeTo(0,0).\r
+        attr('id',this.getShadowDivId()) //for use in hide\r
+        .insertAfter(div);\r
 \r
         \r
         var postShowFcn = function(){\r
@@ -1677,94 +1478,112 @@ function PopupDiv(content){
                 'top':(rect.y + me.shadowOffset)+'px',\r
                 'width':(rect.width)+'px',\r
                 'height':(rect.height)+'px'\r
-            }).fadeTo(me.defaultFadeTime,me.shadowOpacity);\r
+            }).fadeTo(me.defaultFadeTime,me.shadowOpacity, function(){\r
+                var v = me.getFirstFocusableElement();\r
+                if(v){\r
+                    v.focus();\r
+                }\r
+            });\r
 \r
-            \r
-            \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.hide().css('visibility','visible').show(arg1,function(){\r
+        div.hide().css('visibility','visible').show(this.defaultFadeTime,function(){\r
             postShowFcn();\r
-            if(arg2){\r
-                arg2();\r
-            }\r
+            me.trigger('show');\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
+    p.setBoundsAsPopup = function(popupInvoker){\r
+        var invoker = popupInvoker;\r
+        var div = this.getDiv();\r
+        var wdw = this.$J(window);\r
+        var oldCss= this.isSizable() ?  undefined : this.setSizable(true);\r
+        \r
+        var windowRectangle = this.getBoundsOf(wdw); //returns the window rectangle\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
+        this.setMaxSize({\r
+            height : spaceAbove>spaceBelow ? spaceAbove : spaceBelow,\r
+            width: wdw.scrollLeft()+wdw.width()-invokerOffset.left\r
+        }); //width will be ignored (for the moment)\r
+        \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
+        //setting the minimum size to the invoker width, minheight the same as maxHeight (see above)\r
         this.setMinSize({\r
-            width: invoker.outerWidth()\r
+            width: invoker.outerWidth()+this.shadowOffset //workaround to NOT consider the shadow, as offset below substracts the shadow\r
+        //height : spaceAbove>spaceBelow ? spaceAbove : spaceBelow //why this? because if we click the popup a\r
+        //computed height CH seems to be set. At subsequent popup show, CH will be the same UNLESS a new maxHeight lower than CH is set\r
+        //however, we want CH to change even if a new maxHeight greater than CH is set\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
+        //setting the top and left. This must be done at last because popupDiv.outerHeight(true)\r
+        //must have been computed according to the height set above...\r
+        this.offset({\r
+            'left': invokerOffset.left,\r
+            'top': (spaceAbove > spaceBelow ? invokerOffset.top -  div.outerHeight(true) :\r
+                invokerOffset.top + invokerOuterHeight)\r
+        });\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility']\r
+            });\r
+        }\r
+    };\r
+    //places and resize the popupdiv inside parent\r
+    //padding is a dict {top:,left:,bottom:..,right:,...} measuring the distance of the popupdiv from the corners, so that\r
+    //padding={top:0.25,left:0.25,bottom:0.25,right:0.25} will place the popupdiv at the center of parent\r
+    //padding={top:25,left:25,bottom:25,right:25} will place the popupdiv at distances 25 px from parent sides\r
+    //in other words, padding keys lower or euqals to 1 will be conbsidered as percentage, otherwise as absolute measures in px\r
+    p.setBoundsInside = function(parent, padding){\r
         var div = this.getDiv();\r
-        var bounds = this._getBounds(parent);\r
+        var oldCss = this.isSizable() ?  undefined : this.setSizable(true);\r
+\r
+        var bounds = this.getBoundsOf(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
+        //rebuilding:\r
+        if(!padding){\r
+            padding = {\r
+                top:0,\r
+                left:0,\r
+                bottom:0,\r
+                right:0\r
+            };\r
+        }\r
+        for(var k in padding){\r
+            if(padding[k]<0){\r
+                padding[k]=0;\r
+            }else if(padding[k]<=1){\r
+                padding[k] = k=='top' || k =='bottom' ? h*padding[k] : w*padding[k];\r
+            }else{\r
+                padding[k] = pInt(padding[k]);\r
+            }\r
+        }\r
+        this.setSize({\r
+            'width':w-padding['left']-padding['right'],\r
+            'height':w-padding['top']-padding['bottom']\r
+        });\r
+        this.offset({\r
+            'left':padding['left'],\r
+            'top': padding['top']\r
+        });\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility']\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
@@ -1777,10 +1596,11 @@ function PopupDiv(content){
             width:0,\r
             height:0\r
         };\r
+        var w = window;\r
         if(!jQueryElement){\r
-            jQueryElement = this.$J(window);\r
+            jQueryElement = this.$J(w);\r
         }\r
-        if(jQueryElement[0] === window){\r
+        if(jQueryElement[0] === w){\r
             ret.x = jQueryElement.scrollLeft();\r
             ret.y = jQueryElement.scrollTop();\r
         }else{\r
@@ -1795,6 +1615,8 @@ function PopupDiv(content){
 \r
     p.setMaxSize = function(size){\r
         var div = this.getDiv();\r
+        var oldCss= this.isSizable() ?  undefined : this.setSizable(true);\r
+\r
         this._convertSize(div, size);\r
         var css = {};\r
         if('width' in size){\r
@@ -1806,10 +1628,21 @@ function PopupDiv(content){
         if(css){\r
             div.css(css);\r
         }\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility'],\r
+                'top':oldCss['top'],\r
+                'left':oldCss['left']\r
+            });\r
+        }\r
         return size;\r
     };\r
     p.setMinSize = function(size){\r
         var div = this.getDiv();\r
+        var oldCss= this.isSizable() ?  undefined : this.setSizable(true);\r
+\r
         this._convertSize(div, size);\r
         var css = {};\r
         if('width' in size){\r
@@ -1821,14 +1654,25 @@ function PopupDiv(content){
         if(css){\r
             div.css(css);\r
         }\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility'],\r
+                'top':oldCss['top'],\r
+                'left':oldCss['left']\r
+            });\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
+    //TODO: check if div is sizable????\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
+        \r
         if('width' in size){\r
             size.width -= (eD.width + this.shadowOffset);\r
         }\r
@@ -1837,49 +1681,152 @@ function PopupDiv(content){
         }\r
     },\r
 \r
-    p.setSize = function(div, size){ //does it works like that?\r
-        this.setMaxSize(div, size);\r
-        this.setMinSize(div, size);\r
+    p.setSize = function(size){\r
+        var div = this.getDiv();\r
+        var oldCss= this.isSizable() ?  undefined : this.setSizable(true);\r
+\r
+        this.setMaxSize(size);\r
+        this.setMinSize(size);\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility'],\r
+                'top':oldCss['top'],\r
+                'left':oldCss['left']\r
+            });\r
+        }\r
     };\r
 \r
     p.offset = function(offs){\r
-        //if offs is a jquery element, size it as a popup.\r
+        var div = this.getDiv();\r
+        var oldCss= this.isSizable() ?  undefined : this.setSizable(true);\r
+        \r
         this.getDiv().offset(offs);\r
+        if(oldCss){\r
+            this.setSizable(false);\r
+            div.css({\r
+                'display':oldCss['display'],\r
+                'visibility':oldCss['visibility'],\r
+                'maxWidth':oldCss['maxWidth'],\r
+                'maxHeight':oldCss['maxHeight'],\r
+                'minWidth':oldCss['minWidth'],\r
+                'minHeight':oldCss['minHeight']\r
+            });\r
+        }\r
     };\r
 \r
-    p.hide = function(){\r
+    p.close = 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
+        var shadow = $J('#'+this.getShadowDivId());\r
+        //        $J.each(div, function(i,e){\r
+        //            shadow = shadow.add($J('#'+$J(e).attr('id')+'_shadow'));\r
+        //        });\r
+        shadow.remove();\r
+        if(this.getCloseOperation() == 'remove'){\r
+            div.remove(this.defaultFadeOutTime);\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
+            div.hide(this.defaultFadeOutTime);\r
         }\r
-        both.hide.apply(both, args);\r
-    };\r
+        this.setSizable(false);\r
+        this.trigger('close');\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
+    \r
+})(PopupDiv.prototype);\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
+//        this.setSizable(false);\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
+//        this.setSizable(false);\r
+//    };\r
+\r
+\r
+//default private functions not accessible from outside (memeory leaks? dont think so)\r
+//    var setAsPopupOf = function(popupDiv, invoker){\r
+////        if(!(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') ||\r
+////            invoker.is('input[type=submit]'))){\r
+////            return;\r
+////        }\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.setBoundsAsPopup.apply(me,[invoker]);\r
+//        };\r
+//        this.callbackPostShow = function(){\r
+//            var fcn = removeOnBlur ? me.remove : me.hide;\r
+//            me.setFocusable.apply(me);\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.show.apply(me);\r
+//            return false;\r
+//        });\r
+//    };\r
+//\r
+//    p.setAsWindowDialog = function(timeInMsec, padding){\r
+//\r
+//        var me =this;\r
+//        this.callbackPreShow = function(){\r
+//            me.setBoundsInside.apply(me,[padding]);\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
+//
\ No newline at end of file
index 6a8c6b297429f10d0e42105aa7fc7208182c8bb6..70cb940603230f6052f2e3596eb33c3494b32783 100644 (file)
@@ -7,6 +7,35 @@ var playlistUtils = {
         this.playlists[name]=id;
     },
 
+//    /*shows the popup for adding an item to the playlist*/
+//    showPopupAddToPlaylist: function(event,resourceType,objectId, optionalMessage){
+//        var $J = jQuery;
+//        var content = $J('<div/>').addClass("_popup_add_to_playlist");
+//        var addToPlaylist = this.addToPlaylist;
+//        for(var p in this.playlists){
+//            var id = this.playlists[p];
+//
+//            var a =  $J('<a/>').
+//            attr('href','#').
+//            addClass("component_icon").
+//            addClass("list_item icon_playlist").
+//            html(p).
+//            //by wrapping the addToPlaylist function in order to accept the id variable as an argument
+//            //we avoid calling the function with id = number_of_playlists for all anchors
+//            //by returning another function (basically create another closure) we avoid executing the function
+//            //immediately
+//            click(function(id_){
+//                    return function(){
+//                        addToPlaylist(id_,resourceType,objectId,optionalMessage);
+//                        return false;
+//                    }
+//                }(id)
+//            );
+//            content.append(a);
+//        }
+//        return popup.show(content,event);
+//    },
+
     /*shows the popup for adding an item to the playlist*/
     showPopupAddToPlaylist: function(event,resourceType,objectId, optionalMessage){
         var $J = jQuery;
@@ -20,8 +49,8 @@ var playlistUtils = {
             addClass("component_icon").
             addClass("list_item icon_playlist").
             html(p).
-            //by wrapping the addToPlaylist function in order to accept the id variable as an argument 
-            //we avoid calling the function with id = number_of_playlists for all anchors 
+            //by wrapping the addToPlaylist function in order to accept the id variable as an argument
+            //we avoid calling the function with id = number_of_playlists for all anchors
             //by returning another function (basically create another closure) we avoid executing the function
             //immediately
             click(function(id_){
index 5435ba5ee9ef8c821d0c2aa0fb26aa729b359577..7a1f9915af8e80c4183a62f558143192b53cbe45 100644 (file)
@@ -138,21 +138,22 @@ var TimesideClass = Class.extend({
         return text.length * ratio * fontSize;
     },
     
-    //formats (ie returns a string representation of) a time which is in the form seconds,milliseconds, eg 07.6750067
-    //formatArray is an array of strings which can be:
-    // 'h' hours. Use 'hh' for a zero-padding to 10 (so that 6 hours is rendered as '06')
-    // 'm' hours. Use 'mm' for a zero-padding to 10 (so that 6 minutes is rendered as '06')
-    // 's' hours. Use 'ss' foar a zero-padding to 10 (so that 6 seconds is rendered as '06')
-    // 'D' deciseconds
-    // 'C' centiseconds (it will be padded to 10, so that 5 centiseconds will be rendered as '05')
-    // 'S' milliseconds (it will be padded to 100, so that 5 milliseconds will be rendered as '005')
-    // If formatArray is null or undefined or zero-length, it defaults to ['mm','ss']
-    // 'h','m' and 's' will be prepended the separator ':'. For the others, the prepended separator is '.'
-    // Examples:
-    // makeTimeLabel(607,087) returns '10:07'
-    // makeTimeLabel(611,087,['m':'s']) returns '10:7'
-    // makeTimeLabel(611,087,['m':'s','C']) returns '10:7.09'
-    //========================================================================================
+    /*
+     *formats (ie returns a string representation of) a time which is in the form seconds,milliseconds (eg 07.6750067)
+     * formatArray is an array of strings which can be:
+     * 'h' hours. Use 'hh' for a zero-padding to 10 (so that 6 hours is rendered as '06')
+     * 'm' hours. Use 'mm' for a zero-padding to 10 (so that 6 minutes is rendered as '06')
+     * 's' hours. Use 'ss' foar a zero-padding to 10 (so that 6 seconds is rendered as '06')
+     * 'D' deciseconds
+     * 'C' centiseconds (it will be padded to 10, so that 5 centiseconds will be rendered as '05')
+     * 'S' milliseconds (it will be padded to 100, so that 5 milliseconds will be rendered as '005')
+     * If formatArray is null or undefined or zero-length, it defaults to ['mm','ss']
+     * 'h','m' and 's' will be prepended the separator ':'. For the others, the prepended separator is '.'
+     * Examples:
+     * makeTimeLabel(607,087)               returns '10:07' (formatArray defaults to ['mm','ss'])
+     * makeTimeLabel(607,087,['m':'s'])     returns '10:7'
+     * makeTimeLabel(607,087,['m':'s','C']) returns '10:7.09'
+     */
     makeTimeLabel: function(time, formatArray){
         if(!(formatArray)){
             formatArray = ['mm','ss'];
@@ -175,12 +176,10 @@ var TimesideClass = Class.extend({
         //Examples: format(6) = "6", format(6,1)= "06", format(23,1)= "23"
 
         //first of all, instantiate the power function once (and not inside the function or function's loop):
+        //note that minimumNumberOfDigits lower to 2 returns integer as it is
         var mpow = Math.pow; //instantiate mpow once
         var format = function(integer,minimumNumberOfDigits){
             var n = ""+integer;
-//            if(!(ceilAsPowerOfTen)){
-//                return n;
-//            }
             var zero = "0"; //instantiating once increases performances???
             for(var i=1; i< minimumNumberOfDigits; i++){
                 if(integer<mpow(10,i)){
@@ -196,26 +195,24 @@ var TimesideClass = Class.extend({
             if(f=='h'){
                 ret[i]=hours;
             }else if(f=='hh'){
-                ret[i]=format(hours,1);
+                ret[i]=format(hours,2);
             }else if(f=='m'){
                 ret[i]=minutes;
             }else if(f=='mm'){
-                ret[i]=format(minutes,1);
+                ret[i]=format(minutes,2);
             }else if(f=='s'){
                 ret[i]=seconds;
             }else if(f=='ss'){
-                ret[i]=format(seconds,1);
+                ret[i]=format(seconds,2);
             }else if(f=='S'){
                 separator = ".";
                 ret[i]=format(round(time*1000),3);
             }else if(f=='C'){
                 separator = ".";
                 ret[i]=format(round(time*100),2);
-                consolelog('NOW=======================================');
-                consolelog(time);
             }else if(f=='D'){
                 separator = ".";
-                ret[i]=format(round(time*10),1);
+                ret[i]= round(time*10);
             }
             if(i>0){
                 ret[i] = separator+ret[i];
@@ -230,7 +227,6 @@ var TimesideClass = Class.extend({
     debug : function(message) {
         if (this.debugging && typeof console != 'undefined' && console.log) {
             console.log(message);
-        //console.log('TimeSide.' + this.__class__.__name__ + ': ' + message);
         }
     },
     //init constructor. Define the 'bind' and 'fire' (TODO: rename as 'trigger'?) methods
index 93e3ec3753aa3a0eaf989b4bf582bb27697e1a3d..bf0997422f8f6afa761d37a07762b6037b97a8df 100644 (file)
     });
 
     jQuery(document).ready(function(){
-        var ar = [];
-        for(var i=0; i<100; i++){
-            ar.push('<a href=#>'+i+'</a>');
-        }
-        var p = new PopupDiv(ar.join('<br/>'));
-        //var p = new PopupDiv({'title':"azzo",'description':'w'});
-         consolelog(p);
-            p.getDiv().find('a').each(function(i,aa){
-                jQuery(aa).click(function(){alert(jQuery(aa).html());p.hide();return false;});
-            });
+//        var ar = [];
+//        for(var i=0; i<100; i++){
+//            ar.push('<a href=#>'+i+'</a>');
+//        }
+//        var p = new PopupDiv(ar.join('<br/>'));
+//        p.getDiv().find('a').each(function(i,aa){
+//                jQuery(aa).click(function(){alert(jQuery(aa).html());p.hide();return false;});
+//            });
 
+        var p = new PopupDiv({'close me and see what you can get':function(){p.hide();}});
+//        var p = new PopupDiv({'close me and see what you can get':function(){p.hide();},'options':['ferrari','maserati','bmw'],'inputa':'default','liar':true});
         var a = jQuery('<a/>').attr('href','#').html('clickme');
-       
-        p.setAsPopupOf(a);
+
+        p.setInvoker(a);
         jQuery('body').append(a);
     });
 </script>