插入优先点击功能?

时间:2013-12-11 07:41:47

标签: jquery

我有一个按钮,其中包含:

  • 内联onclick
  • 3附加点击处理程序:

实施例

<input id='b1' type='button' value='go' onclick='alert("0")';'/>
$("#b1").on('click',function (){alert('1');});
$("#b1").on('click',function (){alert('2');});
$("#b1").on('click',function (){alert('3');});

警告0,1,2,3。

但是如何在“自定义索引”中插入新的onclick

例如,让我们说我想在1,2的警报之间插入一个函数。

我该怎么做?

p.s:

控制内联onclick不是问题,我只需要使用attr并稍后执行。 对我来说问题是.on寄存器。我想过$.data("events")但它已被弃用,应该只用于调试建议。 (也 - 它的语法已经改变了。)

JSBIN

7 个答案:

答案 0 :(得分:6)

我写了small jQuery plugin声称这样做。

如何使用?

使用on jQuery函数(实际上是我的插件重写的),如下所示:

<script src="path/to/jQuery.js"></script>
<script src="path/to/jQuery-priorityze.js"></script>

<button id="go">Test 1</button>

<script>
  var $go = $("#go");
  $go.on('click', 5, function () { console.log('nice'); });
  $go.on('click', {priority: 4}, function () { console.log('a'); });
  $go.on('click', 6, function () { console.log('plugin?'); });
  $go.on('click', 1, function () { console.log('Is'); });
  $go.on('click', 3, function () { console.log('this'); });
  $go.on('click', 2, function () { console.log('not'); });
<script>

如果未提供优先级,插件将选择将1递增到最新提供的优先级的事件的优先级。

如何在您的示例中使用

  

我希望在不改变现有结构的情况下获得解决方案

在页面中加入我的插件并使用:

$("#b1").on('click', function (){alert('1');}); // 1
$("#b1").on('click', function (){alert('2');}); // 2
$("#b1").on('click', function (){alert('3');}); // 3

$("#b1").on('click', 1.5, function (){alert('4');}); // 1.5

// 0 -> 1 -> 4 -> 2 -> 3
// seems that onclick attribute is stronger that .on

function topPriority() {
  alert('top priority');
}

设置1.5优先级将最后一个处理程序放在第一个(1)和第二个(2)之间。 就像我评论onclick属性强于on jQuery函数。

UPDATED JSBIN

源代码

在Github上查看源代码here并检查测试。

别忘了给它上演明星:https://github.com/IonicaBizau/jQuery-prioritize :-)

它是如何工作的?

该插件与jQuery >= 1.8.x兼容,并使用$._data($el[0]).events,如here所述。

贡献

你想为这个项目做贡献吗?大!请按照以下步骤操作:

  1. 搜索in the repo issues您要修复的问题。
  2. 如果您要添加未添加为问题的新功能,请先将其添加到问题列表中。
  3. 将项目分成您的个人资料。
  4. 修复您要修复的问题。
  5. 提出拉取请求。
  6. 我会尝试尽快合并拉取请求。

答案 1 :(得分:2)

如果你需要一个dinamic的东西,你可以在你的代码中的任何一点添加一些事件,而不改变你已经在做的结构,我建议一个简单的解决方法:

