trying to scrape and organize css in Javascript by class - javascript

I obtain some CSS and store it in a var, but i am trying to use regexes to parse classes. Thats the easy part, but it seems that i have issues with the regex to scrape contents between the braces to store.
My attempt is at: http://jsfiddle.net/2qaCY/
All i want is to iteratively loop through the classes and scrape the contents between the braces.
code on fiddle:
var css = ".Winning{color: #24CCFF;background-color: #FF8091;}.Losing{color: #2EFFCE;background-color: #DB4DFF;}.crayons{font-family: papyrus;font-size: 32pt;}";
var reg = /\.[a-zA-Z0-9]*\{/ig;
var matches = css.match(reg);
for (var m in matches) {
var sClass = matches[m].substr(0, matches[m].length - 1);
$("body").append(sClass + "<br />");
var c = new RegExp("\\." + sClass + "[\\n\\s]*\{[\\s\\n.]*\}", "ig");
var out = c.exec(css);
$("body").append(out);
$("body").append("<br /><br />");
}

Ok, so the following example stores the class in an array and the whole thing in a map where the key is the class and the contents are the value for that key.
If you want a solution with regexp it's 10 more minutes but this is what you want I believe.
http://jsfiddle.net/2qaCY/11/
var css = ".Winning{color: #24CCFF;background-color: #FF8091;}.Losing{color: #2EFFCE;background-color: #DB4DFF;}.crayons{font-family: papyrus;font-size: 32pt;}";
var reg = /\.[a-zA-Z0-9]*\{[a-zA-Z0-9:\- #;]+\}/ig;
var matches = css.match(reg);
var classes = []
var classMap = {}
matches.map(function(item) {
var cl = (item.split("{")[0])
classes.push(cl)
classMap[cl] = item.split("{")[1].split("}")[0]
})
// All the classes in an array
console.log(classes);
console.log(classMap);

Related

Using map\reduce with nested elements in javascript

I have a search form that allows the user to add as many search terms as they like. When the user enters all of the search terms and their search values and clicks search, a text box will be updated with the search terms. I've got this working with a for loop, but I'm trying to improve my dev skills and am looking for a way to do this with map\filter instead.
Here's the code I'm trying to replace:
var searchTerms = $("#search-form").find(".mdc-layout-grid__inner");
var searchString = "";
for(var i = 0; i < searchTerms.length - 1; i ++)
{
var select = $(searchTerms[i]).find(".select2-selection")[0];
var selectText = $(select).select2('data')[0].text + ":";
var textBox = $(searchTerms[i]).find(".mdc-text-field__input")[0];
searchString = searchString += selectText.replace(/\./g,"").replace(/ /g,"") + textBox.value;
if(i < searchTerms.length - 1)
{
searchString = searchString += " ";
}
}
$("#er-search-input").val(searchString);
Here's a codepen of the current solution.
i'm trying the below, but I get the feeling I'm miles away:
const ret = searchTerms.map((u,i) => [
$($(u[i]).find(".select2-selection")[0]).select2('data')[0].text + ":",
$(u[i]).find(".mdc-text-field__input")[0].value,
]);
My question is, is it possible to do this with map?
Firstly you're repeatedly creating a jQuery object, accessing it by index to get an Element object only to then create another jQuery object from that. Instead of doing this, you can use eq() to get a specific element in a jQuery object by its index.
However if you use map() to loop through the jQuery object then you can avoid that entirely by using this to reference the current element in the iteration. From there you can access the required elements. The use of map() also builds the array for you, so all you need to do is join() the results together to build the required string output.
Finally, note that you can combine the regex expressions in the replace() call by using the | operator, and also \s is more robust than using a whitespace character. Try this:
var $searchTerms = $("#search-form").find(".mdc-layout-grid__inner");
var searchString = $searchTerms.map(function() {
var $searchTerm = $(this);
var selectText = $searchTerm.find('.select2-selection').select2('data')[0].text + ':';
var $textBox = $searchTerm.find('.mdc-text-field__input:first');
return selectText.replace(/\.|\s/g, "") + $textBox.val();
}).get().join(' ');
$("#er-search-input").val(searchString);

InDesign Target XML Structure element by partial name

In my Structure pane there are some elements that their partial name is identical, eg. image01, image03, image03 etc.
I want to know if there is a way to access them via scripting using the itemByName() method, but by providing a partial name, like in CSS i can use
h1[rel*="external"]
Is there a similar way to do this in:
var items2 = items.xmlElements.itemByName("image");
You could try something like the code below. You can test against the markupTag.name properties with a regular expression. The regex is equivalent to something like /^image/ in your example (find image at the beginning of a string).
function itemsWithPartialName(item, partialName) {
var elems = item.xmlElements;
var result = [];
for (var i=0; i<elems.length; i++) {
var elem = elems[i];
var elemName = elem.markupTag.name;
var regex = new RegExp("^" + partialName);
if (regex.test(elemName)) {
result.push(elem);
}
}
return result;
}
itemsWithPartialName(/* some xml item */, 'image');
You can use an XPath:
var rootXE = app.activeDocument.xmlElements.item(0);
var tagXEs = rootXE.evaluateXPathExpression("//*[starts-with(local-name(),'image')]");

JS Regex for a word which is not contained in <a>?

I'm using the following js to highlight the content of searched string in html, but the problem is that this also affects the url string.
var a = new RegExp(keywords, "igm");
container.innerHTML = container.innerHTML.replace(a, "<span style='background:#FF0;'>" + keywords + "</span>");
If the keyword is in the url, then the url will be relaced with xxxx.com/<span style='background:#FF0;'>product</span> which is wrong.
So is there any way to filter out the words that not contained in url? Not sure if there is a RegExp could do this. Thanks in advance.
Here is a block of code that does what you ask:
// prepare the replacement as a function
function do_replacement(node) {
var a = new RegExp(keywords, "igm");
node.innerHTML = node.innerHTML.replace(a,
"<span style='background:#FF0;'>" + keywords + "</span>");
}
// back up the links
var link_backups = new Array();
var link_refs = new Array();
var container_links = container.getElementsByTagName("a");
for (var i = 0; i < container_links.length; i++) {
var copy = container_links[i].cloneNode(true);
// the link target (href) is not contained in the link's innerHTML
// remove this line if you don't want to replace the link's TEXT
do_replacement(copy);
link_backups.push(copy);
link_refs[i] = container_links[i];
}
do_replacement(container);
// restore the backed up links
// (this uses link_refs[] because container_links[] could have changed)
for (var i = 0; i < link_refs.length; i++) {
container.replaceChild(link_backups[i], link_refs[i]);
}
This will (probably) fail if your keywords matches the tag name (<a>) of the links, e.g. when keywords = "a".
However, I'm sure you'll merely run into another instance of HTML code that you don't actually want to replace. JS doesn't really have the best of ways to manipulate just the DOM's text. For example, changing Node.textContent will kill all of the node's HTML content.

Get array of ids from e.g xx_numbers

How can I retrieve an array of ids with only a prefix in common?
E.g.
I've got a list of say 50 divs and they all got and ID looking like: aa_0000. Where 'a' is a prefix and '0' represents random numbers.
You want all elements of which their id starts with something common?
Assuming they are all div elements, this should work....
// Just so we can stay DRY :)
var prefix = 'aa_',
matchElement = 'div';
// Do we have an awesome browser?
if ('querySelectorAll' in document) {
var matchedDivs = document.querySelectorAll(matchElement + '[id^="' + prefix + '"]');
} else {
var allDivs = document.getElementsByTagName(matchElement),
matchedDivs = [],
regex = new RegExp('^' + prefix);
for (var i = 0, allDivsLength = allDivs.length; i < allDivsLength; i++) {
var element = allDivs[i];
if (element.id.match(regex)) {
matchedDivs.push(element);
}
}
}
console.log(matchedDivs.length); // Expect 3
jsFiddle.
If you want to explicitly match ones with numbers, try the regex /^aa_\d+$/.
If you have jQuery floating around, you can use $('div[id^="aa__"]').
For people using jQuery:
$('div[id^="aa_"]')

How to use contents of array as variables without using eval()?

I have a list of variables or variable names stored in an array. I want to use them in a loop, but I don't want to have to use eval(). How do I do this? If I store the values in an array with quotes, I have to use eval() on the right side of any equation to render the value. If I store just the variable name, I thought I'd be storing the actual variable, but it's not working right.
$(data.xml).find('Question').each(function(){
var answer_1 = $(this).find("Answers_1").text();
var answer_2 = $(this).find("Answers_2").text();
var answer_3 = $(this).find("Answers_3").text();
var answer_4 = $(this).find("Answers_4").text();
var theID = $(this).find("ID").text();
var theBody = $(this).find("Body").text();
var answerArray = new Array();
answerArray = [answer_1,answer_2,answer_3,answer_4,theID,theBody]
for(x=0;x<=5;x++) {
testme = answerArray[x];
alert("looking for = " + answerArray[x] + ", which is " + testme)
}
});
You can put the values themselves in an array:
var answers = [
$(this).find("Answers_1").text(),
$(this).find("Answers_2").text(),
$(this).find("Answers_3").text(),
$(this).find("Answers_4").text()
];
for(x=0;x<=5;x++) {
alert("looking for = " + x + ", which is " + answers[x])
}
EDIT: Or even
var answers = $(this)
.find("Answers_1, Answers_2, Answers_3, Answers_4")
.map(function() { return $(this).text(); })
.get();
If your answers share a common class, you can change the selector to $(this).find('.AnswerClass').
If you need variable names, you can use an associate array:
var thing = {
a: "Hello",
b: "World"
};
var name = 'a';
alert(thing[name]);
This would make it easier to get the array populated.
var answers = new Array();
$("Answers_1, Answers_2, Answers_3, Answers_4", this).text(function(index, currentText) {
answers[index] = currentText;
});
As others have mentioned, if you can put the variables in an array or an object, you will be able to access them more cleanly.
You can, however, access the variables through the window object:
var one = 1;
var two = 2;
var three = 3;
var varName = "one";
alert(window[varName]); // -> equivalent to: alert(one);
Of course, you can assign the varName variable any way like, including while looping through an array.

Categories

Resources