jQuery .html() working OK, but JavaScript .innerHTML not working - javascript

I'm unable to find out the reason why $('#valvonta_d').html(data); is working, but valvonta_div.innerHTML = data; is not working at all.
I have some JavaScript/jQuery code:
$(document).ready(function(){
valvonta = function() {
var kaavio = 106;
jQuery.post("hae_tilanteet.php", {
kaavio: kaavio
}).done(function(data) {
// the following would work, but I prefer using JavaScript:
// $('#valvonta_d').html(data);
// this is not working
var valvonta_div = document.getElementById('valvonta_d');
valvonta_div.innerHTML = data;
});
};
setTimeout(valvonta, 6000);
};
I have this HTML code:
<div id="valvonta_d"></div>

the value of variable data is <script>...</script>.
<script> elements inserted via innerHTML are intentionally disabled/ignored by the browser out of concern for it potentially permitting cross-site scripting.
You'll have to evaluate them yourself by retrieving their contents in a separate step.
}).done(function(data) {
var valvonta_div = document.getElementById('valvonta_d');
valvonta_div.innerHTML = data;
Array.from(valvonta_div.querySelectorAll('script')).forEach(function (script) {
if (script.getAttribute('src')) return;
// `(0, ...)` for global eval via indirect reference
(0, eval)(script.textContent || '');
});
});
Though, if you can, try to avoid the need to eval().
In general at least, you should be able to define a generic form of the <script> as a function, included within the page prior to this.
function prepareVolvanta(kaavio, container) {
// ...
}
Then, call that function when the content is ready.
var valvonta_div = document.getElementById('valvonta_d');
valvonta_div.innerHTML = data; // content markup only
prepareVolvanta(kaavio, valvonta_div);
Related: Can scripts be inserted with innerHTML?

Related

How to have my scripts interact with each other?

When my webpage has loaded it runs this script:
$(function() {
return $.ajax({
type: "get",
dataType: "json",
url: "/get_script",
success: function(data, status, xhr) {
return $("#myScript").html(data.myScript);
}
});
});
The script gets another script from my server (the data.myScript object). The new script that is added to my webpage looks like this:
<script>
initScript = function() {
return window.random_string = Math.random().toString(36).substring(7);
};
$(window).bind("popstate", 'hashchange', function() {
return initScript();
});
window.random_string = null;
initScript();
</script>
If the new script needs to make variables available for other scripts on the webpage I put them into a window.my_variable variable, but I'd like instead to be able to call e.g. MyScript.random_string.
I'd also like to be able to trigger the initScript function from other scripts. Like e.g. MyScript.initScript()
How do I achieve this?
Firstly I'd suggest using $.getScript to load your JS code assuming you cannot embed it directly in a <script> tag.
To solve your actual issue you just need to structure it in the manner you require. Simply create an object like var MyScript = {}; then place all the functions and variables as properties within that object, something like this:
$.getScript('/get_script', function() {
// put logic to run after the script has loaded here...
// note that you don't need your .html(data.myScript) any more
MyScript.initScript();
console.log(MyScript.random_string);
});
// in your external script:
var MyScript = {
initScript = function() {
this.random_string = Math.random().toString(36).substring(7);
},
random_string: null;
}

How to show the result of this jQuery function without the need of clicking the button?

I have this function below, however I want to make it work on windows load and show the result without clicking the button.
This is the code I use https://raw.githubusercontent.com/SuyashMShepHertz/indexedDB_sample/master/index.html
How to do this?
$("#getBtn").click(function(){
var type = 'permanent';
var request = db.transaction(["hashes"],"readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event){
$("#result").html("Name : "+request.result.name);
};
});
just put your code in
$( window ).load(function() {
//Code Here
});
If you need it both on click and initially when the page loads, make it a reusable function:
function doTheThing() {
var type = 'permanent';
var request = db.transaction(["hashes"], "readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event) {
$("#result").html("Name : " + request.result.name);
};
}
Then call it from both places you need it:
On page load
On click
To call it on page load, just make sure your script is at the end of the HTML (just before the closing </body> tag; this is best practice unless you have a good reason for doing something else) and call it:
doTheThing();
If you can't put the script at the end of the HTML, you can use jQuery's ready callback instead:
// Concise, but easy to misunderstand:
$(doTheThing);
// Or more verbose but also more clear:
$(document).ready(doTheThing);
(See note below about doing it directly or indirectly.)
To call it on click, hook it up, either directly or indirectly:
// Directly
$("#getBtn").click(doTheThing);
// Or indirectly
$("#getBtn").click(function() {
doTheThing();
});
The only reason for hooking it up indirectly would be to avoid having it receive the event object jQuery will pass it automatically, and to avoid having its return value examined by jQuery to see if it should stop propagation and prevent the default event action.
To avoid creating globals, I'd make sure the entire thing is in a scoping function:
(function() {
function doTheThing() {
var type = 'permanent';
var request = db.transaction(["hashes"], "readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event) {
$("#result").html("Name : " + request.result.name);
};
}
doTheThing();
$("#getBtn").click(doTheThing);
})();
just put it in $(document).ready, like this
$(document).ready(function(){
var type = 'permanent';
var request = db.transaction(["hashes"],"readwrite").objectStore("hashes").get(type);
request.onsuccess = function(event){
$("#result").html("Name : "+request.result.name);
};
});

