From 22f799fee18c9bed3179b8c9f0f40236a2a6404b Mon Sep 17 00:00:00 2001 From: riccardo Date: Fri, 29 Apr 2011 20:47:44 +0200 Subject: [PATCH] popup still work in progress, play with streaming resolved --- telemeta/htdocs/js/application.js | 752 ++++++++++++------------- telemeta/htdocs/timeside/src/player.js | 70 ++- 2 files changed, 393 insertions(+), 429 deletions(-) diff --git a/telemeta/htdocs/js/application.js b/telemeta/htdocs/js/application.js index 498cda73..6fa4fbdb 100644 --- a/telemeta/htdocs/js/application.js +++ b/telemeta/htdocs/js/application.js @@ -404,7 +404,12 @@ var popup={ } } //now we can build the divShadow - var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div); + var divShadow = div.clone(false,false).empty().css({ + 'zIndex':999, + 'borderColor':'#000', + 'display':'none', + 'backgroundColor':'#000' + }).insertAfter(div); //store the divs to be removed this._cfg_.divsToDelete = [div,divShadow]; //add a listener to the document. If one of the content children is clicked/keypressed, @@ -434,11 +439,11 @@ var popup={ divShadow.fadeTo(0,0.4, function(){ divShadow.css({ - 'top': (position.top+shadowOffset), - 'left': (position.left+shadowOffset), - 'width': div.outerWidth(true), - 'height': div.outerHeight(true) - }); + 'top': (position.top+shadowOffset), + 'left': (position.left+shadowOffset), + 'width': div.outerWidth(true), + 'height': div.outerHeight(true) + }); }); }); @@ -616,397 +621,362 @@ function consolelog(text){ } } +function PopupUtils(){ + var $J= jQuery; + var wdow = $J(window); //reference the window object (doing it once speeds up a bit performances) + var doc = $J(document); + var screenRect = function(){ + return { + x:wdow.scrollLeft(), + y:wdow.scrollTop(), + width:wdow.width(), + height:wdow.height() + }; + }; + -//var PopupClass=function(innerHTML,event){ -// var $J = jQuery; //reference to jQuery -// var className = 'component'; //the optional div class name -// var div = $J('
').css({ //create the div (the popup) -// position: 'absolute', -// overflow:'auto', //necessary to properly display the content -// display: 'none', -// zIndex:1000 -// }); -// if(className){ -// div.addClass(className); -// }; -// -// if(content instanceof $J){ -// div.append(content); -// }else{ -// div.html(content); -// } -// //create the div shadow -// var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div); -// //append to the body -// var body = $J('body'); -// body.append(div); -// divShadow.insertAfter(div); -// div = div.add(divShadow); -// //set the id -// var time = new Date().getTime(); -// div.attr('id','popup_'+time); -// divShadow.attr('id','popupshadow_'+time); -// //make thid class a jQuery object: -// $J.extend(this,div); -// //override some methods: -// // -// //private function which binds/unbinds click and key events -// var toggleBind = function(element, callback){ -// var clickNamespace = "click.popup__"+time; -// var keydownNamespace = "keyup.popup__"+time; -// element.unbind(clickNamespace); -// element.unbind(keydownNamespace); -// if(callback){ -// element.bind(clickNamespace, callback); -// element.bind(keydownNamespace,callback); -// } -// }; -// -// var doc = $J(document); //reference to the document -// -// //hide: -// var hide = this.hide; -// this.hide = function(){ -// toggleBind(doc); -// }; -// -// //remove: -// var me = this; -// var remove = this.remove; -// this.remove = function(){ -// me.hide(); -// remove.apply(me,arguments); -// }; -// -// //show: -// var shadowOffset = 5; //the shadow offset, change to increment/ decrement -// var show = this.show; -// -// this.show = function(){ -// place($J(me[0]),event); -// var position = $J(me[0]).offset(); -// $J(me[1]).css({ -// 'top': (position.top + shadowOffset), -// 'left': (position.left + shadowOffset), -// 'width': div.outerWidth(true), -// 'height': div.outerHeight(true) -// }); -// toggleBind(doc, me.hide); -// -// if(arguments.length>0){ -// var oldCallback = arguments[arguments.length-1]; -// arguments[arguments.length-1] = function(){ -// $J(me[1]).fadeTo(0,0.4,oldCallback); -// } -// show.apply(me, arguments); -// }else{ -// show.apply(me); -// $J(me[1]).fadeTo(0,0.4); -// } -// -// }; -// -// -// -// -// -// _cfg_:{ -// jQuery:jQuery, -// div: function(){ -// var div = this.jQuery('
').css({ //this is _cfg_ -// position: 'absolute', -// overflow:'auto', //necessary to properly display the content -// display: 'none', -// border: '1px solid #e1e1e1', -// zIndex:1000 -// }); -// if(this.className){ -// div.addClass(this.className); -// } -// return div; -// }, -// className: 'component', -// // mouseDownNamespace : "mousedown.popup__", -// // keyDownNamespace : "keydown.popup__", -// -// //namespace: 'popup__', //used for namespaces when binding click to document -// handlersToRestore: [], -// event: null, -// divsToDelete:null, -// toggleBind: function(element, functionE){ -// var clickNamespace = "click.popup__"; -// var keydownNamespace = "keyup.popup__"; -// element.unbind(clickNamespace); -// element.unbind(keydownNamespace); -// if(functionE){ -// element.bind(clickNamespace, functionE); -// element.bind(keydownNamespace,functionE); -// } -// } -// }, -// -// isShowing: function(){ -// return this._cfg_.divsToDelete ? true : false; -// }, -// -// -// hide: function(){ -// var toggleBind = this._cfg_.toggleBind; -// -// var $J = this._cfg_.jQuery; -// -// toggleBind($J(document)); -// if(this._cfg_.divsToDelete){ -// for(var i=0; i < this._cfg_.divsToDelete.length; i++){ -// this._cfg_.divsToDelete[i].empty().remove(); -// } -// } -// if(this._cfg_.event && this._cfg_.handlersToRestore){ -// var type = this._cfg_.event.type; //which should be the same as h.type below, without namespaces? -// var invokerElement = this._cfg_.event.target; -// if(invokerElement){ -// var e = $J(invokerElement); -// toggleBind(e); -// if(type){ -// //e.unbind(type); -// for(var i=0; i0){ -// namespace="."+namespace; -// } -// var what = h.type+ namespace; -// e.bind(what, functionCode); -// } -// } -// } -// } -// this._cfg_.event=null; -// this._cfg_.handlersToRestore=null; -// }, -// -// show:function(content, optionalEvent){ -// consolelog("showing popup:"+optionalEvent); -// //if showing, hide -// if(this.isShowing()){ -// this.hide(); -// } -// -// var $J = this._cfg_.jQuery; -// var div = this._cfg_.div(); -// //toggleBind sets the functions to hiding/keep shown the popup when clicking or -// //using the keyboard keys -// var toggleBind = this._cfg_.toggleBind; -// -// //remove the callback on invoker so that clicking on invoker does nothing -// //moreover, toggleBind on invoker so that clicking invoker doesn't hide the popup -// this.oldCallback = undefined; -// var oldHandlers=[]; -// var invokerElement = optionalEvent && optionalEvent.target ? $J(optionalEvent.target) : undefined; -// if(invokerElement){ -// optionalEvent.stopPropagation(); //othewrwise the popup hides immediately -// //cause the event is catched from the document click (added later, see below) -// // but apparently as soon as we add it it catches even the current event) -// var type = optionalEvent.type; -// var clickEvents =invokerElement.data("events")[type]; -// $J.each(clickEvents, function(key, value) { -// oldHandlers.push(value); -// }) -// invokerElement.unbind(type); //remove (temporarily) the binding to the event. -// //for instance, if we show the popup by clicking invoker, when the popup is shown do nothing -// //on clicking invoker until popup.hide is called -// toggleBind(invokerElement,function(e){ //add bindings to stop cancel the popup in case the invoker is clicked again -// e.stopPropagation(); -// return false; -// }); -// } -// //store the functions removed from invoker, if any, to restore them in this.hide -// this._cfg_.handlersToRestore = oldHandlers; -// this._cfg_.event = optionalEvent; -// -// //toggleBind on each child of content so that clicking and pressing keys on -// //a child doesn't hide the popup -// var children = $J(content).find('*'); -// $J(children).each(function(){ -// toggleBind($(this),function(e){ -// e.stopPropagation(); -// return false; -// }); -// }); -// //showing -// var doc = $J(document); -// $J('body').append(div); -// -// content.css('position','static'); //this is really important to place the content in the normal flow -// //within the div. static is the default -// content.show(); //in case the div is display:none -// div.append(content); -// -// //positioning div: center of the screen if no invoker, below the invoker otherwise -// var wdow = $J(window); //reference the window object (doing it once speeds up a bit performances) -// var windowH = wdow.height(); -// var windowW = wdow.width(); -// var position = div.offset(); -// var shadowOffset=5; -// var size = { -// width:div.outerWidth(true)+shadowOffset, -// height:div.outerHeight(true)+shadowOffset -// }; -// if(invokerElement){ -// position = invokerElement.offset(); -// position.top+= invokerElement.outerHeight(true); -// }else{ -// position.top = wdow.scrollTop()+ (windowH-size.height)/2; -// position.left = wdow.scrollLeft()+(windowW-size.width)/2; -// } -// //position div. This must be done immediately cause here below we want to get the div offset -// //(div position in absolute - ie, document's - coordinates) -// div.css({ -// 'top': position.top, -// 'left': position.left, -// 'right': 'auto', //in case right has been set by some css class rule -// 'bottom': 'auto' //see above... + /** + * sets dialogDiv (a jQuery object or a DivDialog, see below) as popup mode. In other words, + * scans each sub-element of dialogDiv and assigns to it a onblur event: when the subselemnt looses the focus and the focus + * is NOT given to another dialogDiv subelement, hides or removes (depending on removeOnHide param) dialogDiv. + * The workaround is quite tricky and maybe not well formed, as it uses a timeout function. However, any other implementation was trickier + * and with potential drawbacks. Note that any subelement of dialogDiv is assigned a "focus" attribute with the current time in millisecs + */ +// var setAsPopup = function(dialogDiv, removeOnHide){ +// dialogDiv.setAsPopup(removeOnHide ? function(){dialogDiv.remove();} : function(){dialogDiv.hide();}); +// }; + + this.bindClickToPopup = function(invokerAsJQueryObj, popupContent){ + var p = new DivDialog(popupContent); + var oldShow = p.show; + // var pint = parseInt; + p.show = function(){ + + var rect = screenRect(); + var offs = invokerAsJQueryObj.offset(); + var height = invokerAsJQueryObj.outerHeight(); + + var spaceAbove = offs.top - rect.y; + var spaceBelow = rect.height - height - spaceAbove; + + consolelog('wHeight:'+rect.height+ ' space above: '+spaceAbove + ' spacebelow: '+spaceBelow); + + if(spaceAbove>spaceBelow){ + p.css({'maxHeight':(spaceAbove-p.shadowoffset)+'px', 'top':rect.y+'px'}); + }else{ + p.css({'maxHeight':(spaceBelow-p.shadowoffset)+'px', 'top':(offs.top+height)+'px'}); + } + p.css({'height':'auto','width' :'auto', 'maxWidth': (rect.x+rect.width-offs.left)+'px'}); + + //consolelog("size"); consolelog(size); +// p.offset({ +// left: rect.x + pint((rect.width-size.width)/2), +// top: rect.y + pint((rect.height-size.height)/2) // }); -// //set the maximum size -// //due to overflow:auto a scrollbar will automatically appear -// var max = Math.max; //reference max immediately (speeds up performances a bit) -// var maxSize = { -// width: max(20,windowW + wdow.scrollLeft() -position.left-shadowOffset), -// height: max(20, (windowH + wdow.scrollTop() -position.top- shadowOffset)) -// } -// //position div and size: -// var divPadding = { -// left: div.outerWidth()-div.width(), -// top:div.outerHeight()-div.height() -// }; //setting width on a div means the width(), -// //but calculations here are made according to outerWidth(true), so we need this variable (se below) -// -// //the shadow in the background will be created according to the actual div size -// //However, since we do not specify neither width nor height, the calculation of the div size -// //works if maxWidth and maxHeight do set a width and height. In order to do so, they -// //must be lower or equal to the actual div width and height. That's why the "min" here below:' -// div.css({ -// 'maxWidth': Math.min(div.width(), maxSize.width-divPadding.left), -// 'maxHeight': Math.min(div.height(), maxSize.height-divPadding.top) + //consolelog("offset"); consolelog({ + // left: rect.x + pint((rect.width-size.width)/2), + // top: rect.y + pint((rect.height-size.height)/2) + // }); + + oldShow.apply(p,arguments); + p.refreshShadowPosition(); + p.setFocus(); + }; + consolelog(invokerAsJQueryObj); + p.css({ + 'minWidth':invokerAsJQueryObj.outerWidth()+'px', + 'left':invokerAsJQueryObj.offset().left+'px' + }); + + p.setPopupFocus(function(){p.hide();}); + + invokerAsJQueryObj.unbind('click').click(function(evt){ + p.show(); + return false; + }); + //p.show(); + //p.setFocus(); + } + /** + * Shows an info dialog centered in screeen. The dialog is a DivDialog with maxwidth and maxheight equals to the half of the + * visible window width and height, respectively. Content can be a jQuery object (ie an array of html elements) or a string + * denoting the innerHTML of the dialog div. timeInMsec can be: + * a number (in msec) specifying after how much time the dialog will be removed (for fast messages) + * the string 'hide' to specify that the div will be hidden when it looses focus + * the string 'remove' to specify that the div will be removed when it looses the focus + * + */ + this.showInfoDialog = function(content, timeInMsec){ + var p = new DivDialog(content); + var oldShow = p.show; + var pint = parseInt; + p.show = function(){ + oldShow.apply(p,arguments); + var rect = screenRect(); +// var pint = parseInt; +// p.css({ +// 'maxWidth':pint(rect.width/2)+'px', +// 'maxHeight':pint(rect.height/2)+'px' // }); +//consolelog("screeenrect"); consolelog(rect); + var size = p.size(); + //consolelog("size"); consolelog(size); + p.offset({ + left: rect.x + pint((rect.width-size.width)/2), + top: rect.y + pint((rect.height-size.height)/2) + }); + //consolelog("offset"); consolelog({ + // left: rect.x + pint((rect.width-size.width)/2), + // top: rect.y + pint((rect.height-size.height)/2) + // }); + + p.refreshShadowPosition(); + + }; + var rect = screenRect(); + p.css({ + 'maxWidth':pint(rect.width/2)+'px', + 'maxHeight':pint(rect.height/2)+'px' + }); + + if(typeof timeInMsec == 'number'){ //set a timeout + setTimeout(function(){ + p.remove(); + p=null; + },timeInMsec); + }else if(timeInMsec == 'hide'){ //is a boolean + p.setPopupFocus(function(){p.hide();}); + }else if(timeInMsec == 'remove'){ //is a boolean + p.setPopupFocus(function(){p.remove();}); + } + p.show(); + p.setFocus(); + }; +} + +//content: string or jQueryElement +//type 'popup', +//DivDialog(content,type,attributes) + +var pppUtils = new PopupUtils(); +function DivDialog(content){ + var $J = jQuery; + var doc = $J(document); + var firstFocusableElement = undefined; //set in focusout + var className = 'component'; + var basecss = { + 'position':'absolute', + 'display':'none' + }; + var popup = $J('
').addClass(className).css(basecss).css({ + 'zIndex':1000 + }); + var popupContent = $J('
').css({ + 'overflow':'auto' + }); + + var popupshadow = popup.clone(true,true).removeAttr('id').empty().css({ + 'backgroundColor':'#000', + 'border':'0px', + 'zIndex':900, + 'margin':'0px', + 'padding':'0px' + }).fadeTo(0,0.4); + var both = popup.add(popupshadow); + + + if(content){ + if(content instanceof $J){ + popupContent.empty().append(content); + }else{ + popupContent.html(content); + } + } + popup.append(popupContent); + + + +// if(invoker.is('a') || invoker.is('input[type=button]') || invoker.is('button') || +// invoker.is('input[type=submit]')){ +// var w = invoker.outerWidth(); +// popup.css({'minWidth':w+'px'}); +// this.show = show1(); +// }else{ // -// //last thing: if invoker element exist, set width at least invoker element width -// if(invokerElement){ -// var iEw = invokerElement.outerWidth(); //no margins considered -// if(iEwdiv.outerWidth()){ -// div.css({ -// 'minWidth':iEw-divPadding.left -// }); -// } +// } + + this.maxSize = function(size){ + popup.css({'maxHeight':size.height,'maxWidth':size.width}); + popupContent.css({'maxHeight':size.height-(popup.outerHeight()-popup.height()),'maxWidth':size.width-(popup.outerWidth()-popup.width())}); + }; + this.minsize = function(size){ + popup.css({'minHeight':size.height,'minWidth':size.width}); + }; + this.offset = function(){ + var ret = popup.offset.apply(popup,arguments); + //refreshPosition(); + return me; + }; + + //function (private) to refresh shadow position + this.shadowoffset = 5; + this.size = function(){ + return { + width: popup.outerWidth(), + height:popup.outerHeight() + }; + }; + + + + this.refreshShadowPosition = function(){ + if(!popup.is(":visible")){ + popupshadow.hide(); //to be sure + return; + }else{ + popupshadow.show(); + } + var offs = popup.offset(); + offs.top+=this.shadowoffset; + offs.left+=this.shadowoffset; + popupshadow.offset(offs); + popupshadow.css({ + 'width':popup.outerWidth()+'px', + 'height':popup.outerHeight()+'px' + }); + popupContent.css({ + 'maxWidth': (parseInt(popup.css('maxWidth')) -(popupContent.outerWidth()-popupContent.width())) +'px', + 'maxHeight':(parseInt(popup.css('maxHeight'))-(popupContent.outerHeight()-popupContent.height()))+'px' + }); + }; + + //dummy overriding of some jquery functions + var me = this; + this.remove = function(){ + both.empty(); + both.remove.apply(both,arguments); + return me; + }; + this.find = function(){ + return popupContent.find.apply(popupContent,arguments); + }; + this.hide = function(){ + return both.hide.apply(both,arguments); + return me; + }; + + this.show = function(){ + if(!(popup.parent().length)){ + $J('body').append(both); + } + var ret = popup.show.apply(popup,arguments); + //refreshPosition(); + return me; + }; + + this.setFocus = function(){ + if(firstFocusableElement && firstFocusableElement.parent().length && firstFocusableElement.is(':visible')){ + firstFocusableElement.focus(); + } + } + //popup specific functions + + //set css: note that margin position and zIndex will be overridden + this.css = function(){ + var arg = arguments; + if(arguments.length==2){ //setting a single css element + if(arguments[0] == 'margin' || arguments[0] == 'position' || arguments[0] == 'zIndex'){ + return me; + } + }else if(arguments.length==1){ //single argument + if(typeof arguments[0] == 'string'){ + return popup.css(arguments[0]); + }else{ + var a = arguments[0]; + for(var k in a){ + if(k == 'margin' || k == 'position' || k == 'zIndex'){ + delete a[k]; + } + } + arg = [a]; +// consolelog('css'); +// consolelog(arg); + } + }else{ + return me; + } + var ret = popup.css.apply(popup,arg); + //refreshPosition(); + return me; + }; + + + +// this.bindAsPopupFor = function(jQueryAnchorElement){ +// if(!jQueryAnchorElement.attr('id')){ +// jQueryAnchorElement.attr('id','popup_'+new Date().getTime()); // } -// //now we can build the divShadow -// var divShadow = div.clone(false,false).empty().css({'zIndex':999,'borderColor':'#000','display':'none','backgroundColor':'#000'}).insertAfter(div); -// //store the divs to be removed -// this._cfg_.divsToDelete = [div,divShadow]; -// //add a listener to the document. If one of the content children is clicked/keypressed, -// //we won't come here. Otherwise hide popup -// var me = this; -// var hide = this.hide; -// toggleBind(doc,function(e){ -// hide.apply(me); -// e.stopPropagation(); -// }); -// div.show(300, function(){ //basically in between fast (200) and slow (600) -// //position div shadow: -// divShadow.show(); -// consolelog(div.outerHeight(true)+" "+div.outerHeight(false)); -// consolelog(divShadow.outerHeight(true)+" "+divShadow.outerHeight(false)); +// var id = jQueryAnchorElement.attr('id'); // -// //set focus to the first input component, if any. Otherwise try with anchors, otherwise do nothing -// var inputs = $J(div).find(':input'); -// if(inputs && inputs[0]){ -// inputs[0].focus(); -// }else{ -// inputs = $J(div).find('a'); -// if(inputs && inputs[0]){ -// inputs[0].focus(); -// } -// } +// anchorElement.click(function(){ // -// divShadow.fadeTo(0,0.4, function(){ -// divShadow.css({ -// 'top': (position.top+shadowOffset), -// 'left': (position.left+shadowOffset), -// 'width': div.outerWidth(true), -// 'height': div.outerHeight(true) -// }); -// -// }); -// }); -// return false; //to avoid scrolling if we clicked on an anchor -// }, +// }) // -// //field must be a dictionary of label:defaultValues (both strings) -// //callbackOnOk is the callback to be executed on ok, if null ok will simply hide the dialog -// createDivDialog : function(field,callbackOnOk){ -// -// var $J = this._cfg_.jQuery; -// var table = $J(''); -// var fieldElms = {}; -// for(var label in field){ -// var input = $('') -// .attr('type','text').val(field[label]).attr("name",label); -// table.append($J('') -// .append($J('
').html(label)) -// .append($J('').append(input))); -// fieldElms[label]=input; -// } -// -// var p = this; -// var onCancel= function(){ -// p.hide(); -// return false; -// }; -// -// var onOk= function(){ -// if(callbackOnOk){ -// var ret = {}; -// var inputs = table.find("input"); -// $J.each(inputs, function(key,value){ -// var v = $J(value); -// ret[v.attr('name')] = v.val(); -// }); -// callbackOnOk(ret); -// return false; -// }else{ -// return onCancel(); -// } -// }; -// var subdiv = $J('
').css({ -// 'padding':'1ex', -// 'float':'right' -// }). -// append( -// $J(''). -// html('Ok'). -// addClass('component_icon'). -// addClass('button'). -// addClass('icon_ok'). -// attr('href','#'). -// click(function(){ -// return onOk(); -// }) -// ); -// if(callbackOnOk){ -// subdiv.append( -// $J(''). -// html('Cancel'). -// addClass('component_icon'). -// addClass('button'). -// addClass('icon_cancel'). -// attr('href','#'). -// click(function(){ -// return onCancel(); -// }) -// ); -// } -// //popupDialog(element,table,onOk); -// return $J('
').append(table).append(subdiv); // } -//} \ No newline at end of file + + this.setPopupFocus = function(callbackOnFocusLost){ + + //find all foccusable elements + var elementsWithFocus = $J(popupContent).find('textarea,a,input'); + //focus must be given also to the containing popup beacuse + //if a scrollbar is present, moving the scrollbar sets the focus to popup (not popupContent. So + //apparently even if the scrollbar is caused by css 'popupContent.scroll=auto', it's like if it was + //'part' of the parent container popup) + //TODO: TEST IT WITH OTHER BROWSERS!!!! if not working, manda tutto affanculo and use click events + popup.attr('tabindex',1); + elementsWithFocus = elementsWithFocus.add(popup); + //build the attribute focus to recognize subelement of popup + var focusid = 'popupfocus'+(new Date().getTime()); + //bind the blur to each focusable element: + elementsWithFocus.each(function(i,e){ + var ee = $J(e); + ee.attr(focusid,'true'); + ee.blur(function(){ + //wait 250msec to see if the focus has been given to another popup focusable element: if yes, do nothing + //otherwise execute callback + setTimeout(function(){ + var v = document.activeElement; + consolelog(v); + if(v && $J(v).attr(focusid)){ + return; + } + callbackOnFocusLost(); + },200) + }); //set here another time delay. 300 seems to be the good compromise between visual hide and safetiness that + //meanwhile the focus has already been given to the next component + }); + //set the first focusable element + firstFocusableElement = $J(elementsWithFocus[0]); + }; + + this.attr = function(){ + var ret = popup.attr.apply(popup,arguments); + //refreshPosition(); + return me; + }; + this.html = function(){ + if(arguments.length==0){ + return popupContent.html(); + } + var ret = popupContent.html.apply(popup,arguments); + //refreshPosition(); + return me; + } + this.append = function(){ + var ret = popupContent.append.apply(popup,arguments); + //refreshPosition(); + return me; + } +} + + diff --git a/telemeta/htdocs/timeside/src/player.js b/telemeta/htdocs/timeside/src/player.js index 2b49a5a9..abf0e8ae 100644 --- a/telemeta/htdocs/timeside/src/player.js +++ b/telemeta/htdocs/timeside/src/player.js @@ -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('
').css({ + var popupMarker = $J('
').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("
"+gettrans('title')+"
"+gettrans('title')+"
"+ gettrans('description')+"
"); 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); -- 2.39.5