Fix function on how to find & replace a string within a container - javascript

I have made a function here:
function locationOfVideo(){//Outputs video location div according to post text
var ytVideoDiv = '<div class="youtube-video"><div id="<?php echo $divName; ?>-video"></div></div>';
$j('#main .content:contains("<--video-->")').replace('<--video-->', ytVideoDiv);
}
I thought this would work, but I am sorely mistaken and a bit tired. Anyways, what am i doing wrong here?

replace is a plain js function to replace part of a string or similar, not to replace the content of a jQuery object.
If the goal is to replace all the content in the selected element, and if you're using the right selector, you could use html() and do :
$j('#main .content:contains("<--video-->")').html(ytVideoDiv);
or to replace just the string <--video--> :
$j('#main .content:contains("<--video-->")').html(function(i,html) {
return html.replace('<--video-->', ytVideoDiv)
});​
FIDDLE

Don't use <--video--> in your html, change to some other like {video}.
Then do it with:
$('#main .content:contains("{video}")').replaceWith(function() {
return $(this).text().replace('{video}', ytVideoDiv);
});

$j('#main .content:contains("<!--video-->")').replace('<--video-->', ytVideoDiv);
should be:
var videoNode = $j('#main .content:contains("<!--video-->")');
videoNode.html(videonode.html().replace('<!--video-->', ytVideoDiv));
or:
$j('#main .content:contains("<!--video-->")').html(function(index, oldhtml) { return oldhtml.replace('<--video-->', ytVideoDiv); });

It's better to output elements with special tag like abbr, check out javascript template usabe like jquery-timeago:
<abbr class="timeago" title="2011-12-17T09:24:17Z">December 17, 2011</abbr>
replace:
$('abbr.timeago').timeago()

Related

Check if field contains numbers, wrap the numbers with container and class?

If you have something simple like this in HTML:
<div class="main">Item 7,000</div>
How to make javascript apply an html element and a class for the 7,000 part (because its numeric) on page load? To something like this:
<div class="main">Item <span class="wrap">7,000</span></div>
Or maybe just an html element, if with class not possible.
I apologies I don't have any code to share right now. I'm still browsing other questions.
Maybe it should be something with jQuery if $.isNumeric() is true then apply element?
There will be edge case but accomplishes your goal
$(function () {
$(".main").each(function (index, element) {
var $element = $(element);
var wrapped = $element.text().replace(/(.+?)((\d{1,3},?)+)/g, '$1<span class="wrap">$2</span>');
$element.html(wrapped);
});
});
.wrap {
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main">Item 7,000</div>
<div class="main">Item 960</div>
<div class="main">Item 7,000,000</div>
If you use node.textContent you can get the string inside the div
string = document.querySelector('#main').textContent // --> "Item 7,000"
From here you can use Array#split to separate each word:
array = string.split(' '); --> ['Item','7,000']
Now remove the comma and check isNaN for each, return an array w:
newNode = array.map((e)=> isNaN(e.replace(/,/g,"")) ? e : {element:'span', content: e})
Now you have ['Item', { element: 'span', content: '7,000'}] which you can use to generate the contents of the div element in your example...
There might be way better ways to do this, I am just trying to help :)
Use javascript regex find a matching number and replace with span
var regex =/\b(\d+)\b/g
var regex =/\b(\d+)\b/g
var text = document.getElementById("main").innerHTML;
document.getElementById("main").innerHTML = text.replace(regex,'<span class="wrap">$1</span>')
span.wrap{
color:red;
}
<p id="main">Item : 7000</p>

Jquery: Replace a part of each attribute [duplicate]

