]> git.parisson.com Git - telemeta.git/commitdiff
popup still work in progress, play with streaming resolved
authorriccardo <riccardo@parisson.com>
Fri, 29 Apr 2011 18:47:44 +0000 (20:47 +0200)
committerriccardo <riccardo@parisson.com>
Fri, 29 Apr 2011 18:47:44 +0000 (20:47 +0200)
telemeta/htdocs/js/application.js
telemeta/htdocs/timeside/src/player.js

index 498cda736915b0eb1feca4eeb2e4401dd71fdd56..6fa4fbdbef3a6022587bc30e38248a779bd70842 100644 (file)
@@ -404,7 +404,12 @@ var popup={
             }\r
         }\r
         //now we can build the divShadow\r
-        var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div);\r
+        var divShadow = div.clone(false,false).empty().css({\r
+            'zIndex':999,\r
+            'borderColor':'#000',\r
+            'display':'none',\r
+            'backgroundColor':'#000'\r
+        }).insertAfter(div);\r
         //store the divs to be removed\r
         this._cfg_.divsToDelete = [div,divShadow];\r
         //add a listener to the document. If one of the content children is clicked/keypressed,\r
@@ -434,11 +439,11 @@ var popup={
 \r
             divShadow.fadeTo(0,0.4, function(){\r
                 divShadow.css({\r
-                'top': (position.top+shadowOffset),\r
-                'left': (position.left+shadowOffset),\r
-                'width': div.outerWidth(true),\r
-                'height': div.outerHeight(true)\r
-            });\r
+                    'top': (position.top+shadowOffset),\r
+                    'left': (position.left+shadowOffset),\r
+                    'width': div.outerWidth(true),\r
+                    'height': div.outerHeight(true)\r
+                });\r
 \r
             });\r
         });\r
@@ -616,397 +621,362 @@ function consolelog(text){
     }\r
 }\r
 \r
