2017-01-14 2 views
0

Je me sens comme si c'est vraiment simple et j'ai un moment "bois pour les arbres", mais ce moment a duré plus d'un jour maintenant, il est donc temps d'obtenir de l'aide ! J'ai googlé cela et lu beaucoup de réponses SO, mais encore une fois, j'ai du mal à appliquer les réponses que j'ai vu à mon problème exact, sans doute en raison de mes propres lacunes.Accepter la fonction comme variable de plugin jQuery et les paramètres de retour

Pour illustrer le problème, j'ai ce plugin exemple de jQuery (j'ai essayé de créer un violon pour cela, mais ne sais pas comment inclure un externe plug-in à la page 'dans un violon):

(function ($) { 

    $.fn.test = function (options) { 
     var settings = $.extend({ 
      onItemClick: function() { }, 
      itemArray: new Array(), 
     }, options); 

     for (i = 0; i < settings.itemArray.length; i++) { 
      var $item = $("<li></li>"); 
      $item.html(settings.itemArray[i].itemLabel); 
      $item.click(function() { 
       settings.onItemClick.call(settings.itemArray[i]); 
      }); 
      this.append($item); 
     } 

     return this; 

    }; 

}(jQuery)); 

Comme vous pouvez le voir, j'accepte une fonction en tant que variable - onItemClick. J'ai omis le test que cela existe et est une fonction par souci de concision.

Ma page d'exemple ressemble à ceci:

<body> 
    <div> 
     <ul id="testList"></ul> 
    </div> 
</body> 
</html> 

<script type="text/javascript"> 
    $(function() { 

     var testDataArray = new Array(); 

     var itemLabel = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]; 
     var itemDate = ["2017-01-03", "2015-08-03", "2016-06-21", "2016-12-20", "2013-09-07"]; 

     for (i = 0; i < itemDate.length; i++) { 
      var testData = {}; 
      testData["itemLabel"] = itemLabel[i]; 
      testData["itemDate"] = itemDate[i]; 

      testDataArray[i] = testData; 
     }; 

     $("#testList").test({ 
      itemArray: testDataArray, 
      onItemClick: function (item) {     
       alert(item.itemLabel + ": " + item.item.Date); 
      } 
     }); 
    }) 
</script> 

Alors, quand je l'appelle le plug-in de ma page, je veux être en mesure de passer une fonction en tant que paramètre et être en mesure d'inclure des variables dans cette fonction qui sera rempli avec des valeurs réelles par le plugin. Ce dernier point est où je suis coincé.

Le code que j'ai écrit ne fonctionne pas tel quel. Sans surprise, il jette l'erreur

Impossible de lire la propriété « itemDate » undefined

parce settings.itemArray ne sait pas dans le cadre de la fonction que j'essaie de joindre à l'événement de clic l'article. Je comprends cela, je ne comprends tout simplement pas comment le faire correctement!

+0