在您创建的代码的开头:

  • 一个空的回调数组。
  • $("#b1").on('click')分配给遍历调用每个回调的数组的函数
  • 并创建一个名为onclick的新jQuery函数,而不是.on('clic',它执行相同但接收索引。这样的事情
  • 现在,代码中您呼叫的任何位置:$("#b1").on('click',function (){alert('1');});现在您必须在所有其他事件之后调用$("#b1").onclick(function (){alert('1');}); //或$("#b1").onclick(function (){alert('1');}, INDEX); //如果您需要你想要一个特定的订单(INDEX是一个整数)

完整的代码是:

$("#b1").on('click',function(){
 for (var i = 0; i < callbacks.length; i++) 

     callbacks[i]();
});
callbacks= new Array();
jQuery.fn.extend({
  onclick: function(callback, index) {

      if (index) {
        callbacks.splice(index, 0,callback);
      }
      else   callbacks.push(callback); 
  } 
});

你只需将它放在一开始,然后,无论你在什么地方注册一个事件,你都会像过去那样做,例如:

$("#b1").onclick(function (){alert('1');}); 
$("#b1").onclick(function (){alert('2');}); 
$("#b1").onclick(function (){alert('3');}); 

$("#b1").onclick(function (){alert('new 2');},2); //index 2

您可以在此jsfiddle

中试用

答案 2 :(得分:1)

实际上,JQuery(而不是vanilla js)保证了多个回调的顺序,但它保留了一些内部JQuery机制。您可以创建回调数组并迭代它:

var callbacks = [
function (){alert('1');},
function (){alert('2');},
function (){alert('3');}
];

$("#b1").click(function() {
   for (var i = 0; i < callbacks.length; i++) callbacks[i]();
});

现在,您可以通过随机播放来维护订单,或像常规数组一样扩展callbacks数组

答案 3 :(得分:1)

好的,这不是不可能的。首先,我只确定这适用于使用jQuery添加的事件,但我认为它可能适用于其他情况。有一些事情需要考虑:

  • 有几种方法可以向元素添加点击(或其他)事件:
    • 为元素添加onclick属性。
    • 将事件处理程序直接绑定到元素。
    • 事件委托,将处理程序绑定到文档或父元素,并在触发每个事件时扫描它们以查看它是否与处理程序的选择器匹配。
  • 同一事件的多个事件处理程序排队,并一个接一个地执行。它们排队的顺序有点复杂,考虑到有不同的方式来附加事件和浏览器做不同的事情。 Here is an article talking about this issue。我的经验是,如果在添加其他事件处理程序之后添加事件处理程序,则在同一元素上添加任何其他事件之后它将排队。在Chrome 31中,元素的onclick属性首先出现,但如果在文档加载后更改该属性,则会在附加到该元素的任何其他处理程序之后执行该属性。

因此,目标是添加一个新的事件处理程序,它将以您选择的任何顺序执行,而无需修改任何现有代码,并使用jQuery。所以我创建了一个脚本,它的工作方式如下:它抓取所有类型的所有点击事件,从目标事件到文档,并保留与目标匹配的事件。它从目标元素中删除当前的onclick函数,并将其添加到事件中。然后,它会添加自定义onclick函数,并断开绑定到目标的所有单击事件。在自定义onclick函数stopPropagation()中,事件不会冒泡DOM,将新函数插入所需的索引,然后按顺序运行事件。它不应该混淆由其他元素触发的任何点击事件

这是一个有效的jsfiddle:http://jsfiddle.net/mMG99/8/

这是代码,它可能会被清理很多:

<input id='b1' type='button' value='go' onclick='alert("0");'/>

<br>

<input id='index' type='number' min='0' />
<input id='b2' type='button' value='add listener at this index'/>

// Uses different ways to add the event handlers to test if this works with each
$("#b1").on('click',function (){alert('1');});
$("#b1").bind('click',function (){alert('2');});
$(document).on('click', '#b1', function (){alert('3');});

var selector = '#b1';
var insertedFunction = function(){alert('heyooo!');};    
var $target = $(selector);
var oldOnClickFunction = new Function($target.attr('onclick'));

var targetEvents = [oldOnClickFunction];
var boundEvents = $._data($target.get(0), "events");
boundEvents && boundEvents.click && $.each(boundEvents.click, function(i, val){
  targetEvents.push(val.handler);
});

var $targets = $(document).add($target.parents());   
$targets.each(function(){
  var eventObj = $._data(this, "events");
  eventObj && eventObj.click && $.each(eventObj.click, function(i, val){
    if($target.filter(val.selector).length) {
      targetEvents.push(val.handler);
    } 
  });
});

newOnClick = function(event){
  event.stopPropagation();
  $.each(targetEvents, function(i, handler){
    handler(event);
  });     
};

$("#b2").on('click', function(){
  $target.attr('onclick', 'newOnClick(event)');
  var removeAt = targetEvents.indexOf(insertedFunction);
  if (removeAt != -1) {
    targetEvents.splice(removeAt,1);  
  }
  targetEvents.splice(parseInt($('#index').val()), 0, insertedFunction);
  $target.off('click');
});

答案 4 :(得分:0)

最简单的方法是更改​​代码的最少量,将新函数调用放在您想要的事件处理程序中。但最好的方法是只有一个事件处理程序调用你想调用的所有函数,而不是有一些事件监听器:

<input id='b1' type='button' value='go' onclick='alert("0")';'/>

$("#b1").on('click',function (){
  alert('1');
  newFunctionCall();
  alert('2');
  alert('3');
});

答案 5 :(得分:0)

我不确定你能找到适合自己的工作方式,至少你想做的事情。

无论如何,你需要某种切换器,只要你无法阅读有关当前事件的任何信息,就无法解开 - &gt;这个切换器应该在你用“alert”替换的功能中实现。

相当有趣的解决方案(仅在Chrome中检查):http://jsbin.com/UsuRanAR/3/edit

function alert(a) {
  setTimeout(function(){
    console.log(a);
  },((a == 1 || a == 'top priority')?0:200));
}

我担心这是你从这种情况中获得的最大值。

答案 6 :(得分:0)

我打算建议:

添加占位符html节点,隐藏原始节点,单击占位符时,执行“优先级”操作然后触发单击原始节点:

var $clone = $('#b1').clone().attr('id', null).attr('onclick', null);
$clone.insertBefore('#b1');
$('#b1').hide();

$clone.on('click', function(e){
    alert('Kilroy was here');
    $('#b1').trigger('click');
    // do not duplicate the bubbling/default action
    return false;
});

fiddle

但出于某种原因,在这种情况下,onclick回调最后被调用...