覆盖 JQuery 选择器以支持元素 id 中的美元符号 ($)
Override JQuery Selector to support Dollar Sign ($) in element id
我正在尝试编写一个 JQuery 插件来支持元素 id 中的 $,我的代码是:
DollarSignPlugin.js:
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
var jQueryInit = $.fn.init;
$.fn.init = function(arg1, arg2, rootjQuery){
arg2 = arg2 || window.document;
if (arg1 && arg1.replace) {
var newArg1 = escapeJQueryElementName(arg1);
return new jQueryInit(newArg1, arg2, rootjQuery);
}
return new jQueryInit(arg1, arg2, rootjQuery);
};
它运行良好,但我遇到了当前行的一个问题:
var $anyselector = $("#");
JQuery 抛出错误 "Syntax error, unrecognized expression: #".
此行来自 bootstrap 单击带有 href="#" 的任何选项卡时。
删除我的插件时不会出现此错误,如果我将替换功能直接复制粘贴到 jquery 文件,它也可以正常工作。
那么有没有更好的方法来覆盖选择器或者我的代码有问题,请帮忙?
与其尝试通过覆盖实际上只应在内部使用的内容来解决此问题,更好的解决方案是创建一个支持转义选择器的新别名 jQuery 的函数。
顺便说一句,请记住,不应该对 HTML 的内容进行转义,例如$('<span>give me $$$</span>')
,所以我粗略地检查了一下。
(function(jQuery) {
jQuery.withSelectorEscaping = function() {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
return function(selector, context) {
// avoid doing this for HTML
if (selector && selector.replace && selector[0] !== '<') {
selector = escapeJQueryElementName(selector);
}
return jQuery(selector, context);
};
}
}(jQuery));
// create new alias here
$ = jQuery.withSelectorEscaping();
// use new alias
console.log($('#'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
此代码片段向 jQuery
本身添加了一个名为 jQuery.withEscaping
的新函数;它 returns 一个你可以分配给你选择的别名的函数,我在这里选择了 $
但你也可以这样做:
$foo = jQuery.withSelectorEscaping();
它不影响 jQuery
本身的行为,只为需要它的东西公开您的转义功能。
我强烈建议您不要这样做(但如果您愿意,请继续阅读,我在下面有一个修复程序),因为:
这意味着您在代码中使用了无效的选择器,这是一个维护问题——在某些时候,进行维护的人不会理解发生了什么,或者您会遇到困难条件等
您当前的实施会搞乱
$("<div></div>").appendTo(document.body);
(通过在美元符号前加上反斜杠)。谁知道它还搞砸了什么?
相反,我只需要一个简单的:
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
示例:
// Plugin
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
// Use
$gid("a$b").css("color", "blue");
$gid("$c").css("color", "green");
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
但是:如果你打算这样做,你必须小心,尽可能轻柔地踩踏。这意味着使用完全相同数量的参数、相同的 this
值等调用原件;并确保 $.fn.init.prototype
在替换 $.fn.init
后具有与之前相同的值。
做这两件事似乎可以解决问题:
// Plugin
(function () {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
var slice = Array.prototype.slice;
var jQueryInit = $.fn.init;
$.fn.init = function (arg1) {
var args = slice.call(arguments, 0);
if (arg1 && arg1.replace) {
args[0] = escapeJQueryElementName(arg1);
}
return jQueryInit.apply(this, args);
};
$.fn.init.prototype = $.fn;
})();
// Use
$("#a$b").css("color", "blue"); // Using special version that handles $ without \
$("#$c").css("color", "green"); // Using special version that handles $ without \
$("<div>Checking '#' selector, should get 0: " + $("#").length + "</div>").appendTo(document.body);
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
我正在尝试编写一个 JQuery 插件来支持元素 id 中的 $,我的代码是:
DollarSignPlugin.js:
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
var jQueryInit = $.fn.init;
$.fn.init = function(arg1, arg2, rootjQuery){
arg2 = arg2 || window.document;
if (arg1 && arg1.replace) {
var newArg1 = escapeJQueryElementName(arg1);
return new jQueryInit(newArg1, arg2, rootjQuery);
}
return new jQueryInit(arg1, arg2, rootjQuery);
};
它运行良好,但我遇到了当前行的一个问题:
var $anyselector = $("#");
JQuery 抛出错误 "Syntax error, unrecognized expression: #".
此行来自 bootstrap 单击带有 href="#" 的任何选项卡时。
删除我的插件时不会出现此错误,如果我将替换功能直接复制粘贴到 jquery 文件,它也可以正常工作。
那么有没有更好的方法来覆盖选择器或者我的代码有问题,请帮忙?
与其尝试通过覆盖实际上只应在内部使用的内容来解决此问题,更好的解决方案是创建一个支持转义选择器的新别名 jQuery 的函数。
顺便说一句,请记住,不应该对 HTML 的内容进行转义,例如$('<span>give me $$$</span>')
,所以我粗略地检查了一下。
(function(jQuery) {
jQuery.withSelectorEscaping = function() {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
return function(selector, context) {
// avoid doing this for HTML
if (selector && selector.replace && selector[0] !== '<') {
selector = escapeJQueryElementName(selector);
}
return jQuery(selector, context);
};
}
}(jQuery));
// create new alias here
$ = jQuery.withSelectorEscaping();
// use new alias
console.log($('#'));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
此代码片段向 jQuery
本身添加了一个名为 jQuery.withEscaping
的新函数;它 returns 一个你可以分配给你选择的别名的函数,我在这里选择了 $
但你也可以这样做:
$foo = jQuery.withSelectorEscaping();
它不影响 jQuery
本身的行为,只为需要它的东西公开您的转义功能。
我强烈建议您不要这样做(但如果您愿意,请继续阅读,我在下面有一个修复程序),因为:
这意味着您在代码中使用了无效的选择器,这是一个维护问题——在某些时候,进行维护的人不会理解发生了什么,或者您会遇到困难条件等
您当前的实施会搞乱
$("<div></div>").appendTo(document.body);
(通过在美元符号前加上反斜杠)。谁知道它还搞砸了什么?
相反,我只需要一个简单的:
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
示例:
// Plugin
function $gid(id) {
var e = document.getElementById(id);
if (!e) {
return $();
}
if (e.id === id) {
return $(e);
}
// Fallback processing for old IE that matches name attributes
return $('[id="' + id.replace(/"/g, '\"') + '"]').filter(function() {
return this.id === id;
}).first();
}
// Use
$gid("a$b").css("color", "blue");
$gid("$c").css("color", "green");
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
但是:如果你打算这样做,你必须小心,尽可能轻柔地踩踏。这意味着使用完全相同数量的参数、相同的 this
值等调用原件;并确保 $.fn.init.prototype
在替换 $.fn.init
后具有与之前相同的值。
做这两件事似乎可以解决问题:
// Plugin
(function () {
function escapeJQueryElementName(elementName) {
elementName = elementName.replace(/\$/g, "$");
return elementName.replace(/$/g, "\$");
}
var slice = Array.prototype.slice;
var jQueryInit = $.fn.init;
$.fn.init = function (arg1) {
var args = slice.call(arguments, 0);
if (arg1 && arg1.replace) {
args[0] = escapeJQueryElementName(arg1);
}
return jQueryInit.apply(this, args);
};
$.fn.init.prototype = $.fn;
})();
// Use
$("#a$b").css("color", "blue"); // Using special version that handles $ without \
$("#$c").css("color", "green"); // Using special version that handles $ without \
$("<div>Checking '#' selector, should get 0: " + $("#").length + "</div>").appendTo(document.body);
<div id="a$b">a$b</div>
<div id="$c">$c</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>