动态修改一个元素,使其与给定的选择器匹配
Modify an element on-the-fly so it matches a given selector
假设我有这样的元素:
<div class="some-class"></div>
和选择器类似:
#mydiv.super.another-class[some-attribute="true"]
我想让我的div与这个选择器匹配。这需要
- 添加id
mydiv
- 添加类
super
、another-class
- 添加值为
true
的属性some-attribute
所以最后的div看起来像
<div class="some-class super another-class" id="mydiv" some-attribute="true"></div>
有什么方法可以做类似的事情吗
$(".some-class").makeMatch('#mydiv.super.another-class[some-attribute="true"]');
这将解析选择器并为任何有效选择器执行上面列出的步骤?
我知道我可以做一些函数来解析选择器并执行它,但选择器可能非常复杂,同一个选择器可能以多种不同的方式组成,所以我决定尝试找到一些可靠的现有解决方案。
你知道这样的事情吗,或者可能有本土的方式吗?
编辑:根据评论,我会尝试用不同的方式解释我的问题。
问题的要点是:
是否可以使用javascript解析任何有效的选择器,以了解它指向的id、类和属性?
所以我们想要
var selectorData = parseSelector('#my-id.class-one.class-two[attr-one="value-one"]');
selectorData.id //my-id
selectorData.classes //class-one class-two
selectorData.attributes["attr-one"] //value
因为有了这个关于选择器的数据,所以很容易让任何元素与之匹配
一种可能的方法是:
// create a jQuery plug-in, 'makeMatch()' and pass a selector
// string as an argument:
(function ($) {
$.fn.makeMatch = function (selector) {
// finding a string of one or more alphanumeric characters,
// underscores and hyphens that starts with the '#' character,
// using String.prototype.match() with a regular expression:
var id = selector.match(/#['w-]+/),
// similar to the above, though this string starts with a
// period (escaped with a back-slash because the period
// is a special character in regular expressions), using
// the 'g' (global) flag to retrieve all matching
// sequences:
classes = selector.match(/'.['w-]+/g),
// this string looks for strings starting with a '['
// (again escaped because it's a special character) and
// continuing until it matches a character that is *not*
// ']':
attributeValuePairs = selector.match(/'[[^']]+/g);
// if we have an 'id' sequence:
if (id) {
// assigning the found id sequence to the id variable
// (preventing us from accessing a property of a null
// object) after replacing the leading '#' character
// with an empty string:
id = id[0].replace(/^#/,'');
}
// iterating over the passed-in jQuery object, 'this' (here)
// is the collection of nodes:
return this.each(function () {
// caching the current node found in the collection:
var self = this;
// if we have an id (it's not null):
if (id) {
// setting the id to that matched-id:
self.id = id;
}
// if we have an array of classes:
if (classes) {
// adding the classes from the array, by joining
// each class-string together with spaces and replacing
// the period characters (though we could simply do:
// classes.replace(/'./g,' ') instead):
$(self).addClass(classes.join(' ').replace(/'./g, ''));
}
if (attributeValuePairs) {
// creating a variable to avoid re-initialising a
// variable within the forEach():
var av;
attributeValuePairs.forEach(function(avp) {
// replacing the initial '[' character from
// each element of the array with an empty string
// and splitting that string on the '=' character
// to form a two-part array (if a '=' character
// is found):
av = avp.replace(/^'[/, '').split('=');
// if we do have a two-part array:
if (av.length === 2) {
// setting the attribute held in 'av[0]' with
// the value held in 'av[1]' (after replacing
// any quotes held in that string):
self.setAttribute(av[0], av[1].replace(/"|'/g, ''));
}
});
}
});
};
})(jQuery);
(function($) {
$.fn.makeMatch = function(selector) {
var id = selector.match(/#['w-]+/),
classes = selector.match(/'.['w-]+/g),
attributeValuePairs = selector.match(/'[[^']]+/g);
if (id) {
id = id[0].replace(/^#/,'');
}
return this.each(function() {
var self = this;
if (id) {
self.id = id;
}
if (classes) {
$(self).addClass(classes.join(' ').replace(/'./g, ''));
}
if (attributeValuePairs) {
var av;
attributeValuePairs.forEach(function(avp) {
av = avp.replace(/^'[/, '').split('=');
if (av.length === 2) {
self.setAttribute(av[0], av[1].replace(/"|'/g, ''));
}
});
}
});
};
})(jQuery);
$(".some-class").makeMatch('#mydiv.super.another-class[some-attribute="true"]');
div {
border: 1px solid #000;
width: 200px;
height: 200px;
}
#mydiv.super.another-class[some-attribute="true"] {
border: 2px solid red;
background: transparent url(http://lorempixel.com/200/200/nightlife) 50% 50% no-repeat;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="some-class"></div>
不过,值得注意的是,我还没有解决布尔属性/属性(如checked
、selected
等)或添加无值属性的能力的问题。这是可以做到的,我只是还没有时间解释这样一个功能可能暗示的所有边缘情况。
参考文献:
- JavaScript:
Array.prototype.forEach()
Array.prototype.join()
- CCD_ 10
- JavaScript正则表达式指南
- CCD_ 11
String.prototype.replace()
- jQuery:
addClass()
each()
- "如何创建一个基本的[jQuery]插件。"
我为编写了一个小的jquery函数
$.fn.makeMatch = function(ids, classes, attr) {
this.attr('id', ids).addClass(classes).attr(attr);
return this;
}
你现在只需要:
$('div').makeMatch('firstComesOneId', 'then classes seperated by space', {'data-arrayKey1' : 'value1', 'data-arrayKey2' : 'value2'})
将输出:
<div id="firstComesOneId" class="then classes seperated by space" data-arrayKey1="value1" data-arrayKey2="value2">
希望这正是你所需要的。
在操作人员告诉我以上不是他需要的方式(尽管它有效)之后,我希望他需要的功能是:
$.fn.stringToObject = function(values) {
var selectorData = [];
var start_posID = values.indexOf('#') + 1;
var end_posID = values.indexOf('.',start_posID);
selectorData['id'] = values.substring(start_posID,end_posID);
var classSplit = values.split('.');
var classLength = classSplit.length -1;
var attrSplit = values.match(/'[/g);
var attrLength = attrSplit.length;
var start_posClass = end_posID;
var end_posClass = values.indexOf('[',start_posClass);
var stringClass = values.substring(start_posClass, end_posClass);
selectorData['classes'] = stringClass.replace(/'./g, " ");
for (var i = 0; i <= attrLength; i++) {
if (i == 0) {
var start = values.indexOf('[') + 1;
} else if(i == attrLength) {
start = nextstart -1;
} else {
start = nextstart +2;
}
var end = values.indexOf(']',start);
var newstring = values.substring(start, end);
var nextstart = end;
var newstringLength = newstring.length;
var firstPartOffset = newstring.indexOf('=');
var firstPart = newstring.substring(0, firstPartOffset);
var secondPart = newstring.substring(firstPartOffset +1, newstringLength);
selectorData[firstPart] = secondPart;
};
return selectorData;
}
以下是使用方法:
var valueArray = $( "div" ).stringToObject('#mydiv.super.another-class[some-attribute1="true"][some-attribute2="truesdsda"][some-attribute3="trueasd"][some-attribute4="true"][some-attribute5="truedfg"]');
console.log(valueArray); // gives you everything
console.log(valueArray.id); // = gives you the id
console.log(valueArray.classes); // = gives you the classes
console.log(valueArray['some-attribute5']); // = gives you the value from some-attribute5
花了我一些时间,我真的希望这能有所帮助:)
问候timmi
希望它能起作用。
$(".some-class").addClass('super');
$(".some-class").addClass('another-class');
$(".some-class").attr('id','myDiv');
$(".some-class").attr('some-attribute',true);
相关文章:
- Windows8应用程序(html&Javascript):从图片库(除了文件选择器)显示图像的另一种方式
- 在动态创建的元素上获取对特定选择器的引用
- AngularJS-在JSON选择器中使用变量名
- 每当您在选择器内移动鼠标时,悬停功能就会重复
- 使用CSS或js,使用动态选择器选择任意li的下一个元素
- jQuery最近父级的数据属性选择器
- 为什么不'在JQuery中找到第二个css选择器的工作
- 为什么 .focus() 不起作用,而 .css(“color”,“red”) 在同一个选择器上起作用
- jquery IE7中的第n个选择器
- Webdriver.io pageObject模式-通过传递参数来定义元素选择器
- 动态修改一个元素,使其与给定的选择器匹配
- jQuery日期[时间]选择器-如何保存时间范围(+修改日期格式)
- 修改元素属性后,Jquery 选择器不起作用
- Javascript 文件修改了未从中调用它的 html 文件?Jquery 选择器
- 使用JavaScript修改CSS选择器:之后
- 修改DOM后,jQuery选择器不工作
- Jquery修改的选择器类没有被拾取
- jQuery选择器不检测修改的元素
- 修改sencha中的CSS psuedo选择器样式
- 可以修改jQuery id选择器