Load Javascript into ajax loaded content

I am new to working with AJAX and have some experience with Java/Jquery. I have been looking around for an solution to my problem but i cant seem to find any.
I am trying to build a function in a webshop where the product will appear in a popup window instead of loading a new page.
I got it working by using this code:
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
$("#product-overlay-inner").load(myUrl, function() {
});
$("#product-overlay").fadeIn();
return false;
});
product-slot a = Link to the product in the category page.
product-content = the div i want to insert in the popup from the product page.
product-overlay-inner = The popup window.
product-overlay = The popup wrapper.
The problem that i now have is that my Javascript/Jquery isnt working in the productpopup. For example the lightbox for the product image or the button to add product to shoppingcart doesnt work. Is there anyway to make the javascript work inside the loaded content or to load javascript into the popup?
I hope you can understand what my problem is!
Thank you in advance!
EDIT: The platform im using has jquery-ui-1.7.2
I know this is an old thread but I've been working on a similar process with the same script loading problem and thought I'd share my version as another option.
I have a basic route handler for when a user clicks an anchor/button etc that I use to swap out the main content area of the site, in this example it's the ".page" class.
I then use a function to make an ajax call to get the html content as a partial, at the moment they are php files and they do some preliminary rendering server side to build the html but this isn't necessary.
The callback handles placing the new html and as I know what script I need I just append it to the bottom in a script tag created on the fly. If I have an error at the server I pass this back as content which may be just a key word that I can use to trigger a custom js method to print something more meaningful to the page.
here's a basic implementation based on the register route handler:
var register = function(){
$(".page").html("");
// use the getText ajax function to get the page content:
getText('partials/register.php', function(content) {
$(".page").html(content);
var script = document.createElement('script');
script.src = "js/register.js";
$(".page").append(script);
});
};
/******************************************
* Ajax helpers
******************************************/
// Issue a Http GET request for the contents of the specified Url.
// when the response arrives successfully, verify it's plain text
// and if so, pass it to the specified callback function
function getText(url, callback) {
var request = new XMLHttpRequest();
request.open("GET", url);
request.onreadystatechange = function() {
// if the request is complete and was successful -
if (request.readyState === 4 && request.status === 200) {
// check the content type:
var type = request.getResponseHeader("Content-Type");
if (type.match(/^text/)) {
callback(request.responseText);
}
}
};
// send it:
request.send(null); // nothing to send on GET requests.
}
I find this a good way to 'module-ize' my code into partial views and separated JavaScript files that can be swapped in/out of the page easily.
I will be working on a way to make this more dynamic and even cache these 'modules' for repeated use in an SPA scenario.
I'm relatively new to web dev so if you can see any problems with this or a safer/better way to do it I'm all ears :)
Yes you can load Javascript from a dynamic page, but not with load() as load strips any Javascript and inserts the raw HTML.
Solution: pull down raw page with a get and reattach any Javascript blocks.
Apologies that this is in Typescript, but you should get the idea (if anything, strongly-typed TypeScript is easier to read than plain Javascript):
_loadIntoPanel(panel: JQuery, url: string, callback?: { (): void; })
{
// Regular expression to match <script>...</script> block
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts: string = "";
var match;
// Do an async AJAX get
$.ajax({
url: url,
type: "get",
success: function (data: string, status: string, xhr)
{
while (match = re.exec(data))
{
if (match[1] != "")
{
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
// Replace the contents of the panel
//panel.html(data);
// If you only want part of the loaded view (assuming it is not a partial view)
// using something like
panel.html($(data).find('#product-content'));
// Add the scripts - will evaluate immediately - beware of any onload code
panel.append(scripts);
if (callback) { callback(); }
},
error: function (xhr, status, error)
{
alert(error);
}
});
}
Plain JQuery/Javascript version with hooks:
It will go something like:
var _loadFormIntoPanel = function (panel, url, callback) {
var that = this;
var re = /<script\b[^>]*>([\s\S]*?)<\/script>/gm;
var scripts = "";
var match;
$.ajax({
url: url,
type: "get",
success: function (data, status, xhr) {
while(match = re.exec(data)) {
if(match[1] != "") {
// TODO: Any extra work here to eliminate existing scripts from being inserted
scripts += match[0];
}
}
panel.html(data);
panel.append(scripts);
if(callback) {
callback();
}
},
error: function (xhr, status, error) {
alert(error);
}
});
};
$(".product-slot a").live('click', function() {
var myUrl = $(this).attr("href") + " #product-content";
_loadFormIntoPanel($("#product-overlay-inner"), myUrl, function() {
// Now do extra stuff to loaded panel here
});
$("#product-overlay").fadeIn();
return false;
});

How to replace DOM node with remote javascript in PhantomJS

I'm new to PhantomJS and javascript, so forgive me if there is a simple solution.
I'm using PhantomJS to do screenshots of websites, and I want to replace certain DOM nodes with dynamic content from a remote javascript, something like this:
<script language="JavaScript" src="http://server/dynamic.js" type="text/javascript"></script>
My first try:
var page = require('webpage').create();
page.open('http://stackoverflow.com', function (status) {
if (status !== 'success') {
phantom.exit();
}
page.evaluate(function() {
//// Case #1: what I really want
// var s = '<script language="JavaScript" src="http://server/dynamic.js" type="text/javascript"></script>';
//// Case #2: simple js test case
// var s = '<script language="JavaScript" type="text/javascript">document.write("<p>THIS IS A TEST</p>");</script>';
//// Case #3: very simple case
var s = '<b>THIS IS A TEST</b>';
var node = document.getElementById('mainbar');
var pnode = node.parentNode;
var newele = document.createElement('div');
newele.innerHTML = s;
pnode.replaceChild(newele, node);
});
page.render('test.jpg');
phantom.exit();
});
For the simple case (case #3) where I'm just replacing it with some text, it works fine, but not for either of the javascript cases. It seems the javascript isn't being evaluated after being inserted via replaceChild(). I tried page.reload() just before page.render() but it didn't help.
Next, I tried creating the new element using iframe:
var newele = document.createElement('iframe');
newele.setAttribute('src', 'javascript:document.write("<p>THIS IS A TEST</p>");');
This works for the simple js test case #2, but I can't figure out how to make iframe work with what I really want (Case #1).
Any suggestions?
I came up with a workable solution:
var newele = document.createElement('iframe');
newele.setAttribute('src', 'javascript:document.write("<script src=\'http://server/dynamic.js\'></script>");');
I also had to put in a bit of delay:
window.setTimeout(function () {
page.render('test.jpg');
phantom.exit();
}, 500);
This works, but feels a little klugy to me. I would love to hear a better solution.
Nope, you can add your javascript reference to the page like this, right before calling evaluate the first time (excerpt):
...
page.open(url, function (status) {
if (status !== 'success') {
console.log('Error: Cannot load url. Status: {0}.'.format(status));
phantom.exit(1);
} else {
page.injectJs('../../../code/common/jquery.min.js');
// call evaluate once to change the dropdown:
page.evaluate(function (myobj) {
// manipulate DOM here with jquery, or whatever you want.
}, myobj);
...
Please note that you can call evaluate several times, so you can extract stuff from the page, call javascript functions from the page, modify DOM, etc.

read this xml with jquery

I'm having trouble reading this xml with jQuery.
http://jsfiddle.net/VLtqY/2/
XML:
<myElements type="AA" coID="A923">
<element1>01</element1>
<element2>02</element2>
<element3>03</element3>
</myElements>
I'm looking for the following output:
element1=01
element2=02
element3=03
A little help please.
First, you need to wrap your xml variable in a call to the jQuery function, as in $(xml). Then, a call to children() will get all of your target elements.
Here's a very basic (and sloppy), working example of iterating through the elements, but it's just the selector that needs changing:
var xml = '<myElements type="AA" coID="A923"><element1>01</element1> <element2>02</element2><element3>03</element3></typeData>';
var myOutput = $("#output");
myOutput.append("=== start ===<br />");
$(xml).children().each(function () {
var xmlnode = $(this);
myOutput.append(this.tagName + xmlnode.text() + '<br/>');
});
myOutput.append("=== end ===");
Working demo: http://jsfiddle.net/UByfW/2/
Try this
$('*', xml).each(function () {
replacing the the line
$(xml).find("myElements").each(function () {
or
$(xml).children().each(function () {
The reason is self-explanatory: you must fetch the children, not the root element.
You can use the jQuery parseXML (see docs) function to parse the string of XML into an XML document object. Just add this line somewhere between the variable declaration and your each loop:
xml = $.parseXML(xml);
The rest of it should work fine then. You can see an example here.
I would really suggest ajax for this. IE hates the way jquery grabs the xml.I have been using this for a very long time with lots of success and no problems.
$.ajax({
url: "path-to-file.xml",
dataType: ($.browser.msie) ? "text" : "xml",
success: function(data){
var xml;
if (typeof data == "string") {
xml = new ActiveXObject("Microsoft.XMLDOM");
xml.async = false;
xml.loadXML(data);
} else {
xml = data;
}
alert($(xml).find('element1').text());
alert($(xml).find('element2').text());
alert($(xml).find('element3').text());
},//END SUCCSESS
error: function(){
alert("Sorry, There was an error loading this information. Refresh the page or try again later. ");
history.go(-1);
}
});//END AJAX CALL
I know this looks like a lot, but it really isn't that bad. Put your path to your xml, in the .each() do what you want to do.

Categories