+function PopupUtils(){\r
+    var $J= jQuery;\r
+    var wdow = $J(window); //reference the window object (doing it once speeds up a bit performances)\r
+    var doc = $J(document);\r
+    var screenRect = function(){\r
+        return {\r
+            x:wdow.scrollLeft(),\r
+            y:wdow.scrollTop(),\r
+            width:wdow.width(),\r
+            height:wdow.height()\r
+        };\r
+    };\r
+    \r
 \r
-//var PopupClass=function(innerHTML,event){\r
-//    var $J = jQuery; //reference to jQuery\r
-//    var className = 'component'; //the optional div class name\r
-//    var div = $J('<div/>').css({  //create the div (the popup)\r
-//                position: 'absolute',\r
-//                overflow:'auto', //necessary to properly display the content\r
-//                display: 'none',\r
-//                zIndex:1000\r
-//            });\r
-//            if(className){\r
-//                div.addClass(className);\r
-//            };\r
-//\r
-//     if(content instanceof $J){\r
-//         div.append(content);\r
-//     }else{\r
-//         div.html(content);\r
-//     }\r
-//     //create the div shadow\r
-//     var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div);\r
-//     //append to the body\r
-//     var body = $J('body');\r
-//     body.append(div);\r
-//     divShadow.insertAfter(div);\r
-//     div = div.add(divShadow);\r
-//     //set the id\r
-//     var time = new Date().getTime();\r
-//     div.attr('id','popup_'+time);\r
-//     divShadow.attr('id','popupshadow_'+time);\r
-//     //make thid class a jQuery object:\r
-//     $J.extend(this,div);\r
-//     //override some methods:\r
-//     //\r
-//     //private function which binds/unbinds click and key events\r
-//     var toggleBind = function(element, callback){\r
-//            var clickNamespace = "click.popup__"+time;\r
-//            var keydownNamespace =  "keyup.popup__"+time;\r
-//            element.unbind(clickNamespace);\r
-//            element.unbind(keydownNamespace);\r
-//            if(callback){\r
-//                element.bind(clickNamespace, callback);\r
-//                element.bind(keydownNamespace,callback);\r
-//            }\r
-//        };\r
-//\r
-//     var doc = $J(document); //reference to the document\r
-//\r
-//     //hide:\r
-//     var hide = this.hide;\r
-//     this.hide = function(){\r
-//         toggleBind(doc);\r
-//     };\r
-//\r
-//     //remove:\r
-//     var me = this;\r
-//     var remove = this.remove;\r
-//     this.remove = function(){\r
-//         me.hide();\r
-//         remove.apply(me,arguments);\r
-//     };\r
-//\r
-//     //show:\r
-//     var shadowOffset = 5; //the shadow offset, change to increment/ decrement\r
-//     var show = this.show;\r
-//\r
-//     this.show = function(){\r
-//         place($J(me[0]),event);\r
-//         var position = $J(me[0]).offset();\r
-//         $J(me[1]).css({\r
-//                'top': (position.top + shadowOffset),\r
-//                'left': (position.left + shadowOffset),\r
-//                'width': div.outerWidth(true),\r
-//                'height': div.outerHeight(true)\r
-//            });\r
-//         toggleBind(doc, me.hide);\r
-//\r
-//         if(arguments.length>0){\r
-//             var oldCallback = arguments[arguments.length-1];\r
-//             arguments[arguments.length-1] = function(){\r
-//                 $J(me[1]).fadeTo(0,0.4,oldCallback);\r
-//             }\r
-//             show.apply(me, arguments);\r
-//         }else{\r
-//             show.apply(me);\r
-//             $J(me[1]).fadeTo(0,0.4);\r
-//         }\r
-//\r
-//     };\r
-//\r
-//\r
-//\r
-//\r
-//\r
-//    _cfg_:{\r
-//        jQuery:jQuery,\r
-//        div: function(){\r
-//            var div = this.jQuery('<div/>').css({ //this is _cfg_\r
-//                position: 'absolute',\r
-//                overflow:'auto', //necessary to properly display the content\r
-//                display: 'none',\r
-//                border: '1px solid #e1e1e1',\r
-//                zIndex:1000\r
-//            });\r
-//            if(this.className){\r
-//                div.addClass(this.className);\r
-//            }\r
-//            return div;\r
-//        },\r
-//        className: 'component',\r
-//        //        mouseDownNamespace : "mousedown.popup__",\r
-//        //        keyDownNamespace : "keydown.popup__",\r
-//\r
-//        //namespace: 'popup__', //used for namespaces when binding click to document\r
-//        handlersToRestore: [],\r
-//        event: null,\r
-//        divsToDelete:null,\r
-//        toggleBind: function(element, functionE){\r
-//            var clickNamespace = "click.popup__";\r
-//            var keydownNamespace =  "keyup.popup__";\r
-//            element.unbind(clickNamespace);\r
-//            element.unbind(keydownNamespace);\r
-//            if(functionE){\r
-//                element.bind(clickNamespace, functionE);\r
-//                element.bind(keydownNamespace,functionE);\r
-//            }\r
-//        }\r
-//    },\r
-//\r
-//    isShowing: function(){\r
-//        return this._cfg_.divsToDelete ? true : false;\r
-//    },\r
-//\r
-//\r
-//    hide: function(){\r
-//        var toggleBind = this._cfg_.toggleBind;\r
-//\r
-//        var $J = this._cfg_.jQuery;\r
-//\r
-//        toggleBind($J(document));\r
-//        if(this._cfg_.divsToDelete){\r
-//            for(var i=0; i < this._cfg_.divsToDelete.length; i++){\r
-//                this._cfg_.divsToDelete[i].empty().remove();\r
-//            }\r
-//        }\r
-//        if(this._cfg_.event && this._cfg_.handlersToRestore){\r
-//            var type = this._cfg_.event.type; //which should be the same as h.type below, without namespaces?\r
-//            var invokerElement = this._cfg_.event.target;\r
-//            if(invokerElement){\r
-//                var e = $J(invokerElement);\r
-//                toggleBind(e);\r
-//                if(type){\r
-//                    //e.unbind(type);\r
-//                    for(var i=0; i<this._cfg_.handlersToRestore.length; i++){\r
-//                        var h = this._cfg_.handlersToRestore[i];\r
-//                        var functionCode = h.handler;\r
-//                        var namespace = ""+h.namespace;\r
-//                        if(namespace.length>0){\r
-//                            namespace="."+namespace;\r
-//                        }\r
-//                        var what = h.type+ namespace;\r
-//                        e.bind(what, functionCode);\r
-//                    }\r
-//                }\r
-//            }\r
-//        }\r
-//        this._cfg_.event=null;\r
-//        this._cfg_.handlersToRestore=null;\r
-//    },\r
-//\r
-//    show:function(content, optionalEvent){\r
-//        consolelog("showing popup:"+optionalEvent);\r
-//        //if showing, hide\r
-//        if(this.isShowing()){\r
-//            this.hide();\r
-//        }\r
-//\r
-//        var $J = this._cfg_.jQuery;\r
-//        var div = this._cfg_.div();\r
-//        //toggleBind sets the functions to hiding/keep shown the popup when clicking or\r
-//        //using the keyboard keys\r
-//        var toggleBind = this._cfg_.toggleBind;\r
-//\r
-//        //remove the callback on invoker so that clicking on invoker does nothing\r
-//        //moreover, toggleBind on invoker so that clicking invoker doesn't hide the popup\r
-//        this.oldCallback = undefined;\r
-//        var oldHandlers=[];\r
-//        var invokerElement = optionalEvent && optionalEvent.target ? $J(optionalEvent.target) : undefined;\r
-//        if(invokerElement){\r
-//            optionalEvent.stopPropagation(); //othewrwise the popup hides immediately\r
-//            //cause the event is catched from the document click (added later, see below)\r
-//            // but apparently as soon as we add it it catches even the current event)\r
-//            var type = optionalEvent.type;\r
-//            var clickEvents =invokerElement.data("events")[type];\r
-//            $J.each(clickEvents, function(key, value) {\r
-//                oldHandlers.push(value);\r
-//            })\r
-//            invokerElement.unbind(type); //remove (temporarily) the binding to the event.\r
-//            //for instance, if we show the popup by clicking invoker, when the popup is shown do nothing\r
-//            //on clicking invoker until popup.hide is called\r
-//            toggleBind(invokerElement,function(e){ //add bindings to stop cancel the popup in case the invoker is clicked again\r
-//                e.stopPropagation();\r
-//                return false;\r
-//            });\r
-//        }\r
-//        //store the functions removed from invoker, if any, to restore them in this.hide\r
-//        this._cfg_.handlersToRestore = oldHandlers;\r
-//        this._cfg_.event = optionalEvent;\r
-//\r
-//        //toggleBind on each child of content so that clicking and pressing keys on\r
-//        //a child doesn't hide the popup\r
-//        var children = $J(content).find('*');\r
-//        $J(children).each(function(){\r
-//            toggleBind($(this),function(e){\r
-//                e.stopPropagation();\r
-//                return false;\r
-//            });\r
-//        });\r
-//        //showing\r
-//        var doc = $J(document);\r
-//        $J('body').append(div);\r
-//\r
-//        content.css('position','static'); //this is really important to place the content in the normal flow\r
-//        //within the div. static is the default\r
-//        content.show(); //in case the div is display:none\r
-//        div.append(content);\r
-//\r
-//        //positioning div: center of the screen if no invoker, below the invoker otherwise\r
-//        var wdow = $J(window); //reference the window object (doing it once speeds up a bit performances)\r
-//        var windowH = wdow.height();\r
-//        var windowW = wdow.width();\r
-//        var position = div.offset();\r
-//        var shadowOffset=5;\r
-//        var size = {\r
-//            width:div.outerWidth(true)+shadowOffset,\r
-//            height:div.outerHeight(true)+shadowOffset\r
-//        };\r
-//        if(invokerElement){\r
-//            position = invokerElement.offset();\r
-//            position.top+=  invokerElement.outerHeight(true);\r
-//        }else{\r
-//            position.top = wdow.scrollTop()+ (windowH-size.height)/2;\r
-//            position.left = wdow.scrollLeft()+(windowW-size.width)/2;\r
-//        }\r
-//        //position div. This must be done immediately cause here below we want to get the div  offset\r
-//        //(div position in absolute - ie, document's - coordinates)\r
-//        div.css({\r
-//            'top': position.top,\r
-//            'left': position.left,\r
-//            'right': 'auto', //in case right has been set by some css class rule\r
-//            'bottom': 'auto' //see above...\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
+//    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 oldShow = p.show;\r
+       // var pint = parseInt;\r
+        p.show = function(){\r
+\r
+            var rect = screenRect();\r
+            var offs = invokerAsJQueryObj.offset();\r
+            var height = invokerAsJQueryObj.outerHeight();\r
+\r
+            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
+\r
+            if(spaceAbove>spaceBelow){\r
+                p.css({'maxHeight':(spaceAbove-p.shadowoffset)+'px', 'top':rect.y+'px'});\r
+            }else{\r
+                p.css({'maxHeight':(spaceBelow-p.shadowoffset)+'px', 'top':(offs.top+height)+'px'});\r
+            }\r
+            p.css({'height':'auto','width' :'auto', 'maxWidth': (rect.x+rect.width-offs.left)+'px'});\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
-//        //set the maximum size\r
-//        //due to overflow:auto a scrollbar will automatically appear\r
-//        var max = Math.max; //reference max immediately (speeds up performances a bit)\r
-//        var maxSize = {\r
-//            width: max(20,windowW +  wdow.scrollLeft() -position.left-shadowOffset),\r
-//            height: max(20, (windowH + wdow.scrollTop() -position.top- shadowOffset))\r
-//        }\r
-//        //position div and size:\r
-//        var divPadding = {\r
-//            left: div.outerWidth()-div.width(),\r
-//            top:div.outerHeight()-div.height()\r
-//        }; //setting width on a div means the width(),\r
-//        //but calculations here are made according to outerWidth(true), so we need this variable (se below)\r
-//\r
-//        //the shadow in the background will be created according to the actual div size\r
-//        //However, since we do not specify neither width nor height, the calculation of the div size\r
-//        //works if maxWidth and maxHeight do set a width and height. In order to do so, they\r
-//        //must be lower or equal to the actual div width and height. That's why the "min" here below:'\r
-//        div.css({\r
-//            'maxWidth': Math.min(div.width(), maxSize.width-divPadding.left),\r
-//            'maxHeight': Math.min(div.height(), maxSize.height-divPadding.top)\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
+        p.css({\r
+            'minWidth':invokerAsJQueryObj.outerWidth()+'px',\r
+            'left':invokerAsJQueryObj.offset().left+'px'\r
+        });\r
+\r
+        p.setPopupFocus(function(){p.hide();});\r
+\r
+        invokerAsJQueryObj.unbind('click').click(function(evt){\r
+           p.show();\r
+           return false;\r
+        });\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
+     * visible window width and height, respectively. Content can be a jQuery object (ie an array of html elements) or a string\r
+     * denoting the innerHTML of the dialog div. timeInMsec can be:\r
+     * a number (in msec) specifying after how much time the dialog will be removed (for fast messages)\r
+     * the string 'hide' to specify that the div will be hidden when it looses focus\r
+     * the string 'remove' to specify that the div will be removed when it looses the focus\r
+     *\r
+     */\r
+    this.showInfoDialog = function(content, timeInMsec){\r
+        var p = new DivDialog(content);\r
+        var oldShow = p.show;\r
+        var pint = parseInt;\r
+        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
+\r
+        p.refreshShadowPosition();\r
+\r
+        };\r
+        var rect = screenRect();\r
+        p.css({\r
+            'maxWidth':pint(rect.width/2)+'px',\r
+            'maxHeight':pint(rect.height/2)+'px'\r
+        });\r
+        \r
+        if(typeof timeInMsec == 'number'){ //set a timeout\r
+            setTimeout(function(){\r
+                p.remove();\r
+                p=null;\r
+            },timeInMsec);\r
+        }else if(timeInMsec == 'hide'){ //is a boolean\r
+            p.setPopupFocus(function(){p.hide();});\r
+        }else if(timeInMsec == 'remove'){ //is a boolean\r
+            p.setPopupFocus(function(){p.remove();});\r
+        }\r
+        p.show();\r
+        p.setFocus();\r
+    };\r
+}\r
+\r
+//content: string or jQueryElement\r
+//type 'popup',\r
+//DivDialog(content,type,attributes)\r
+\r
+var pppUtils = new PopupUtils();\r
+function DivDialog(content){\r
+    var $J = jQuery;\r
+    var doc = $J(document);\r
+    var firstFocusableElement = undefined; //set in focusout\r
+    var className = 'component';\r
+    var basecss = {\r
+        'position':'absolute',\r
+        'display':'none'\r
+    };\r
+    var popup = $J('<div/>').addClass(className).css(basecss).css({\r
+        'zIndex':1000\r
+    });\r
+    var popupContent = $J('<div/>').css({\r
+        'overflow':'auto'\r
+    });\r
+    \r
+    var popupshadow = popup.clone(true,true).removeAttr('id').empty().css({\r
+        'backgroundColor':'#000',\r
+        'border':'0px',\r
+        'zIndex':900,\r
+        'margin':'0px',\r
+        'padding':'0px'\r
+    }).fadeTo(0,0.4);\r
+    var both = popup.add(popupshadow);\r
+\r
+\r
+    if(content){\r
+        if(content instanceof $J){\r
+            popupContent.empty().append(content);\r
+        }else{\r
+            popupContent.html(content);\r
+        }\r
+    }\r
+    popup.append(popupContent);\r
+\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
-//        //last thing: if invoker element exist, set width at least invoker element width\r
-//        if(invokerElement){\r
-//            var iEw = invokerElement.outerWidth(); //no margins considered\r
-//            if(iEw<maxSize.width && iEw>div.outerWidth()){\r
-//                div.css({\r
-//                    'minWidth':iEw-divPadding.left\r
-//                });\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
+    };\r
+    this.minsize = function(size){\r
+        popup.css({'minHeight':size.height,'minWidth':size.width});\r
+    };\r
+     this.offset = function(){\r
+        var ret = popup.offset.apply(popup,arguments);\r
+        //refreshPosition();\r
+        return me;\r
+    };\r
+\r
+    //function (private) to refresh shadow position\r
+    this.shadowoffset = 5;\r
+    this.size = function(){\r
+        return {\r
+            width: popup.outerWidth(),\r
+            height:popup.outerHeight()\r
+        };\r
+    };\r
+\r
+\r
+\r
+    this.refreshShadowPosition = function(){\r
+        if(!popup.is(":visible")){\r
+            popupshadow.hide(); //to be sure\r
+            return;\r
+        }else{\r
+            popupshadow.show();\r
+        }\r
+        var offs = popup.offset();\r
+        offs.top+=this.shadowoffset;\r
+        offs.left+=this.shadowoffset;\r
+        popupshadow.offset(offs);\r
+        popupshadow.css({\r
+            'width':popup.outerWidth()+'px',\r
+            'height':popup.outerHeight()+'px'\r
+        });\r
+        popupContent.css({\r
+            'maxWidth': (parseInt(popup.css('maxWidth')) -(popupContent.outerWidth()-popupContent.width())) +'px',\r
+            'maxHeight':(parseInt(popup.css('maxHeight'))-(popupContent.outerHeight()-popupContent.height()))+'px'\r
+        });\r
+    };\r
+\r
+    //dummy overriding of some jquery functions\r
+    var me = this;\r
+    this.remove = function(){\r
+        both.empty();\r
+        both.remove.apply(both,arguments);\r
+        return me;\r
+    };\r
+    this.find = function(){\r
+        return popupContent.find.apply(popupContent,arguments);\r
+    };\r
+    this.hide = function(){\r
+        return both.hide.apply(both,arguments);\r
+        return me;\r
+    };\r
+    \r
+    this.show = function(){\r
+        if(!(popup.parent().length)){\r
+            $J('body').append(both);\r
+        }\r
+        var ret = popup.show.apply(popup,arguments);\r
+        //refreshPosition();\r
+        return me;\r
+    };\r
+\r
+    this.setFocus = function(){\r
+        if(firstFocusableElement && firstFocusableElement.parent().length && firstFocusableElement.is(':visible')){\r
+            firstFocusableElement.focus();\r
+        }\r
+    }\r
+    //popup specific functions\r
+\r
+    //set css: note that margin position and zIndex will be overridden\r
+    this.css = function(){\r
+        var arg = arguments;\r
+        if(arguments.length==2){ //setting a single css element\r
+            if(arguments[0] == 'margin' || arguments[0] == 'position' || arguments[0] == 'zIndex'){\r
+                return me;\r
+            }\r
+        }else if(arguments.length==1){  //single argument\r
+            if(typeof arguments[0] == 'string'){\r
+                return popup.css(arguments[0]);\r
+            }else{\r
+                var a = arguments[0];\r
+                for(var k in a){\r
+                    if(k == 'margin' || k == 'position' || k == 'zIndex'){\r
+                        delete a[k];\r
+                    }\r
+                }\r
+                arg = [a];\r
+//                consolelog('css');\r
+//                consolelog(arg);\r
+            }\r
+        }else{\r
+            return me;\r
+        }\r
+        var ret = popup.css.apply(popup,arg);\r
+        //refreshPosition();\r
+        return me;\r
+    };\r
+\r
+\r
+\r
+//    this.bindAsPopupFor = function(jQueryAnchorElement){\r
+//        if(!jQueryAnchorElement.attr('id')){\r
+//            jQueryAnchorElement.attr('id','popup_'+new Date().getTime());\r
 //        }\r