Do someone know what is the best way to replace some string inside a onclick attribute ?
I need to get the current value and replace some text inside parameters.
Exemple, I have this link:
My link
And I want this:
My link
In other words, I want something like this:
$('a').attr('onclick', $(this).attr('onclick').replace('1', '2'));
And I know I can do this, but I need something dynamic retreiving the values of current element:
$("a").attr('onClick', "myfunction('parameter2a','parameter2b')");
Finally it working when I made a simple demo: http://jsfiddle.net/GkWhh/4/
Thank you for your solutions !
$('a[onclick]').attr('onclick', function(i, v){
return v.replace(/1/g, '2');
});
http://jsfiddle.net/cj9j7/
If you need something more dynamic do not use onclick attributes, changing onclick attributes is hackish, you can use click method instead.
var param = 1;
$('a').click(function(){
// ...
if ('wildguess') {
param = 1;
} else {
param++;
}
})
sounds like a really bad idea but anyway - you can access the string value of the onlick attribute using something like that:
$('a').each(function() { this.attributes.onclick.nodeValue = this.attributes.onclick.nodeValue.replace('1', '2'); })
You can do this: http://jsfiddle.net/SJP7k/
var atr = $('a').attr('onclick');
var str = atr.split('1');
var natr = str.join('2');
$('a').attr('onclick',natr);

How to search specific attribute within a tag and remove it using javascript regex

