ugrás a tartalomhoz

Jquery plugin probléma

C_hris · 2009. Jún. 7. (V), 09.03
Sziasztok!

Adott a következő kód

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">  
       
<head>

    <title></title>  
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>  
    <script>  
 
(function($){
var opts;
 
  //-----------------------------------------------
$.fn.plugintest = function(options)
       {
  opts = $.extend({}, $.fn.plugintest.defaults, options);

  return this.each(function()
        {
       
        $(this).bind("click",
          function(event)
       {                
        $.fn.dosomething( $(this) );
      });

    });
           
  };
 
  //-----------------------------------------------
  $.fn.dosomething = function(obj)
       {
       $(obj).css('color', opts.color);
       };
       
  //-----------------------------------------------
  $.fn.plugintest.defaults =
      {
      color    : 'blue'
      };
 
})(jQuery);
       
    </script>  
       
    <script type="text/javascript">  
    $(document).ready(function() {  
        $('#box1').plugintest();  
        $('#box2').plugintest( { color    : 'red' } );  
        $('#box3').plugintest( { color    : 'green' } );  
    });    
    </script>  
    <style>  
      body {font-family:arial;}  
    </style>  
</head>      
<body>  
 
<div id="box1">Box1</div>
<div id="box2">Box2</div>
<div id="box3">Box2</div>


 
</body>  
</html>


Miért van az, hogy ha kattintok a szövegekre akkor mindig zöld lesz annak ellenére, hogy különböző options lett megadva a paramétereknél.
 
1

Valahogy így...

Ustak · 2009. Jún. 7. (V), 10.12
Ha újra elolvasnám a cikkemet, biztos pontosan el tudnám magyarázni, és ha előkaparnám a könyvet a polcról, akkor is, de tömören a lényeg annyi, hogy a fenti kódodban mivel a javascript a változóra magára emlékszik, és nem a a változó értékére, ezért a lefutott kód után mindig az utolsó értéket fogja lehozni a click-re. Ezt most egy paraméter átadással (Z=i) és egy tömbbel megoldottam, de tuti van ügyesebb módja, remélem lesz aki megoldja optimálisabban:-)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"    
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">  
       
       <head>

           <title></title>  
               <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>  
                   <script>  
                    
                    (function($){
                        var opts = [];
                        var i=0;
                        //-----------------------------------------------
                        $.fn.plugintest = function(options) {
                            opts.push($.extend({}, $.fn.plugintest.defaults, options));
                            return this.each(function() {     
                                var z=i; 
                                $(this).bind("click", function(event) {                
                                            $.fn.dosomething( $(this),opts[z]);
                                        });
                                i++;
                                });
                                                     
                        };
                                                        
                        //-----------------------------------------------
                         $.fn.dosomething = function(obj,opts) {
                                $(obj).css('color',opts.color);
                        };
                        //-----------------------------------------------
                        $.fn.plugintest.defaults = {
                                color    : 'blue'
                        };
                    })(jQuery);
                           
                    </script>  
                                      
                    <script type="text/javascript">  
                    $(document).ready(function() {  
                    $('#box1').plugintest();  
                    $('#box2').plugintest( { color    : 'red' } );  
                    $('#box3').plugintest( { color    : 'green' } );  
                    });    
                    </script>  
                    <style>  
                    body {font-family:arial;}  
                    </style>  
                    </head>      
                    <body>  
                                                                 
                        <div id="box1">Box1</div>
                        <div id="box2">Box2</div>
                        <div id="box3">Box2</div>
                    </body>  
                    </html>
Üdv:
Gábor
2

...

C_hris · 2009. Jún. 7. (V), 10.46
Köszi.
Ezzel csak az a baj hogy mindig át kell adni az opts paramétert.

Úgy próbálkoztam még hogy átadtam a data-val az options-t minden elemnek, de biztos kell lennie szebb megoldásnak.

(function($){
var opts;
  //-----------------------------------------------
$.fn.plugintest = function(options)
    {
  opts = $.extend({}, $.fn.plugintest.defaults, options);

  return this.each(function()
        {
        $(this).data('opts', opts);  
       
        $(this).bind("click",
          function(event)
       {    
        $.fn.dosomething( $(this) );
      });

    });
           
  };
 
  //-----------------------------------------------
  $.fn.dosomething = function(obj)
       {
       color=$(obj).data('opts').color;
             
       $(obj).css('color', color);
       };
       
  //-----------------------------------------------
  $.fn.plugintest.defaults =
      {
      color    : 'blue'
      };
 
})(jQuery);
3

A data

Ustak · 2009. Jún. 7. (V), 10.53
szerintem jó ötlet, pillanatnyilag nem jut olyan eszembe, ahogy így vagy úgy ne kelljen újabb változót felhasználni.
4

A szép megoldás az, hogy

tgr · 2009. Jún. 7. (V), 16.08
A szép megoldás az, hogy átadod paraméterként, de ha ezt valamiért mindenáron el akarod kerülni, akkor használj cikluson belüli lokális változókat. Javascriptben egy függvény látja annak azt a scope-ot, ahol definiálták (ezt hívják úgy, hogy closure), tehát amikor pl. az alábbi példában kiiratod az i-t, akkor valójában a globális scope "i" nevű változójának aktuális értékét iratod ki ötször egymás után (amit az első for ciklus feltolt 5-re, és a kiiratások során végig annyi is marad):

var i, a = [];
for (i=0; i<5; i++) {
  a.push(function() {
    console.log(i);
  });
}

// eredmény: 5, 5, 5, 5, 5
for (var j=0; j<5; j++) {
  a[j]();
}
A megoldás az, hogy minden ciklusban létrehozol egy új változót, és azt adod át (nekem a példában ehhez kellett egy névtelen függvény, mert JS-ben a for ciklusnak nincs saját scope-ja; a te példádban az each() ezt megoldja). Ebben az esetben létrejön 5 névtelen függvény, mindegyiknek van egy k nevű változója, így kiiratáskor 5 különböző változót iratsz ki:

var i, a = [];
for (i=0; i<5; i++) {
  (function() {
    var k=i;
    a.push(function() {
      console.log(k);
    });
  })();
}

// eredmény: 0, 1, 2, 3, 4
for (var j=0; j<5; j++) {
  a[j]();
}
Vagyis a te esetedben az each()-nek paraméterül adott függvény elején kell valami var localopts = opts; parancs, és utána a localopts-ra hivatkozni. De closure-rel paraméterezni egy publikus függvényt roppant ronda megoldás szvsz.