*/\r
\r
/**\r
- * class for showing non-modal dialogs such as popups or combo lists. Requires jQuery. If you're scared about the doc, scroll below to\r
- * see some examples.\r
+ * Class for showing non-modal dialogs such as popups or combo lists. Requires jQuery.\r
* This class builds an absolutely positioned div for popup forms, message dialogs or listitem popup (emilating the\r
- * <select> tag element popup).\r
+ * <select> tag element popup). If you're scared about the doc, scroll below to see some examples.\r
* Usage:\r
* var p = new PopupDiv(dictionary); p.show(); or simply new PopupDiv(dictionary).show();\r
* dictionary is an object with the following parameters (In brackets the default value if missing). None of them is mandatory, but\r
- * at least content should be specified (unless showing an empty div is what you want to get)\r
+ * at least the property 'content' should be specified, unless showing an empty div is what you want to get)\r
* content (""): the popup content. Can be:\r
- * a dictionnary of (key: val) pairs for form filling popup. Each pair represents a row in the popupm built as a div with\r
- * a string (key) followed by an input with value = val (the popup takes care of inputs horizontal alignement so there should be\r
- * no need of extra css).\r
- * The input is determined as follows:\r
- * val is boolean: checkbox input\r
- * val is an array of strings: select tag (non multi select)\r
- * otherwise: text input (with val.toString as value)\r
+ * 1) a dictionnary of key:val pairs (form filling popup). Each pair represents a row in the popup. The row will be a div with\r
+ * a <span> with innerHTML=key followed by an <input> with value = val. The popup takes care of <span>s and <input>s horizontal alignement so there should be\r
+ * no need of extra css). The type of <input> is determined as follows:\r
+ * a) val is boolean: <input type=checkbox>\r
+ * b) val is an array of strings: <select> tag (non multi select. Yes, it is not an <input> tag in the strict term...)\r
+ * c) otherwise: <input type=text> with val.toString as value\r
* If showOk is true (see below), a click on the ok anchor will trigger the popup onOk callback (see below) with\r
- * argument a dictionary of (key: val) pairs, where each val is the relative input value\r
- * an array of strings for listItem popup. Each array element represents a line of the popup (internally, an anchor with\r
- * inner html the array element value). A click on each anchor triggers the onOk callback (see onOk below)\r
- * a jQuery object: the content will be appended to the popup\r
- * otherwise: content.toString() will be set as the popup innerHTML\r
- * invoker (jQuery(window)): a jQuery object representing an html element. If invoker is a clickable element (anchor, input of type button or submit,\r
- * button), then the PopupDiv bounds will be placed according to invoker as if it was a popup list of a select tag. Otherwise, the popupdiv will be centered inside invoker. Note that\r
- * internally each popupdiv is appended to the body element, so it will be visually centered in invoker, it should not belong\r
- * to invoker children\r
+ * argument a dictionary of (key: <input> value) pairs\r
+ * 2) an array of strings for (list item popup). Each array element (string) S will be represented by a row of the popup (internally, an anchor with innerHTML=S). A click on each anchor triggers the onOk callback (see onOk below), with argument an object of the form {selIndex:N},\r
+ where N is the index of the anchor being clicked\r
+ * 3) a jQuery object: the content will be appended to the popup\r
+ * 4) otherwise: content.toString() will be set as the popup innerHTML\r
+ * In all of these cases, object inserted in the popup via the content property can be retrieved and manipulated via the popup.find method (same syntax as in jQuery)\r
+ * invoker (jQuery(window)): a jQuery object representing an html element. If invoker is:\r
+ * a clickable element (anchor, input of type button or submit, button), then the PopupDiv will behave as a <select> popuplist of invoker.\r
+ * Thus, when showing, the PopupDiv will calculate the available space nearby invoker to show up in the window corner next to invoker which best fits its size. In this case the parameter focusable (see below) is usually set to true\r
+ * Otherwise, the popupdiv will be centered inside invoker. Note that internally each popupdiv is appended to the body element, so it will\r
+ * be visually centered in invoker, it does not belong to invoker children (well, unless invoker is the jQuery('body') element). In this case the parameters bounds and/or boundsExact (see below) might be also specified\r
* bounds ({'top':0.25, 'left':0.25, 'right':0.25, 'bottom':0.25}): if invoker is a clickable element, it is ignored. Otherwise, specifies the\r
- * insets (margins) of the popup within invoker (internally, the popup has no margins, so bounds represents the distances from each window\r
- * size). Each bounds element can be in percentage of invoker size if lower than 1 (eg, bounds first element is 0.25: popup left margin is\r
- * 25% of invoker height, and so on) or as pixel measure (if greater than 1)\r
+ * insets (margins) of the popup within invoker (internally, the popup has no margins, so bounds represent the distances from each window\r
+ * size: top, left, right, bottom). Each bounds element can be in percentage of invoker size if lower than 1 (eg, bounds.left = 0.25: popup left margin is 25% of invoker width, and so on) or as pixel measure (if greater than 1)\r
* boundsExact (false): if invoker is a clickable element, it is ignored. Otherwise, specifies whether bounds (see above) should be a hint\r
* (maximum allowed margins) or an exact measure. In other words, with boundsExact the popup will have the size of the rectangle R\r
* determined by invoker size and bounds. Otherwise, the maximum popup size will be R, and if the popup size is included in R, it\r
- * will be centered in R.\r
+ * will be centered in R. NOTE: padding margin and border, if set via the property popupClass or popupCss (see below) might alter\r
+ * the real height and width of the rectangle (those properties are ADDED to the natural height/width of the popup)\r
* focusable (false): boolean. When true, the popup gains the focus when shown, and disappears when losses the focus\r
* (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 anchor whose\r
- * click will trigger the popup.onOk callback. This parameter should always be true for form filling popup (see content)\r
- * onOk (null): callback. callback to be executed when the ok button is pressed. The callback takes as argument a dictionary of the popup data.\r
- * which is not empty only if the popup was built as form filling or listitem popup (see content above). In this last two cases,\r
- * the data returned is a dictionnary of [key:value] pairs (form filling popup) or a dictionary with one key (selIndex) and the\r
- * selected index that was clicked. This parameter should be specified for form filling popup (see content). popup.close() is always called\r
- * after onOk callback is executed, but without triggering the onClose callback, if any (see below)\r
- * onShow (function): callback to be executed when the popup shows up\r
- * defaultCloseOperation ('hide'): specified what to do when popup.close() is called. 'remove' removes the html element from the document,\r
- * 'hide' or any other value simply call jQuery.hide() on the popup\r
- * onClose (null): callback to be executed when the popup .close() function is called. It includes the case when focusable=true and\r
- * the popup looses the focus BUT NOT when the ok button (if any) is pressed (see onOk above)\r
- * shadowOffset (4): the shadow offset. Each popup has a 'shadow' which renders a kind of 3d raised effect. Set to 0 if no shadow must be visualized\r
- * popupClass ("") [see note1]: the popup class, if any, in the same form as jQuery.addClass() argument (ie, it can include multiple classes separated by space).\r
- * The top and bottom divs (housing title and close anchor and ok button respectively) are not affected by this parameter\r
- * popupCss ({}) [see note1]: the popup css, if any, in the same form as jQuery.css() argument.\r
- * The top and bottom divs (housing title and close anchor and ok button respectively) are not affected by this parameter\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
+ * 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
+ * [A:E_value] of the dictionary. Elements with such attributes are automatically created when content (see above) is\r
+ * an object (form fill popup) or an array (listItem popup), but the user might provide its own custom implementation, for instance:\r
+ * popup.setContent("<input type='text' "+popup.getFormDataAttrName()+"='default value'/>");popup.showOk=true;\r
+ * After each onOk callback has been executed, popup.close() will be always called\r
+ * onShow (null): callback to be executed when the popup shows up\r
+ * defaultCloseOperation ('hide'): specified what to do when popup.close() is called. 'remove' calls jQuery.remove() on the popup, ie it removes the html element from the document, 'hide' or any other value simply call jQuery.hide() on the popup\r
+ * onClose (null): callback to be executed when the popup .close() function is called. The callback must take one argument (boolean) which\r
+ * denotes wether the popup is closing after the ok button has been pressed or not. On the other hand, the argument is false, e.g.,\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 anchor) will close the popup and trigger popup.close() (and associated callbacks bindings, if any)\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
* title (""): a parameter specifying whether the popup should have a title. The title will be placed on the top of the popup.\r
- * okButtonClass ('') [see note1]: the ok button (anchor) class, if showOk = true, in the same form as jQuery.addClass() argument (ie, it can include multiple classes separated by space).\r
- * okButtonTitle ('Ok'): self-explicatory\r
- * p.okButtonAlign ('right'): self explicatory. Takes the same argument as css text-align property\r
- * closeButtonClass ('') [see note1]: the close button (anchor) class, if showClose = true, in the same form as jQuery.addClass() argument (ie, it can include multiple classes separated by space).\r
- * closeButtonTitle ('x'): self- explicatory\r
- * titleClass ('') [see note1]: the title (inpuit of type text) class, if title is not empty, in the same form as jQuery.addClass() argument (ie, it can include multiple classes separated by space).\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
+ * 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
+ * listItemCss ('') [see note1+3]: 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
* fadeInTime ('fast'): the fade in time when popup.show() is called. See jQuery show for possible values (briefly, a number in milliseconds or the string 'fast' or 'slow')\r
* fadeOutTime (0): the fade out time when popup.close() is called. See jQuery show for possible values (briefly, a number in milliseconds or the string 'fast' or 'slow')\r
- * shadowOpacity (0.25): elf-explicatory. 1 means shadow completely black, 0 completely transparent (bascially, no shadow)\r
+ * shadowOpacity (0.25): self-explanatory. 1 means shadow completely black, 0 completely transparent (bascially, no shadow)\r
* zIndex (10000): the popup zIndex. Should be left untouched unless there are issues with other component with hight zIndex.\r
- * listItemClass ('') [see note1]: the list items css, valid only if the popup is a listitem popup (see content above),\r
- * in the same form as jQuery.addClass() argument (that is, can take multiple classes separated by space).\r
- * listItemCss ('') [see note1]: the list items css, valid only if the popup is a listitem popup (see content above),\r
- * in the same form as jQuery.addClass() argument (ie, a dictionary of key:value pairs).\r
*\r
* [note1] IMPORTANT: For every css or class parameter, some css styles might be overridden before showing the popup because they would interfere with the correct placement and\r
* appearence of the popup: surely, 'display', 'position' and 'visibility' are among them. Usually, also 'size' css properties\r
* such as width, height, left, right ectetera. Css and class parameters are useful for customizing the popup 'visually' (eg, colors, font,\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
*\r
- * EXAMPLES: given an anchor <a> (jQuery element)\r
+ * And finally, EXAMPLES:\r
+ * Given an anchor <a> (jQuery element)\r
* 1) show a popup when clicking <a> leaving the user choose among three oprions: 'banana', 'orange' and 'apple'. The popup will\r
* behave as a default popup hiding when it looses focus\r
* //setup parameters\r
* }\r
* //bind the click event of the anchor:\r
* a.click(function(){ new PopupDiv(dict).show();});\r
- * \r
+ *\r
* 1) show a popup when clicking <a> leaving the user choose the fruit as text. The popup will close either when ok or close are clicked\r
* //setup parameters\r
* var choices = {'yourFruit':'banana'}; //banana will be the default value when the popup shows\r
* var dict = {\r
* content: choices,\r
- * showClose: true, \r
+ * showClose: true,\r
* showOk: true,\r
* onOk: function(data){\r
* var fruitChosen = data['yourFruit'];\r
//we use an input rather than a span for two reasons:\r
//1: span with overflow:hidden have problems in vertical align with the close button in FF and IE\r
//2: if text title overlaps, with a span it is not selectable, with an input it is\r
- var header = $J('<div/>').append($J('<input/>')).append($J('<a/>').attr('href','#').click(function(){\r
+ //we however append a span to calculate the input width, not really ortodox I know. See setTitle (below)\r
+ var header = $J('<div/>').append($J('<a/>').attr('href','#').click(function(){\r
me.close();\r
return false;\r
- })); //.css('float','right');\r
+ })).append(' ').append($J('<div/>').css('clear','both')); //.css('float','right');\r
var container = $J('<div/>').css('overflow','auto');\r
var footer = $J('<div/>').append($J('<a/>').attr('href','#').click(function(){\r
me.trigger('ok',true);\r
return false;\r
}));\r
- header.find('*').add(footer.find('*')).css('display','none');\r
+ //header.find('*').add(footer.find('*')).css('display','none');\r
div.append(header).append(container).append(footer);\r
//defining immediately the method getDiv (because it is used below)\r
this.getDiv = function(){\r
return listeners;\r
}\r
\r
- \r
+\r
//setting static properties, if any.\r
- //The idea is that static PopupDiv properties SPP (eg, PopupDiv.shadowOffset = 5) should be added to the current PopupDiv\r
+ //The idea is that static PopupDiv properties SPP (eg, PopupDiv.shadowOffset = 5) must define default PopupDiv properties values\r
+ //and they should be added to the current PopupDiv\r
//instance prototype ONCE (properties in the prototype are shared between all PopupDiv instances)\r
//and then deleted from the PopupDiv function.\r
//The problem is how to access the prototype: nor __proto__ neither Object.getPrototypeOf(this) are cross browser\r
var k;\r
var staticProps = undefined;\r
for(k in PopupDiv){\r
- if(!staticProps){\r
- staticProps = {};\r
- }\r
var f = PopupDiv[k];\r
if(typeof f !== 'function'){ //do not assign functions (PopupDiv.function... might be used in future as\r
//static functions accessible from outside\r
+ if(!staticProps){\r
+ staticProps = {};\r
+ }\r
staticProps[k] = f;\r
}\r
}\r
} else {\r
// May break if the constructor has been tampered with:\r
// proto = this.constructor.prototype;\r
- //so we assign tis class BUT we DO NOT remove static properties\r
+ //so we assign static properties to this instance BUT we DO NOT remove static properties\r
proto = this;\r
remove = false;\r
}\r
\r
//populating the prototype object:\r
(function(p){\r
+ //in the functions below, this refers to the new Popup instance, not to the prototype\r
+\r
//private static variables\r
var $ = jQuery;\r
var w_ = window;\r
var d_ = document;\r
var wdw = $(w_);\r
var popupStaticId = 'popup_'+(new Date().getTime());\r
- //var doc = $(d_);\r
-\r
-\r
- //in the functions below, this refers to the new Popup instance, not to the prototype\r
-\r
-\r
\r
p.isClickElement = function(element){\r
return element && element.length==1 && element instanceof $ && element[0] !== w_ && element[0] !== d_ &&\r
return ret;\r
};\r
\r
- p.closeLater = function(millseconds){\r
- var me = this;\r
- setTimeout(function(){\r
- me.close();\r
- },millseconds);\r
- },\r
+ p.setTitle = function(title){\r
+ this.getDiv().children().eq(0).find(':title').eq(0).val(title);\r
+ }\r
\r
//methods:\r
p.find = function(argumentAsInJQueryFind){\r
- return $(this.getDiv().children()[1]).find(argumentAsInJQueryFind);\r
+ return this.getDiv().children().eq(1).find(argumentAsInJQueryFind);\r
};\r
\r
p.bind = function(eventName, callback){ //eventname: show, close or ok\r
for(i=0; i<callbacks.length; i++){\r
callbacks[i].apply(me,[data]);\r
}\r
- if(arguments.length>1 && arguments[1]){\r
- //workaround to remove listeners on close:\r
- if('close' in listeners){\r
- var v = listeners['close'];\r
- delete listeners['close'];\r
- this.close();\r
- listeners['close'] = v;\r
- }else{\r
- this.close();\r
- }\r
-\r
+ this.__okButtonHasBeenPressed = true;\r
+ this.close();\r
+ delete this['__okButtonHasBeenPressed'];\r
+ }else if(eventName == 'close'){\r
+ var okBHBP = this.__okButtonHasBeenPressed || false;\r
+ for(i=0; i<callbacks.length; i++){\r
+ callbacks[i].apply(me,[okBHBP]);\r
}\r
}else{\r
for(i=0; i<callbacks.length; i++){\r
if(content instanceof $){\r
container.append(content);\r
}else if(content instanceof Array){\r
- \r
+\r
var me = this;\r
//var name = this.getListItemName();\r
var input = $('<input/>').attr('type','hidden').attr(att,'selIndex');\r
setTimeout(function(){\r
var v = doc_.activeElement;\r
//console.log(v);\r
- if((v && $(v).attr(focusAttr)) || me.isClosing){\r
+ if((v && $(v).attr(focusAttr)) || me.__isClosing){\r
//if we are closing, we will call back this method which removes the focus attributes, bt meanwhile the\r
//timeout should execute\r
return;\r
return undefined;\r
};\r
\r
+ p.refresh = function(content, title){\r
+ var showing = this.isShowing();\r
+ var focusable = this.focusable;\r
+ if(content!==undefined){\r
+ this.setContent(content);\r
+ if(showing && focusable){\r
+ this.setFocusCycleRoot(this.focusable);\r
+ }\r
+ }\r
+ if(title!=undefined){\r
+ if(showing){\r
+ this.setTitle(title);\r
+ }else{\r
+ this.title = title;\r
+ }\r
+ }\r
+ if(!showing){\r
+ return; //show(), when called, will update size and other stuff written in this method here bwloe\r
+ }\r
+ var invoker = this.invoker;\r
+ if(this.isClickElement(invoker)){\r
+ this.setBoundsAsPopup(invoker, true);\r
+ }else{\r
+ this.setBoundsInside(invoker, this.bounds, this.boundsExact, true);\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
+ this.shadow(); //updates shadow\r
+ if(focusable){\r
+ this.getFirstFocusableElement().focus();\r
+ }\r
+ }\r
+\r
+ p.setTitle= function(title){\r
+ var subdiv = this.getDiv().children().eq(0);\r
+ var text = subdiv.contents().filter(function() {\r
+ return this.nodeType == 3;\r
+ });\r
+ var node = text.get(0);\r
+ if(!title){\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
+ }\r
+\r
+ p.isShowing = function(){\r
+ return this.getDiv().is(':visible');\r
+ };\r
+\r
p.show = function(){\r
var div = this.getDiv();\r
var me = this;\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
this.setFocusCycleRoot(this.focusable);\r
\r
var subdiv = div.children();\r
//configure buttons. Text and classes are added here cause might have been changed\r
var topDiv = $(subdiv[0]);\r
- var titleInput = topDiv.find(':text').eq(0); //$(':text') is equivalent to $('[type=text]') (selects all <input type="text"> elements)\r
var closeBtn = topDiv.find('a').eq(0);\r
+\r
if(!this.showClose && !this.title){\r
topDiv.hide();\r
}else{\r
topDiv.css({\r
- 'paddingBottom':'1em',\r
- 'whiteSpace': 'nowrap'\r
- }).show(); //add padding to bottom\r
+ 'paddingBottom':'0.25em'\r
+ }); //add padding to bottom\r
//warning: do NOT use real numbers such as 0.5ex cause browsers round it in a different manner\r
//whiteSpace is FUNDAMENTAL in calculating the popup div in case the title is the longest (max width) element\r
//in the popup div. We will set the same whitespace css also on the title (see below)\r
\r
+ if(this.titleClass && this.title){\r
+ topDiv.attr('class',this.titleClass);\r
+ this.titleClass='';\r
+ }\r
+\r
+\r
if(this.showClose){\r
- closeBtn.attr('class',this.closeButtonClass); //removes all existing classes, if any (see jQuery removeClass doc)\r
- closeBtn.html(this.closeButtonTitle);\r
- closeBtn.css({\r
- 'display':'inline-block',\r
- 'visibility':'visible',\r
- 'marginLeft':'1em'\r
+ closeBtn.css('marginLeft','0.5em').attr('class',this.closeButtonClass).html(this.closeButtonTitle).css({\r
+ 'display':'inline-block','float':'right'\r
//warning: do NOT use real numbers such as 0.5ex cause browsers round it in a different manner\r
//inline-block in order to retrieve/set width and height on the element\r
});\r
}else{\r
- closeBtn.css({\r
- 'margin':'0px'\r
- }).hide(); //margin:0 is to be sure, as afterwards we must span the title the whole popup width\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.val(this.title).attr('readonly','readonly').attr('class',this.titleClass).removeClass().css({\r
- 'display':'inline-block',\r
- 'backgroundColor':'transparent',\r
- 'padding': '0px',\r
- 'margin':'0px',\r
- 'border':'0px',\r
- 'visibility': this.title ? 'visible' : 'hidden',\r
- 'width':'',\r
- 'maxWidth':'1px' //it is too tricky to set the width of the input spanning the whole title (in case of long titles)\r
- //we might use a span, but we experienced problems in vertical align with the close button, as stated somewhere above.\r
- //Moreover, a long title messes up the calculations in popup mode:\r
- //a long title most likely determines the popup size, the latter the popup position, and once\r
- //positioned and sized the popup size determines the title width (in order to span the title or letting the close button be visible)\r
- //This is not robust at all and in fact it does not render the same popup position in all browsers.\r
- //So, finally, set the input to the minimum allowed width, This means that maxWidth and maxHeight\r
- //will be calculated based on the centraldiv dimensions, which is anyway the core div we want to properly visualize.\r
- //Moreover, this way title resizing does not interfeere with the position\r
- });\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
var bottomDiv = $(subdiv[2]);\r
//see note above about why we dont use okButton.is(':visible')\r
if(this.showOk){\r
bottomDiv.css({\r
- 'paddingTop':'1em',\r
+ 'paddingTop':'0.25em',\r
'textAlign':this.okButtonAlign\r
- }).show(); //add padding to bottom\r
+ }); //add padding to bottom\r
//warning: do NOT use real numbers such as 0.5ex cause browsers round it in a different manner\r
okButton.attr('class', this.okButtonClass); //removes all existing classes, if any\r
okButton.html(this.okButtonTitle);\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
+// 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
- 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
- //start with showing top and bottom if some elements are visible\r
\r
var invoker = this.invoker;\r
\r
- var sizeAsPopup = false;\r
if(this.isClickElement(invoker)){\r
this.setBoundsAsPopup(invoker, true);\r
- sizeAsPopup = true;\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
this.setBoundsInside(invoker, this.bounds, this.boundsExact, true);\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
- // var height = centralDiv.height();\r
- // if(sizeAsPopup && maxHeight<height){\r
- // centralDiv.css('maxHeight',maxHeight+'px');\r
- // }else{\r
- // centralDiv.css({\r
- // 'maxHeight': maxHeight+'px',\r
- // 'minHeight': maxHeight+'px'\r
- // });\r
- // }\r
- // //set central div max width ONLY IF NECESSARY:\r
- // var maxWidth = div.width();\r
- // var width = $(subdiv[1]).outerWidth(true);\r
- // if(sizeAsPopup && maxWidth<width){\r
- // centralDiv.css('maxWidth',maxWidth+'px');\r
- // }else{\r
- // centralDiv.css({\r
- // 'maxWidth': maxWidth+'px',\r
- // 'minWidth':maxWidth+'px'\r
- // });\r
- // }\r
-\r
-\r
-\r
- //creating shadow. REmove attributes tabindex (unnecessary) and especially focusAttr,\r
- //so that clicking tab key and setting the shadow focusable hides the popup. If one wants the shadow not to hide the popup. keep\r
- //focusAttr BUT insert shadow in the focus cycle root (see method)\r
- var shadow = div.clone(false,false).empty().css({\r
- 'backgroundColor':'#000',\r
- 'borderColor':'#000',\r
- 'visibility':'visible',\r
- 'zIndex':this.zIndex-1\r
- }).removeAttr('tabindex').removeAttr(this.getFocusAttr()).fadeTo(0,0).\r
- attr('id',this.getShadowDivId()) //for use in hide\r
- .insertAfter(div);\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
- var rect = me.getBounds.apply(me);\r
- shadow.css({\r
- 'left':(rect.x + me.shadowOffset)+'px',\r
- 'top':(rect.y + me.shadowOffset)+'px',\r
- 'width':(rect.width)+'px',\r
- 'height':(rect.height)+'px'\r
- }).fadeTo(me.fadInTime,me.shadowOpacity, function(){\r
+ shadow.fadeTo(me.fadInTime,me.shadowOpacity, function(){\r
var v = me.getFirstFocusableElement();\r
if(v){\r
v.focus();\r
});\r
}\r
\r
- div.hide().css('visibility','visible').show(this.fadInTime,function(){\r
+ div.show(this.fadInTime,function(){\r
postShowFcn();\r
});\r
};\r
+ //div must be visible\r
+ p.shadow = function(){\r
+ var shadow = $('#'+this.getShadowDivId());\r
+ var so = this.shadowOffset;\r
+ if(!so && shadow.length){\r
+ shadow.remove();\r
+ return $([]);\r
+ }else if(so){\r
+ var div = this.getDiv();\r
+ if(!shadow.length){\r
+ //creating shadow. Remove attributes tabindex (unnecessary) and especially focusAttr,\r
+ //so that clicking tab key and setting the shadow focusable hides the popup. If one wants the shadow not to hide the popup. keep\r
+ //focusAttr BUT insert shadow in the focus cycle root (see method)\r
+ shadow = div.clone(false,false).empty().css({\r
+ 'backgroundColor':'#000',\r
+ 'borderColor':'#000',\r
+ 'display':'block',\r
+ 'zIndex':this.zIndex-1\r
+ }).removeAttr('tabindex').removeAttr(this.getFocusAttr()).fadeTo(0,0).\r
+ attr('id',this.getShadowDivId()).insertAfter(div);\r
+ }\r
+ var rect = this.getBounds.apply(this);\r
+ shadow.css({\r
+ 'left':(rect.x + so)+'px',\r
+ 'top':(rect.y + so)+'px',\r
+ 'width':(rect.width)+'px',\r
+ 'height':(rect.height)+'px'\r
+ });\r
+ }\r
+ return shadow;\r
+ }\r
\r
p.setBoundsAsPopup = function(popupInvoker, isSizable){\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
+// var oldCss= isSizable ? undefined : this.setSizable();\r
\r
var shadowOffset = this.shadowOffset;\r
var windowRectangle = this.getBoundsOf(wdw); //returns the window rectangle\r
invokerOffset.top + invokerOuterHeight)\r
},isSizable);\r
\r
+ this.postSizeFcn();\r
+\r
+// if(oldCss){\r
+// div.css({\r
+// 'display':oldCss['display'],\r
+// 'visibility':oldCss['visibility']\r
+// });\r
+// }\r
\r
- if(oldCss){\r
- div.css({\r
- 'display':oldCss['display'],\r
- 'visibility':oldCss['visibility']\r
- });\r
- }\r
};\r
//places and resize the popupdiv inside parent\r
//padding is a dict {top:,left:,bottom:..,right:,...} measuring the distance of the popupdiv from the corners, so that\r
p.setBoundsInside = function(parent, pd, boundsExact, isSizable){\r
\r
var div = this.getDiv();\r
- var oldCss = isSizable ? undefined : this.setSizable();\r
+// var oldCss = isSizable ? undefined : this.setSizable();\r
+ \r
+ this.preSizeFcn();\r
+ isSizable = true;\r
\r
var bounds = this.getBoundsOf(parent);\r
-\r
+ \r
+ \r
var x=bounds.x;\r
var y = bounds.y;\r
var w = bounds.width\r
},isSizable);\r
\r
}\r
- //convert to percentage in order to keep same dimensions when zooming\r
\r
+ this.postSizeFcn();\r
\r
- if(oldCss){\r
- div.css({\r
- 'display':oldCss['display'],\r
- 'visibility':oldCss['visibility']\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 subdivsshow = subdivs.eq(1);\r
+ if(this.showClose || this.title){\r
+ subdivsshow = subdivsshow.add(subdivs.eq(0));\r
+ }\r
+ if(this.showOk){\r
+ subdivsshow = subdivsshow.add(subdivs.eq(2));\r
+ }\r
+ \r
+ subdivsshow.css({\r
+ 'overflow':'auto',\r
+ 'maxHeight':'',\r
+ 'maxWidth':'',\r
+ 'minHeight':'',\r
+ 'minWidth':'',\r
+ 'height':'auto',\r
+ 'width':'auto',\r
+ 'display':'block'\r
+ });\r
+ }\r
+ \r
+ p.postSizeFcn = function(){\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
+ var div = this.getDiv();\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({'overflow':'hidden', 'width':'100%'}); //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
+ //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
+ //same for width:\r
+ var maxWidth = div.width();\r
+ var width = centralDiv.outerWidth(true);\r
+\r
+ if(maxHeight<=0 || maxWidth<=0){\r
+ centralDiv.hide();\r
+ return;\r
+ }\r
+ \r
+ if(maxHeight<height){\r
+ centralDiv.css('maxHeight',maxHeight+'px');\r
+ }\r
+ \r
+ if(maxWidth<width){\r
+ centralDiv.css('maxWidth',maxWidth+'px');\r
+ }\r
+\r
};\r
\r
p.getBounds = function(){\r
}\r
};\r
\r
- p.isClosing = false;\r
p.close = function(){\r
- this.isClosing = true;\r
+ this.__isClosing = true;\r
this.setFocusCycleRoot(false);\r
var div = this.getDiv();\r
var shadow = $('#'+this.getShadowDivId());\r
\r
if(remove){\r
div.remove();\r
- //this is because all bindings will be removed, including blur events\r
- //we remove this.getFocusAttr() to reupdate focus cycle root when calling show again\r
}\r
\r
//restore event data on invoker, if any\r
var id = '_tmpHandlers'+me.getId();\r
if(me[id]){\r
var oldHandlers = me[id];\r
- delete me[id];\r
+ delete me[id];\r
me.invoker.unbind('click');\r
for(var k =0; k< oldHandlers.length; k++){\r
var h = oldHandlers[k];\r
}\r
}\r
\r
- me.isClosing = false;\r
+ delete me['__isClosing'];\r
me.trigger('close');\r
});\r
\r
};\r
\r
+ p.closeLater = function(millseconds){\r
+ var me = this;\r
+ setTimeout(function(){\r
+ me.close();\r
+ },millseconds);\r
+ },\r
\r
p.setSizable = function(){\r
//if false, just update the flag\r
});\r
//set the div invisible but displayable to calculate the size (callbackPreShow)\r
div.css({\r
- 'visibility':'hidden',\r
'maxWidth':'',\r
'maxHeight':'',\r
'minWidth':'',\r
}\r
\r
})(PopupDiv.prototype);\r
+\r
return false;
}
}
+
+
},
//functions for converting seconds (player unit) to milliseconds (sound manager unit) and viceversa:
toSec: function(milliseconds){
//resume playing if it was playing:
if(wasPlaying){
var player = this;
+
//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(){
var ruler = player.getRuler();
var sPosInMsec = player.toMsec(player.soundPosition);
- var waitDiv = this.getContainer().find('.ts-wait');
var bufferingString = 'buffering';
- //var forceWait = !imgWaitDisplaying || waitDiv.html() != bufferingString;
+ //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 fireOnMarkerPosition = function(seconds){}; //does nothing by default
+ var map = player.getMarkerMap();
+ var markerCrossListeners = player.listenersMap['markerCrossed'];
+
+ if(map && map.length && markerCrossListeners){
+ var idx = 0;
+ if(player.soundPosition>0){
+ idx = map.insertionIndex(player.soundPosition);
+ if(idx<0){
+ idx=-idx-1;
+ }
+ }
+ var len = map.length;
+ if(idx>-1 && idx < len){
+ var markers = map.toArray();
+ var marker = markers[idx];
+ var margin = 0.5; //1 second (0.5*2) of margin (before+after)
+ var offs = marker.offset;
+ var intervalUpperBound = offs+margin;
+ var intervalLowerBound = offs-margin;
+ var data = {index:idx,marker:marker};
+ fireOnMarkerPosition = function(seconds){
+ if(marker){
+ if(seconds>intervalLowerBound && seconds < intervalUpperBound){
+ player.fire('markerCrossed',data);
+ idx++;
+ if(idx<len){
+ marker = markers[idx];
+ offs = marker.offset;
+ intervalUpperBound = offs+margin;
+ intervalLowerBound = offs-margin;
+ data = {index:idx,marker:marker};
+ }else{
+ marker = undefined;
+ }
+ }
+ }
+ };
+ }
+ }
var playOptions = {
position: sPosInMsec,
whileplaying: function(){
player.soundPosition = sPosInSec;
ruler.movePointer(sPosInSec);
}
+ fireOnMarkerPosition(sPosInSec);
}
- // consolelog('currentState '+currentState+ ' nspc: '+numberOfSubsequentPlayCall);
-
- // if(buffering && (forceWait || !imgWaitDisplaying)){
- // imgWaitDisplaying = true;
- // forceWait = false;
- // player.setWait.apply(player,[bufferingString]);
- // }else if(!buffering && sPosInMsec < sPos){
- // //isBuffering seems to be true at regular interval, so we could be in the case
- // //that !buffering but is actually buffering and no sound is heard, so
- // //we add the condition sPosInMSec !=sPos as a "sound heard" condition
- // sPosInMsec = sPos;
- // var sPosInSec = toSec(sPos);
- // player.soundPosition = sPosInSec;
- // ruler.movePointer(sPosInSec);
- // if(imgWaitDisplaying){
- // player.setWait.apply(player,[false]);
- // imgWaitDisplaying = false;
- // }
- // }
},
onfinish: function() {
//whileplaying is NOT called onsinfish. We must update the pointer:
//if(sound && this.isPlaying()){
sound.stop();
this.setWait(false);
+ this.fire('paused');
return false;
},
isWaitVisible: function(){
//this.loadMarkers(callback);
this.loadMarkers(markersArray);
- //set the marker popup
- //functions to set the marker popup
- // var popupMarker = $J('<div/>').addClass('component').css({
- // 'dislay':'none',
- // 'position':'absolute',
- // 'zIndex':1000,
- // 'overflow':'auto',
- // 'display':'none' //TODO: remove this
- // //'backgroundColor':'#666'
- // });
- // $J('body').append(popupMarker);
- // var w = v.width();
- // var h = v.height();
- // var offs = v.offset(); //relative to the document
- // var width = parseInt(w/2);
- // var height = parseInt(h/2);
- // var margin = 5;
- // popupMarker.css({
- // 'left':(margin+offs.left+width)+'px',
- // 'top': parseInt(margin+offs.top)+'px',
- // 'width':width+'px',
- // 'height':height+'px'
- // });
- // popupMarker.html("<table style='width:100%'><tr><td>"+gettrans('title')+"</td><td class='title'></td></tr><tr><td>"+
- // gettrans('description')+"</td><td class='description'></td></tr></table>");
- // this.getMarkerPopup = function(){
- // return popupMarker;
- // }
- },
-
- showMarkerPopup: function(markerIndex){
- // var popup = this.getMarkerPopup();
- //
- // if(popup.attr('id') != 'markerpopup'+markerIndex){
- //
- // 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){
- // popup.attr('id','markerpopup'+markerIndex);
- // popup.find('.title').html(marker.title);
- // popup.find('.description').html(marker.desc);
- // if(!popup.is(':visible')){
- // popup.show('fast');
- // }
- // }
- // }
},
/**
elements.css(style);
elements.css('position','absolute');
-
-
//refreshing images:
this.refreshImage();
this.getRuler().resize();
-
-
- //adjusting select size:
- // var select = container.find('.ts-visualizer');
- // var imgWait = container.find('.ts-wait');
- //
- // //NOTE: some buttons might be hidden AFTER THIS METHOD HAS BEEN INVOKED
- // //Therefore, setting the width of select or imgWait is skipped for the moment.
- // select.css('fontSize','90%'); //this is to increase probability that the select width will fit the available space
- //
- // var control = container.find('.ts-control');
- // var maxHeight = control.height();
- // select.add(imgWait).css('maxHeight',(maxHeight-2)+'px'); //at least a margin left and top of 1 px (see below)
- //
- // var span = (maxHeight-select.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
- // select.css({
- // 'margin':'0px',
- // 'marginTop':span+'px',
- // 'marginLeft':span+'px'
- // });
- // var span2 = (maxHeight - imgWait.outerHeight())/2; //do not include margins in oputerHeight (we will set them to zero below)
- // imgWait.css({
- // 'margin':'0px',
- // 'marginTop':span2+'px',
- // 'marginLeft':span+'px'
- // })
-
-
return this;
},
getImageUrl : function(){
}
},
- // refreshImage: function(optionalImageAsJQueryElement){
- // var image;
- // var container = this.getContainer();
- // if(optionalImageAsJQueryElement){
- // image = optionalImageAsJQueryElement;
- // }else{
- // image = container.find('.ts-image');
- // }
- // var select = container.find('.ts-visualizer');
- // var funcImg = function(player_image_url, width, height){
- // var _src_ = null;
- // if (player_image_url && (width || height)) {
- // _src_ = player_image_url.replace('WIDTH', width + '').replace('HEIGHT', height + '');
- // }
- // return _src_;
- // };
- // var imageUrl = getVisualizers()[""+select.val()];
- // var imgSrc = funcImg(imageUrl, image.width(),image.height());
- // if(image.attr('src')==imgSrc){
- // return;
- // }
- //
- // var player= this;
- // player.setWait.apply(player,['refreshing image']);
- // image.load(function(){
- // player.setWait.apply(player,[false]);
- // select.show();
- // image.unbind('load');
- // });
- //
- // image.attr('src', imgSrc);
- //
- // },
-
getSoundVolume :function(){
var s = this.getSound();
return s ? s.volume : 0;
return false;
},
- // setSoundVolume: function(volume){
- //
- // if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest
- // //see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number
- // volume = 100;
- // }
- // if(volume<0){
- // volume = 0;
- // }else if(volume>100){
- // volume = 100;
- // }
- // var sound = this.getSound();
- // // if(sound.volume == volume){
- // // return;
- // // }
- // sound.setVolume(volume);
- // //update the anchor image:
- // var indices = [20,40,60,80,100,100000];
- //
- // var volumeElm = this.getContainer().find('.ts-volume');
- // for(var i=0; i <indices.length; i++){
- // if(volume<indices[i]){
- // var pos = -28*i;
- // pos = '0px '+ pos+ 'px'; //DO NOT SET !important as in FF3 DOES NOT WORK!!!!!
- // volumeElm.css('backgroundPosition',pos);
- // return;
- // }
- // }
- // // this.elements.volume.css('backgroundPosition','0px 0px !important')
- //
- // },
-
setSoundVolume: function(volume){
if(typeof volume != 'number'){ //note: typeof for primitive values, instanceof for the rest
//see topic http://stackoverflow.com/questions/472418/why-is-4-not-an-instance-of-number
var rulerAdd = ruler.add;
+ var debug_ = player.debug; //TODO: remove
if(markers){
//add markers to the map. No listeners associated to it (for the moment)
}
//add markers to ruler and div
map.each(function(i,marker){
- rulerAdd.apply(ruler,[marker.offset, i, 'isEditable' in marker ? marker.isEditable : false]);
+ //isEditable and id are added if not present
+ rulerAdd.apply(ruler,[marker.offset, i, marker.isEditable]);
});
}
- //BINDINGS:
- //
- //1) ADD
- //
- //add binding to the setMarker button (html anchor):
- // var setMarkerButton = player.getContainer().find('.ts-set-marker');
- //
- // var showAddMarkerButton = this.canAddMarker();
- // if(setMarkerButton){
- // if(showAddMarkerButton){
- // setMarkerButton.show().attr('href','#').unbind('click').bind('click', function(){
- // player.addMarker(player.getSoundPosition());
- // return false;
- // });
- // }else{
- // setMarkerButton.hide().unbind('click');
- // }
- // }
+
//the function above calls map.add:
//mapuiAdd.apply(mapUI,[data.marker, data.index,data.isNew]);
rulerAdd.apply(ruler,[data.marker.offset, data.index,data.marker.isEditable]);
player.fire('markerAdded',data);
- consolelog('add');
- consolelog(data);
+ debug_('add');
+ debug_(data);
});
//2) MOVE
var to = data.toIndex;
ruler.move.apply(ruler,[from,to]);
player.fire('markerMoved',data);
- consolelog('moved');
- consolelog(data);
+ debug_('moved');
+ debug_(data);
});
map.bind('remove',function(data){
ruler.remove.apply(ruler, [data.index]);
player.fire('markerRemoved',data);
- consolelog('removed');
- consolelog(data);
+ debug_('removed');
+ debug_(data);
});
}