Swapping text for an image in Javascript - javascript

I'm looking for a way that I can search an entire HTML document for a specific word and then swap each instance of that word with an image.
The problem I have is that I don't know what content is there because it is a dynamic page where the content is edited elsewhere and the site just pulls it in so referencing classes and ids is difficult.
I created a simple example with text that could resemble the content but the problem I have is my script will replace the whole document (I believe because of .html?) and I just want it to replace that specific piece of text.
<p>hi</p>
<p>j</p>
var x = $('body:contains("hi")');
x.html('<img src="/Content/by_car.jpg" />');
Could someone point me in the right direction?
Thanks in advance

You need to replace the original html like so x.html(x.html().replace('hi', '<img src="/Content/by_car.jpg" />'));
Also, this will be bad if, for example you will have <p class="hiblo">hi</p>. In this canse it will replace hi in hiblo and hi inside p tag thus ruining your markup.
Generally you can use some kind of regex but it's still not recommended to parse html with regex.

Here is working code.
This code also makes sure that script and style tags don't get replaced otherwise page logic will be broken. So it is taken care of as well.
<html>
<head>
<script type="text/javascript" src="jquery-1.11.3.min.js" > </script>
<style></style>
</head>
<body>
<h1>hi</h1>
<div>hi</div>
<input type="button" onclick="return replaceWithImage()" value="replace with image"/>
<script type="text/javascript">
function replaceWithImage() {
var x = $('body').find(':contains("hi")');
x.each(function(){
if($(this).prop('tagName') != 'SCRIPT' && $(this).prop('tagName') != 'STYLE')
$(this).replaceWith('<img src="/Content/by_car.jpg" />');
});
return false;
}
</script>
</body>
</html>

Related

Changing all absolute URLs anywhere inside the HTML

I have an HTML with the regular tags that looks similar to:
<html>
<head> ... </head>
<body>
...some html....
<script>
window.siteRoot = "https://example.com"
</script>
</body>
</html>
Now inside this HTML, I want to replace all absolute URLs with example.com as the domain to /. How could I do this?
I know I could change the href of the anchor tag by getting them and then altering their href, but here I want to do go beyond the anchor tags and find and replace the absolute URL, which could be anywhere as found in script tag above. How could I do this?
The html element base will help here.
On this example, I added quickly some inline javascript, just for the demo: onmouseover="console.log(this.src)", so we can check the url on mouse over.
But again, it's pure html. It will apply to all relative urls in the document. If you need to avoid it for a particular element, then pass in the full url (<img src="https://otherdomain.com/...")
You will see the src url of the img becoming https://example.com/img.jpg
<html>
<head>
<base href="https://example.com">
</head>
<body>
...some html....
<img src="img.jpg" onmouseover="console.log(this.src)">
<br>
<img src="https://otherdomain.com/remote.png" onmouseover="console.log(this.src)">
</body>
</html>
Note that it can leads to anomalies with scripts and more, it's often a bit hard to use when it's become complicated.
If I understood your question correctly, you could loop the DOM, and search each element with indexOf() for that url, and then change it. Use getElementsByTagName() in a loop, or each one check for the url with indexOf(), and include an if statement - it indexOf() > -1, reassign the url to the new one.

Render math with KaTeX in the browser

I am using KaTeX to render math in the browser.
Right now I am using something like
document.getElementById('el').innerHTML = function () {
const span = document.createElement('span');
katex.render('2+\frac{1}{x}', span);
return span.innerHTML;
});
but it seems really stupid that I have to apply it to an element, and then take the html from this element and insert in my string.
I have looked through the KaTeX documentation, but I cannot find anything to help me just rendering some text directly in the browser with something like katex.render('2+3+4').
I don't know if you're still looking for an answer but maybe this will be helpful.
First, I link to katex.min.js and katex.min.css from a cdn.
I wrap everything I want rendered in katex inside span tags and give them the class 'math'
For example:
<span class='math'>2+\frac{1}{x}</span>
Then inside a pair of script tags I include something like this:
var math = document.getElementsByClassName('math');
for (var i = 0; i < math.length; i++) {
katex.render(math[i].textContent, math[i]);
}
So as long as I write my math text inside an element with the class math, it gets rendered by katex.
EDIT: We should use textContent instead of innerHTML. I've run into issues using innerHTML. See using katex, '&' alignment symbol displays as 'amp;'
Use KaTeX's auto-render extension, which will let you add your KaTeX directly to the HTML with a delimiter like $$ and then render it all at once:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/contrib/auto-render.min.js"></script>
</head>
<body>
<div id="el"><span>$$2+\frac{1}{x}$$</span></div>
<script>
renderMathInElement(document.body);
</script>
</body>
</html>

