how to get style="i want the css code" using regexp (javascript) - javascript

var text = '..<anything><anything style="color:red;">hello</anything><anything style="color:blue; font-size:1em;">hello</anything></anything>...';
or
var text = "..<anything><anything style='color:red;'>hello</anything><anything style='color:blue; font-size:1em;'>hello</anything></anything>...";
result:
array[0] = "color:red;";
array[1] = "color:blue; font-size:1em;";

Make a temporary element and use innerHTML, then getElementsByTagName and getAttribute('style') if it's a string like that.
If it's a reference to a DOM element skip the innerHTML part.
var d = document.createElement('div'),
text = '..<anything><anything style="color:red;">hello</anything><anything style="color:blue; font-size:1em;">hello</anything></anything>...',
styles = [];
d.innerHTML=text;
var els = d.getElementsByTagName('*');
for ( var i = els.length; i--; ) {
if ( els[i].getAttribute('style') ) {
styles.push( els[i].getAttribute('style') )
}
}
styles
The jQuery would be..
$(text).find('*').map(function() { return this.getAttribute('style') })

As has already been mentioned, it's not a great idea to use regular expressions for parsing HTML.
However, if you're determined to do it that way, this will do the job for you:
var matches = text.match(/\bstyle=(['"])(.*?)\1/gi);
var styles = [];
for(var i = 0; i < matches.length; i++) {
styles.push(matches[i].substring(7, matches[i].length - 1));
}

meder has already given the correct answer, but since a regex solution was desired I'll give one. All the usual warnings about parsing a nonregular language like HTML (or SGML, or XML) with regular expressions apply.
/<[a-z]+(?:\s+ [a-z]+\s*=\s*(?:[^\s"']*|"[^"]*"|'[^']*'))\s+style\s*=\s*"([^"]*)">/g

Related

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')]");

Selecting inside a DOM element

This is the html code
<div class="extra-sub-block sub-block-experience">
<h6 style="display:inline;" id="exp-pos-0" class="extra-sub-block-head sub-block-head-experience">CEO</h6>
</div>
<div class="extra-sub-block sub-block-experience">
<h6 style="display:inline;" id="exp-pos-1" class="extra-sub-block-head sub-block-head-experience">COO</h6>
</div>
There are several such similar structures. Now I try to extract the values from each block.
var temp=document.getElementsByClassName('sub-block-experience');
var result=$(temp[0]+"#exp-pos-0");
This throws an error. I followed selecting element inside another DOM
I also tried
var temp=document.getElementsByClassName('sub-block-experience');
var result=temp[0].find('h6');
This doesn't work as well. What am I doing wrong here. Help?
For extracting the values from all blocks, you can use .map() function as follows:
var results = $('.extra-sub-block-head').map(function(){
return $(this).text();
})
Demo
side note: Since id is unique in a document, you can directly access the element using id selector like var result= $("#exp-pos-0");instead of var result=$(temp[0]+"#exp-pos-0");
Try, var result=$(temp[0]).find('h6');
Even, in the documentation link that you gave in question, it shows that you should wrap your result from document.getElementById in $() to be applied with jQuery. What it does is, that it converts the native javascript object into a jquery object.
Demo
function testIt(){
var tags, index;
tags = document.getElementsByTagName('h6');
for (index = 0; index < inputs.length; ++index) {
//do something ...
}
}
If I am correct you are trying to get ceo and coo?.If that's the case then with jquery:
var x= $('.extra-sub-block h6');
//values are
$(x[O]).html();
$(x[1]).html();
You could also use plain javascript:
var result = document.querySelectorAll('.sub-block-experience h6');
Or if you like it separate:
var temp = document.querySelectorAll('.sub-block-experience');
var result = [];
for(var i = 0, elem; elem = temp[i]; i++) {
result = result.concat(elem.querySelectorAll('h6'));
}
But be aware of the browser compatability of querySelectorAll and querySelector.

Replacing all urls in a div

I am trying to write javascript code to find all the urls inside a div. Now this would be pretty easy if all the urls within the div were separated by spaces in which case I can just do a regex on what's inside the div to find them. However, the urls within this outer div may be in sub divs (or any other html tag) and I want to consider the subdivs as separators as well (and I don't want to get rid of these subdivs). To give an example, in the following I want to find www.foo.com and www.bar.com within the div with id "outer":
<div id="outer"><div>www.foo.com</div>www.bar.com</div>
What would be a good way of doing this?
You can apply a recursive call to all non-text child nodes.
function replaceWwwInNodes(node) {
//text node
if (node.nodeType === 3) {
node.textContent = node.textContent.replace(/* ??? */)
}
else {
Array.prototype.forEach.call(node.childNodes, function (elem) {
replaceWwwInNodes(elem);
});
}
}
replaceWwwInNodes(document.getElementById('outer'));
http://jsfiddle.net/UDX5V/
Try to use this sample http://jsfiddle.net/iklementiev/TaCx9/1/
var data = document.getElementById("outer").innerText;
var myRe = /www\.[0-9a-z-]+\.[a-z]{2,4}/igm;
var matches= data.match(myRe)
for (var i = 0; i < matches.length; i++) {
alert('match: ' + matches[i]);
}
this help to find all urls.
try this
var expression = /[-a-zA-Z0-9#:%_\+.~#?&//=]{2,256}\.[a-z]{2,4}\b(\/[-a-zA-Z0-9#:%_\+.~#?&//=]*)?/gi;
var regex = new RegExp(expression);
var regContent = $("#outer").html();
var newContent = regContent;
if(regContent.match(regex))
{
var textContent = regContent.match(regex);
for(var i=0;i<regContent.match(regex).length;i++)
{
newContent = newContent.replace(new RegExp(regContent.match(regex)[i], "g"), "test");
}
$("#outer").html(newContent);
}
this will get all url content and replace it as "test".

Make a text Highlight using javascript

I want to make a word bold in given paragraph. Here is a javascript code.
var hlWord = "idm";
var nregex = new RegExp(hlWord,"gi");
var div = document.getElementById("SR").innerHTML;
var rword = div.replace(nregex,"<b>"+hlWord+"</b>");
document.getElementById("SR").innerHTML = rword;
Here is a HTML code.
<div id="SR">
Download here free idm.
click here to download
</div>
This is work well and make all idm bold but here is a problem that it also change
url to like this
click here to download
This is not a valid url.This is the problem that this code make the url damaged.
Please tell me how can I avoid this.
Thanks...
You can iterate through all the text nodes with the methods in this thread, change them and replace them with new bold ones.
var hlWord = "idm";
var nregex = new RegExp(hlWord,"gi");
var sr = document.getElementById('SR');
function escape_html(html) {
return html.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
(function findTextNodes(current) {
// make a shadow copy of the child nodes.
var current_children = Array.prototype.slice.call(current.childNodes);
for(var i = 0; i < current_children.length; i++) {
var child = current.childNodes[i];
// text node
if(child.nodeType == 3) {
var value = escape_html(child.nodeValue);
var html = value.replace(nregex, '<b>' + hlWord + '</b>');
if (html != value) {
var node = document.createElement('div');
node.innerHTML = html;
// make a shadow copy of the child nodes.
var childNodes = Array.prototype.slice.call(node.childNodes);
// replace the plain text node with the bold segments
for (var j = 0; j < childNodes.length; j++) {
var c = childNodes[j];
current.insertBefore(c, child);
}
current.removeChild(child);
}
}
else {
findTextNodes(child);
}
}
})(sr);
Check the code example at jsFiddle.
UPDATE:
Passerby pointed out that innerHTML should be used carefully. Escape text nodeValue before processing.
After some try-and-fail, I made a working demo that may be more complicated than you might have think:
http://jsfiddle.net/4VKNk/
var cache=[];
var reg=/idm/gi;
var id=function(ID){return document.getElementById(ID);}
function walkElement(ele){
if(ele.childNodes.length>0){
for(var i=0;i<ele.childNodes.length;i++){
walkElement(ele.childNodes[i]);
}
}else if(ele.nodeType==3){//text node
if(reg.test(ele.nodeValue)){
cache.push(ele);
}
}
}
id("test").onclick=function(){
cache=[];
walkElement(id("SR"));
while(cache.length>0){
var ele=cache.shift();
var val=ele.nodeValue;
var pnt=ele.parentNode;
var nextSibling=ele.nextSibling;
var i=0;
var r,tmp;
pnt.removeChild(ele);
while(r=reg.exec(val)){
tmp=document.createTextNode(val.substring(i,r.index));
if(nextSibling){
pnt.insertBefore(tmp,nextSibling);
tmp=document.createElement("strong");
tmp.appendChild(document.createTextNode("idm"));
pnt.insertBefore(tmp,nextSibling);
}else{
pnt.appendChild(tmp);
tmp=document.createElement("strong");
tmp.appendChild(document.createTextNode("idm"));
pnt.appendChild(tmp);
}
i=reg.lastIndex;
}
if(i<val.length-1){
tmp=document.createTextNode(val.substring(i,val.length));
if(nextSibling){
pnt.insertBefore(tmp,nextSibling);
}else{
pnt.appendChild(tmp);
}
}
}
};
I took the approach of DOM manipulation.
Explanation:
Walk through the whole DOM tree under target element, and cache all TEXT_NODE (nodeType==3);
Use RegExp.exec() method to get the index of each match;
While you find a match, add back the text that come before it, and then add a highlight element (<strong>) that contains the match; continue this step;
If we still have text left, add it back.
The reason I need to cache the TEXT_NODEs first, is that if we directly modify it in walkElement, it will change childNodes.length of its parent, and break the process.

Using innerHTML.replace to replace text to create link

I'm using Sharepoint (WSS 3.0), which is unfortunately very limited in its ability to format survey questions (i.e., it strips any HTML you enter). I saw a solution elsewhere that suggested we add some JS to our master page file in order to allow line breaks. This works beautifully, but I'd like to see if we can allow links as well.
In our WSS surveys, I can now use {{br}} anywhere I want a line break (this works). I have tried extending the code to allow the use of link tags (e.g., {{link1}}url{{link2}}URL Title{{link3}}; but, this doesn't work, presumably because the updates aren't happening as a whole, and the browser then tries to render it piece by piece, confusing it. (FF and IE show different results, but both fail. If I mix up the order of the JS below -- i.e., do link3, 2 and then 1 -- the output changes as well, but still fails.) Is there a better way to do this?
<script language="JavaScript">
var className;
className = 'ms-formlabel';
var elements = new Array();
var elements = document.getElementsByTagName('td');
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className){
elements[e].innerHTML = elements[e].innerHTML.replace(/{{br}}/g,'<br/>');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link1}}/g,'<a href="');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link2}}/g,'">');
elements[e].innerHTML = elements[e].innerHTML.replace(/{{link3}}/g,'</a>');}
}
</script>
Instead of modifying the innerHTML property in chunks (the browser tries to update the DOM each time you change innerHTML, which if you provide incomplete/broken markup, will obviously mess things up), do all your modifications against your own string variable, and then overwrite the entire innerHTML with your completed string:
<script language="JavaScript">
var className;
className = 'ms-formlabel';
var elements = new Array();
var elements = document.getElementsByTagName('td');
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className) {
var newHTML = elements[e].innerHTML;
newHTML = newHTML.replace(/{{br}}/g,'<br/>');
newHTML = newHTML.replace(/{{link1}}/g,'<a href="');
newHTML = newHTML.replace(/{{link2}}/g,'">');
newHTML = newHTML.replace(/{{link3}}/g,'</a>');}
elements[e].innerHTML = newHTML;
}
</script>
The simple answer would be to build up the innerHTML and replace it all at once:
for (var e = 0; e < elements.length; e++)
{
if (elements[e].className == className) {
var newHTML = elements[e].innerHTML;
newHTML = newHTML.replace(/{{br}}/g,'<br/>');
newHTML = newHTML.replace(/{{link1}}/g,'<a href="');
newHTML = newHTML.replace(/{{link2}}/g,'">');
newHTML = newHTML.replace(/{{link3}}/g,'</a>');
elements[e].innerHTML = newHTML;
}
}
The more complex answer would be to use capturing groups in your regex and pass a function as the 2nd parameter to replace(), so as to use a single call to replace() for the HTML. For example,
elements[e].innerHTML = elements[e].innerHTML.replace(/({{link1}})|({{link2}})|({{link3}})/g,
function (match) {
var map = {
'{{link1}}' : '<a href="',
'{{link2}}' : '>',
'{{link3}}' : '</a>', }
return map[match];
});
The second solution is more complex and leads to some ugly regexes, but is more efficient than calling replace() over and over again.

Categories

Resources