créer [plunker] (https://plnkr.co) exemple – GProst

Répondre

1

Voici un extrait de travail.

vous étiez sur le bon chemin;

  1. j'avais ajouté un argument 'item' à la fonction de rappel onItemClick dans le plugin
  2. lorsque vous appelez une fonction à partir d'un plug-in de cette manière le premier argument devrait être undefined comme dans settings.onItemClick.call(undefined, itemToSend);
  3. votre plugin crée un certain nombre d'éléments de liste dans le dom, mais la fonction de clic d'origine n'a aucun moyen de différencier entre eux lorsque l'élément de tableau est choisi. pour cette raison tous revenaient comme arrayitem 5, donc dans cette version l'index de l'élément de liste est cliqué, et ceci est utilisé pour choisir l'élément de tableau, ou le contenu de l'élément de tableau pourrait être attaché au dom élément via l'attribut de données (comme commenté)
  4. votre fonction d'alerte appelé item.item.Date au lieu de item.itemDate
  5. la fonction de clic a été déplacé à l'extérieur de la boucle for et le sélecteur est associé avec le sélecteur principal du plug-in, pour permettre pour plusieurs listes

espérons que cela aide.

(function($) { 
 

 
    $.fn.test = function(options) { 
 
    var settings = $.extend({ 
 
     onItemClick: function(item) { 
 

 
     }, 
 
     itemArray: [], 
 
    }, options); 
 

 

 
    var arrayItems = settings.itemArray; 
 

 
    for (i = 0; i < arrayItems.length; i++) { 
 
     var $item = $("<li></li>"); 
 
     $item.html(arrayItems[i].itemLabel); 
 

 
     // $item.html(arrayItems[i].itemLabel).data('arrayItems', arrayItems[i]); 
 

 
     this.append($item); 
 
    } 
 
    $('li', this).click(function() { 
 
     var indx = $(this).index(), 
 
     itemToSend = arrayItems[indx]; 
 
     // var itemToSend = $(this).data('arrayItems'); 
 
     settings.onItemClick.call(undefined, itemToSend); 
 
    }); 
 
    return this; 
 

 
    }; 
 

 
}(jQuery)); 
 

 
// copy everything above to a separate file and call via html 
 

 

 
$(function() { 
 

 
    var testDataArray = []; 
 

 
    var itemLabel = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]; 
 
    var itemDate = ["2017-01-03", "2015-08-03", "2016-06-21", "2016-12-20", "2013-09-07"]; 
 

 
    for (i = 0; i < itemDate.length; i++) { 
 
    var testData = {}; 
 
    testData.itemLabel = itemLabel[i]; 
 
    testData.itemDate = itemDate[i]; 
 

 
    testDataArray[i] = testData; 
 
    }; 
 

 
    $("#testList").test({ 
 
    itemArray: testDataArray, 
 
    onItemClick: function(item) { 
 
     console.log(item.itemLabel + ": " + item.itemDate); 
 
    } 
 
    }); 
 
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 

 
<!-- <script src="/test.js"></script> --> 
 

 
<div> 
 
    <ul id="testList"></ul> 
 
</div>

+0

Merci beaucoup pour cela. Cette solution produit l'effet souhaité, avec l'événement click des éléments qui écrivent les valeurs de l'objet dans le tableau sur la console. Cependant, je ne pense pas que cela réponde à la question que j'essayais de poser - je ne l'ai probablement pas expliquée clairement! Dans mon exemple, le code qui affiche l'alerte est dans la page, pas le plugin, ce qui est critique. Ce que je veux, c'est que le plugin retourne l'élément en tant que variable que le développeur qui écrit la page pourrait utiliser comme bon lui semble. Ceci est un exemple de ce que j'essaie de faire: https://fullcalendar.io/docs/selection/select_callback/ –

+0

réponse éditée pour refléter. pas de changement au code, il suffit de déplacer le script du plugin vers un fichier différent et d'appeler via html. Les données de variable d'article sont transmises d'avant en arrière selon les besoins. votre fonction 'onItemClick' dans le script de la page est la même que la fonction de rappel que vous avez après je crois. Votre plugin est déjà écrit et structuré comme une fonction privée, donc que ce soit dans la même page ou appelé depuis un autre fichier, il fonctionnera tant qu'il est chargé avant l'appel du plugin. – Sam0

+0

Merci encore. J'ai réalisé que j'avais trop simplifié mon problème réel pour formuler cette question, au point que votre réponse, même si elle répond parfaitement au problème tel que je le pose, ne fonctionne pas vraiment dans mon code réel. Cependant, vous avez certainement mis une bonne piste - c'était la clé pour réaliser que je pouvais attacher le gestionnaire de clic après avoir rendu les éléments et référencer l'objet du tableau original. Ce que j'ai fini par faire est d'ajouter l'objet du tableau lié à chaque élément ("item", dans cet exemple) au .data() de l'élément DOM, ce qui facilite la référence ultérieure. –