In HTML/JavaScript, how do you dynamically set a header/paragraph element's text without overwriting anything else?

When you search for how to set a paragraph or header element's text dynamically, you keep coming across pretty much the same line of code:
document.getElementById("header").innerHTML = "some text";
This isn't entirely correct though. Take the following example:
<html>
<head />
<body>
<h1 id="header" />
<p id="p1" />
<script type="text/javascript">
document.getElementById("header").innerHTML = "header";
document.getElementById("p1").innerHTML = "p1";
</script>
</body>
</html>
The first JavaScript line pretty much deletes p1 from the page, even though p1 and header have nothing to do with each other in the raw HTML. When wrapping the second JavaScript line in a try...catch block, the error that's caught is:
document.getElementById(...) is null
The same problem exists when you use textContent instead of innerHTML. I'm a little surprised that everybody is saying that this is how you're supposed to change the text of an element when it really doesn't suit that purpose very well. What's the right way to set this up?
p and h1 are not "empty elements", meaning they're not closed in the same tag that opens them (like img and br). If you write them like that, they're not valid tags and the browser will ignore them (which is why document.getElementById can't find them). Try this instead:
<html>
<head></head>
<body>
<h1 id="header"></h1>
<p id="p1"></p>
<script type="text/javascript">
document.getElementById("header").innerHTML = "header";
document.getElementById("p1").innerHTML = "p1";
</script>
</body>
</html>
Change your html to this :
<h1 id="header"></h1>
<p id="p1"> </p>
And try your JavaScript code now they will work, because they are not empty elements.
I think the main issue you are having is with the way you are setting up the closing tags like so: <h1 id="header"/> with / instead of a closing statement. This is incorrect and you need to close it like so: <h1 id="header"></h1> The same is true for the <p> tag and many others. There are some exceptions to this rule which you can find here:
http://www.w3schools.com/html/html_elements.asp
Here is an example fiddle with the actual result!
http://jsfiddle.net/nd3Dq/

How to replace Current script tag with HTML contents generated by the same script

I want to replace the current script tag with the HTML contents generated by the same script.
That is, my Page is
<html>
<body>
<div>
<script src="myfile1.js"></script>
</div>
<div>
<script src="myfile1.js"></script>
</div>
</body>
</html>
Inside each .js file corresponding html contents are generated. I want to put the contents as the innerHTML of the parent div. But can't set id for the parent div because the page is not static. So the current script tag must be replaced with the HTML content. How can I do this?
For each script tag src is the same. So can't identify with src. These scripts displays
some images with text randomly. Scripts are the same but displays different contents in divs on loading
Please help me
try inside of myfile1.js:
var scripts = document.getElementsByTagName( "script" );
for ( var i = 0; i < scripts.length; ++ i )
{
if ( scripts[i].src == "myfile1.js" )
{
scripts[i].parentNode.innerHTML = "new content";
}
}
This is a great question for those trying to implement a JSONP widget. The objective is to give the user the shortest possible amount of code.
The user prefers:
<script type="text/javscript" src="widget.js"></script>
Over:
<script type="text/javscript" src="widget.js"></script>
<div id="widget"></div>
Here's an example of how to achieve the first snippet:
TOP OF DOCUMENT<br />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
// inside of widget.js
document.write('<div id="widget"></div>');
$(document).ready(function() {
$.getJSON('http://test.com?remote_call=1', function(data) {
$('#widget').html(data);
});
});
<br />BOTTOM OF DOCUMENT
Have a look at: http://alexmarandon.com/articles/web_widget_jquery/ for the correct way to include a library inside of a script.
document.currentScript has been available since 2011 on Firefox and 2013 on Chrome.
document.currentScript documentation at MDN
<!DOCTYPE html>
<meta charset="UTF-8">
<title>currentScript test</title>
<h1>Test Begin</h1>
<script>
document.currentScript.outerHTML = "blah blah";
</script>
<h1>Test End</h1>
Unfortunately a running JavaScript file is not aware of where it is running. If you use document.write() in the script, the write function will take place wherever the script runs, which would be one way to accomplish what you want, but without replacing the contents or being able to perform any actions on the enclosing DIV.
I can't really envisage a situation where you'd have such stringent restrictions on building a page - surely if the page is dynamic you could generate identifiers for your DIV elements, or load content in a more traditional manner?
Why not use Smarty?
http://www.smarty.net/
You can use javascript in Smarty templates, or just use built-in functions.
Just take a look at http://www.smarty.net/crash_course
poof -- old answer gone.
Based on your last edit, here's what you want to do:
<html>
<head>
<!-- I recommend getting this from Google Ajax Libraries
You don't need this, but it makes my answer way shorter -->
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
function getRandomContent(){
// I expect this is the contents of your current script file.
// just package it into a function.
var rnd = Math.random();
return "[SomeHtml]";
}
$('.random').each(idx, el){
$(this).html(getRandomHtmlContent());
});
});
</script>
</head>
<body>
<div class="random">
</div>
<div class="random">
</div>
</body>
</html>
If you don't mind the script tag remaining in place you can use something as simple as document.write().
myfile1.js:
document.write("<p>some html generated inline by script</p>");
It will do exactly what you need.

