我正在尝试将自定义jquery选择器组合在一起,以便在Asp.net中匹配asp客户端ID。我正在处理来自这两个博客条目here和here
的信息问题是我现在正在页面上的每个元素上返回一个匹配项。我知道为什么(这是我每次想的时候都在查询所有节点)但是我的大脑绝对是疲惫的,我已经把自己写成了提交。
如果有人能弄清楚出了什么问题,并给我一些指示,我会非常感激。
选择器的用法如下:
$("input:clientID(TextBox1)")
干杯!
编辑:到目前为止我已经有了这段代码,但是这将返回以给定id结尾的所有节点。
(function ($) {
$.expr[":"].clientID = function (objNode, intStackIndex, arrProperties, arrNodeStack) {
var keyValue, tName, $node, len, id;
if (arrProperties[3]) {
// Split into array (name,value):
keyValue = arrProperties[3];
// Check to see whether a tag node has been supplied.
if (objNode) {
// Get the name.
tName = objNode.tagName;
$node = $(objNode);
id = $node.attr("id");
if ((id.lastIndexOf(keyValue) === id.length - keyValue.length) && ($node.is(":first"))) {
return true;
}
else if (id === keyValue) {
return true;
}
else {
return false;
}
} else {
// No node supplied so will use the ends with attribute selector.
return $("[id$=\"_" + keyValue + "\"]").first().length > 0;
}
} else {
// If we have made it this far, then we found no
// match. Return false to indicate that this node
// did not match our selector.
return false;
}
};
} (jQuery));
答案 0 :(得分:2)
我认为你误解了jQuery选择器应该如何工作。这是他们的工作方式。假设您使用以下内容进行查询:
$("input:clientID(TextBox1)");
jQuery首先找到所有输入元素,然后,每个输入元素询问您的函数是否应该包含它。因此,如果您的页面有10个input
元素,那么您的函数将被调用10次。
您不必自己查询DOM 。
通过这种理解,您可以更轻松地确定节点的ID是否包含_TextBox1
。
(function ($) {
$.expr[":"].clientID = function(objNode, intStackIndex, arrProperties, arrNodeStack) {
// we need to something to query
if( ! arrProperties[3] ) return false;
return objNode.id.indexOf( "_" + arrProperties[3] ) !== -1;
};
} (jQuery));
我将把ASP.net的细节留给你,因为我不熟悉如何生成ASP.net clientID。但是,根据我的理解,您还可以简单地使用内置的jQuery选择器实现相同的功能(正如其他人提到的那样)。
要选择可能是“xxx_xxx_clientID”或“clientID”的ID,可以将代码修改为:
var testID = arrProperties[3];
if( objNode.id == testID ) return true;
// ends with code
testID = "_" + testID;
var lastIndex = objNode.id.lastIndexOf(testID);
return lastIndex !== -1 && lastIndex == (objNode.id.length - testID.length);
为了只匹配第一个结果,你可以在找到某个东西时设置一个标志变量。这应该比使用James的解决方案快得多,但不太干净。
(function ($) {
// assign the clientID filter with a self-executing anonymous function
$.expr[":"].clientID = (function(){
// create a "private" flag variable
var alreadyFound = false;
return function(objNode, intStackIndex, arrProperties, arrNodeStack) {
if( intStackIndex === 0 ) alreadyFound = false;
if( alreadyFound ) return false;
var testID = arrProperties[3];
if( objNode.id == testID){
alreadyFound = true;
} else {
// ends with code
testID = "_" + testID;
var lastIndex = objNode.id.lastIndexOf(testID);
alreadyFound = lastIndex !== -1 && lastIndex == (objNode.id.length - testID.length);
}
return alreadyFound;
};
})();
} (jQuery));
我们的clientID函数(而且没有其他人)可以通过闭包访问alreadyFound
变量。
答案 1 :(得分:0)
开箱即用,但如何将ClientIDMode更改为静态而不用担心呢?
<asp:Label ID="Label1" runat="server" ClientIDMode="[Mode Type]" />
http://weblogs.asp.net/asptest/archive/2009/01/06/asp-net-4-0-clientid-overview.aspx
答案 2 :(得分:0)
我只是添加一个答案,以便显示最终代码。如果没有Skabbes,我就无法做到这一点,所以他会得到积分。
选择器返回具有给定clientid的asp控件的第一个实例。它没有标记名(虽然它慢得多)。我已经尽最大努力优化了它,但是如果有人能加快它的速度,那就太好了。
Usage: $("input:clientID(TextBox1)");
享受......
(function ($) {
// A cache for holding our grepped array.
var cache = [];
$.expr[":"].clientID = function (node, stackIndex, properties, nodeStack) {
// <summary>
// Selects a single Asp.Net server control whose id has been prefixed.
// </summary>
// <param name="node" type="Object">
// This is a reference to the current DOM element being evaluated.
// This is not a jQuery version of the element but the actual DOM node.
// </param>
// <param name="stackIndex" type="Integer">
// This is the zero-based index of the given node within the stack of
// nodes that will be evaluated with this selector call.
// </param>
// <param name="properties" type="Array">
// This is an array of meta data about the custom jQuery selector execution.
// Of this, only the fourth argument (index 3) is of any real value - it contains
// the string data that was passed to the jQuery selector.
// </param>
// <param name="nodeStack" type="Array">
// This is an array of the DOM elements that are being evaluated with this selector.
// The inStackIndex integer above is the current DOM element's index within this array.
// </param>
// <returns type="jQuery"/>
var testID = properties[3],
endsWithID = "_" + testID,
nodeID,
id = node.id,
lastIndex,
grep = function (elems, callback, inv) {
/// <summary>
/// Tweaked for speed version of the native jQuery grep.
/// </summary>
var ret = [], retVal, len = elems.length;
inv = !!inv;
// Go through the array, only saving the items
// that pass the validator function
while (len--) {
retVal = !!callback(elems[len], len);
if (inv !== retVal) {
ret.push(elems[len]);
}
}
// reverse since we are descending.
return ret.reverse();
};
// Check if there is anything in the cache and grep if not.
if (cache.length === 0) {
var trimmed = grep(nodeStack, function (val, key) {
return val.id.lastIndexOf(testID) !== -1;
});
cache = trimmed;
}
// Get the first node id only.
nodeID = cache[0].id;
lastIndex = nodeID.lastIndexOf(endsWithID);
// Clear the cache on the last element.
if (stackIndex === nodeStack.length - 1) {
cache.length = 0;
}
// Check the id.
if ((nodeID === id) || (lastIndex !== -1 && nodeID.substring(lastIndex + 1) === id)) {
return true;
}
// Strict.
return false;
};
} (jQuery));