-//        //now we can build the divShadow\r
-//        var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div);\r
-//        //store the divs to be removed\r
-//        this._cfg_.divsToDelete = [div,divShadow];\r
-//        //add a listener to the document. If one of the content children is clicked/keypressed,\r
-//        //we won't come here. Otherwise hide popup\r
-//        var me = this;\r
-//        var hide = this.hide;\r
-//        toggleBind(doc,function(e){\r
-//            hide.apply(me);\r
-//            e.stopPropagation();\r
-//        });\r
-//        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
+//        var id = jQueryAnchorElement.attr('id');\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
-//            if(inputs && inputs[0]){\r
-//                inputs[0].focus();\r
-//            }else{\r
-//                inputs = $J(div).find('a');\r
-//                if(inputs && inputs[0]){\r
-//                    inputs[0].focus();\r
-//                }\r
-//            }\r
+//        anchorElement.click(function(){\r
 //\r
-//            divShadow.fadeTo(0,0.4, function(){\r
-//                divShadow.css({\r
-//                'top': (position.top+shadowOffset),\r
-//                'left': (position.left+shadowOffset),\r
-//                'width': div.outerWidth(true),\r
-//                'height': div.outerHeight(true)\r
-//            });\r
-//\r
-//            });\r
-//        });\r
-//        return false; //to avoid scrolling if we clicked on an anchor\r
-//    },\r
+//        })\r
 //\r
