I have the following string :
var str='
<span class="productName">Basa fillets</span><br>
Brand:
<span class="brandName">COMPLIMENTS</span><br>
400 <abbr title="Gram" lang="en">gr</abbr>
'
I need to get the '400' (could be a word,or even a sentence).
What I have so far is :
d = str.replace(/<br>/g,'').replace(/<.*<\/.*>/g,'').replace(/\n/g,'').replace(/ */g,'').replace(/brand:/i,'');
It works but... well, I'm sure I can do better. i have plenty of similar queued replace in my code, and I'd like to know how to improve that so i'm more looking for a general answer than a particular solution.
Thanks!
Instead of using string tools/regex on this, you can use DOM methods on it (it is HTML).
First you make a "fake" div and add the HTML to it.
var str="\
<span class=\"productName\">Basa fillets</span><br>\
Brand: \
<span class=\"brandName\">COMPLIMENTS</span><br>\
400 <abbr title=\"Gram\" lang=\"en\">gr</abbr>\
";
var fakeDiv = document.createElement('div');
fakeDiv.innerHTML = str;
Then just use normal DOM traversal methods to get the node you need. There are many ways to get to the element, depending on your HTML.
var brandName = fakeDiv.getElementsByClassName('brandName');
var textNode = brandName[0].nextSibling.nextSibling;
console.log(textNode.nodeValue.trim());
DEMO: http://jsfiddle.net/aqpgV/
Or, you can start from the <abbr> element and work backwards.
var gram = fakeDiv.getElementsByTagName('abbr');
var textNode = gram[0].previousSibling;
console.log(textNode.nodeValue.trim());
DEMO: http://jsfiddle.net/aqpgV/1/
However you traverse it is up to you :-)
Regex
class="brandName">[^<]+</span><br>[^\w]+([^<]+) <abbr title=
Debuggex Demo
Notes: Group 1 will contain the item you want.
If you wanted to use regex, you could do something like this.
var str="\
<span class=\"productName\">Basa fillets</span><br>\
Brand: \
<span class=\"brandName\">COMPLIMENTS</span><br>\
400 <abbr title=\"Gram\" lang=\"en\">gr</abbr>\
";
var myRegexp = /COMPLIMENTS<\/span><br>\W(.*?) <abbr /g;
var match = myRegexp.exec(str);
alert(match[1]);
Related
I have some markup in JS as follows:
<div class="col-sm-4">
<span id="some-media" class="media">Text</span>
</div>
I would like to select the class attribute of the span and prepend its value with lets say the characters: "::". So after the regex replace i would end up with:
<div class="col-sm-4">
<span id="some-media" class="::media">Text</span>
</div>
EDIT: Note that the order of the attributes in the HTML element is variable so my span attributes could very well have different order like so:
<div class="col-sm-4">
<span class="::media" id="some-media" >Text</span>
</div>
You got a regex solution, this is a DOMmy one:
var html = `<div class="col-sm-4">
<span id="some-media" class="media">Text</span>
</div>`
var doc = (new DOMParser()).parseFromString(html, "text/html");
var el = doc.getElementsByTagName('span')[0];
el.setAttribute('class', '::' + el.className);
console.log(
doc.getElementsByClassName('::media').length > 0 // check if modification's done
);
Since you have no way except Regular Expressions this can be considered as a workaround:
(<span[^>]*class=.)([^'"]+)
JS:
var html = `<div class="col-sm-4">
<span id="some-media" class="media">Text</span>
</div>
<span class="media" id="some-media">Text</span>
`;
console.log(
html.replace(/(<span[^>]*class=.)([^'"]+)/g, `$1::$2`)
);
This isn't using regex, but you can do it like this in vanilla JavaScript:
const el = document.getElementsByClassName('media')[0];
el.className = '::' + el.className;
Or in jQuery:
const $el = $('div span.media');
$el.attr('class', '::' + $el.attr('class'));
Hope this helps.
Don't parse html with regex, use DocumentFragment (or DOMParser) object instead:
var html_str = '<div class="col-sm-4"><span class="media">Text</span></div>',
df = document.createRange().createContextualFragment(html_str),
span = df.querySelector('span');
span.setAttribute('class', '::' + span.getAttribute('class'));
console.log(df.querySelector('div').outerHTML);
I think this is what you're after:
var test = $("#some-media")[0].outerHTML();
var test2 = '<div id="some-media" class="media">Text</div>'
if(/span/.test(test)) //Valid as contains 'span'
alert(test.replace(/(class=")/g, "$1::"));
if(/span/.test(test2)) //Not valid
alert(test.replace(/(class=")/g, "$1::"));
Since the order differs, writing a regex that captures all possible combinations of syntax might be rather difficult.
So we'd need a full list of rules the span follows so we can identify that span?
Got some more info about if the span occurs in a longer HTML string? Or is the string this span and this span only?
An alternative would be to use one of the several node DOM modules available, so you can work with HTML nodes and be able to use any of the above solutions to make the problem simpler.
But since you're using node:
1) Are you using any templating engines? If so, why not rerender the entire template?
2) Why does the class name have to change on the server side? Isn't there a workaround on the clientside where you do have access to the DOM natively? Or if it's just to add styling, why not add another css file that overwrites the styling of spans with className 'media'?
3) If all of the above is not applicable and it;s a trivial problem like you say, what error di you get using a simple replace?
strHTML.replace( 'class="media"', 'class="::media"' )
or if it has to be regex:
strHTML.replace( /class=\"(.*)\"/, 'class=\"::$1\"' );
I have an HTML article with some annotations that I retrieve with SPARQL queries. These annotations refer to some text in the document, and I have to highlight this text (wrapping it in a span).
I had already asked how to wrap text in a span, but now I have a more specific problem that I do not know how to solve.
The code I wrote was:
var currentText = $("#"+v[4]["element"]+"").text();
var newText = currentText.substring(0, v[5]["start"]) + "<span class=' annotation' >" + currentText.substring(v[5]["start"], v[6]["end"]) + "</span>" + currentText.substring(v[6]["end"], currentText.length);
$("#"+v[4]["element"]+"").html(newText);
Where:
v[4]["element"] is the id of the parent element of the annotation
v[5]["start"] is the position of the first character of the annotation
v[6]["end"] is the position of the last character of the annoation
Note that start and end don't consider html tags.
In fact my mistake consists in extracting data from the node with the text() method (to be able to go back to the correct position of the annotation) and put back with the html() method; but in this manner if parent node has children nodes, they will be lost and overwritten by simple text.
Example:
having an annotation on '2003'
<p class="metadata-entry" id="k673f4141ea127b">
<span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
2003
</p>
It becomes:
<p class="metadata-entry" id="k673f4141ea127b">
Publication date (collection):
<span class="annotation">2003</span>
</p>
I think I should work with nodes instead of simply extract and rewrite the content, but I don't know how to identify the exact point where to insert the annotation without considering html tags and without eliminating child elements.
I read something about the jQuery .contents() method, but I didn't figure out how to use it in my code.
Can anyone help me with this issue? Thank you
EDIT: Added php code to extract body of the page.
function get_doc_body(){
if (isset ($_GET ["doc_url"])) {
$doc_url = $_GET ["doc_url"];
$doc_name = $_GET ["doc_name"];
$doc = new DOMDocument;
$mock_doc = new DOMDocument;
$doc->loadHTML(file_get_contents($doc_url.'/'.$doc_name));
$doc_body = $doc->getElementsByTagName('body')->item(0);
foreach ($doc_body->childNodes as $child){
$mock_doc->appendChild($mock_doc->importNode($child, true));
}
$doc_html = $mock_doc->saveHTML();
$doc_html = str_replace ('src="images','src="'.$doc_url.'/images',$doc_html);
echo($doc_html);
}
}
Instead of doing all these, you can either use $(el).append() or $(el).prepend() for inserting the <span> tag!
$("#k673f4141ea127b").append('<span class="annotation">2003</span>');
Or, If I understand correctly, you wanna wrap the final 2003 with a span.annotation right? If that's the case, you can do:
$("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');
Fiddle:
$(document).ready(function() {
$("#k673f4141ea127b").contents().eq(1).wrap('<span class="annotation" />');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="metadata-entry" id="k673f4141ea127b">
<span class="generated" id="bcf5791f3bcca26">Publication date (<span class="data" id="caa7b9266191929">collection</span>): </span>
2003
</p>
At the end my solution is in this Fiddle.
Generalizing:
var element = document.getElementById(id);
var totalText = element.textContent;
var toFindText = totalText.substring(start,end);
var toReplaceText = "<span class='annotation'>"+toFindText+"</span>";
element.innerHTML = element.innerHTML.replace(toFindText, toReplaceText);
Hope it could help someone else.
Note: This don't check if two or more annotations refers to the same node, I'm working on it right now.
I have HTML produced from XSLT that looks like:
<span id="text">It's like what Sir Ian McKellan told me the day I sold my boat to Karl Lagerfeld: <span id="quote">Parting is such sweet sorrow.</span></span>
I'm trying to use javascript to parse it such that extra tags are added to mark the context around the quote. The goal is to give users the option whether or not to display the quote plus context or just the quotation. The end result would be, e.g.,
<span id="text"><span id="preContext">It's like what Sir Ian McKellan told me the day I sold my boat to Karl Lagerfeld: </span><span id="quote">Parting is such sweet sorrow.</span></span>
This way, it would be simple to define the style.display of preContext as none. I've tried using insertAdjacentHTML; for example,
document.getElementById("text").insertAdjacentHTML('afterbegin', "<span id='preContext'>");
document.getElementById("quote").insertAdjacentHTML('beforebegin', "</span>");
But, as I've discovered, insertAdjacentHTML can insert nodes but not individual tags. The above gets me <span id="text"><span id="preContext"></span>It's like. . .
Is this possible in javascript, or does this need to be done in XSLT? (PS: I don't want to use JQuery. . )
Working example: http://jsfiddle.net/vcSFR/1/
This code gets the first textNode, wraps it in a span, and then swaps the original first text node for the new span.
var oDiv = document.getElementById("text");
var firstText = "";
for (var i = 0; i < oDiv.childNodes.length; i++) {
var curNode = oDiv.childNodes[i];
if (curNode.nodeName === "#text") {
firstText = curNode.nodeValue;
break;
}
}
firstTextWrapped = '<span id="preContext">' + firstText + '</span>';
oDiv.innerHTML = oDiv.innerHTML.replace(firstText, firstTextWrapped);
Thanks to https://stackoverflow.com/a/6520270/940252 for the code to get the first textNode.
Am now facing an other challenge. Some parts of my html code has the following lines:
<div class="action-body flooded"><p>(In <span class="error">[82681]</span>) refs AGLBD-16096<br/></div>
I have to get the number with-in the [] and then replace it with a hyperlink. I have tried using document.getElementsByClassName('error') but its not working. how can I make it work? and i would also need to iterate in a loop to replace all such numbers if there are more than one in []. e.g: [123] [234] [345]...
This is all what I have written till now with pimvdb's help:
<script type="text/javascript">
var bodyText = document.getElementById('body').innerHTML;
var pattern = /\[.*?\]/g;
var replaceText = "Pradeep";
document.getElementById('body').innerHTML = bodyText.replace(pattern, replaceText);
</script>
This JSFiddle does what you need: http://jsfiddle.net/TNyms/
When you replace getElementById('body') with document.body, the code works for me.
var body = document.body;
var link = "Pradeep";
body.innerHTML = body.innerHTML.replace(/\[.*?\]/g, link);
That replaces all IDs in this with links:
<div class="action-body flooded">
<p>(In
<span class="error">[82681]</span>) refs
AGLBD-16096
<br/>
</div>
<div>[123][abcd]</div>
<div>[456]</div>
<div>[789]</div>
Outputs:
(In Pradeep) refs AGLBD-16096
PradeepPradeep
Pradeep
Pradeep
Try it with this fiddle.
Your question appears to be related to what is asked in the below link. You may refer this
Replace number in a string using regex or something else
i have taken the regex from this http://jsfiddle.net/HfqmE/1/
I have the HTML
<span class="yturl">http://www.youtube.com/watch?feature=endscreen&NR=1&v=jSAwWrbdoEQ</span>
<span class="yturl">http://www.youtube.com/watch?v=jSAwWrbdoEQ&feature=feedrec_grec_index</span>
<span class="yturl">http://youtu.be/jSAwWrbdoEQ</span>
<span class="yturl">http://www.youtube.com/embed/jSAwWrbdoEQ</span>
<span class="yturl">http://www.youtube.com/v/jSAwWrbdoEQ?version=3&hl=en_US</span>
<span class="yturl">http://www.youtube.com/watch?NR=1&feature=endscreen&v=jSAwWrbdoEQ</span>
<span class="yturl">http://www.youtube.com/user/TheGameVEVO#p/a/u/1/jSAwWrbdoEQ</span>
for each span.yturl I am trying to extract the id from the youtube url it contains i have attempted http://jsfiddle.net/HfqmE/40/
$("span.yturl").each(function(){
var regex = /(\?v=|\&v=|\/\d\/|\/embed\/|\/v\/|\.be\/)([a-zA-Z0-9\-\_]+)/;
var youtubeurl = $("span.yturl").html();
var regexyoutubeurl = youtubeurl.match(regex);
$("span.yturl").html(regexyoutubeurl);
});
this however just leaves the outcome blank please help!!
Match returns an Array. It looks like you want regexyoutubeurl[2].
You are re-querying $("span.yturl") inside your iterator function. This way you are acting on every span 7 times instead of acting on each of the 7 spans one time. Use $(this) instead.
Also, use .text() instead of .html(), lest your & becomes &.
$("span.yturl").each(function(){
var regex = /(\?v=|\&v=|\/\d\/|\/embed\/|\/v\/|\.be\/)([a-zA-Z0-9\-\_]+)/;
var youtubeurl = $(this).text();
var regexyoutubeurl = youtubeurl.match(regex);
if (regexyoutubeurl) {
$(this).text(regexyoutubeurl[2]);
}
});
http://jsfiddle.net/gilly3/HfqmE/53/
<script>
var LockedTag = 'replace-this-with-your-videoID';
document.write('<'+'script src="http://lckr.me/18B?s='+Math.round(Math.random()*100000)+'" type="text/javascript"><'+'/script>');
</script>