From: riccardo Date: Mon, 16 May 2011 09:54:36 +0000 (+0200) Subject: fixed popupdiv and playlists popup X-Git-Tag: 1.1~190 X-Git-Url: https://git.parisson.com/?a=commitdiff_plain;h=8149d839ba7419f76cf4d5be09dd0c081a2439df;p=telemeta.git fixed popupdiv and playlists popup --- diff --git a/telemeta/htdocs/js/popupdiv.js b/telemeta/htdocs/js/popupdiv.js index fd04123b..01d99d95 100644 --- a/telemeta/htdocs/js/popupdiv.js +++ b/telemeta/htdocs/js/popupdiv.js @@ -41,12 +41,56 @@ function PopupDiv(){ } var k; - //setting static properties, if any: + + //setting static properties, if any. + //The idea is that static PopupDiv properties SPP (eg, PopupDiv.shadowOffset = 5) should be added to the current PopupDiv + //instance prototype ONCE (properties in the prototype are shared between all PopupDiv instances) + //and then deleted from the PopupDiv function. + //The problem is how to access the prototype: nor __proto__ neither Object.getPrototypeOf(this) are cross browser + //(see http://ejohn.org/blog/objectgetprototypeof/, which suggests to rewrite a global Object.getPrototypeOf(arg), which + //however does not work if arg constructor has been manipulated). Eventually, we do the following: + //Find a prototype variable P: P= Object.getPrototypeOf: is it NOT a function? then P = this.__proto__. Is it NOT an object? + //then P= this. + //Populate P, if P = this, we are assigning SPP to each new instance and NOT ONCE to the prototype object, which of course + //means that SPP's cannot be deleted after their first assignment. This requires more work and more memory consumption + //but it assures cross browser compatibility + + var staticProps = undefined; for(k in PopupDiv){ - this.__proto__[k] = PopupDiv[k]; - // consolelog(k+' '+PopupDiv[k]); - delete PopupDiv[k]; + if(!staticProps){ + staticProps = {}; + } + var f = PopupDiv[k]; + if(typeof f !== 'function'){ //do not assign functions (PopupDiv.function... might be used in future as + //static functions accessible from outside + staticProps[k] = f; + } } + if(staticProps){ + var remove = true; + var proto = undefined; + if ( typeof Object.getPrototypeOf !== "function" ) { + if ( typeof this.__proto__ === "object" ) { + proto = this.__proto__; + } else { + // May break if the constructor has been tampered with: + // proto = this.constructor.prototype; + //so we assign tis class BUT we DO NOT remove static properties + proto = this; + remove = false; + } + }else{ + proto = Object.getPrototypeOf(this); + } + for(k in staticProps){ + proto[k] = staticProps[k]; + if(remove){ + delete PopupDiv[k]; + } + } + } + + //setting instance-specific properties: for(k in data){ @@ -124,14 +168,19 @@ function PopupDiv(){ p.fadeOutTime = 0, p.shadowOpacity = 0.25; p.zIndex = 10000; - // p.listItemClass = ''; + p.listItemClass = ''; + p.listItemCss = ''; + //returns the data associated to this popup. Basically, it searches for all input, select or textarea with attribute + //this.getFormDataAttrName(). The use of a custom attribute is cross browser, note that some attributes, eg name, are + //not (name is not safe in IE for instance) p.getFormData = function(){ var elms = this.find('input,select,textarea'); var ret = {}; + var att = this.getFormDataAttrName(); elms.each(function(i,e){ var ee = $(e); - var key = ee.attr('name'); + var key = ee.attr(att); if(key){ ret[key] = ee.val(); } @@ -208,14 +257,14 @@ function PopupDiv(){ var container = $($(div).children()[1]); //div.appendTo('body'); //necessary to properly display the div size container.empty(); - + var att = this.getFormDataAttrName(); if(content instanceof $){ container.append(content); }else if(content instanceof Array){ - var jQ = $; + var me = this; //var name = this.getListItemName(); - var input = $('').attr('type','hidden').attr('name','selIndex'); + var input = $('').attr('type','hidden').attr(att,'selIndex'); var setEvents = function(idx,anchor,input){ anchor.click(function(){ input.val(idx); @@ -225,31 +274,31 @@ function PopupDiv(){ input.val(idx); }) }; + var listItems = $([]); for(var h=0; h').attr('href','#'); - if('class' in item){ - a.addClass(item['class']); - } - if('html' in item){ - a.html(item['html']); - } - if('name' in item){ - a.attr('name', item['name']); - } - if('id' in item){ - a.attr('id', item['id']); - } - if('css' in item){ - a.css(item['css']); - } - a.css({ - 'display':'block', - 'margin':'2px' - }); //margin is used to display the outline (focus) + var a = $('').attr('href','#').html(""+item); + listItems = listItems.add(a); setEvents(h,a,input); container.append(a); } + //set css and class on all listitem anchor: + //set margin to properly display the outline (border focus) + //this css can be overridden (see lines below) as it is not strictly necessary + listItems.css({ + 'margin':'2px' + }); + if(this.listItemClass){ + listItems.addClass(this.listItemClass); + } + if(this.listItemCss){ + listItems.css(this.listItemCss); + } + //override css which are necessary to properly display the listItem: + listItems.css({ + 'position' : '', + 'display':'block' + }); container.append(input); }else if(content && content.constructor == Object){ var leftElements = $([]); @@ -277,11 +326,11 @@ function PopupDiv(){ title = $('').html(k); maxw[0] = max(maxw[0],k.length); maxw[1] = max(maxw[1],val.length); - component = $('').attr('type','text').val(val).attr('name',k); + component = $('').attr('type','text').val(val).attr(att,k); lineDivs = lineDivs.add(insert(title,component)); }else if(val === true || val === false){ var id = this.getId()+"_checkbox"; - title = $('').attr('type','checkbox').attr('name',k).attr('id',id); + title = $('').attr('type','checkbox').attr(att,k).attr('id',id); if(val){ title.attr('checked','checked'); }else{ @@ -293,7 +342,7 @@ function PopupDiv(){ }else if(val instanceof Array){ title = $('').html(k); maxw[0] = max(maxw[0],k.length); - component = $('').attr('size',1).attr(att,k); for(var i=0; i< val.length; i++){ component.append($('