-//    //field must be a dictionary of label:defaultValues (both strings)\r
-//    //callbackOnOk is the callback to be executed on ok, if null ok will simply hide the dialog\r
-//    createDivDialog : function(field,callbackOnOk){\r
-//\r
-//        var $J = this._cfg_.jQuery;\r
-//        var table = $J('<table/>');\r
-//        var fieldElms = {};\r
-//        for(var label in field){\r
-//            var input = $('<input/>')\r
-//            .attr('type','text').val(field[label]).attr("name",label);\r
-//            table.append($J('<tr/>')\r
-//                .append($J('<td/>').html(label))\r
-//                .append($J('<td/>').append(input)));\r
-//            fieldElms[label]=input;\r
-//        }\r
-//\r
-//        var p = this;\r
-//        var onCancel= function(){\r
-//            p.hide();\r
-//            return false;\r
-//        };\r
-//\r
-//        var onOk= function(){\r
-//            if(callbackOnOk){\r
-//                var ret = {};\r
-//                var inputs = table.find("input");\r
-//                $J.each(inputs, function(key,value){\r
-//                    var v = $J(value);\r
-//                    ret[v.attr('name')] = v.val();\r
-//                });\r
-//                callbackOnOk(ret);\r
-//                return false;\r
-//            }else{\r
-//                return onCancel();\r
-//            }\r
-//        };\r
-//        var subdiv = $J('<div/>').css({\r
-//            'padding':'1ex',\r
-//            'float':'right'\r
-//        }).\r
-//        append(\r
-//            $J('<a/>').\r
-//            html('Ok').\r
-//            addClass('component_icon').\r
-//            addClass('button').\r
-//            addClass('icon_ok').\r
-//            attr('href','#').\r
-//            click(function(){\r
-//                return onOk();\r
-//            })\r
-//            );\r
-//        if(callbackOnOk){\r
-//            subdiv.append(\r
-//                $J('<a/>').\r
-//                html('Cancel').\r
-//                addClass('component_icon').\r
-//                addClass('button').\r
-//                addClass('icon_cancel').\r
-//                attr('href','#').\r
-//                click(function(){\r
-//                    return onCancel();\r
-//                })\r
-//                );\r
-//        }\r
-//        //popupDialog(element,table,onOk);\r
-//        return $J('<div/>').append(table).append(subdiv);\r
 //    }\r
