this.stretch(div.find('.markersdivDescription'));
return div;
},
- //overridden
+ //overridden. Do not call explicitly, use marker map.move
move: function(from, to, newOffset){
//call super method
this.each(Math.min(from,realIndex),Math.max(from,realIndex)+1, function(i, div){
setIdx.apply(t,[div,i]);
});
-
this.setOffset(me[realIndex],newOffset);
//TODO: create a function?
},
-
+//TODO: what is doing this method here?
setFocus: function(index,value){
// this.each(function(i,div){
// if(i==index && value){
var e_indexLabel = div.find('.ts-marker');
var e_offsetLabel =div.find('.markersdivOffset');
e_indexLabel.add(e_offsetLabel).unbind('click').click(function(){
+ //Timeside.player.moveMarker(index,0.2);return; //just a try
me.setFocus(index,true);
me.fire('focus', {
'index': index
end('SoundManager is not responding. Try to:\n - Reload the page\n - Empty the cache (see browser preferences) and reload the page\n - Restart the browser');
},maxTime);
- // var playerDiv = $J('#player');
- // var markersUI = $J("#markers_div_id");
+
analyzerContentArray.push(elm.attr('unit'));
analyzerContentArray.push('</td></tr>');
});
-
-
-
-
+
//loaded analizer, loading player
//msgElm.html('Loading markers...');
$J('#analyzer_div_id').find('table').find('tbody:last').append(analyzerContentArray.join(""));
//setting up the select tag
+
+ player.bind('waitShown', function(data){
+ visualizersSelectElement.hide();
+ });
+ player.bind('waitHidden', function(data){
+ visualizersSelectElement.css('display','inline-block');
+ });
+
//assigning event on select:
visualizersSelectElement.change(
function (){
var ch = control.height();
var margin = 3;
visualizersSelectElement.css({
- 'display':'inline-block',
+ 'display': 'inline-block',
'height':(ch-2*margin)+'px',
'position':'absolute',
'top':margin+'px',
'right':margin,
'margin':0
- });
- player.bind('waiting', function(data){
- if(data.value){ //is waiting
- visualizersSelectElement.hide();
- return;
- }
- visualizersSelectElement.css('display','inline-block');
- });
+ }).hide(); //hide it to be sure. We could check player.isImgRefreshing but we have to think about event queue...
+
control.append(visualizersSelectElement);
//Eventually, do 3 last things:
//1) call end (without arguments simply clears the wait span and avoid subsequent calls to end(msg) to
var popupdiv = new PopupDiv({
focusable: false,
titleClass: 'markersdivTitle',
- showClose:false,
+ showClose:true,
bounds: {
top:0.4,
left:0.1,
defaultCloseOperation: 'hide'
});
var popupShowFunction = function(data){
-// if(popupTimeoutId !== undefined){
-// cT(popupTimeoutId);
-// }
-// popupTimeoutId=undefined;
- popupdiv.refresh(data.marker.desc,data.marker.title);
- if(!popupdiv.isShowing()){
- popupdiv.show();
- }
-// var index = data.index;
-// if(index+1 == map.length || map.toArray()[index+1].offset-data.marker.offset>3){
-// popupTimeoutId = popupdiv.setTimeout('close',3000);
-// }
- };
+ // if(popupTimeoutId !== undefined){
+ // cT(popupTimeoutId);
+ // }
+ // popupTimeoutId=undefined;
+
+ popupdiv.refresh(data.marker.desc,data.marker.title);
+ if(!popupdiv.isShowing()){
+ popupdiv.show();
+ }
+ // var index = data.index;
+ // if(index+1 == map.length || map.toArray()[index+1].offset-data.marker.offset>3){
+ // popupTimeoutId = popupdiv.setTimeout('close',3000);
+ // }
+ };
if(POPUP_TIMEOUT<0){
player.bind('markerCrossed',popupShowFunction);
}else{
popupTimeoutId=undefined;
popupShowFunction(data);
var index = data.index;
- if(index+1 == map.length || map.toArray()[index+1].offset-data.marker.offset>3){
+ //consolelog(data);
+ //consolelog(index+') '+data.marker.offset+' | '+(map.toArray()[index+1].offset+' - '+data.timeMarginInSec));
+ if(index+1 == map.length || map.toArray()[index+1].offset-data.marker.offset-data.timeMarginInSec>3){
popupTimeoutId = popupdiv.setTimeout('close',3000);
}
//consolelog('firing markercrossed');
});
p.bind('show', function(){
- this.closeLater(1500); //this refers to p
+ this.setTimeout('close',1500); //this refers to p
});
p.show();
}
* (popup.close() is called, see below)\r
* showOk (false): determines whether or not an ok button should be shown at the bottom of the popup. The ok button is an <a> tag whose\r
* click will trigger the popup.onOk callback (see below). This parameter should always be true for form filling popup (see PopupDiv.content above) and when onOk is specified (see below)\r
- * okButtonTitle ('Ok'): self-explanatory\r
+ * okButtonTitle ('Ok') [see note4]: self-explanatory\r
* onOk (null): callback. callback to be executed when the ok button is pressed. When specified, showOk must be set to true.\r
* The callback takes as argument a dictionary that the popup will build by retrieving all <input> <select> or <textarea>\r
* elements among its children: each element E whith attribute A = popup.getFormDataAttrName() (static popup method), will denote the property\r
* if the close button is clicked (see showClose below), or when popup.focusable=true and the popup looses the focus\r
* showClose (false): a parameter specifying whether a close button should appear on the top-right corner of the popup. Clicking the close button\r
* (internally, an <a> tag) will close the popup and trigger popup.close() (and associated callbacks bindings, if any)\r
- * closeButtonTitle ('x'): self-explanatory\r
+ * closeButtonTitle ('x') [see note4]: self-explanatory\r
* title (""): a parameter specifying whether the popup should have a title. The title will be placed on the top of the popup.\r
* shadowOffset (4): the shadow offset, in pixels. Each popup has a 'shadow' which renders a kind of 3d raised effect. Set to 0 if no shadow must be visualized\r
* p.okButtonAlign ('right'): self-explanatory. Takes the same argument as css text-align property. The css property text-align is set on the ok button parent div, so if okButtonClass (see below) is specified it might override the button alignement behaviour\r
* popupClass ("") [see note1+2]: the popup class(es). The top and bottom divs (housing title/close and ok buttons respectively) are not affected by this parameter\r
* popupCss ({}) [see note1+3]: the popup css. The top and bottom divs (housing title/close and ok buttons respectively) are not affected by this parameter\r
- * okButtonClass ('') [see note1+2]: the ok button class\r
- * closeButtonClass ('') [see note1+2]: the close button class\r
+ * okButtonClass ('') [see note1+2+4]: the ok button class\r
+ * closeButtonClass ('') [see note1+2+4]: the close button class\r
* titleClass ('') [see note1+2]: the title class\r
* listItemClass ('') [see note1+2]: the list items css, valid only if the popup is a listitem popup (see content above):\r
* it applies to each popup row (internally, an <a> tag with display block)\r
* backgrounds etcetera)\r
* [note2]: class arguments are in the same form of jQuery.addClass() argument (ie, a string which can denote also multiple classes separated by spaces)\r
* [note3]: css arguments are in the same form of jQuery.css() argument (ie, an object of cssName:cssValue pairs)\r
+ * [note4]: to customize ok button (closeButton respectively) with css (eg, with an icon), specify a background image in the class AND an height and a width (or padding),\r
+ * otherwise title and icon might overlap or, if okButtonTitle (closeButtonTitle respectively) is the empty string '', the button will be invisible. Note that the anchor has by default\r
+ * display = inline-block, so dimensions can be specified.\r
*\r
* And finally, EXAMPLES:\r
* Given an anchor <a> (jQuery element)\r
}else{\r
container.append(""+content);\r
}\r
-\r
};\r
\r
p.setFocusCycleRoot = function(value){\r
}\r
var invoker = this.invoker;\r
if(this.isClickElement(invoker)){\r
- this.setBoundsAsPopup(invoker, true);\r
+ this.setBoundsAsPopup(invoker);\r
}else{\r
- this.setBoundsInside(invoker, this.bounds, this.boundsExact, true);\r
+ this.setBoundsInside(invoker, this.bounds, this.boundsExact);\r
}\r
- //set title and close button to span whole width, if necessary\r
- //closeButton.outerWidth should be zero if this.showClose = false\r
- //titleInput.outerWidth(true) should be equal to titleInput.width(), as margins borders and padding are zero, however we want to calculate it safely\r
- // if(this.showClose || this.title){\r
- // var topDiv = this.getDiv().children().eq(0);\r
- // var closeBtn = topDiv.find('a').eq(0);\r
- // var titleInput = topDiv.find(':text').eq(0);\r
- // var titleW = topDiv.width() - closeBtn.outerWidth(true) - (titleInput.outerWidth(true)-titleInput.width());\r
- // titleInput.css({\r
- // 'maxWidth':'',\r
- // 'width':(titleW)+'px'\r
- // });\r
- // }\r
-\r
+ \r
this.shadow(); //updates shadow\r
if(focusable){\r
this.getFirstFocusableElement().focus();\r
\r
p.setTitle= function(title){\r
var subdiv = this.getDiv().children().eq(0);\r
+\r
+\r
var text = subdiv.contents().filter(function() {\r
return this.nodeType == 3;\r
});\r
+ \r
var node = text.get(0);\r
if(!title){\r
- title='';\r
+ //if title is the empty string, apparently the text node seems to be "deleted", so resetting\r
+ //the title later has no effect. Setting a white space is not really perfect, as we could have extra space. However,\r
+ //if assures at least a minimum width if the container is empty\r
+ title=' ';\r
}\r
if (node.textContent) {\r
node.textContent = title;\r
} else if (node.nodeValue) {\r
node.nodeValue = title;\r
}\r
-\r
- // var titleIpt = subdiv.find(':text').hide();\r
- // var titleSpan = subdiv.find('span').css({'display':'inline-block','float':'left'});\r
- // if(title){\r
- // titleSpan.html(title);\r
- // }else{\r
- // titleSpan.hide();\r
- // }\r
- // var titleSpanWidth = titleSpan.html(title).width();\r
- // titleIpt.val(title).css('width',titleSpanWidth+'px');\r
- // titleSpan.html('').css('display','none');\r
+// consolelog('"'+ title+'"');\r
+// consolelog(text);\r
+// consolelog(node);\r
}\r
\r
p.isShowing = function(){\r
var div = this.getDiv();\r
var me = this;\r
\r
- var cssModified = (this.popupClass || this.popupCss);\r
if(this.popupClass){\r
//this.popupClass might be in the prototype (not set by user)\r
div.removeClass().addClass(this.popupClass);\r
div.css(this.popupCss);\r
this.popupCss = ''; //override prototype property\r
}\r
- //css modified, restore properties we need not to change:\r
- //cssModified should be true ALL first times we call show, as this.popupCss = {} )ie, it evaluates to TRUE)\r
- if(cssModified){\r
- div.css({\r
- 'position':'absolute',\r
- 'zIndex':this.zIndex,\r
- 'margin':'0px',\r
- 'overflow':'hidden'\r
- });\r
- }\r
-\r
- //this.setSizable();//this means the popupdiv is display: !none and visibility:hidden, so every element\r
- //inside it should be visible and therefore sizable. Being visible means that jQuery.is(':visible') returns true\r
+ \r
\r
this.setFocusCycleRoot(this.focusable);\r
\r
var topDiv = $(subdiv[0]);\r
var closeBtn = topDiv.find('a').eq(0);\r
\r
- if(!this.showClose && !this.title){\r
- topDiv.hide();\r
- }else{\r
+ if(this.showClose || this.title){\r
topDiv.css({\r
'paddingBottom':'0.25em'\r
}); //add padding to bottom\r
}else{\r
closeBtn.hide(); //margin:0 is to be sure, as afterwards we must span the title the whole popup width\r
}\r
- //in any case, show titleElement cause even if title="", titleElement is used to position close on the right\r
- // titleInput.css({\r
- // 'backgroundColor':'transparent',\r
- // 'padding': '0px',\r
- // 'margin':'0px',\r
- // 'border':'0px'\r
- // }).attr('readonly','readonly').attr('class',this.titleClass).css({\r
- // 'display':'inline-block','float':'left'\r
- // //it is too tricky to set the width of the input spanning the whole title (in case of long titles)\r
- // //we experienced problems in vertical align with the close button, as stated somewhere above.\r
- // //we will use a span (see setTitle below)\r
- // });\r
this.setTitle(this.title);\r
}\r
\r
okButton.attr('class', this.okButtonClass); //removes all existing classes, if any\r
okButton.html(this.okButtonTitle);\r
okButton.css({\r
- 'display':'inline-block',\r
- 'visibility':'visible'\r
+ 'float':'none',\r
+ 'display':'inline-block'\r
}); //in order to set width and height on the element\r
- }else{\r
- bottomDiv.hide();\r
}\r
\r
- // var centralDiv = $(subdiv[1]);\r
- // //reset properties of the central div\r
- // centralDiv.css({\r
- // 'overflow':'auto',\r
- // 'maxHeight':'',\r
- // 'maxWidth':'',\r
- // 'minHeight':'',\r
- // 'minWidth':'',\r
- // 'height':'',\r
- // 'width':'',\r
- // 'visibility':'visible'\r
- // }).show();\r
-\r
+ if(!div.parent().length){ //to be done before setSizeAsPopup or setBoundsInside\r
+ div.appendTo('body');\r
+ }\r
\r
var invoker = this.invoker;\r
\r
if(this.isClickElement(invoker)){\r
- this.setBoundsAsPopup(invoker, true);\r
+ this.setBoundsAsPopup(invoker);\r
//storing click events, when showing clicking on an event must give the focus to the popup\r
//old handlers will be restored in close()\r
this['_tmpHandlers'+this.getId()] = undefined;\r
}\r
\r
}else{\r
- this.setBoundsInside(invoker, this.bounds, this.boundsExact, true);\r
+ this.setBoundsInside(invoker, this.bounds, this.boundsExact);\r
}\r
\r
- // //set title and close button to span whole width, if necessary\r
- // //closeButton.outerWidth should be zero if this.showClose = false\r
- // //titleInput.outerWidth(true) should be equal to titleInput.width(), as margins borders and padding are zero, however we want to calculate it safely\r
- // if(this.showClose || this.title){\r
- // var titleW = topDiv.width() - closeBtn.outerWidth(true) - (titleInput.outerWidth(true)-titleInput.width());\r
- // titleInput.css({\r
- // 'maxWidth':'',\r
- // 'width':(titleW)+'px'\r
- // });\r
- // }\r
- //\r
- // //set central div max height ONLY IF NECESSARY (overflow). Until here, the main popup is sized and placed\r
- // //but the central div might overflow\r
- // var height = centralDiv.height();\r
- // var maxHeight = (div.height()-topDiv.outerHeight(true)-bottomDiv.outerHeight(true)-\r
- // (centralDiv.outerHeight(true)-centralDiv.height()));\r
- // if(maxHeight<height){\r
- // centralDiv.css('maxHeight',maxHeight+'px');\r
- // }\r
- // //same for width:\r
- // var maxWidth = div.width();\r
- // var width = centralDiv.outerWidth(true);\r
- // if(maxWidth<width){\r
- // centralDiv.css('maxWidth',maxWidth+'px');\r
- // }\r
-\r
\r
-\r
var shadow = this.shadow();\r
var postShowFcn = function(){\r
me.trigger('show');\r
return shadow;\r
}\r
\r
- p.setBoundsAsPopup = function(popupInvoker, isSizable){\r
+ p.setBoundsAsPopup = function(popupInvoker){\r
var invoker = popupInvoker;\r
\r
this.preSizeFcn();\r
- isSizable = true;\r
\r
var div = this.getDiv();\r
- // var oldCss= isSizable ? undefined : this.setSizable();\r
\r
var shadowOffset = this.shadowOffset;\r
var windowRectangle = this.getBoundsOf(wdw); //returns the window rectangle\r
this.setMaxSize({\r
height : (placeAbove ? spaceAbove : spaceBelow),\r
width: (placeLeft ? spaceLeft : spaceRight)\r
- },isSizable); //width will be ignored (for the moment)\r
+ }); //width will be ignored (for the moment)\r
//decrement of one pixel cause when the popup has to be reduced and the shadows bounds "touch" the window right or bottom sides,\r
//the window scrolls (and it shouldn't)\r
\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
- },isSizable);\r
+ });\r
\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
'left': placeLeft ? invokerOffset.left+ invokerOuterWidth - div.outerWidth(true)-shadowOffset : invokerOffset.left,\r
'top': (placeAbove ? invokerOffset.top - div.outerHeight(true) :\r
invokerOffset.top + invokerOuterHeight)\r
- },isSizable);\r
+ });\r
\r
this.postSizeFcn();\r
\r
- // if(oldCss){\r
- // div.css({\r
- // 'display':oldCss['display'],\r
- // 'visibility':oldCss['visibility']\r
- // });\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, pd, boundsExact, isSizable){\r
+ p.setBoundsInside = function(parent, pd, boundsExact){\r
\r
var div = this.getDiv();\r
- // var oldCss = isSizable ? undefined : this.setSizable();\r
\r
this.preSizeFcn();\r
- isSizable = true;\r
-\r
+ \r
var bounds = this.getBoundsOf(parent);\r
\r
\r
this.setMinSize({\r
width:maxSize.width,\r
height:maxSize.height\r
- },isSizable); //a copy cause the argument will be modified\r
+ }); //a copy cause the argument will be modified\r
this.setMaxSize({\r
width:maxSize.width,\r
height:maxSize.height\r
- }, isSizable); //a copy cause the argument will be modified\r
+ }); //a copy cause the argument will be modified\r
\r
this.offset({\r
'left':x + padding['left'],\r
'top': y + padding['top']\r
- },isSizable);\r
+ });\r
}else{\r
this.setMaxSize({\r
width:maxSize.width,\r
height:maxSize.height\r
- },isSizable); //a copy cause the argument will be modified\r
+ }); //a copy cause the argument will be modified\r
var spanLeft = maxSize.width - div.outerWidth(true);\r
var spanTop = maxSize.height - div.outerHeight(true);\r
this.offset({\r
'left':x + padding['left'] + (spanLeft > 0 ? spanLeft/2 : 0),\r
'top': y + padding['top'] +(spanTop > 0 ? spanTop/2 : 0)\r
- },isSizable);\r
+ });\r
\r
}\r
\r
this.postSizeFcn();\r
-\r
- // if(oldCss){\r
- // div.css({\r
- // 'display':oldCss['display'],\r
- // 'visibility':oldCss['visibility']\r
- // });\r
- // }\r
};\r
p.preSizeFcn = function(){\r
- this.setSizable();\r
- var subdivs = this.getDiv().children().hide();\r
+ var div = this.getDiv();\r
+ var subdivs = div.children().hide();\r
var subdivsshow = subdivs.eq(1);\r
if(this.showClose || this.title){\r
subdivsshow = subdivsshow.add(subdivs.eq(0));\r
subdivsshow = subdivsshow.add(subdivs.eq(2));\r
}\r
\r
- subdivsshow.css({\r
- 'overflow':'auto',\r
- 'maxHeight':'',\r
- 'maxWidth':'',\r
- 'minHeight':'',\r
- 'minWidth':'',\r
+ subdivsshow.add(div).css({\r
+ 'maxHeight':'none',\r
+ 'maxWidth':'none',\r
+ 'minHeight':'none',\r
+ 'minWidth':'none',\r
'height':'auto',\r
'width':'auto',\r
- 'display':'block'\r
+ 'display':'block',\r
+ 'overflow':'visible',\r
+ 'float':'none'\r
+ });\r
+\r
+ div.css({\r
+ 'margin':'0px',\r
+ 'zIndex':this.zIndex,\r
+ 'position':'absolute'\r
});\r
}\r
\r
var subdivs = div.children();\r
var topDiv = subdivs.eq(0);\r
\r
- //we must set a width:100% on the topDiv in order to stretch the whole HEIGHT (having two elements inside it with float:left and right)\r
- //however, we might have here a width LOWER than the actual div width, so stretch it more if it's lower:\r
- \r
- // if(this.showClose || this.title){\r
- // var closeBtn = topDiv.find('a').eq(0);\r
- // var titleInput = topDiv.find(':text').eq(0);\r
- // var span = topDiv.find('span').eq(0).hide();\r
- // var titleW = topDiv.width() - closeBtn.outerWidth(true) - (titleInput.outerWidth(true)-titleInput.width());\r
- // titleInput.html(span.html()).css({\r
- // 'maxWidth':'',\r
- // 'width':(titleW)+'px'\r
- // });\r
- // }\r
-\r
- var topBottom = $([]);\r
- if(this.showClose || this.title){\r
- topBottom = topBottom.add(subdivs.eq(0));\r
- }\r
- if(this.showOk){\r
- topBottom = topBottom.add(subdivs.eq(2));\r
- }\r
- topBottom.css({\r
- 'overflow':'hidden',\r
- 'width':'100%'\r
- }); //to span the whole width\r
-\r
-\r
var centralDiv = subdivs.eq(1);\r
centralDiv.css('overflow','auto');\r
var bottomDiv = subdivs.eq(2);\r
ret.height = jQueryElement.height();\r
return ret;\r
};\r
-\r
- p.setMaxSize = function(size, isSizable){\r
+ //getDiv must be sizable (preShowFcn must have been called)\r
+ p.setMaxSize = function(size){\r
var div = this.getDiv();\r
- var oldCss = isSizable ? undefined : this.setSizable();\r
-\r
+ \r
this._convertSize(div, size);\r
var css = {};\r
if('width' in size){\r
if(css){\r
div.css(css);\r
}\r
- if(oldCss){\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, isSizable){\r
+ //getDiv must be sizable (preShowFcn must have been called)\r
+ p.setMinSize = function(size){\r
var div = this.getDiv();\r
- var oldCss= isSizable ? undefined : this.setSizable();\r
-\r
+ \r
this._convertSize(div, size);\r
var css = {};\r
if('width' in size){\r
if(css){\r
div.css(css);\r
}\r
- if(oldCss){\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
}\r
};\r
\r
- p.offset = function(offs, isSizable){\r
+ p.offset = function(offs){\r
var div = this.getDiv();\r
- var oldCss= isSizable? undefined : this.setSizable();\r
- //offset does NOT consider margins. Do we have top and left?\r
-\r
- this.getDiv().offset(offs);\r
- if(oldCss){\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
+ div.offset(offs);\r
};\r
\r
p.close = function(){\r
return t;\r
},\r
\r
- p.setSizable = function(){\r
- //if false, just update the flag\r
- var div = this.getDiv();\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
- 'maxWidth':'',\r
- 'maxHeight':'',\r
- 'minWidth':'',\r
- 'minHeight':'',\r
- 'height':'',\r
- 'width':''\r
- }).show();\r
-\r
-\r
- return css;\r
- }\r
p.getShadowDivId = function(){\r
return this.getId()+"_shadow";\r
}\r
return this.getId()+"_data";\r
}\r
\r
-})(PopupDiv.prototype);\r
-\r
+})(PopupDiv.prototype);
\ No newline at end of file
pFloat: parseFloat, //reference to function parseFloat for faster lookup
//overridden
- add: function(obj) {
+ add: function(newMarker) {
//var markers = this.toArray();
- if(!('offset' in obj)){
+ if(!('offset' in newMarker)){
return -1;
}
-
- if(typeof obj.offset != 'number'){ //check to be sure:
- obj.offset = this.pFloat(obj.offset);
+ if(typeof newMarker.offset != 'number'){ //check to be sure:
+ newMarker.offset = this.pFloat(newMarker.offset);
}
- if(!('id' in obj)){
- obj.id = Timeside.utils.uniqid();
+ if(!('id' in newMarker)){
+ newMarker.id = Timeside.utils.uniqid();
}
- if(!('isEditable' in obj)){
- obj.isEditable = false;
+ if(!('isEditable' in newMarker)){
+ newMarker.isEditable = false;
}
- var marker = obj; //this.createMarker(obj);
+ var marker = newMarker; //this.createMarker(obj);
var idx = this.insertionIndex(marker);
if(idx>=0){ //it exists? there is a problem....
- this.debug('adding a marker already existing!!'); //should not happen. however...
+ this.debug('adding an already existing marker!!'); //should not happen. however...
return -1;
}
this.fire('add', {
marker: marker,
index: idx
- //,isNew: (typeof obj == 'number' || typeof obj == 'string')
+ //,isNew: (typeof obj == 'number' || typeof obj == 'string')
});
//var temp = new MarkerDiv();
// this.debug(this.createMarkerDiv());
return idx;
},
- //overridden
- //identifier can be an number (marker index) or a marker (the index will be aearched)
- remove: function(identifier) {
+ //overridden method. Contrarily to super method,
+ //where the first argument is the index (integer), here the
+ //the first argument can also be a marker. Its index will be found and, if valid, the super method will be called
+ //RETURNS -1 IF SOMETHING HAS GONE WRONG, OTHERWISE THE
+ remove: function(markerOrMarkerIndex) {
var idx = -1;
- if(typeof index == 'number'){
- idx = identifier;
- }else if('id' in identifier && 'offset' in identifier){
- idx = this.insertionIndex(identifier);
+ if(typeof markerOrMarkerIndex == 'number'){
+ idx = markerOrMarkerIndex;
+ }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){
+ idx = this.insertionIndex(markerOrMarkerIndex);
+ //idx>=0 ONLY if marker has been found
}
if(idx<0 || idx>=this.length){
- this.debug('remove: marker not found');
+ this.debug('markermap.remove: index out of bounds or marker not found');
return -1;
}
var marker = this._super(idx);
this.fire('remove',{
- 'index':idx,
- 'marker':marker
- });
- return idx;
+ 'index':idx,
+ 'marker':marker
+ });
+ return idx;
},
- //overridden method
- move: function(markerIndex, newOffset){
+ //overridden method. Contrarily to super method,
+ //where the first argument is the 'from' index, here the
+ //the first argument can also be a marker
+ move: function(markerOrMarkerIndex, newOffset){
+ var oldIndex = -1;
+ if(typeof markerOrMarkerIndex == 'number'){
+ oldIndex = markerOrMarkerIndex;
+ }else if('id' in markerOrMarkerIndex && 'offset' in markerOrMarkerIndex){
+ oldIndex = this.insertionIndex(markerOrMarkerIndex);
+ //oldIndex>=0 ONLY if marker has been found
+ }
+ if(oldIndex<0 || oldIndex>=this.length){
+ this.debug('markermap.move: index out of bounds or marker not found');
+ return -1;
+ }
+
var newIndex = this.insertionIndex(newOffset);
//select the case:
if(newIndex<0){
//just return the real insertionIndex
newIndex = -newIndex-1;
}
-
- var realIndex = this._super(markerIndex,newIndex);
+
+ //realIndex is the REAL INDEX AT WHICH WILL BE the moving marker M AFTER move.
+ //It newIndex = oldIndex+1
+ //we move M IMMEDIATELY AFTER ITSELF, which means, after removing M, that M has realIndex=n, as before
+ var realIndex = this._super(oldIndex,newIndex);
var markers = this.toArray();
var marker = markers[realIndex];
marker.offset = newOffset;
this.fire('move', {
marker: marker,
- fromIndex: markerIndex,
+ index: realIndex,
+ fromIndex: oldIndex,
toIndex: newIndex,
oldOffset: oldOffset
//,newIndex: realIndex
});
+ return newIndex;
},
init: function(container, sound, soundDurationInMsec, soundImgFcn, soundImgSize, markersArray, newMarkerCallback) {
this._super();
+ this.playState = 0; //0: not playing, 1: loading, 2:buffering, 3 playing (sound heard)
//container is the div #player
if (!container){
this.getContainer = function(){
return container;
- }
+ };
this.getSound = function(){
return sound;
- }
+ };
if(typeof soundImgFcn == 'string'){
var url = soundImgFcn;
this.imageCallback = new function(w,h){
var sd = this.toSec(soundDurationInMsec);
this.getSoundDuration = function(){
return sd;
- }
+ };
this.soundPosition = sound.position ? this.toSec(sound.position) : 0;
//public methods: returns the sound position
//Basically, NOT specifying any src for image tags can be harmful,
//see http://www.nczonline.net/blog/2009/11/30/empty-image-src-can-destroy-your-site/ and
//http://geekswithblogs.net/bcaraway/archive/2007/08/24/114945.aspx for details
- var html = ["<div class='ts-viewer'>",
+ var html = [//"<div class='ts-viewer'>",
"<div class='ts-ruler'></div>",
"<div class='ts-wave'>",
"<div class='ts-image-canvas'></div>",
// "<img class='ts-image' src='/images/transparent.png' alt='' />",
"</div>",
"</div>",
- "</div>",
+ //"</div>",
"<div class='ts-control'>",
//"<div class='ts-layout'>",
//"<div class='ts-playback'>",
var play = control.find('.ts-play');
play.attr('href', '#').bind('click', function(){
- me.setWait('loading',function(){
- me.play.apply(me);
- });
+ me.play.apply(me);
return false;
});
control.find('a').attr('href', '#') ;
//SET NECESSARY CSS (THIS WILL OVERRIDE CSS SET IN STYLESHEETS):
- var viewer = container.find('.ts-viewer');
+ //var viewer = container.find('.ts-viewer');
var wave = container.find('.ts-wave');
var ruler_ = container.find('.ts-ruler');
- wave.add(viewer).add(control).add(ruler_).css({
+ wave.add(control).add(ruler_).css({
'position':'relative',
'overflow':'hidden'
});
});
//END NECESSARY CSS
- this.setWait(false);
-
+
//creating the ruler
- var ruler = new Timeside.classes.Ruler(viewer, this.getSoundDuration());
+ var waveImage = container.find('.ts-image-canvas');
+ var ruler = new Timeside.classes.Ruler(ruler_, waveImage, this.getSoundDuration());
+ //var ruler = new Timeside.classes.Ruler(viewer, this.getSoundDuration());
this.getRuler = function(){
return ruler;
}
//this.resize(); //which calls also ruler.resize() (see below)
- //binds click for the pointer
- var v = $J('#player').find('.ts-viewer');
+ //binds click for the pointer:
+ var v = wave; //.add(ruler);
v.unbind('click').click(function(evt){
var w = v.width();
var x = evt.pageX - v.offset().left; //using absolute coordinates allows us to
markersArray = [];
}
this.loadMarkers(markersArray);
+
+
+ //IE7 BUG: the divs wave and control do not shift downwards after canvas is drawn and covers part of the rulrer.
+ //Weird enough (with IE it isn't actually), we have just to set the property we already set in the css:
+ //ie, top: auto. This is however useful even if somebody specified a top property on the divs
+ ruler_.add(wave).add(control).css('top','auto');
+// if(h > $J('.ts-wave').position().top){
+// $J('.ts-wave').css('top',0+'px');
+// }
+
},
if(!sound){
return false;
}
- /*Numeric value indicating the current playing state of the sound.
+ return this.playState;
+ /*Numeric value indicating the current playing state of the sound.
* 0 = stopped/uninitialised
* 1 = playing or buffering sound (play has been called, waiting for data etc.)
*Note that a 1 may not always guarantee that sound is being heard, given buffering and autoPlay status.*/
- return sound && sound.playState==1;
+ //return sound && sound.playState==1;
},
setSoundPosition: function(newPositionInSeconds){
//if the player is playing and NOT yet fully loaded, simply calling:
//So:
var wasPlaying = this.isPlaying();
if(wasPlaying){
- this.getSound().stop(); //dont call this.pause cause it hides the waitbar, if visible
+ this.getSound().stop(); //dont call this.pause cause it hides the waitbar, if visible and resets the playState
}
//update pointer position. If this call is due to a pointer move (mouse release),
//ruler.isPointerMovingFromMouse=true and the following code has no effect (the pointer is already at the good position)
//delay a little bit the play resume, this might avoid fast pointer repositioning
//(it should not be the case, but it happens. why??)
setTimeout(function(){
+ //player.playState = 1; //set to loading, so we do not display waitbar 'loading' again
player.play.apply(player);
},100);
}
},
-
+ //given a marker at index I, specifies that a marker corss event is fired whenever the sound position (pointer)
+ //is in the interval ]markerCrossedOffsetMargin-I,I+markerCrossedOffsetMargin[
+ //the value is in seconds
+ //markerCrossedOffsetMargin : 0.5,
play : function(){
var player = this;
var sound = player.getSound();
- var imgWaitDisplaying = this.isWaitVisible();
+ //var imgWaitDisplaying = this.isWaitVisible();
//soundManager multishot set false should prevent the play when already playing. We leave this check for safety
+
if(!player || !sound){
- if(!player.isPlaying() && imgWaitDisplaying){
- this.setWait(false);
- }
return false;
}
-
- var toSec = player.toSec;
- var ruler = player.getRuler();
- var sPosInMsec = player.toMsec(player.soundPosition);
- var bufferingString = 'buffering';
+ //setting markercorss callback
//for these varirables, see explanation below:
- var numberOfSubsequentPlayCall=0;
- var minimumNumberOfSubsequentPlayCall=3;
- var isPlayingId=2;
- var isBufferingId=1;
- var uninitializedId=0;
- var currentState=uninitializedId;
+ //var numberOfSubsequentPlayCall=0;
+ //var minimumNumberOfSubsequentPlayCall=3;
+ //var isPlayingId=2;
+ //var isBufferingId=1;
+ //var uninitializedId=0;
+ //var currentState=uninitializedId;
var fireOnMarkerPosition = function(seconds){}; //does nothing by default
var map = player.getMarkerMap();
var markerCrossListeners = player.listenersMap['markerCrossed'];
-
+ //optimizing: if no listeners associated to markerCrossListeners, avoid creating a function
if(map && map.length && markerCrossListeners){
var idx = 0;
if(player.soundPosition>0){
var offs = marker.offset;
var intervalUpperBound = offs+margin;
var intervalLowerBound = offs-margin;
- var data = {
+ var data = { //if you change data, change it also below
index:idx,
- marker:marker
+ marker:marker,
+ timeMarginInSec: margin
};
fireOnMarkerPosition = function(seconds){
if(marker){
offs = marker.offset;
intervalUpperBound = offs+margin;
intervalLowerBound = offs-margin;
- data = {
+ data = { //if you change data, change it also above
index:idx,
- marker:marker
+ marker:marker,
+ timeMarginInSec: margin
};
}else{
marker = undefined;
};
}
}
+
+ var toSec = player.toSec;
+ var ruler = player.getRuler();
+ var sPosInMsec = player.toMsec(player.soundPosition);
+ var bufferingString = this.msgs.buffering;
+ var loadingString = this.msgs.loading;
+
+ var updateWaitBar = this.setWait;
+
+ if(loadingString && !this.playState){ //
+ updateWaitBar.apply(this,[loadingString]); //calling setWait of an empty string hides the wait, we dont want it here
+ //ps: without apply this in updateWait is the dom window
+ this.playState = 1;
+ }
+ var playState = this.playState;
var playOptions = {
position: sPosInMsec,
whileplaying: function(){
+
var sPos = this.position;
- var buffering = this.isBuffering; //this refers to the soundmanager sound obj
+ var buffering = this.isBuffering || typeof sPos != 'number' || sPos < sPosInMsec;
+ //var buffering = this.isBuffering; //this refers to the soundmanager sound obj
//Now, what are we doing here below? we could simply check whether is buffering or not..
//Unfortunately, when buffering some playState (isBuffering = false) are also fired, randomly
//ONCE in a while
//pointer as a result of a real play state, and we avoid blinking of the wait element
switch(buffering){
case true:
- numberOfSubsequentPlayCall = 0; //reset the count
- switch(currentState){
- case isBufferingId: //do nothing (wait element already displaying)
+ switch(playState){
+ case 2: //do nothing (wait element already displaying)
break;
default: //update the wait element showing it:
- currentState = isBufferingId;
- player.setWait.apply(player,[bufferingString]);
+ playState = 2;
+ player.playState = 2;
+ if(bufferingString){
+ updateWaitBar.apply(player,[bufferingString]);
+ }
}
break;
default:
- switch(currentState){
- case uninitializedId:
- case isBufferingId: //in these 2 cases, increment numberOfSubsequentPlayCall
- numberOfSubsequentPlayCall++;
- if(numberOfSubsequentPlayCall == minimumNumberOfSubsequentPlayCall){
- //if is not buffering, we could skip this. However, there could be the waitbar displaying for some other reason:
- player.setWait.apply(player,[false]);
- currentState = isPlayingId; //set state for future subsequent calls of this case
- }else{
- break; //do not move pointer (default condition below)
- }
+ switch(playState){
+ case 0:
+ case 1:
+ case 2: //update waitbar
+ updateWaitBar.apply(player,[player.isImgRefreshing ? player.msgs.imgRefreshing : '']);
+ //currentState = isPlayingId; //set state for future subsequent calls of this case
+ playState = 3;
+ player.playState = 3;
default: //move pointer
var sPosInSec = toSec(sPos);
player.soundPosition = sPosInSec;
//whileplaying position to the end. We tried with a setTimeout function but the visual effect is not
//removed. So we leave this small 'bug'
ruler.movePointer(player.getSoundDuration());
- if(imgWaitDisplaying){
- player.setWait.apply(player,[false]);
- imgWaitDisplaying = false;
- }
+ updateWaitBar.apply(player,[player.isImgRefreshing ? player.msgs.imgRefreshing : '']);
+ player.playState = 0;
+ player.fire('playbackEndReached');
+
+ //player.fire('endReached');
}
};
+ // var playOptions = {
+ // position: sPosInMsec,
+ // whileplaying: function(){
+ // var sPos = this.position;
+ // var buffering = this.isBuffering; //this refers to the soundmanager sound obj
+ // //Now, what are we doing here below? we could simply check whether is buffering or not..
+ // //Unfortunately, when buffering some playState (isBuffering = false) are also fired, randomly
+ // //ONCE in a while
+ // //the result is a blinking 'isBuffering' 'isPlaying' state in the wait element displaying the state (not so nice),
+ // //which is also costly in terms of computation. So, we wait for at least N playstate fired SUBSEQUENTLY, without
+ // //NO bufferingState fired between them. N is set to minimumNumberOfSubsequentPlayCall. When this happens, we can start moving the
+ // //pointer as a result of a real play state, and we avoid blinking of the wait element
+ // switch(buffering){
+ // case true:
+ // numberOfSubsequentPlayCall = 0; //reset the count
+ // switch(currentState){
+ // case isBufferingId: //do nothing (wait element already displaying)
+ // break;
+ // default: //update the wait element showing it:
+ // currentState = isBufferingId;
+ // player.playState = 2;
+ // if(bufferingString){
+ // player.setWait(bufferingString);
+ // }
+ // }
+ // break;
+ // default:
+ // switch(currentState){
+ // case uninitializedId:
+ // case isBufferingId: //in these 2 cases, increment numberOfSubsequentPlayCall
+ // numberOfSubsequentPlayCall++;
+ // if(numberOfSubsequentPlayCall == minimumNumberOfSubsequentPlayCall){
+ // //if is not buffering, we could skip this. However, there could be the waitbar displaying for some other reason:
+ // player.setWait(player.isImgRefreshing ? player.msgs.imgRefreshing : '');
+ // currentState = isPlayingId; //set state for future subsequent calls of this case
+ // player.playState = 3;
+ // }else{
+ // break; //do not move pointer (default condition below)
+ // }
+ // default: //move pointer
+ // var sPosInSec = toSec(sPos);
+ // player.soundPosition = sPosInSec;
+ // ruler.movePointer(sPosInSec);
+ // }
+ // fireOnMarkerPosition(sPosInSec);
+ // }
+ //
+ // },
+ // onfinish: function() {
+ // //whileplaying is NOT called onsinfish. We must update the pointer:
+ // //note that for small length sounds (wg, 5 secs) the pointer shifts abruptly from the last
+ // //whileplaying position to the end. We tried with a setTimeout function but the visual effect is not
+ // //removed. So we leave this small 'bug'
+ // ruler.movePointer(player.getSoundDuration());
+ // player.setWait(player.isImgRefreshing ? player.msgs.imgRefreshing : '');
+ // player.playState = 0;
+ // pauseFunction('endReached');
+ //
+ // //player.fire('endReached');
+ // }
+ // };
+
sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play
sound.play(playOptions);
return false;
},
+
+ msgs : {
+ loading : 'loading',
+ buffering: 'buffering',
+ imgRefreshing : 'refreshing img'
+ },
pause: function(){
var sound = this.getSound();
//we don't check if it's playing, as the stop must really stop anyway
//if(sound && this.isPlaying()){
- sound.stop();
- this.setWait(false);
- this.fire('paused');
+ if(sound){
+ var v = this.isPlaying();
+ sound.stop();
+ this.playState = 0;
+ this.fire('paused',{
+ 'wasPlaying':v
+ });
+ this.setWait(this.isImgRefreshing ? this.msgs.imgRefreshing : '');
+ }
return false;
},
isWaitVisible: function(){
return this.getContainer().find('.ts-control').find('.ts-wait').html();
},
- setWait: function(value, optionalCallback){
- var c = this.getContainer();
- var waitDiv = c.find('.ts-control').find('.ts-wait');
+ setWaitElement: function(element){
- var player = this;
- var wait = function(){};
- if(value){
- var wtext = "";
- if(typeof value == 'string'){
- wtext = value;
- }
- waitDiv.html(wtext);
- wait= function(){
- waitDiv.css('display','inline-block');
- player.fire('waiting',{
- 'value': wtext || true
- }); //assures is a string or a true boolean
- };
- }else{
- wait = function(){
- waitDiv.hide();
- player.fire('waiting',{
- 'value':false
- });
- }
+ },
+
+ getWaitElement: function(){
+ return this.getContainer().find('.ts-control').find('.ts-wait');
+ },
+
+ //msg string: undefined: do nothing, empty: hide, otherwise show wait with html = msg
+ setWait: function(msg){
+ var wait = undefined;
+ // if(typeof msg == 'function'){
+ // wait = msg();
+ // if(wait){
+ // msg = wait.html();
+ // }else{
+ // return;
+ // }
+ // }else{
+ wait = this.getWaitElement();
+ if(!wait || msg === undefined){
+ return;
}
- var delay = 100;
- if(optionalCallback){
- wait();
- setTimeout(optionalCallback, delay);
- }else{
- //if there is no callback, delay the wait function in order to emulate a paraller thread
- //running:
- setTimeout(wait, delay);
+ if(wait.html()!=msg){
+ wait.html(msg);
+ }
+ // }
+
+ var visible = wait.css('display') != 'none';
+
+ if(msg && !visible){
+ wait.show();
+ this.fire('waitShown');
+ }else if(!msg && visible){
+ wait.hide();
+ this.fire('waitHidden');
}
},
if (height) {
- //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css
- var elements = wave.find('.ts-image-container').css('zIndex','0')
- .add(wave.find('.ts-image-canvas').css('zIndex','1')); //the two children of ts-wave. Set also the zIndex
- //in order to visualize the canvas OVER the wav image
+ //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css
+ var elements = wave.find('.ts-image-container').css('zIndex','0')
+ .add(wave.find('.ts-image-canvas').css('zIndex','1')); //the two children of ts-wave. Set also the zIndex
+ //in order to visualize the canvas OVER the wav image
- //elements.css('width', 'auto'); // for IE6. We leave it although IE6 is not anymore supported
- var style = {
- width: wave.width(),
- height: height
- }
- elements.css(style);
- elements.css('position','absolute');
+ //elements.css('width', 'auto'); // for IE6. We leave it although IE6 is not anymore supported
+ var style = {
+ width: wave.width(),
+ height: height
+ }
+ elements.css(style);
+ elements.css('position','absolute');
}
this.refreshImage();
this.getRuler().resize();
-
-
-//
-// if (!height) {
-// //this.debug('ERROR: image height is zero in player.,resize!!!!')
-// //height = image.height();
-// //if (!height){
-// height = 1; //200;
-// wave.css('minHeight',height+'px');
-// //}
-// }
-// //set image, imagecontainer and canvas (container on imagecontainer for lines and pointer triangles) css
-// var elements = wave.find('.ts-image-container').css('zIndex','0')
-// .add(wave.find('.ts-image-canvas').css('zIndex','1')); //the two children of ts-wave. Set also the zIndex
-// //in order to visualize the canvas OVER the wav image
-//
-// elements.css('width', 'auto'); // for IE6. We leave it although IE6 is not anymore supported
-// var style = {
-// width: wave.width(),
-// height: height
-// }
-// elements.css(style);
-// elements.css('position','absolute');
-//
-// //refreshing images:
-//
-// this.refreshImage();
-// this.getRuler().resize();
-//
-// return this;
},
getImageUrl : function(){
var image = this.getContainer().find('.ts-image');
var container = this.getContainer();
var imageC = container.find('.ts-image-container');
var image = imageC.find('.ts-image');
- // if(optionalImageAsJQueryElement){
- // image = optionalImageAsJQueryElement;
- // }else{
- // image = container.find('.ts-image');
- // }
-
- //consolelog(this);
+
var size = this.getImageSize();
if(!size.width || !size.height){
- consolelog('size is zero!!!!');
return;
}
var imgSrc = this.imageCallback(size.width,size.height);
}
var player= this;
- var waitString = 'refreshing img';
- player.setWait.apply(player,[waitString]);
-
+ //var waitString = 'refreshing img';
if(imageNotYetCreated){
image = this.$J('<img/>');
'width':'100%',
'height':'100%'
}); // for IE7. Does not seem to hurt IE8, FF, Chrome
-
- image.load(function(){
- if(player.getWaitString()===waitString){
- //we could have started playback, which means that if the wait bar has a different text,
- //another method is responsible for hiding it and therefore MUST stay visible
- player.setWait.apply(player,[false]);
+
+ var updateWait = function(){};
+ var ir = player.msgs.imgRefreshing;
+ var we = player.getWaitElement();
+ if(ir && we){
+ updateWait = function(){
+ if(!player.playState || player.playState==3){
+ player.setWait('');
+ }
}
+ }
+ image.load(function(){
image.unbind('load');
if(imageNotYetCreated){
imageC.append(image.addClass('ts-image'));
}
+ updateWait();
+ player.isImgRefreshing = false;
+ player.fire('ImgRefreshed');
});
-
+ if(ir && we && (!this.playState || this.playState===3)){ //if loading (1) or buffering (2) do not update wait.
+ //If not playing (undefined or 0) playing (3) update wait
+ this.setWait(ir);
+ }
+ this.isImgRefreshing = true;
+ this.fire('ImgRefreshing');
image.attr('src', imgSrc);
},
//this is intended to be a private method, use setImageSize from outside the player object)
_setImageSize: function(width,height,jQueryContainerElement, jQueryWaveElement, resize){
if(width || height){
- consolelog('SETTING SIZE!!!');
var re = /(?:px|ex|em|%)$/;
if(width){
width+='';
map.remove(identifier);
}
},
+
+ moveMarker: function(identifier, newOffset){ //identifier can be an number (marker index) or a marker (the index will be aearched)
+ var map = this.getMarkerMap();
+ if(map){
+ //note that map.move does everything BUT moving visually a marker on the ruler
+// var r = this.getRuler();
+// var m = r.toArray()[identifier];
+// m.move(r.toPixelOffset(newOffset)); //TODO: check what happens here inside, no 'fire' hopefully...
+ map.move(identifier,newOffset);
+ }
+ },
+
getMarker: function(index){
var map = this.getMarkerMap();
if(map){
//and now add a binding to the map when we move a marker:
map.bind('move', function(data){
+ consolelog(data);
var from = data.fromIndex;
var to = data.toIndex;
- ruler.move.apply(ruler,[from,to]);
+ ruler.move.apply(ruler,[from,to,data.marker.offset]);
player.fire('markerMoved',data);
debug_('moved');
debug_(data);
*/
Timeside.classes.Ruler = Timeside.classes.TimesideArray.extend({
//init constructor: soundDuration is IN SECONDS!!! (float)
- init: function(viewer, soundDuration){
+ init: function(rulerContainer, waveContainer, soundDuration){
this._super();
- var cssPref = this.cssPrefix;
-
+ //var cssPref = this.cssPrefix;
+
this.getSoundDuration= function(){
return soundDuration;
};
-
- var waveContainer = viewer.find('.' + cssPref + 'image-canvas');
+
+ //var waveContainer = viewer.find('.' + cssPref + 'image-canvas');
this.debug( 'WAVECONTAINER?? LENGTH='+ waveContainer.length);
this.getWaveContainer =function(){
return waveContainer;
return waveContainer.width();
};
this.debug( 'init ruler: container width '+this.getContainerWidth());
-
+
//private function used in resize() defined below
- var container = viewer.find('.' + cssPref + 'ruler');
-
+ //var container = viewer.find('.' + cssPref + 'ruler');
+
this.getRulerContainer = function(){
- return container;
+ return rulerContainer;
}
},
+// init: function(viewer, soundDuration){
+// this._super();
+// var cssPref = this.cssPrefix;
+//
+// this.getSoundDuration= function(){
+// return soundDuration;
+// };
+//
+// var waveContainer = viewer.find('.' + cssPref + 'image-canvas');
+// this.debug( 'WAVECONTAINER?? LENGTH='+ waveContainer.length);
+// this.getWaveContainer =function(){
+// return waveContainer;
+// };
+// //TODO: we dont need containerWiever here!!!
+// //better: it is usefult only for the canvas defined below. However...
+// this.getContainerWidth =function(){
+// return waveContainer.width();
+// };
+// this.debug( 'init ruler: container width '+this.getContainerWidth());
+//
+// //private function used in resize() defined below
+// var container = viewer.find('.' + cssPref + 'ruler');
+//
+// this.getRulerContainer = function(){
+// return container;
+// }
+// },
- colors:{}, //used to draw rulermarkers
+ //colors:{}, //used to draw rulermarkers
resize : function(){
var duration = this.getSoundDuration(); //in seconds
this.debug("Can't draw ruler with a duration of 0");
return;
}
+
var $J = this.$J;
var rulerContainer = this.getRulerContainer();
rulerContainer.append(firstSpan); //to calculate height, element must be in the document, append it
var verticalMargin = 1;
var h = 2*(verticalMargin+firstSpan.outerHeight());
+ //h is the default height of the ruler svg (according to ruler font size)
+ //to accomodate the necessary space for the labels
+ //however, if we set a custom height on the ruler, ie h2 is nonzero:
+ var h2 = rulerContainer.height();
+ //then, set the custom height as height for the canvas:
+ //note that, as markers and pointer have position: absolute, they do not affect div height
+ if(h2){
+ h = h2;
+ }
//TODO: set height in div ruler????
- rulerContainer.css('height',h+'px');
+ //rulerContainer.css('height',h+'px');
var obj = this.calculateRulerElements(rulerContainer.width(),h,firstSpan.outerWidth());
this.drawRuler(rulerContainer,h,obj.path);
this.each(function(i,rulermarker){
rulermarker.refreshPosition();
});
- //IE7 BUG: the viewer might not shift downwards after canvas is drawn and covers part of the rulrer.
- //Weird enough (with IE it isn't actually), we have just to set a dummy css top to zero
- //(which will be REALTIVE to ts-wave div normal flow, as ts-wave has position relative in order
- //to accomodate image and canvas absolutely positioned)
- //Basically, if we have to tell IE to do what it is supposed to do
- if(h > $J('.ts-wave').position().top){
- $J('.ts-wave').css('top',0+'px');
- }
+
},
//overridden: Note that the pointer is NOT cleared!!!!!
clear: function(){
var markers = this._super();
+ //now remove also the labels in the player ruler:
for( var i=0; i<markers.length; i++){
markers[i].remove();
}
return markers;
},
- //overridden TimesideArray methods (add, move, remove):
+
+ //overridden
remove: function(index){
var rulermarker = this._super(index);
rulermarker.remove();
rulermarker.setIndex(i, true);
});
},
- //overridden
- move: function(from, to){
+
+ //overridden: do not call directly this method, use markermap.move
+ move: function(from, to, newOffset){
var newIndex = this._super(from,to);
+ //update label if it is the case:
+ var rulermarker = this.toArray()[newIndex];
+ var pixelOffset = this.toPixelOffset(newOffset);
+ if(rulermarker.positionInPixels != pixelOffset){ //should not be the case if this method is called from a mouse event
+ rulermarker.move(pixelOffset);
+// consolelog('moved');
+// }else{
+// consolelog('nothing to move');
+ }
+
//this.debug('ruler.move: [from:'+from+', to:'+to+', real:'+newIndex+']');
if(newIndex!=from){
var i1 = Math.min(from,newIndex);
// var pointer = new RulerMarker($J(layout.get(0)),this.getWaveContainer(),markerClass);
- var pointer = new Timeside.classes.RulerMarker(this,this.getWaveContainer(),markerClass);
+ var pointerOrMarker = new Timeside.classes.RulerMarker(this,this.getWaveContainer(),markerClass);
//call super constructor
//if it is a pointer, dont add it
if(markerClass != 'pointer'){
- this._super(pointer,index); //add at the end
+ this._super(pointerOrMarker,index); //add at the end
//note that setText is called BEFORE move as move must have the proper label width
this.each(index, function(i,rulermarker){
rulermarker.setIndex(i,i!=index);
this.debug('added marker at index '+index+' offset: '+offset);
}else{
//note that setText is called BEFORE move as move must have the proper label width
- pointer.setText(this.makeTimeLabel(0));
+ pointerOrMarker.setText(this.makeTimeLabel(0));
}
//proceed with events and other stuff: move (called AFTER setText or setText)
- pointer.move(this.toPixelOffset(soundPosition));
+ pointerOrMarker.move(this.toPixelOffset(soundPosition));
//pointer.setText(markerClass== 'pointer' ? this.makeTimeLabel(0) : this.length);
//click on labels stop propagating. Always:
- var lbl = pointer.getLabel();
+ var lbl = pointerOrMarker.getLabel();
lbl.bind('click', function(evt){
evt.stopPropagation();
return false;
//if there are no events to associate, return it.
if(!isMovable){
- return pointer;
+ return pointerOrMarker;
}
//namespace for jquery event:
doc.bind('mousemove.'+eventId, function(evt){
var x = evt.pageX;
newPos = startPos+(x-startX);
- pointer.move(newPos);
+ pointerOrMarker.move(newPos);
//update the text if pointer
if(markerClass=='pointer'){
- pointer.setText(me.makeTimeLabel(me.toSoundPosition(newPos)));
+ pointerOrMarker.setText(me.makeTimeLabel(me.toSoundPosition(newPos)));
}
return false;
return false;
}
var data = {
- 'markerElement':pointer,
+ 'markerElement':pointerOrMarker,
'soundPosition': me.toSoundPosition.apply(me,[newPos]),
'markerClass':markerClass
};
return false;
});
- return pointer;
+ return pointerOrMarker;
},
}
this.length = me.length; //in order to match the javascript array property
},
- length:0, //implement it as public property to be consistent with Array length property. Be careful however to NOT TO modify directly this property!!!
+ //length:0, //implement it as public property to be consistent with Array length property. Be careful however to NOT TO modify directly this property!!!
//adds at the end of the array. If index is missing the object is appended at the end
add : function(object, index){
var array = this.toArray();
.ts-skin-lab .ts-player {
padding: 0;
- /*clear: both;
- background: white;*/
- /*padding-top: 10px;
- padding-bottom: 10px;*/
border: solid 1px #ADADAD;
margin-top: 2px;
}
-.ts-skin-lab .ts-player .ts-viewer {
+/*.ts-skin-lab .ts-player .ts-viewer {
margin: 0;
border: 0;
-}
+}*/
height: 130px;
}
-/*.ts-skin-lab .ts-player .ts-wave .ts-image {
- width: 360px;
- height: 130px;
- background: transparent;
-}*/
-
-/*.ts-skin-lab .ts-player {
- background: #3c4251;
-
- border: solid #b2b2b2 1px;
-}
-
-.ts-skin-lab .ts-player .ts-viewer {
- margin: 0 12px 10px 12px;
- border: solid 1px white;
-}*/
-
-.ts-skin-lab .ts-player .ts-viewer .ts-marker {
+/*.ts-skin-lab .ts-player .ts-viewer .ts-marker {*/
+.ts-skin-lab .ts-player .ts-ruler .ts-marker {
padding: 0 0.5em;
background: #e65911;
color: #FFF;
stroke-width:0;
}
-.ts-skin-lab .ts-player .ts-viewer a.ts-pointer {
+/*.ts-skin-lab .ts-player .ts-viewer a.ts-pointer {*/
+.ts-skin-lab .ts-player .ts-ruler a.ts-pointer {
color: #BB0000;
background-color: white;
padding: 0 0.5em;
border: solid 1px #BB0000;
text-decoration: none;
- /*background-color: #e7e7e7;
- border: 1px solid #3c4251; #a10006 !important;*/
-moz-border-radius: .3em !important;
-webkit-border-radius: .3em !important;
border-radius: .3em !important;
padding-right: 60px;
font-size: 80%;
color:white;
-}
-
-
-/*.ts-skin-lab .ts-player .ts-ruler{
- color: #c3c2cc;
- background-color: #2a3242;
-}*/
-
-/*canvas (svg). If svg is not supported, a parser in the palyer
-converts these values (nb: not all are supported) to specigic vml attributes. In this case, however, ONLY CLASSES WRITTEN
-ALONE ARE PARSED (eg ".ts-blabla, .ts-marker-canvas{...}" WILL NOT BE RECOGNIZED)*/
-
-/*ruler canvas (svg)"*/
-/*.ts-skin-lab .ts-player .ts-ruler .ts-svg-ruler-upper-rect{
- fill: #2a3242;
- stroke-width:0;
- stroke: #c3c2cc; to be sure...
-}*/
-/*.ts-skin-lab .ts-player .ts-ruler .ts-svg-ruler-lines{
- stroke-width:1;
- stroke:#9498a1;
-}*/
-/*class for the canvas (svg) associated to a marker.
-.ts-skin-lab .ts-player .ts-wave .ts-image-canvas .ts-svg-pointer-line {
- fill: #a10006;
- stroke-width:0;
-} */
-
-/*class for the canvas (svg) associated to a marker.*/
-/*.ts-skin-lab .ts-player .ts-wave .ts-image-canvas .ts-svg-marker-line {
- fill: #7290bc;
- stroke-width:0;
-}*/
\ No newline at end of file
+}
\ No newline at end of file