我正在编写一个jquery插件,该插件应该处理指定开放行为的链接的额外信息。
例如,我想支持标记:
<a href="somewhere" data-openmode="NewWindow" class="openmode" />
<a href="somewhere" data-openmode="Modal" class="openmode" />
<a href="somewhere" class="openmode" /> <!-- Not specified -->
第一个应该在新窗口中打开,第二个应该在模式对话框中打开,第三个应该以本机行为打开(无论在标签上设置了什么目标)。
我想为这种行为创建一个尽可能通用的插件。我现在写了:
(function ($) {
$.fn.myOpenMode = function () {
return this.mousedown(function () {
var $this = $(this);
var mode = $this.data("openmode");
var href = this.href;
var handled = true;
if (mode) {
switch (mode) {
case "NewWindow":
case "1":
window.open(href, "_blank");
break;
case "Dialog":
case "2":
openAsDialog(href);
break;
// Actually, there are other options, but I removed them for clarity
default:
handled = false;
}
}
else {
handled = false;
}
return !handled;
});
};
})(jQuery);
此代码允许我从任何页面调用类似:
$(function(){
$(".openmode").myOpenMode();
});
这适用于静态生成的标记。但是,我的应用程序可能会动态生成标记(大部分时间都使用jsRender,但这并不重要)。
但是因为加载javascript文件时会设置一次这种行为,所以不会动态生成对象。
我应该怎样处理我的要求?
我尝试使用on
方法来监控加载事件,但这不起作用:
$(function(){
$(document).on("load",".openmode", function() { $(this).myOpenMode(); });
});
我知道这不起作用,因为“加载”事件不起泡
我正在考虑修改我的插件以在插件中放置“on”,但我不喜欢这个想法,因为它在插件中引入了一些超出范围的行为
我也可以在每次创建动态节点时调用插件,但它也会将依赖项引入其他部分。我的插件不会像我想的那样自主。
有没有人有建议来处理我的要求,让我的插件尽可能隔离?
[edit] 这适用于IE8及更高版本(理想情况下适用于其他浏览器)
[edit] 这里有一个jsFiddle来说明问题(只需点击Add
并尝试点击新创建的元素。)
答案 0 :(得分:8)
添加到$.fn
的插件应仅适用于列出的元素,而不适用于将来的所有元素。
您应该专注于让您的插件提供机制,例如:
(function($) {
$.fn.openmode = function(cmd) {
cmd = cmd || 'on';
switch (cmd) {
case 'click':
// read props, open windows, etc
break;
case 'on':
this.addClass('openmode');
break;
case 'off':
this.removeClass('openmode');
break;
}
});
})(jQuery);
然后允许插件用户注册触发该机制的事件处理程序,必要时使用事件委托:
$(document).on('click', 'a.openmode', function() {
$(this).openmode('click');
});
后一个代码也可以放入jQuery命名空间,作为实用函数:
(function($) {
$.openmode = function(cmd) {
cmd = cmd || 'on';
switch (cmd) {
case 'on':
$(document).on('click.openmode', 'a.openmode', function() {
$(this).openmode('click');
});
break;
case 'off':
$(document).off('click.openmode', 'a.openmode');
break;
}
};
})(jQuery);
这样只需要打电话:
$.openmode();
将完成为每个当前(和将来).openmode
元素启用插件所需的所有工作。
答案 1 :(得分:2)
我迟到了回答,但希望它有所帮助。我有同样的问题。
$.fn.plugin = function(){
//some code
}
$(".element").plugin(); //works fine
$(".elementParent").append(".newElement");
$(".newElement").plugin(); // doesn´t work
它没有用,因为你需要在添加元素后再次调用插件,就像这样
function runPlugin(){
$.fn.plugin = function(){
//some code
}
}
runPlugin(); //call plugin here
$(".element").plugin(); //works fine
$(".elementParent").append(".newElement");
runPlugin(); // call plugin here
$(".newElement").plugin(); // works fine
答案 2 :(得分:1)
我在插件中找到了依赖on()
方法的solution。
在这种情况下,插件等待selector
参数仍然将选择器保持在应用程序级别(而不是插件级别):
(function ($) {
$.fn.myOpenMode = function (selector) {
return $(document).on("mousedown", selector ,function () {
var $this = $(this);
var mode = $this.data("openmode");
var href = this.href;
var handled = true;
if (mode) {
switch (mode) {
case "NewWindow":
alert("NewWindow");
break;
case "Dialog":
alert("Dialog");
break;
default:
handled = false;
}
} else {
handled = false;
}
return !handled;
});
};
})(jQuery);
然后,我必须将调用更改为我的插件:
$(function(){
$.fn.myOpenMode(".openmode");
});
此 按预期工作。但是,我对尊重jQuery插件指南并不十分自信。
因此,如果有人有更好的解决方案,我会很高兴知道。
答案 3 :(得分:1)
您仍然可以实现自己的观察者方法,这里扩展了追加方法:
;(function ($) {
var fctsToObserve = {
append: [$.fn.append, 'self']
}, fctsObserveKeys = '';
$.each(fctsToObserve, function (key, element) {
fctsObserveKeys += "hasChanged." + key + " ";
});
var oOn = $.fn.on;
$.fn.on = function () {
if (arguments[0].indexOf('hasChanged') != -1) arguments[0] += " " + fctsObserveKeys;
return oOn.apply(this, arguments);
};
$.fn.hasChanged = function (types, data, fn) {
return this.on(fctsObserveKeys, types, null, data, fn);
};
$.extend($, {
observeMethods: function (namespace) {
var namespace = namespace ? "." + namespace : "";
var _len = $.fn.length;
delete $.fn.length;
$.each(fctsToObserve, function (key) {
var _pre = this;
$.fn[key] = function () {
var target = _pre[1] === 'self' ? this : this.parent(),
ret = _pre[0].apply(this, arguments);
target.trigger("hasChanged." + key + namespace, arguments);
return ret;
};
});
$.fn.length = _len;
}
});
$.observeMethods()
})(jQuery);
也适用于旧浏览器,但是,观察者遇到了一些性能问题,即使你可以优化它。
答案 4 :(得分:0)