-//}
\ No newline at end of file
+   \r
+    this.setPopupFocus = function(callbackOnFocusLost){\r
+        \r
+        //find all foccusable elements\r
+        var elementsWithFocus = $J(popupContent).find('textarea,a,input');\r
+        //focus must be given also to the containing popup beacuse\r
+        //if a scrollbar is present, moving the scrollbar sets the focus to popup (not popupContent. So\r
+        //apparently even if the scrollbar is caused by css 'popupContent.scroll=auto', it's like if it was\r
+        //'part' of the parent container popup)\r
+        //TODO: TEST IT WITH OTHER BROWSERS!!!! if not working, manda tutto affanculo and use click events\r
+        popup.attr('tabindex',1);\r
+        elementsWithFocus = elementsWithFocus.add(popup);\r
+        //build the attribute focus to recognize subelement of popup\r
+        var focusid = 'popupfocus'+(new Date().getTime());\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.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 = document.activeElement;\r
+                    consolelog(v);\r
+                    if(v && $J(v).attr(focusid)){\r
+                        return;\r
+                    }\r
+                    callbackOnFocusLost();\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
+        //set the first focusable element\r
+        firstFocusableElement = $J(elementsWithFocus[0]);\r
+    };\r
+   \r
+    this.attr = function(){\r
+        var ret =  popup.attr.apply(popup,arguments);\r
+        //refreshPosition();\r
+        return me;\r
+    };\r
+    this.html = function(){\r
+        if(arguments.length==0){\r
+            return popupContent.html();\r
+        }\r
+        var ret = popupContent.html.apply(popup,arguments);\r
+        //refreshPosition();\r
+        return me;\r
+    }\r
+    this.append = function(){\r
+        var ret = popupContent.append.apply(popup,arguments);\r
+        //refreshPosition();\r
+        return me;\r
+    }\r
+}\r
+\r
+\r
index 2b49a5a9cc16f77a51c21a590e78bc5cc1df0101..abf0e8aed196f78b0fb4bb06ee5c6c03cd2ac4cc 100644 (file)
@@ -81,11 +81,24 @@ var Player = TimesideClass.extend({
             return soundPos;
         };
 
+
+//       if(sound.readyState != 3){
+//                /*sound.readyState
+//                 * Numeric value indicating a sound's current load status
+//                 * 0 = uninitialised
+//                 * 1 = loading
+//                 * 2 = failed/error
+//                 * 3 = loaded/success
+//                 */
+//                sound.options.whileloading=function(){
+//
+//                }
+//        };
         
         //implement play here: while playing we do not have to update the sound position, so
         //we call the private variable soundPos
         this.play = function(){
-            if(!player || player.isPlaying()){
+            if(!player || player.isPlaying()){ //TODO: remove?, multishot is set to false
                 return false;
             }
             var sound = player.getSound();
@@ -93,8 +106,6 @@ var Player = TimesideClass.extend({
                 return false;
             }
 
-            
-
             var ruler = player.getRuler();
             
             var playOptions = {
@@ -113,36 +124,15 @@ var Player = TimesideClass.extend({
             };
             //internal play function. Set all properties and play:
             var play_ = function(sound, positionInSec){
-                sound.setPosition(toMsec(positionInSec));
+                //consolelog('position is '+positionInSec+' sec');
+                sound.setPosition(toMsec(positionInSec)); //TODO: remove???
+                //consolelog('sound position is '+sound.position+' msec');
                 sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play
+                playOptions.position = toMsec(positionInSec); //apparently THIS IS WORKING
                 sound.play(playOptions);
             };
-            //var s = toMsec(player.getSoundPosition());
-            if(sound.readyState != 3){
-                /*sound.readyState
-                 * Numeric value indicating a sound's current load status
-                 * 0 = uninitialised
-                 * 1 = loading
-                 * 2 = failed/error
-                 * 3 = loaded/success
-                 */
-                sound.options.onload=function(){
-                    //consolelog('LOADED AND PLAY '+' volume '+ sound.volume+' sPos: '+sound.position);
-                    //we set position and volume to be sure. Sometimes they are buggy
-                    //sound.setPosition(s);
-                    //sound.setVolume(sound.volume); //workaround. Just to be sure
-                    //sound.play(playOptions);
-                    play_(sound, player.getSoundPosition());
-                }
-                sound.load();
-            }else{
-                //consolelog('PLAY IMMEDIATELY'+' volume '+ sound.volume+' sPos: '+sound.position);
-                //we set position and volume to be sure. Sometimes they are buggy
-                //                sound.setPosition(s);
-                //                sound.setVolume(sound.volume); //workaround. Just to be sure/
-                //                sound.play(playOptions);
-                play_(sound, player.getSoundPosition());
-            }
+           
+            play_(sound, player.getSoundPosition());
             
             return false;
         };
@@ -334,12 +324,14 @@ var Player = TimesideClass.extend({
 
         //set the marker popup
         //functions to set the marker popup
-        var popupMarker = $J('<div/>').css({
+        var popupMarker = $J('<div/>').addClass('component').css({
             'dislay':'none',
             'position':'absolute',
-            'zIndex':1000
-        }).addClass('container');
-        $J(document).append(popupMarker);
+            'zIndex':1000,
+            'overflow':'auto'
+            //'backgroundColor':'#666'
+        });
+        $J('body').append(popupMarker);
         var w = v.width();
         var h = v.height();
         var offs = v.offset(); //relative to the document
@@ -352,7 +344,7 @@ var Player = TimesideClass.extend({
             'width':width+'px',
             'height':height+'px'
             });
-        popupMarker.html("<table style='width:100%'><tr><td>"+gettrans('title')+"</td><td class='title></td></tr><tr><td>"+
+        popupMarker.html("<table style='width:100%'><tr><td>"+gettrans('title')+"</td><td class='title'></td></tr><tr><td>"+
             gettrans('description')+"</td><td class='description'></td></tr></table>");
         this.getMarkerPopup = function(){
             return popupMarker;
@@ -362,14 +354,16 @@ var Player = TimesideClass.extend({
     showMarkerPopup: function(markerIndex){
         var popup = this.getMarkerPopup();
        // consolelog(popup.attr('id'));
-        consolelog('popup');
+        
         if(popup.attr('id') != 'markerpopup'+markerIndex){
             
-            var marker = getMarkerMap().toArray()[markerIndex];
-            var pos = this.getPosition();
+            var marker = this.getMarkerMap().toArray()[markerIndex];
+            var pos = this.getSoundPosition();
             var mPos = marker.offset;
             var span = 0.3;
+            
             if(pos>=mPos-span && pos<=mPos+span){
+                consolelog('songpos: '+pos+' nextmarkerpos:'+mPos);
                 popup.attr('id','markerpopup'+markerIndex);
                 popup.find('.title').html(marker.title);
                 popup.find('.description').html(marker.desc);