2010-12-13 4 views
8

J'essaye d'écrire une option de menu contextuel pour une de mes pages. Fondamentalement, une div est un clic droit, un menu d'options apparaît qui peut être utilisé pour effectuer des tâches.jQuery menu contextuel - trouver quel élément l'a déclenché

Mon problème est d'essayer de trouver l'élément d'origine qui a déclenché tout (c'est-à-dire le div qui a été cliqué avec le bouton droit de la souris).

Mon code jQuery est plus ou moins:

//this is what displays the context menu 
$('.outfeedPosition').bind("contextmenu", function (e) { 
    $('#contextMenu').css({ 
     top: e.pageY + 'px', 
     left: e.pageX + 'px' 
    }).show(); 

    //'this' is the element which was clicked by the user. 
    alert($(this).attr('id')); 

    return false; 
}); 



//this is the contextMenu's button handler. 
$('#ctxDelete').click(function() { 
    alert('delete was clicked, but i dont know by which element - so I dont know which one to delete'); 
}); 


<div id="contextMenu"> 
    <ul> 
     <li><a id="ctxInsert" href="#">Insert</a></li> 
     <li><a id="ctxEdit" href="#">Edit</a></li> 
     <li><a id="ctxDelete" href="#">Delete</a></li> 
    </ul> 
</div> 

- donc - je peux voir quel élément a créé l'événement lors de la première clic droit se produit. Mais pas lorsque l'élément de menu est cliqué. Je travaillais à tâtonner quelque chose ensemble en écrivant l'élément dans une zone de texte cachée quand on clique avec le bouton droit de la souris, puis en le lisant quand on clique sur l'une des options, puis en le supprimant quand le menu se ferme. Cela ne semble pas être l'approche idéale - et j'ai l'impression de manquer quelque chose de fondamental.

J'espère que vous verrez ce que j'essaie de faire. Je peux poster un exemple plus complet sur demande.

Répondre

6

Vous pouvez envisager d'utiliser les méthodes jQuery data storage.

Dans votre code de menu contextuel vous pouvez mettre:

$('.outfeedPosition').bind("contextmenu", function (e) { 
    $('#contextMenu').css({ 
     top: e.pageY + 'px', 
     left: e.pageX + 'px' 
    }).show(); 

    //Store the item that was clicked 
    $("#contextMenu").data('originalElement', this); 

    return false; 
}); 

Ensuite, lorsque vous souhaitez référencer l'élément qui a initié le clic, vous pouvez simplement faire ceci:

$('#ctxDelete').click(function() { 
    var originalElement = $("#contextMenu").data('originalElement'); 
    alert('delete was clicked by ' + originalElement.id); 
}); 

Et mettre originalElement en la fonction jQuery $() pour accéder à la qualité jQuery. Peu importe où vous placez les données, n'importe quel élément DOM peut avoir des données associées. Vous pouvez stocker n'importe quoi - dans l'exemple de code ci-dessus, je stocke le HTMLElement brut (pas jQueryified) mais vous pouvez le stocker aussi si vous le souhaitez.

Voir ici pour un petit exemple: http://www.jsfiddle.net/jonathon/sTJ6M/

+1

Deux remarques: 1. Vous utilisez le moteur de sélection pour trouver l'élément #contextMenu plusieurs fois. Il serait raisonnable de mettre en cache cet objet jQuery: 'var $ contextMenu = $ (" # contextMenu ");' 2. Il pourrait être judicieux de se prémunir contre le fait que 'originalElement' ne soit pas défini, auquel cas' originalElement.id' serait lancer une erreur –

+1

Salutations Šime. Je suis d'accord avec vos arguments mais je n'étais pas trop concerné par le refactoring. Je ne faisais que glisser dans le code de l'OP et expliquer comment utiliser les méthodes de données. Dans ce cas, plutôt que de mettre en cache l'objet, vous pouvez simplement bénéficier de l'enchaînement et ne pas avoir besoin de la variable supplémentaire :) –

+0

Merci Jonathon, c'est exactement ce dont j'avais besoin! –

2

ajouter un champ caché et trouve en fonction du clic, comme ceci:

<div class="myItem"> 
    <div id="contextMenu"> 
     <ul> 
      <li><a id="ctxInsert" href="#">Insert</a></li> 
      <li><a id="ctxEdit" href="#">Edit</a></li> 
      <li><a id="ctxDelete" href="#">Delete</a></li> 
     </ul> 
    </div> 
    <input type="hidden" class="myID" value="1"> 
</div> 

puis avec JQuery

$('#ctxDelete').click(function() { 
    var id = $(this).closest('.myItem').find('.myID').val(); 
    alert('delete was clicked, by element with ID = ' + id); 
}); 
+0

Vous pouvez regarder les méthodes de stockage de données - il évite d'avoir à créer un type d'entrée cachée pour des choses comme cela (et vous permet d'enregistrer un objet, pas seulement des chaînes): http: //api.jquery.com/catégorie/divers/stockage de données/ –

+0

semble cool, mais le problème est .. il se déclenche quand un clic gauche est effectué .. +1 si :) –

+0

c'est le point n'est-ce pas? – Jason

2

Je suis un peu en retard à la fête ici, mais je trouve que lorsque le menu contextuel est généré l'élément actif obtient la classe « menu contextuel actif », a ajouté à lui. Cela peut seulement être dans des versions plus récentes. J'utilise le menu contextuel 1.6.6.

ajouter simplement:

var originalElement = $('.context-menu-active'); 

au gestionnaire de menu contextuel. Ici, il est combiné avec l'exemple de code.

$(function(e){ 
    $.contextMenu({ 
     selector: '.context-menu-one', 
     callback: function(key, options) { 
      var originalElement = $('.context-menu-active'); 
      var m = "clicked: " + originalElement[0].innerHTML; 
      window.console && console.log(m); 
     }, 
     items: { 
      "edit": {name: "Edit"}, 
      "cut": {name: "Cut"}, 
      "copy": {name: "Copy"}, 
      "paste": {name: "Paste"}, 
      "delete": {name: "Delete"}, 
      "sep1": "---------", 
      "quit": {name: "Quit"} 
     } 
    }); 

    $('.context-menu-one').on('click', function(e){ 
     console.log('clicked', this); 
    }) 
}); 
Questions connexes