簡體   English   中英

如何創建同一JS對象的多個實例,分別控制CSS和DOM元素?

[英]how to create multiple instances of the same JS object controlling separate CSS and DOM elements?

我處於將對象創建為插件的早期階段,該插件創建並控制一組DIVINPUT元素。 目的是讓多個實例執行相同的操作,但每個實例僅適用於自己的DIV和INPUT。

如片段中的黃點所示,第一部分工作正常。

現在,只有當我創建第二個實例時,第一個(紅點)才停止工作。 第一個對象仍然存在,我可以尋址並設置其參數,只有應該管理的動畫已停止。 因此,當存在兩個對象時,新輸入的eventListener不能正常工作,或者我初始化該對象的方式是錯誤的。 在這里我需要幫助。

在繼續使對象的解析器變得更復雜之前,我會問這個問題,因為此后它應該解析並繪制更復雜的多個輸入。

如何正確分離兩個控制器實例?

片段:

 function randomButton(button_id){ if(button_id=='demo_1'){ while(MyObject_1.val()==MyObject_1.rand()){} } if(button_id=='demo_2'){ end = MyObject_2.rand(); start = (end-MyObject_2.rand()).toFixed(2); if(start<0){start=0;} MyObject_2.val(end+" , "+start); } } function alertObjectInfo(object){ text = ""; if (null == object || "object" != typeof object) return object; for (var attr in object) { if (object.hasOwnProperty(attr)) text += (object[attr]+"\\n"); } alert(text); } /* start of of the plug-in code */ var MyPlugin = ( function (element, id) { if(id===undefined){ // if no ID is provided genetate a hex string as ID id = ("OBJ-"+(new Date).getTime().toString(16)+"_"+(new Date).getMilliseconds().toString(16)); } element.addEventListener('change', function () { /* this part of the code will only run if the element input value is changed */ parser.input = this.value; parser.run(); object.draw(parser.result); }); defaults = []; defaults['size'] = 24; defaults['radius'] = 12; defaults['padding'] = 4; defaults['bgcolor'] = 'orange'; defaults['color'] = 'yellow'; defaults['transition'] = '1s'; /* the part below is the parser engine that converts the input */ parser = { input : null, result : null, mode : 'single', // default is single run : ( function( value ) { if(value){this.input = value;} // use value as new input if a value is provided if(this.mode==='single' || this.mode==false || this.mode===undefined){ // parse as a single floating point value this.mode = 'single'; // reset mode in case it was undefined this.result = parseFloat(this.input); if(this.result > 1){this.result = 1;} if(this.result < 0){this.result = 0;} return this.result; } if(this.mode==='double' || this.mode==2){ // parse as two seperete floating point values /* to be continued */ } }) }; /* the code below creates an object we can talk to and that will manage sprites */ var object = { id : id, // optional identifier string useful for debugging init : false, // the switch to test if initialise is already done element : element, // the html element we take out input from sprites : [], // the array of sprite elements generated by this object parser : parser, // the input parser engine /* the object's internal functions */ draw : function() { /* the main to draw and move all sprites */ if(this.init==false){alert('error: object is not properly initialised');return false;} this.sprites[1].style.width = (this.parser.result*100)+"%"; }, show : function() { /* the show all sprites function */ element.parentNode.style.display = 'inline'; }, hide : function() { /* the hide all sprites function */ element.parentNode.style.display = 'none'; }, val : function( value ) { /* the set or get value function */ if(value===undefined){ return element.value; }else{ element.value = value; element.dispatchEvent(new Event('change')); } }, rand : function( maxVal, minVal, decVal ) { /* create and set a random value */ if(minVal===undefined){minVal = 0;} // default minimum value if(maxVal===undefined){maxVal = 1;} // default maximum value if(decVal===undefined){decVal = 2;} // default decimal precision if(maxVal < minVal){ // invert minimum and maximum if incorrect offVal = maxVal; maxVal = minVal; minVal = offVal; } offVal = 1; // set or reset offVal for (i = 0; i < decVal; i++) { offVal = offVal/10; } r = (Math.random())*((maxVal+offVal)-(minVal)) + minVal; if(r>maxVal){r=maxVal;} p = Math.pow(10, decVal); r = Math.floor(r*p) / p; element.value = r; element.dispatchEvent(new Event('change')); return r; }, initialise : function() { if(this.init==false){ /* this part will initialise everything with default values once */ wrapper = element.parentNode; container = document.createElement("div"); container.style.backgroundColor = defaults['bgcolor']; container.style.height = defaults['size']+'px'; container.style.padding = defaults['padding']+'px'; container.style.boxSizing = 'border-box'; relativeRad = (defaults['size']/2)+'px'; container.style.borderRadius = (relativeRad+' '+relativeRad+' '+relativeRad+' '+relativeRad); wrapper.appendChild(container); this.sprites.push(container); mover = document.createElement("div"); mover.style.backgroundColor = 'inherit'; mover.align = 'right'; // not yet controled by defaults mover.style.width = '0%'; // start at 0% always mover.style.minWidth = (defaults['size']-(defaults['padding']*2))+'px'; mover.style.transition = defaults['transition']; container.appendChild(mover); this.sprites.push(mover); sprite = document.createElement("div"); sprite.style.backgroundColor = defaults['color']; sprite.style.height = (defaults['size']-(defaults['padding']*2))+'px'; sprite.style.width = (defaults['size']-(defaults['padding']*2))+'px'; sprite.style.minWidth = (defaults['size']-(defaults['padding']*2))+'px'; sprite.style.display = 'block'; sprite.style.boxSizing = 'border-box'; relativeRad = (defaults['size']/3)+'px'; sprite.style.borderRadius = (relativeRad+' '+relativeRad+' '+relativeRad+' '+relativeRad); sprite.style.transition = defaults['transition']; sprite.innerHTML = '&nbsp;'; mover.appendChild(sprite); this.sprites.push(sprite); this.init = true; return this.init; } } }; object.initialise(); return object; }); /* end of of the plug-in code */ /* MyPlugin init */ var MyObject_1 = new MyPlugin(document.getElementById("demo_input_1"),'Object_1'); var MyObject_2 = new MyPlugin(document.getElementById("demo_input_2"),'Object_2'); // test if we can address sprites of the first object after creating a second object MyObject_1.sprites[2].style.backgroundColor = 'red'; 
 .item-wrap{ background-color: #999; border:0; border-radius: 8px; padding: 16px; margin-bottom: 8px; } .demo_input{ border:0; color:white; font-size:18px; padding:8px; background-color:transparent; width:100%; box-sizing:border-box; text-align:left } .item-text{ border:0; color:white; font-size:18px; font-family:Avenir, Tahoma, sans-serif; padding-left:4px; padding-top:8px; width:100%; box-sizing:border-box; text-align:left } 
 <div class="item-wrap"> <div class="item-text"> <strong>Progress animation based on double values (Beta)</strong><br> <small>The first value still sends the animation to a relative point between 0 and 1. The second value streches the animated sprite to an offset starting point.</small><br> </div> <div id="demo_1_wrap" class="demo"> <input id="demo_input_2" class="demo_input" type="text" value="0 , 0"> </div> <p> <input type="button" name="show" value="show object" onClick="MyObject_2.show()"> <input type="button" name="hide" value="hide object" onClick="MyObject_2.hide()"> <input style="float:right" type="button" name="alert" value="alert object" onClick="alertObjectInfo(MyObject_2)"> <input type="button" name="rand" value="set random" id="demo_2" onClick="randomButton(this.id)"> </p> </div> <div class="item-wrap"> <div class="item-text"> <strong>Progress animation based on a single value input</strong><br> <small>The input value sends the animation to a relative point between 0 and 1. Empty or wrong input does nothing, where 1 or higher shows the animation at 100%</small><br> </div> <div id="demo_1_wrap" class="demo"> <input id="demo_input_1" class="demo_input" type="text" value="0"> </div> <p> <input type="button" name="show" value="show object" onClick="MyObject_1.show()"> <input type="button" name="hide" value="hide object" onClick="MyObject_1.hide()"> <input type="button" name="demo_" value="set random" id="demo_1" onClick="randomButton(this.id)"> <input style="float:right" type="button" name="alert" value="alert object" onClick="alertObjectInfo(MyObject_1)"> </p> </div> 

預期的結果是“ MyObject_1”將控制DIV標記為ID“ demo_1_wrap”的所有元素,第二個實例“ MyObject_2”將對DIV標記為ID“ demo_2_wrap”進行相同的控制。

IE 11也顯示了很多語法問題-為什么不使用常見的IIFE? (MDN上的IIFE),您的錯誤只是一個偵聽器參數 我的修復方法是至少在以下位置打開腳本

Line# in the script / new content
138  this.draw = function (){
179  this.show = function (){
182  this.hide = function (){
185  this.val = function(value) {
194  this.rand = function(maxVal, minVal,decVal) {
would tell no support for default parameters - maybe check for undefined(?)
214  this.initialize = function (){
219      this.container.style.padding = "${this.defaults['padding']}px";
(wrong quotations here)

這里根據最近的一些評論更改了代碼。 目前,此功能適用於Firefox 66,但使用的是舊版瀏覽器(例如Safari 9.1)時。 這段代碼在this.element.addEventListener('change', () => {

如何通過向后兼容來解決最后一個問題?

更新的代碼段:

 function processButton(button_id) { if (button_id == 'demo_1') { window.MyObject_1.val(window.MyObject_1.rand()); } if (button_id == 'demo_2') { var end = MyObject_2.rand(); var start = (end - MyObject_2.rand()).toFixed(2); if (start < 0) { start = 0; } window.MyObject_2.val(end + " , " + start); } if (button_id == 'color_2') { var r = window.MyObject_2.rand(0, 4096, 0).toString(16); window.MyObject_2.val(window.MyObject_2.val() + ' , color:#' + r); } if (button_id == 'label_2') { window.MyObject_2.val(window.MyObject_2.val() + ' , label:%'); window.MyObject_2.val(window.MyObject_2.val() + ' , labelcolor:black'); } } window.processButton = processButton; function alertObjectInfo(object) { text = ""; if (null == object || "object" != typeof object) return object; for (var attr in object) { if (object.hasOwnProperty(attr)) text += (object[attr] + "\\n"); } alert(text); } window.alertObjectInfo = alertObjectInfo; /* start of of the plug-in concept code */ var MyPlugin = function(element, id) { this.element = element; if (id === undefined) { // if no ID is provided genetate a hex string as ID this.id = (("OBJ_" + (new Date).getTime().toString(16) + "_" + (new Date).getMilliseconds().toString(16))); } else { this.id = id; } this.element.addEventListener('change', () => { /* this part of the code will only run if the element input value is changed */ this.parser.run(this.element.value); console.log(); this.draw(); }); this.defaults = []; this.defaults['size'] = 30; this.defaults['radius'] = 30; this.defaults['padding'] = 5; this.defaults['bgcolor'] = 'orange'; this.defaults['color'] = 'yellow'; this.defaults['transition'] = 888; // in milliseconds /* the part below is the parser engine that converts the input */ this.parser = { input: null, result: null, mode: null, run: (function(value) { if (value) { this.input = value; // use value as new input if a value is provided } /* auto detect parser mode based on input style */ if (this.input.indexOf("]") >= 0) { this.mode = 'cumulative'; } else if (this.input.indexOf(")") >= 0) { this.mode = 'nested'; } else if (this.input.indexOf(",") >= 0) { this.mode = 'multi'; } else { this.mode = 'single'; } this.result = [] if (this.mode === 'single' || this.mode == 1 || !this.mode) { // parse as a single floating point value this.mode = 'single'; // reset mode in case it was undefined this.result.push(parseFloat(this.input)); if (this.result[0] > 1) { this.result[0] = 1; } if (this.result[0] < 0) { this.result[0] = 0; } } if (this.mode === 'multi' || this.mode == 2) { // parse as seperate floating point values this.mode = 'multi'; // reset mode in case it defined as 2 let splitted; splitted = this.input.split(','); let opt = {}; for (var i = 0, len = splitted.length; i < len; i++) { if (i < 2) { this.result.push(parseFloat(splitted[i])); } else { // if more than 2 values the rest are option parameters let arr = (splitted[i]).split(':'); let key = arr[0].trim(); let str = arr[1].trim(); opt[key] = str; } } this.result[2] = opt; // add merged options to result } if (this.mode === 'nested' || this.mode == 3) { // parse as seperate floating point values this.mode = 'nested'; // reset mode in case it defined as 3 let splitted; /* to be continued */ } if (this.mode === 'cumulative' || this.mode == 4) { // parse as seperate floating point values this.mode = 'cumulative'; // reset mode in case it defined as 4 let splitted; /* to be continued */ } console.log(this.result); return this.result; }) }; this.init = false; this.sprites = []; this.draw = () => { /* the main function to draw and move all sprites */ if (this.init == false) { alert('error: object is not properly initialised'); return false; } console.log(this.sprites, this.parser.result) if (this.parser.mode === 'single') { this.sprites[1].style.width = (this.parser.result[0] * 100) + "%"; } if (this.parser.mode === 'multi') { let end = this.parser.result[0]; let start = this.parser.result[1]; var opt = this.parser.result[2]; let rel; if (end <= start) { rel = 0; } else { rel = ((end - start) / end).toFixed(2); } this.sprites[1].style.width = (end * 100) + "%"; this.sprites[2].style.width = (rel * 100) + "%"; // now process additional options if (!opt.label) { this.sprites[2].innerHTML = '&nbsp;'; } else { let label = opt.label.replace("%", (parseInt(100 * (end - start))) + ' %'); this.sprites[2].innerHTML = label; } // check for custom sprite color if (opt.color) { this.sprites[2].style.backgroundColor = opt.color; } // check for custom text color if (opt.labelcolor) { this.sprites[2].style.color = opt.labelcolor; } } } this.show = () => { this.element.parentNode.style.display = 'inline'; } this.hide = () => { this.element.parentNode.style.display = 'none'; } this.val = (value) => { if (!value) { return this.element.value; } else { this.element.value = value; this.element.dispatchEvent(new Event('change')); } } this.rand = (maxVal = 1, minVal = 0, decVal = 2) => { let offVal; if (maxVal < minVal) { offVal = maxVal; maxVal = minVal; minVal = offVal; } offVal = 1; for (i = 0; i < decVal; i++) { offVal = offVal / 10; } let r = (Math.random()) * ((maxVal + offVal) - (minVal)) + minVal; if (r > maxVal) { r = maxVal; } let p = Math.pow(10, decVal); r = Math.floor(r * p) / p; return r; } this.initialize = () => { if (!this.init) { this.wrapper = this.element.parentNode; this.container = document.createElement('div'); this.container.style.backgroundColor = this.defaults['bgcolor']; this.container.style.padding = `${this.defaults['padding']}px`; this.container.style.boxSizing = 'border-box'; let relativeRad = (this.defaults['size'] / 2) + 'px'; this.container.style.borderRadius = (relativeRad + ' ' + relativeRad + ' ' + relativeRad + ' ' + relativeRad); this.wrapper.appendChild(this.container); this.sprites = this.sprites.concat(this.container); this.mover = document.createElement('div'); this.mover.style.backgroundColor = 'transparent'; this.mover.align = 'right'; this.mover.style.width = '0%' this.mover.style.minWidth = (this.defaults['size'] - (this.defaults['padding'] * 2)) + 'px'; this.mover.style.transition = parseInt(this.defaults['transition']) + 'ms'; this.container.appendChild(this.mover); this.sprites = this.sprites.concat(this.mover); this.sprite = document.createElement('div'); this.sprite.style.backgroundColor = this.defaults['color']; this.sprite.style.height = (this.defaults['size'] - (this.defaults['padding'] * 2)) + 'px'; this.sprite.style.width = (this.defaults['size'] - (this.defaults['padding'] * 2)) + 'px'; this.sprite.style.minWidth = (this.defaults['size'] - (this.defaults['padding'] * 2)) + 'px'; this.sprite.style.display = 'block'; this.sprite.style.boxSizing = 'border-box'; this.sprite.className += " sprite-text"; this.sprite.style.overflow = 'hidden'; this.sprite.style.textAlign = 'center'; this.sprite.style.top = (this.defaults['padding']); this.sprite.style.fontSize = parseInt(this.defaults['size'] - (this.defaults['padding'] * 3)) + 'px'; this.sprite.style.padding = (this.defaults['padding'] / 2); relativeRad = (this.defaults['size'] / 2) + 'px'; this.sprite.style.borderRadius = (relativeRad + ' ' + relativeRad + ' ' + relativeRad + ' ' + relativeRad); this.sprite.style.transition = parseInt(this.defaults['transition'] / 2) + 'ms'; this.sprite.innerHTML = '&nbsp;'; this.mover.appendChild(this.sprite); this.sprites = this.sprites.concat(this.sprite); this.init = true; return this.init; } } /* the part below finalizes the object setup */ this.initialize(); return this; }; /* end of of the plug-in code */ /* MyPlugin init */ window.MyObject_1 = new MyPlugin(document.getElementById("demo_input_1"), 'Object_1'); window.MyObject_2 = new MyPlugin(document.getElementById("demo_input_2"), 'Object_2'); // test if we can address sprites of the first object after creating a second object MyObject_1.sprites[2].style.backgroundColor = 'green'; 
 .item-wrap { background-color: #999; border: 0; border-radius: 8px; padding: 16px; margin-bottom: 8px; } .demo_input { border: 0; color: white; font-size: 18px; padding: 8px; background-color: transparent; width: 100%; box-sizing: border-box; text-align: left } .item-text { border: 0; color: white; font-size: 18px; font-family: Avenir, Tahoma, sans-serif; padding-left: 4px; padding-top: 8px; width: 100%; box-sizing: border-box; text-align: left } .sprite-text { font-family: Tahoma, sans-serif; text-align: center; } 
 <div class="item-wrap"> <div class="item-text"> <strong>Progress animation based on more values</strong><br> <small>The first value still sends the animation to a relative point between 0 and 1. The second value streches the animated sprite to an offset starting point.</small><br> </div> <div id="demo_1_wrap" class="demo"> <input id="demo_input_2" class="demo_input" type="text" value="0 , 0"> </div> <p> <input type="button" name="show" value="show object" onClick="window.MyObject_2.show()"> <input type="button" name="hide" value="hide object" onClick="window.MyObject_2.hide()"> <input type="button" name="rand" value="set random" id="demo_2" onClick="window.processButton(this.id)"> <input type="button" name="label" value="change color" id="color_2" onClick="processButton(this.id)"> <input style="float:right" type="button" name="label" value="show label" id="label_2" onClick="window.processButton(this.id)"> </p> </div> <div class="item-wrap"> <div class="item-text"> <strong>Progress animation based on a single input</strong><br> <small>The input value sends the animation to a relative point between 0 and 1. Empty or wrong input does nothing, where 1 or higher shows the animation at 100%</small><br> </div> <div id="demo_1_wrap" class="demo"> <input id="demo_input_1" class="demo_input" type="text" value="0" /> </div> <p> <input type="button" name="show" value="show object" onClick="window.MyObject_1.show()"> <input type="button" name="hide" value="hide object" onClick="window.MyObject_1.hide()"> <input type="button" name="demo_" value="set random" id="demo_1" onClick="window.processButton(this.id)"> </p> </div> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM