2011-12-07 10 views
6

मैं वर्तमान में एक सेटिंग चर के साथ एक प्लगइन काम कर रहा हूं जो काफी गहरा है (कुछ स्थानों में 3-4 स्तर)। आम तौर पर स्वीकार jQuery प्लगइन पैटर्न के बाद मैं उड़ निम्नलिखित अंकन का उपयोग पर सेटिंग्स को संशोधित करने के उपयोगकर्ताओं के लिए एक आसान तरीका लागू किया है:jQuery प्लगइन - दीप विकल्प संशोधन

$('#element').plugin('option', 'option_name', 'new_value'); 

यहाँ कोड है कि मैं क्या अब विकल्प विधि के लिए उपयोग कर रहा हूँ के समान है।

option: function (option, value) { 
    if (typeof (option) === 'string') { 
     if (value === undefined) return settings[option]; 

     if(typeof(value) === 'object') 
      $.extend(true, settings[option], value); 
     else 
      settings[option] = value; 
    } 

    return this; 
} 

अब विचार करें मैं बहुत की तरह एक सेटिंग चर है:

var settings = { 
    opt: false, 
    another: { 
     deep: true 
    } 
}; 

मैं मैं निम्नलिखित संकेतन का उपयोग करने के लिए है deep सेटिंग में बदलाव करना चाहते हैं:

$('#element').plugin('option', 'another', { deep: false }); 

हालांकि, चूंकि अभ्यास में मेरी सेटिंग्स 3-4 स्तरों की गहरी हो सकती है, मुझे लगता है कि निम्नलिखित नोटेशन अधिक उपयोगी होगा:

$('#element').plugin('option', 'another.deep', false); 

हालांकि मुझे यकीन नहीं है कि यह कितना व्यवहार्य है, न ही इसे करने के बारे में कैसे जाना है। पहले प्रयास के रूप में मैंने प्रश्न में विकल्प को "ट्रैवर्स" करने का प्रयास किया और इसे सेट किया, लेकिन यदि मैंने अपना ट्रैवर्सिंग वैरिएबल सेट किया है तो यह मूल सेटिंग वैरिएबल में संदर्भों को सेट नहीं करता है।

option: function (option, value) { 
    if (typeof (option) === 'string') { 
     if (value === undefined) return settings[option]; 

     var levels = option.split('.'), 
      opt = settings[levels[0]]; 
     for(var i = 1; i < levels.length; ++i) 
      opt = opt[levels[i]]; 

     if(typeof(value) === 'object') 
      $.extend(true, opt, value); 
     else 
      opt = value; 
    } 

    return this; 
} 

एक और तरीका है कि कहने के लिए: traversing के बाद opt की स्थापना करके, यह स्थापित करने के लिए वास्तव में में settings चर अपरिवर्तित है इस कोड को चलाता है के बाद से है।

मैं लंबे प्रश्न के लिए क्षमा चाहता हूं, किसी भी मदद की सराहना की जाती है। धन्यवाद!


संपादित

मैं यह कर सकता एक दूसरा प्रयास का उपयोग कर के रूप में eval() तो जैसे:

option: function (option, value) { 
    if (typeof (option) === 'string') { 
     var levels = option.split('.'), 
      last = levels[levels.length - 1]; 

     levels.length -= 1; 

     if (value === undefined) return eval('settings.' + levels.join('.'))[last]; 

     if(typeof(value) === 'object') 
      $.extend(true, eval('settings.' + levels.join('.'))[last], value); 
     else 
      eval('settings.' + levels.join('.'))[last] = value; 
    } 

    return this; 
} 

लेकिन मैं वास्तव में अगर कोई मुझे के लिए एक रास्ता दिखा सकते हैं देखना चाहेंगे eval का उपयोग नहीं करें। चूंकि यह एक उपयोगकर्ता इनपुट स्ट्रिंग है, इसलिए मैं eval() नहीं चलाऊंगा क्योंकि यह कुछ भी हो सकता है। या मुझे बताएं कि क्या मैं पागल हो रहा हूं, और इससे कोई समस्या नहीं होनी चाहिए।