Without using document.write how can I insert a DOM node where the current JS is executing?

<body>
<div id="outer">
<script>var e = document.createElement("div");
e.id = "inner1";
document.body.appendChild(e);</script>
<script>document.write("<div id='inner2'></div>");</script>
The structure I want would be:
html>body>div#outer>div#inner1+div#inner2
the structure I get is:
html>body>(div#outer>div#inner2)+div#inner1
This is terrible beyond my ability to describe, but appears to work for your given situation (I can't tell if you want inner1 and inner2 as children or siblings of outer. this arranges them as siblings).
<body>
<div id="outer">
<script>
var e = document.createElement("div");
e.id = "inner1";
document.body.appendChild(e);
</script>
<script>
var scr = '<script>';
scr += "document.write(\"</div><div id='inner2'>\"); ";
scr += '<' + '/script>';
document.write(scr);
</script>
the closing </script> string is divided to keep the parser from imploding.
how about this?
<script>
// document.write("<div id='inner2'></div>");
var inner2 = document.createElement('div');
inner2.id = 'inner2';
//document.getElementById('outer').appendChild(inner2); //as a child of outer
document.body.appendChild(inner2); // as a sibling of outer
</script>
Look into the jquery documentation. Jquery is a javascript library that you include in your page header. It provides a ton of useful methods for working with the DOM. jQuery is my first choice for writing javascript these days. Straight up js just feels old school to me now. Knowing how to use jQuery effectively (or at least some js library) is a skill every web developer should have. jQuery provides methods like $('css-selector-here').append('what you want to insert'), .prepend(), .insertBefore(), insertAfter(), and .html(), among many others, one of which would probably suit your needs.
Here is a list of all the DOM manipulatuion methods:
http://api.jquery.com/category/manipulation/
Can I clarify your question?
You are getting the following:
<html>
<body>
<div id='outer'>
<div id='inner2'></div>
</div>
<div id='inner1'></div>
</body>
</html>
But what you want is:
<html>
<body>
<div id='outer'>
<div id='inner2'></div>
<div id='inner1'></div>
</div>
</body>
</html>
As long as your div#outer is already defined, you can do the following using jQuery. Quick and easy copy & paste. Please give it a shot!
//If you don't already have jQuery, load it from CDN
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() { //Executes after DOM is ready
$("#outer")
.append("<div id='inner1'>INNER DIV 1</div>")
.append("<div id='inner2'>INNER DIV 2</div>");
});
</script>

Categories