Basically I have this kind of tag (just for example)
<div type="text" onclick="event();" onblur="event();">this div has onclick and onblur functions</div>
and I want to remove some attributes to that tag using a reference variable.
var refAttribs = ['onclick', 'onblur'];
So it should strip out all attributes from refAttribs.
Be careful not to strip out the content of the div. Because it also contains a string from the refAttribs variable.
How do I get rid of them using a regex?
Thanks in advance
As you've stated the tag is a string then you could santise it with the following javascript.
var refAttribs = ['onclick', 'onblur'];
function remove(tagToClean)
{
var result = tagToClean;
for(var i=0; i<refAttribs.length; i++)
{
regex = new RegExp(refAttribs[i] + "=\"[a-zA-Z\(\);]*?\"", "g");
result = result.replace(regex, "");
}
return result;
}
You can call the method by passing in your string.
remove('<div type="text" onclick="event();" onblur="event();">this div has onclick and onblur functions</div>');
I'm not 100% sure what you're trying to do here. Are you trying to modify the DOM? If so you will need to modify the method to accept a handle to a DOM node. A little more information would help.
Well, try this:
To remove onclick, the regex will be:
(<[^>]+)\s+onclick\s*=[\'"].*?[\'"]
Debuggex Demo
The removeAttr function:
function removeAttr(html, attr) {
return html.replace(new RegExp('(<[^>]+)\\s+' + attr + '\\s*=[\'"].*?[\'"]', 'gi'), '$1');
}
http://jsfiddle.net/rooseve/pC4aH/1/

How to change text inside span with jQuery, leaving other span contained nodes intact?

I have the following HTML snippet:
<span class="target">Change me <a class="changeme" href="#">now</a></span>
I'd like to change the text node (i.e. "Change me ") inside the span from jQuery, while leaving the nested <a> tag with all attributes etc. intact. My initial huch was to use .text(...) on the span node, but as it turns out this will replace the whole inner part with the passed textual content.
I solved this with first cloning the <a> tag, then setting the new text content of <span> (which will remove the original <a> tag), and finally appending the cloned <a> tag to my <span>. This works, but feels such an overkill for a simple task like this. Btw. I can't guarantee that there will be an initial text node inside the span - it might be empty, just like:
<span class="target"><a class="changeme" href="#">now</a></span>
I did a jsfiddle too. So, what would be the neat way to do this?
Try something like:
$('a.changeme').on('click', function() {
$(this).closest('.target').contents().not(this).eq(0).replaceWith('Do it again ');
});
demo: http://jsfiddle.net/eEMGz/
ref: http://api.jquery.com/contents/
Update:
I guess I read your question wrong, and you're trying to replace the text if it's already there and inject it otherwise. For this, try:
$('a.changeme').on('click', function() {
var
$tmp = $(this).closest('.target').contents().not(this).eq(0),
dia = document.createTextNode('Do it again ');
$tmp.length > 0 ? $tmp.replaceWith(dia) : $(dia).insertBefore(this);
});
​Demo: http://jsfiddle.net/eEMGz/3/
You can use .contents():
//set the new text to replace the old text
var newText = 'New Text';
//bind `click` event handler to the `.changeme` elements
$('.changeme').on('click', function () {
//iterate over the nodes in this `<span>` element
$.each($(this).parent().contents(), function () {
//if the type of this node is undefined then it's a text node and we want to replace it
if (typeof this.tagName == 'undefined') {
//to replace the node we can use `.replaceWith()`
$(this).replaceWith(newText);
}
});
});​
Here is a demo: http://jsfiddle.net/jasper/PURHA/1/
Some docs for ya:
.contents(): http://api.jquery.com/contents
.replaceWith(): http://api.jquery.com/replacewith
typeof: https://developer.mozilla.org/en/JavaScript/Reference/Operators/typeof
Update
var newText = 'New Text';
$('a').on('click', function () {
$.each($(this).parent().contents(), function () {
if (typeof this.tagName == 'undefined') {
//instead of replacing this node with the replacement string, just replace it with a blank string
$(this).replaceWith('');
}
});
//then add the replacement string to the `<span>` element regardless of it's initial state
$(this).parent().prepend(newText);
});​
Demo: http://jsfiddle.net/jasper/PURHA/2/
You can try this.
var $textNode, $parent;
$('.changeme').on('click', function(){
$parent = $(this).parent();
$textNode= $parent.contents().filter(function() {
return this.nodeType == 3;
});
if($textNode.length){
$textNode.replaceWith('Content changed')
}
else{
$parent.prepend('New content');
}
});
Working demo - http://jsfiddle.net/ShankarSangoli/yx5Ju/8/
You step out of jQuery because it doesn't help you to deal with text nodes. The following will remove the first child of every <span> element with class "target" if and only if it exists and is a text node.
Demo: http://jsfiddle.net/yx5Ju/11/
Code:
$('span.target').each(function() {
var firstChild = this.firstChild;
if (firstChild && firstChild.nodeType == 3) {
firstChild.data = "Do it again";
}
});
This is not a perfect example I guess, but you could use contents function.
console.log($("span.target").contents()[0].data);
You could wrap the text into a span ... but ...
try this.
http://jsfiddle.net/Y8tMk/
$(function(){
var txt = '';
$('.target').contents().each(function(){
if(this.nodeType==3){
this.textContent = 'done ';
}
});
});
You can change the native (non-jquery) data property of the object. Updated jsfiddle here: http://jsfiddle.net/elgreg/yx5Ju/2/
Something like:
$('a.changeme3').click(function(){
$('span.target3').contents().get(0).data = 'Do it again';
});
The contents() gets the innards and the get(0) gets us back to the original element and the .data is now a reference to the native js textnode. (I haven't tested this cross browser.)
This jsfiddle and answer are really just an expanded explanation of the answer to this question:
Change text-nodes text
$('a.changeme').click(function() {
var firstNode= $(this).parent().contents()[0];
if( firstNode.nodeType==3){
firstNode.nodeValue='New text';
}
})
EDIT: not sure what layout rules you need, update to test only first node, otherwise adapt as needed

Using jQuery to replace one tag with another

Goal:
Using jQuery, I'm trying to replace all the occurrences of:
<code> ... </code>
with:
<pre> ... </pre>
My solution:
I got as far as the following,
$('code').replaceWith( "<pre>" + $('code').html() + "</pre>" );
The problem with my solution:
but the issues is that it's replacing everything between the (second, third, fourth, etc)"code" tags with the content between the first "code" tags.
e.g.
<code> A </code>
<code> B </code>
<code> C </code>
becomes
<pre> A </pre>
<pre> A </pre>
<pre> A </pre>
I think I need to use "this" and some sort of function but I'm afraid I'm still learning and don't really understand how to piece a solution together.
You can pass a function to .replaceWith [docs]:
$('code').replaceWith(function(){
return $("<pre />", {html: $(this).html()});
});
Inside the function, this refers to the currently processed code element.
DEMO
Update: There is no big performance difference, but in case the code elements have other HTML children, appending the children instead of serializing them feels to be more correct:
$('code').replaceWith(function(){
return $("<pre />").append($(this).contents());
});
This is much nicer:
$('code').contents().unwrap().wrap('<pre/>');
Though admittedly Felix Kling's solution is approximately twice as fast:
It's correct that you'll always obtain the first code's contents, because $('code').html() will always refer to the first element, wherever you use it.
Instead, you could use .each to iterate over all elements and change each one individually:
$('code').each(function() {
$(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
// this function is executed for all 'code' elements, and
// 'this' refers to one element from the set of all 'code'
// elements each time it is called.
});
Try this:
$('code').each(function(){
$(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
});
http://jsfiddle.net/mTGhV/
How about this?
$('code').each(function () {
$(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
});
Building up on Felix's answer.
$('code').replaceWith(function() {
var replacement = $('<pre>').html($(this).html());
for (var i = 0; i < this.attributes.length; i++) {
replacement.attr(this.attributes[i].name, this.attributes[i].value);
}
return replacement;
});
This will reproduce the attributes of the code tags in the replacement pre tags.
Edit: This will replace even those code tags that are inside the innerHTML of other code tags.
function replace(thisWith, that) {
$(thisWith).replaceWith(function() {
var replacement = $('<' + that + '>').html($(this).html());
for (var i = 0; i < this.attributes.length; i++) {
replacement.attr(this.attributes[i].name, this.attributes[i].value);
}
return replacement;
});
if ($(thisWith).length>0) {
replace(thisWith, that);
}
}
replace('code','pre');
As of jQuery 1.4.2:
$('code').replaceWith(function(i,html) {
return $('<pre />').html(html);
});​
You can then select the new elements:
$('pre').css('color','red');
Source: http://api.jquery.com/replaceWith/#comment-45493689
jsFiddle: http://jsfiddle.net/k2swf/16/
If you were using vanilla JavaScript you would:
Create the new element
Move the children of old element into the new element
Insert the new element before the old one
Remove the old element
Here is jQuery equivalent of this process:
$("code").each(function () {
$("<pre></pre>").append(this.childNodes).insertBefore(this);
$(this).remove();
});
Here is the jsperf URL:
http://jsperf.com/substituting-one-tag-for-another-with-jquery/7
PS: All solutions that use .html() or .innerHTML are destructive.
Another short & easy way:
$('code').wrapInner('<pre />').contents();
All answers given here assume (as the question example indicates) that there are no attributes in the tag. If the accepted answer is ran on this:
<code class='cls'>A</code>
if will be replaced with
<pre>A</pre>
What if you want to keep the attributes as well - which is what replacing a tag would mean... ? This is the solution:
$("code").each( function(){
var content = $( "<pre>" );
$.each( this.attributes, function(){
content.attr( this.name, this.value );
} );
$( this ).replaceWith( content );
} );
$('code').each(function(){
$(this).replaceWith( "<pre>" + $(this).html() + "</pre>" );
});
Best and clean way.
You could use jQuery's html function. Below is a sample the replaces a code tag with a pre tag while retaining all of the attributes of the code.
$('code').each(function() {
var temp=$(this).html();
temp=temp.replace("code","pre");
$(this).html(temp);
});
This could work with any set of html element tags that needed to be swapped while retaining all the attributes of the previous tag.
Made jquery plugin, maintaining attributes also.
$.fn.renameTag = function(replaceWithTag){
this.each(function(){
var outerHtml = this.outerHTML;
var tagName = $(this).prop("tagName");
var regexStart = new RegExp("^<"+tagName,"i");
var regexEnd = new RegExp("</"+tagName+">$","i")
outerHtml = outerHtml.replace(regexStart,"<"+replaceWithTag)
outerHtml = outerHtml.replace(regexEnd,"</"+replaceWithTag+">");
$(this).replaceWith(outerHtml);
});
return this;
}
Usage:
$('code').renameTag('pre')

Categories