उत्तर

2

मुद्दा तुम यहाँ में चला रहे हैं वस्तुओं की ओर इशारा करते चर के बीच अंतर करने के लिए नीचे आता है और स्ट्रिंग्स जैसे अन्य प्रकारों के लिए चर।2 चर एक ही Object को इंगित कर सकते हैं, लेकिन एक ही String के लिए नहीं:

var a = { foo: 'bar' }; 
    var b = 'bar'; 
    var a2 = a; 
    var b2 = b; 
    a2.foo = 'hello world'; 
    b2 = 'hello world'; 
    console.log(a.foo); // 'hello world' 
    console.log(b); // 'bar' 

आपका ट्रेवर्सल कोड पाश के अंतिम यात्रा, जिस बिंदु पर opt ही मूल्य युक्त एक चर रहा है जब तक अच्छा काम करता है ऑब्जेक्ट settings.opt.another के अंदर deep के रूप में। इसके बजाय, अपने पाश ही समाप्त हो और इस स्तर opt पर एक key रूप levels के अंतिम तत्व का उपयोग करें, जैसे

var settings = { 
    another: { 
     deep: true 
    } 
    }; 

    var levels = 'another.deep'.split('.') 
    , opt = settings; 

    // leave the last element 
    var i = levels.length-1; 

    while(i--){ 
    opt = opt[levels.shift()]; 
    } 
    // save the last element in the array and use it as a key 
    var k = levels.shift(); 
    opt[k] = 'foobar'; // settings.another.deep is also 'foobar' 

ही Objectsettings.another के रूप में और k के लिए सूचक मूल्य 'deep'

+0

शानदार, संदर्भों पर भ्रम इस मुद्दे को ढंक रहा था। मेरे लिए वह सही करने के लिए धन्यवाद; मेरे पास आपके उत्तर के लिए धन्यवाद एक कार्य विधि है। – Chad

0

ट्रैवर्सल के बजाय eval का उपयोग करने के बारे में कैसे?

var settings = { 
opt: false, 
    another: { 
deep: true, 

    } 
}; 

var x = "settings.another"; 
eval(x).deep = false; 
alert(settings.another.deep); 
+1

के साथ एक String है मैं उपयोगकर्ता इनपुट स्ट्रिंग पर 'eval' का उपयोग करने से बचने की कोशिश कर रहा था, क्योंकि इस तरीके से इसका उपयोग करके मेरी प्लगइन इंजेक्शन जावास्क्रिप्ट को स्वीकार करता है ... – Chad

+0

वैसे भी ब्राउज़र पक्ष पर कोई सुरक्षा नहीं है। कोई उपयोगकर्ता अपने इच्छित जेएस चला सकता है और कोई प्रश्न भेज सकता है। –

0

jQuery $().extend() में बनाया गया हैं वास्तव में आप क्या जरूरत नहीं हो सकता है?

http://api.jquery.com/jQuery.extend/

* कृपया ध्यान true के पहले agument साथ दूसरी विधि हस्ताक्षर एक गहरी मर्ज करता है ...

+0

सच है, लेकिन इसका मतलब है कि उसे उस वाक्यविन्यास का उपयोग करना होगा जिसे वह यहां बदलने की उम्मीद कर रहा है। लक्ष्य फ़ंक्शन पर स्ट्रिंग तर्क में उन बिंदुओं को डॉट नोटेशन के साथ एक्सेस करना है। –

+0

डैनियल की तरह, मैंने उपयोगकर्ता को ऑब्जेक्ट पास करने पर विस्तृत विधि का उपयोग कर रहा है, हालांकि उन्हें गहरी सेटिंग्स के लिए ऑब्जेक्ट पास करना है। मैं उन्हें एक स्ट्रिंग के विकल्प की अनुमति देने की कोशिश कर रहा हूं। – Chad

संबंधित मुद्दे