From: riccardo Date: Thu, 16 Jun 2011 11:45:26 +0000 (+0200) Subject: fixed and checked code methods and minor bugs X-Git-Tag: 1.1~105 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=d16ded53f6f5c1b5ab3c3aebd0281984bb1493dc;p=telemeta.git fixed and checked code methods and minor bugs --- diff --git a/telemeta/htdocs/js/divmarker.js b/telemeta/htdocs/js/divmarker.js index 1b6b50e0..6d8e993a 100644 --- a/telemeta/htdocs/js/divmarker.js +++ b/telemeta/htdocs/js/divmarker.js @@ -61,34 +61,40 @@ Timeside.classes.MarkerMapDiv = Timeside.classes.TimesideArray.extend({ }, //overridden. Do not call explicitly, use marker map.move move: function(from, to, newOffset){ - + //call super method - var realIndex = this._super(from,to); + to = this._super(from,to); + if(to<0){ + return -1; + } + //reflect the same changes in the document: var me = this.toArray(); - if(realIndex!=from){ - var div = me[realIndex]; //me has already been updated + if(to!=from){ + var div = me[to]; //me has already been updated div.detach(); var parent = this.div; - if(to==this.length){ + if(to==this.length-1){ + //consolelog('appending '+this.length+' '+parent.children().length+' '+to); parent.append(div); }else{ - this.$J( parent.children()[realIndex] ).before(div); + //consolelog('inserting '+this.length+' '+parent.children().length+' '+to); + this.$J( parent.children()[to] ).before(div); } } var t = this; var setIdx = t.setIndex; - this.each(Math.min(from,realIndex),Math.max(from,realIndex)+1, function(i, div){ + this.each(Math.min(from,to),Math.max(from,to)+1, function(i, div){ setIdx.apply(t,[div,i]); }); - this.setOffset(me[realIndex],newOffset); + this.setOffset(me[to],newOffset); //TODO: create a function? - this.setEditMode(realIndex,true); - this.setFocus(realIndex,true); - return realIndex; + this.setEditMode(to,true); + this.setFocus(to,true); + return to; }, //overridden remove : function(index){ diff --git a/telemeta/htdocs/js/playerLoader.js b/telemeta/htdocs/js/playerLoader.js index 30fb55c8..9f9808e7 100644 --- a/telemeta/htdocs/js/playerLoader.js +++ b/telemeta/htdocs/js/playerLoader.js @@ -315,7 +315,7 @@ function loadPlayer(analizerUrl, soundUrl, soundImgSize, itemId, visualizers, cu $J('#analyzer_div_id').find('table').find('tbody:last').append(analyzerContentArray.join("")); //setting up the select tag - + player.bind('waitShown', function(data){ visualizersSelectElement.hide(); }); @@ -338,8 +338,11 @@ function loadPlayer(analizerUrl, soundUrl, soundImgSize, itemId, visualizers, cu 'top':margin+'px', 'right':margin, 'margin':0 - }).hide(); //hide it to be sure. We could check player.isImgRefreshing but we have to think about event queue... + }); + if(player.isImgRefreshing){ + visualizersSelectElement.hide(); + } 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 @@ -406,12 +409,20 @@ function loadPlayer(analizerUrl, soundUrl, soundImgSize, itemId, visualizers, cu } popupTimeoutId=undefined; popupShowFunction(data); - var index = data.index; - //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); + + var next = data.nextMarkerTimeInterval ? data.nextMarkerTimeInterval[0] :undefined; + if(next === undefined || next-data.currentSoundPosition > POPUP_TIMEOUT){ + popupTimeoutId = popupdiv.setTimeout('close',POPUP_TIMEOUT*1000); } + + //var index = data.index; + //consolelog('==='); + //consolelog(data.currentSoundPosition); + //consolelog(data.nextMarkerTimeInterval); + //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'); //consolelog(data.marker.title); @@ -462,3 +473,114 @@ function loadPlayer(analizerUrl, soundUrl, soundImgSize, itemId, visualizers, cu } + +/* +* Sets a "tab look" on some elements of the page. Takes at least 3 arguments, at most 5: +* 1st argument: an array (or a jquery object) of html elements, ususally anchors, representing the tabs +* 2nd argument: an array (or a jquery object) of html elements, ususally divs, representing the containers to be shown/hidden when +* clicking the tabs. The n-th tab will set the n-th container to visible, hiding the others. So order is important. Note that if tabs +* or container are jQuery objects, the html elements inside them are sorted according to the document order. That's why tabs and +* container can be passed also as javascript arrays, so that the binding n-th tab -> n-th container can be decided by the user +* regardeless on how elements are written on the page, if already present +* 3rd argument: the selected index. If missing it defaults to zero. +* 4th argument: selectedtab class. Applies to the selected tab after click of one tab. If missing, nothing is done +* 5th argument the unselectedtab class. Applies to all tabs not selected after click of one tab. If missing, nothing is done +* +* NOTE: The last 2 arguments are mostly for customizing the tab "visual look", as some css elements (eg, (position, top, zIndex) +* are set inside the code and cannot be changed, as they are mandatory to let tab anchor behave like desktop application tabs. Note also +* that every tab container is set to 'visible' by means of jQuery.show() +* +* Examples: +* setUpPlayerTabs([jQuery('#tab1),jQuery('#tab1)], [jQuery('#div1),jQuery('#div2)], 1); +* sets the elements with id '#tab1' and '#tab2' as tab and assign the click events to them so that clicking tab_1 will show '#div_1' +* (and hide '#div2') and viceversa for '#tab2'. The selected index will be 1 (second tab '#tab2') +*/ +function setUpPlayerTabs() {//called from within controller.js once all markers have been loaded. + //this is because we need all divs to be visible to calculate size. selIndex is optional, it defaults to 0 + // + + var $J = jQuery; + var tabs_ = arguments[0]; + var divs_ = arguments[1]; //they might be ctually any content, div is a shoertand + + //converting arguments to array: tabs + var tabs=[]; + if(tabs_ instanceof $J){ + tabs_.each(function(i,elm){ + tabs.push(elm); + }); + }else{ + tabs = tabs_; + } + //set the overflow property of the parent tab to visible, otherwise scrollbars are displayed + //and the trick of setting position:relative+top:1px+zIndices (see css) doesnt work) + $J(tabs).each(function(i,tab){ + var t = $J(tab).attr('href','#'); + t.show(); //might be hidden + //set necessary style for the tab appearence: + var overflow = t.parent().css('overflow'); + if(overflow && overflow != 'visible'){ + t.parent().css('overflow','visible'); + } + }); + //converting arguments to array: divs + var divs=[]; + if(divs_ instanceof $J){ + divs_.each(function(i,elm){ + divs.push(elm); + }); + }else{ + divs = divs_; + } + + //reading remaing arguments (if any) + var selIndex = arguments.length>2 ? arguments[2] : 0; + var selectedTabClass = arguments.length>3 ? arguments[3] : undefined; + var unselectedTabClass = arguments.length>4 ? arguments[4] : undefined; + + //function to be associate to every click on the tab (see below) + var tabClicked = function(index) { + for(var i=0; i oldIndex){ + 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); + + newIndex = this._super(oldIndex,newIndex); + + if(newIndex <0){ + this.debug('markermap.move: index out of bounds'); + return -1; + } var markers = this.toArray(); - var marker = markers[realIndex]; + var marker = markers[newIndex]; var oldOffset = marker.offset; marker.offset = newOffset; this.fire('move', { marker: marker, - index: realIndex, fromIndex: oldIndex, toIndex: newIndex, oldOffset: oldOffset diff --git a/telemeta/htdocs/timeside/js/player.js b/telemeta/htdocs/timeside/js/player.js index 30ad305c..df4b8b5b 100644 --- a/telemeta/htdocs/timeside/js/player.js +++ b/telemeta/htdocs/timeside/js/player.js @@ -380,7 +380,9 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ ruler.movePointer(newPositionInSeconds); } //set sound position: + var oldSoundPosition = this.soundPosition; this.soundPosition = newPositionInSeconds; + //resume playing if it was playing: if(wasPlaying){ var player = this; @@ -388,10 +390,11 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ //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); } + this.fire('soundPositionSet',{player:this,oldSoundPosition:oldSoundPosition}); + }, //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[ @@ -439,25 +442,30 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ var data = { //if you change data, change it also below index:idx, marker:marker, - timeMarginInSec: margin + currentSoundPosition: player.soundPosition, + nextMarkerTimeInterval: undefined }; fireOnMarkerPosition = function(seconds){ if(marker){ if(seconds>intervalLowerBound && seconds < intervalUpperBound){ - player.fire('markerCrossed',data); idx++; + marker = idx < len ? markers[idx] : undefined; + offs = marker ? marker.offset : undefined; + data.currentSoundPosition = seconds; + data.nextMarkerTimeInterval = marker ? [offs-margin, offs+margin] : undefined; + player.fire('markerCrossed',data); + if(idx= this.getSoundDuration()){ + playOptions.onfinish(); + }else{ + sound.setVolume(sound.volume); //workaround. Just to be sure. Sometimes it fails when we re-play + sound.play(playOptions); + } return false; }, @@ -619,10 +648,9 @@ Timeside.classes.Player = Timeside.classes.TimesideClass.extend({ if(sound){ var v = this.isPlaying(); sound.stop(); + var data = {player:this, oldPlayState:this.playState, endOfPlayback:false}; this.playState = 0; - this.fire('paused',{ - 'wasPlaying':v - }); + this.fire('playStateChanged',data); this.setWait(this.isImgRefreshing ? this.msgs.imgRefreshing : ''); } return false; diff --git a/telemeta/htdocs/timeside/js/ruler.js b/telemeta/htdocs/timeside/js/ruler.js index 211066d8..585c579e 100644 --- a/telemeta/htdocs/timeside/js/ruler.js +++ b/telemeta/htdocs/timeside/js/ruler.js @@ -282,9 +282,12 @@ Timeside.classes.Ruler = Timeside.classes.TimesideArray.extend({ //overridden: do not call directly this method, use markermap.move move: function(from, to, newOffset){ - var newIndex = this._super(from,to); + to = this._super(from,to); + if(to <0){ //no move (some error) + return -1; + } //update label if it is the case: - var rulermarker = this.toArray()[newIndex]; + var rulermarker = this.toArray()[to]; 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); @@ -294,14 +297,15 @@ Timeside.classes.Ruler = Timeside.classes.TimesideArray.extend({ } //this.debug('ruler.move: [from:'+from+', to:'+to+', real:'+newIndex+']'); - if(newIndex!=from){ - var i1 = Math.min(from,newIndex); - var i2 = Math.max(from,newIndex)+1; + if(to!=from){ + var i1 = Math.min(from,to); + var i2 = Math.max(from,to)+1; //this.debug('updating ['+i1+','+i2+']'); this.each(i1,i2, function(index,rulermarker){ rulermarker.setIndex(index, true); }); } + return to; }, //overridden //add(offset.-1) adds the pointer, isMovable is ingored diff --git a/telemeta/htdocs/timeside/js/timeside.js b/telemeta/htdocs/timeside/js/timeside.js index 05c051cd..aeb262d3 100644 --- a/telemeta/htdocs/timeside/js/timeside.js +++ b/telemeta/htdocs/timeside/js/timeside.js @@ -241,9 +241,12 @@ Timeside.classes.TimesideClass = Timeside.Class.extend({ fire : function(key, dataArgument){ var listenersMap = this.listenersMap; if(!(key in listenersMap)){ - this.debug('"'+key+'" fired but no binding associated to it'); + //this.debug('"'+key+'" fired but no binding associated to it'); return; } + if(arguments.length < 2 || !dataArgument){ + dataArgument = {}; + } var callbacks = listenersMap[key]; var len = callbacks && callbacks.length ? callbacks.length : 0; for(var i=0; i255 ? 255 :c)); - c = c.toString(16); - var len = c.length; - switch(len){ - case 1: - c = '0'+c; - break; - case 2: - break; - default: - return ''; - } - channels[j] = c; - } - return '#'+channels.join(''); - } - } - } - return ''; - } - +// getComputedStyle : function(_elem, _style){ +// var computedStyle; +// var $J = this.$J; +// if(_elem instanceof $J){ //note: '_elem instanceof this.$J' doesnt work. why?? +// _elem = _elem.get(0); +// } +// if (typeof _elem.currentStyle != 'undefined'){ +// computedStyle = _elem.currentStyle; +// }else{ +// computedStyle = document.defaultView.getComputedStyle(_elem, null); +// } +// return computedStyle[_style]; +// }, +// //returns a hex color from strColor. strColor can be one of the predefined css colors (eg, 'aliceBlue', case insensitive) +// //or rgb (eg: rgb(12,0,45)) or an hex color (eg, '#ff98a3' or '#f8g'). Leading and trailing spaces will be omitted, +// //case is insensitive, an empty string is returned in case of error (bad format string, parseInt errors etcetera..) +// color : function(strColor){ +// if(!strColor){ +// return ''; +// } +// strColor = strColor.replace(/(^\s+|\s+$)/g,'').toLowerCase(); +// if(!strColor){ +// return ''; +// } +// var predefined_colors = { +// aliceblue:"#f0f8ff", +// antiquewhite:"#faebd7", +// aqua:"#00ffff", +// aquamarine:"#7fffd4", +// azure:"#f0ffff", +// beige:"#f5f5dc", +// bisque:"#ffe4c4", +// black:"#000000", +// blanchedalmond:"#ffebcd", +// blue:"#0000ff", +// blueviolet:"#8a2be2", +// brown:"#a52a2a", +// burlywood:"#deb887", +// cadetblue:"#5f9ea0", +// chartreuse:"#7fff00", +// chocolate:"#d2691e", +// coral:"#ff7f50", +// cornflowerblue:"#6495ed", +// cornsilk:"#fff8dc", +// crimson:"#dc143c", +// cyan:"#00ffff", +// darkblue:"#00008b", +// darkcyan:"#008b8b", +// darkgoldenrod:"#b8860b", +// darkgray:"#a9a9a9", +// darkgrey:"#a9a9a9", +// darkgreen:"#006400", +// darkkhaki:"#bdb76b", +// darkmagenta:"#8b008b", +// darkolivegreen:"#556b2f", +// darkorange:"#ff8c00", +// darkorchid:"#9932cc", +// darkred:"#8b0000", +// darksalmon:"#e9967a", +// darkseagreen:"#8fbc8f", +// darkslateblue:"#483d8b", +// darkslategray:"#2f4f4f", +// darkslategrey:"#2f4f4f", +// darkturquoise:"#00ced1", +// darkviolet:"#9400d3", +// deeppink:"#ff1493", +// deepskyblue:"#00bfff", +// dimgray:"#696969", +// dimgrey:"#696969", +// dodgerblue:"#1e90ff", +// firebrick:"#b22222", +// floralwhite:"#fffaf0", +// forestgreen:"#228b22", +// fuchsia:"#ff00ff", +// gainsboro:"#dcdcdc", +// ghostwhite:"#f8f8ff", +// gold:"#ffd700", +// goldenrod:"#daa520", +// gray:"#808080", +// grey:"#808080", +// green:"#008000", +// greenyellow:"#adff2f", +// honeydew:"#f0fff0", +// hotpink:"#ff69b4", +// indianred:"#cd5c5c", +// indigo:"#4b0082", +// ivory:"#fffff0", +// khaki:"#f0e68c", +// lavender:"#e6e6fa", +// lavenderblush:"#fff0f5", +// lawngreen:"#7cfc00", +// lemonchiffon:"#fffacd", +// lightblue:"#add8e6", +// lightcoral:"#f08080", +// lightcyan:"#e0ffff", +// lightgoldenrodyellow:"#fafad2", +// lightgray:"#d3d3d3", +// lightgrey:"#d3d3d3", +// lightgreen:"#90ee90", +// lightpink:"#ffb6c1", +// lightsalmon:"#ffa07a", +// lightseagreen:"#20b2aa", +// lightskyblue:"#87cefa", +// lightslategray:"#778899", +// lightslategrey:"#778899", +// lightsteelblue:"#b0c4de", +// lightyellow:"#ffffe0", +// lime:"#00ff00", +// limegreen:"#32cd32", +// linen:"#faf0e6", +// magenta:"#ff00ff", +// maroon:"#800000", +// mediumaquamarine:"#66cdaa", +// mediumblue:"#0000cd", +// mediumorchid:"#ba55d3", +// mediumpurple:"#9370d8", +// mediumseagreen:"#3cb371", +// mediumslateblue:"#7b68ee", +// mediumspringgreen:"#00fa9a", +// mediumturquoise:"#48d1cc", +// mediumvioletred:"#c71585", +// midnightblue:"#191970", +// mintcream:"#f5fffa", +// mistyrose:"#ffe4e1", +// moccasin:"#ffe4b5", +// navajowhite:"#ffdead", +// navy:"#000080", +// oldlace:"#fdf5e6", +// olive:"#808000", +// olivedrab:"#6b8e23", +// orange:"#ffa500", +// orangered:"#ff4500", +// orchid:"#da70d6", +// palegoldenrod:"#eee8aa", +// palegreen:"#98fb98", +// paleturquoise:"#afeeee", +// palevioletred:"#d87093", +// papayawhip:"#ffefd5", +// peachpuff:"#ffdab9", +// peru:"#cd853f", +// pink:"#ffc0cb", +// plum:"#dda0dd", +// powderblue:"#b0e0e6", +// purple:"#800080", +// red:"#ff0000", +// rosybrown:"#bc8f8f", +// royalblue:"#4169e1", +// saddlebrown:"#8b4513", +// salmon:"#fa8072", +// sandybrown:"#f4a460", +// seagreen:"#2e8b57", +// seashell:"#fff5ee", +// sienna:"#a0522d", +// silver:"#c0c0c0", +// skyblue:"#87ceeb", +// slateblue:"#6a5acd", +// slategray:"#708090", +// slategrey:"#708090", +// snow:"#fffafa", +// springgreen:"#00ff7f", +// steelblue:"#4682b4", +// tan:"#d2b48c", +// teal:"#008080", +// thistle:"#d8bfd8", +// tomato:"#ff6347", +// turquoise:"#40e0d0", +// violet:"#ee82ee", +// wheat:"#f5deb3", +// white:"#ffffff", +// whitesmoke:"#f5f5f5", +// yellow:"#ffff00", +// yellowgreen:"#9acd32" +// }; +// var cl = predefined_colors[strColor]; +// if(cl){ +// return cl; +// } +// var pint = parseInt; +// //color parsers: note that the order is not random: we put first the most likely case ('#aaaaaa') and at last +// //the less one ('rgb(...)'), this might increase performances in most cases, especially if this method is called from +// //within a loop +// var color_defs = [ +// { +// re: /^#*(\w{2})(\w{2})(\w{2})$/, //example: ['#00ff00', '336699'], +// process: function (bits){ +// return [pint(bits[1], 16),pint(bits[2], 16),pint(bits[3], 16)]; +// } +// }, +// +// { +// re: /^#*(\w{1})(\w{1})(\w{1})$/, //example: ['#fb0', 'f0f'], +// process: function (bits){ +// return [pint(bits[1] + bits[1], 16),pint(bits[2] + bits[2], 16),pint(bits[3] + bits[3], 16)]; +// } +// }, +// { +// re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, //example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], +// process: function (bits){ +// return [pint(bits[1]), pint(bits[2]),pint(bits[3])]; +// } +// } +// +// ]; +// +// // search through the definitions to find a match +// var nan = isNaN; +// for (var i = 0; i < color_defs.length; i++) { +// var re = color_defs[i].re; +// var processor = color_defs[i].process; +// var bits = re.exec(strColor); +// if (bits) { +// var channels = processor(bits); +// if(channels.length ==3){ +// for(var j=0; j<3; j++){ +// var c = channels[j]; +// c = (nan(c) || c< 0 ? 0 : (c>255 ? 255 :c)); +// c = c.toString(16); +// var len = c.length; +// switch(len){ +// case 1: +// c = '0'+c; +// break; +// case 2: +// break; +// default: +// return ''; +// } +// channels[j] = c; +// } +// return '#'+channels.join(''); +// } +// } +// } +// return ''; +// } +// }); /** @@ -746,149 +749,64 @@ Timeside.classes.TimesideArray = Timeside.classes.TimesideClass.extend({ } return me.splice(0,l); }, - //moves the element from position [from] to position [to]. Shifts all elements - //from position [to] (inclusive) of one position. Note that the elemnt at position from is first removed - //and then inserted at position to. Therefore, - //if to==from+1 the element is not moved. Returns from if the element - //is not moved, i.e. either in the case above, or when: - //1) from or to are not integers or from or to are lower than zero or greater than the array length. - //in any other case, returns the index of the element moved, which is not necessarily to: - //It is, if tofrom+1) is to-1 + //moves the element at position from into position to + //the element that was at from will be at position to + //returns: + //-1 if from or to not integers, or from or to not within the array bounds (lower than zero or greater or equal to this.length) + //from if from === to (no move) + //to otherwise (move succesful) move : function(from, to){ + var pInt = parseInt; - if(pInt(from)!==from || pInt(to)!==to){ + if(pInt(from)!==from || pInt(to)!==to){ //just a check + return -1; + } + if(from === to){ return from; } var me =this.toArray(); var len = me.length; - if((from<0 || from>len)||(to<0 || to>len)){ - return from; - } - //if we moved left to right, the insertion index is actually - //newIndex-1, as we must also consider the removal of the object at index from - if(to>from){ - to--; - } - if(from != to){ - var elm = me.splice(from,1)[0]; - me.splice(to,0,elm); + if((from<0 || from>=len)||(to<0 || to>=len)){ + return -1; } + var elm = me.splice(from,1)[0]; + me.splice(to,0,elm); + return to; } + //moves the element from position [from] to position [to]. Shifts all elements + //from position [to] (inclusive) of one position. Note that the elemnt at position from is first removed + //and then inserted at position to. Therefore, + //if to==from+1 the element is not moved. Returns from if the element + //is not moved, i.e. either in the case above, or when: + //1) from or to are not integers or from or to are lower than zero or greater than the array length. + //in any other case, returns the index of the element moved, which is not necessarily to: + //It is, if tofrom+1) is to-1 +// move : function(from, to){ +// +// var pInt = parseInt; +// if(pInt(from)!==from || pInt(to)!==to){ +// return from; +// } +// var me =this.toArray(); +// var len = me.length; +// if((from<0 || from>len)||(to<0 || to>len)){ +// return from; +// } +// //if we moved left to right, the insertion index is actually +// //newIndex-1, as we must also consider the removal of the object at index from +// if(to>from){ +// to--; +// } +// if(from != to){ +// var elm = me.splice(from,1)[0]; +// me.splice(to,0,elm); +// } +// return to; +// } }); -/* -* Sets a "tab look" on some elements of the page. Takes at least 3 arguments, at most 5: -* 1st argument: an array (or a jquery object) of html elements, ususally anchors, representing the tabs -* 2nd argument: an array (or a jquery object) of html elements, ususally divs, representing the containers to be shown/hidden when -* clicking the tabs. The n-th tab will set the n-th container to visible, hiding the others. So order is important. Note that if tabs -* or container are jQuery objects, the html elements inside them are sorted according to the document order. That's why tabs and -* container can be passed also as javascript arrays, so that the binding n-th tab -> n-th container can be decided by the user -* regardeless on how elements are written on the page, if already present -* 3rd argument: the selected index. If missing it defaults to zero. -* 4th argument: selectedtab class. Applies to the selected tab after click of one tab. If missing, nothing is done -* 5th argument the unselectedtab class. Applies to all tabs not selected after click of one tab. If missing, nothing is done -* -* NOTE: The last 2 arguments are mostly for customizing the tab "visual look", as some css elements (eg, (position, top, zIndex) -* are set inside the code and cannot be changed, as they are mandatory to let tab anchor behave like desktop application tabs. Note also -* that every tab container is set to 'visible' by means of jQuery.show() -* -* Examples: -* setUpPlayerTabs([jQuery('#tab1),jQuery('#tab1)], [jQuery('#div1),jQuery('#div2)], 1); -* sets the elements with id '#tab1' and '#tab2' as tab and assign the click events to them so that clicking tab_1 will show '#div_1' -* (and hide '#div2') and viceversa for '#tab2'. The selected index will be 1 (second tab '#tab2') -*/ -function setUpPlayerTabs() {//called from within controller.js once all markers have been loaded. - //this is because we need all divs to be visible to calculate size. selIndex is optional, it defaults to 0 - // - - var $J = jQuery; - var tabs_ = arguments[0]; - var divs_ = arguments[1]; //they might be ctually any content, div is a shoertand - - //converting arguments to array: tabs - var tabs=[]; - if(tabs_ instanceof $J){ - tabs_.each(function(i,elm){ - tabs.push(elm); - }); - }else{ - tabs = tabs_; - } - //set the overflow property of the parent tab to visible, otherwise scrollbars are displayed - //and the trick of setting position:relative+top:1px+zIndices (see css) doesnt work) - $J(tabs).each(function(i,tab){ - var t = $J(tab).attr('href','#'); - t.show(); //might be hidden - //set necessary style for the tab appearence: - var overflow = t.parent().css('overflow'); - if(overflow && overflow != 'visible'){ - t.parent().css('overflow','visible'); - } - }); - //converting arguments to array: divs - var divs=[]; - if(divs_ instanceof $J){ - divs_.each(function(i,elm){ - divs.push(elm); - }); - }else{ - divs = divs_; - } - - //reading remaing arguments (if any) - var selIndex = arguments.length>2 ? arguments[2] : 0; - var selectedTabClass = arguments.length>3 ? arguments[3] : undefined; - var unselectedTabClass = arguments.length>4 ? arguments[4] : undefined; - - //function to be associate to every click on the tab (see below) - var tabClicked = function(index) { - for(var i=0; i