I am using in-browser XSLT to generate HTML, <script> included. Firefox apparently behaves oddly in this case.
The files below can be obtained and tried from there. (Open doc.xml and look at the log messages in the console.)
Below is the test XSLT stylesheet I made. The XML source doc.xml is simply <?xml-stylesheet type="text/xsl" href="stylesheet.xsl"?><doc/>. The transform creates both an inline and an external script:
<html xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xsl:version="1.0">
<head>
<title>Firefox and XSLT inserted scripts</title>
</head>
<body>
<script type="text/javascript" src="script.js"></script>
<script type="text/javascript">
console.log('inline, asynchronous? '+ document.currentScript.async);
// -> "inline, asynchronous? false"
// alert('inline, pause');
function errorHandler(img) {
img.src = 'http://people.mozilla.com/~faaborg/files/shiretoko/firefoxIcon/firefox-32-noshadow.png';
}
try {
document.write("<p>Inserted</p>");
} catch(e) {
console.error(e.name + ": " + e.message);
// -> "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"
}
</script>
<p><img src="about:blank" onError="window.errorHandler?errorHandler(this):console.log('Too late for handling error!')"/></p>
</body>
</html>
The external script script.js is almost the same as the one inline:
console.log('external, asynchronous? '+document.currentScript.async);
// -> "external, asynchronous? false"
// alert('external, pause');
try {
document.write("<p>Inserted</p>");
} catch(e) {
console.error(e.name + ": " + e.message);
// -> "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"
}
The console displays:
19:21:14.435 "Too late for handling error!" index.xml:1
19:21:14.477 "external, asynchronous? false" script.js:1
19:21:14.478 "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"
script.js:7
19:21:14.479 "inline, asynchronous? false" index.xml:1
19:21:14.480 "InvalidStateError: An attempt was made to use an object that is not, or is no longer, usable"
index.xml:10
At first, the scripts seem synchronous, since async is false.
But in reality, they do behave asynchronously!
One cannot use document.write.
Callbacks (errorHandler() in my example) aren't immediately available.
Does anyone has a clue about what is happening here?
Mozilla's XSLT processor implementation creates a result tree and renders that directly so using document.write is not supported, see https://developer.mozilla.org/en/docs/XSL_Transformations_in_Mozilla_FAQ#What_about_document.write.3F. Other client-side XSLT processor implementations might feed the serialized transformation result to its HTML parser, in that case document.write works.
If you want to output stuff with your scripts inside XSLT then you need to use the DOM methods to create nodes and insert them. See http://home.arcor.de/martin.honnen/xslt/test2013122801.xml for an example.
Related
I wrote the following HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<title>HTML page</title>
</head>
<body>
<script src='http://localhost:3000?callback=mycallbackFunction'> </script>
<script>
function mycallbackFunction(data) {
alert('here');
alert (data['a']);
}
</script>
</body>
</html>
As you can see, the script tag includes a JSONP request to a remote server.
In addition, I wrote the following node.js file and ran it as a server:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.jsonp({'a': 'blabla'});
});
app.listen(3000);
After I had run the node.js file and opened the browser with the html page, I expected to see a pop-up window of alert. But, no. I didn't see anything.
The Network Tab in Developer Tools shows that the request has been accepted:
Do you know how to resolve it?
You need to swap the order of your <script> elements.
Explanation:
Express is correctly serving a script that looks like myCallbackFunction({'a': 'blabla'}), which is exactly what you hoped for. However, this script runs immediately, and myCallbackFunction has yet to be defined, so nothing happens. Then, in the next <script> block, you define myCallbackFunction, but this is useless, since the (failed) call has already happened in the previous <script>.
Also, you have a case mismatch on the C in mycallbackFunction -- make sure the capitalization agrees between the callback parameter and the name of your function.
The solution is to switch the order of both script tags:
<body>
<script>
function mycallbackFunction(data) {
alert('here');
alert (data['a']);
}
</script>
<script src='http://localhost:3000?callback=mycallbackFunction'> </script>
</body>
I'm just blundering into AJAX, and I swear I'll actually learn my way around it real soon now, but all I need at the moment is to get the inner browser height, so I can ask the Google Maps Engine for a map of the appropriate height. (I'm actually making that request via the Google Maps plugin under Joomla. If I could somehow make that request on the client side, then I might not really have to mess with AJAX, but this would still be a good introductory exercize for me.)
I'm trying to grasp the basic AJAX setup by putting together a working minimal document incorporating code from the first answer at how to get screen width through php?. I realize that example is asking for a different attribute than I'll be asking for, but I'm just keeping the code as close to the original as possible.
I'm not totally clear on what code goes where, but apparently it is not this, at http://allbluesdance.com/testajax.php :
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Test Ajax</title>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script>
var width = $(window).width();
//This is ajax code which will send width to your php page in the screenWidth variable
$.ajax({
url: "http://allbluesdance.com/testajax.php", //this will be your php page
data : {screenwidth:width}
}).done(function() {
$(this).addClass("done");
});
</script>
(Yeah, it's running)
<!-- example.php code is here : -->
<?php
echo $width = $_REQUEST['screenwidth'];
?>
</body>
</html>
So unless I've made a dumb syntax error I could use a clue.
Thanks,
Drew
I think you need to specify how AJAX gets the data, either through GET or POST. I Have been using this snippet and it works for me.
// fire off the request
var request = $.ajax({
url: "/list/server.php",
type: "POST",
data: send_data
});
// callback handler that will be called on success
request.done(function (response){
// log a message to the console
console.log(response);
});
HTML code :
<html>
<head>
</head>
<body>
<script type="text/javascript" src="/js/colorbook.js"></script>
<script type="text/javascript">
book.init();
</script>
</body>
</html>
JS code :
var book = (function(){
init = function(){
console.log ( "initialized")
}return init();
}());
Question : The above code works. But I am unable to understand how?. Can any of JS guys help me here or guide me how should I start debug this code to understand it.
Ok so as per your comment. The Javascript you have there is all executed sequentially as the browser reads it from the incoming data stream. That being said, All javascript contained within the first script tag will be executed. Then the second script tag will be executed in sequence as well.
So right now you can look at the book.init() as being the last provided javascript call to be executed.
I tried your JS code in jsfiddle and could not get it to work check This Fiddle to see what I mean.
What is happening in your JS code is the last () at the end of the var book declaration executes the anonymous function which will print the line to the console. However from the code you supplied the book variable never gets a book.init() method. So once that call is reached it will throw an error of undefined.
This is a super simple question that I just can't seem to find a good answer too.
$.get('/myurl.html', function(response){
console.log(response); //works!
console.log( $(response).find('#element').text() ); //null :(
}, 'html');
I am just trying to traverse my the html response. So far the only thing I can think of that would works is to regex to inside the body tags, and use that as a string to create my traversable jQuery object. But that just seems stupid. Anyone care to point out the right way to do this?
Maybe its my html?
<html>
<head>
<title>Center</title>
</head>
<body>
<!-- tons-o-stuff -->
</body>
</html>
This also works fine but will not suit my needs:
$('#myelem').load('/myurl.html #element');
It fails because it doesn't like <html> and <body>.
Using the method described here: A JavaScript parser for DOM
$.get('/myurl.html', function(response){
var doc = document.createElement('html');
doc.innerHTML = response;
console.log( $("#element", doc).text() );
}, 'html');
I think the above should work.
When jQuery parses HTML it will normally strip out the html and body tags, so if the element you are searching for is at the top level of your document structure once the html and body tags have been removed then the find function may not be able to locate the element you're searching for.
See this question for further info - Using jQuery to search a string of HTML
Try this:
$("#element", $(response)).text()
This searches for the element ID in the $(response) treating $(response) as a DOM object.
Maybe I'm misunderstanding something, but
.find('#element')
matches elements with an ID of "element," like
<p id="element">
Since I don't see the "tons of stuff" HTML I don't understand what elements you're trying to find.
My html document looks like this:
<html>
<head> .. load jquery and other stuff </head>
<body>
<div id="cool_container">
<div class="cool">.. no script friendly markup ..</div>
</div>
<a id="cool_link">Link</a>
<script>
function installStuff(){
$('.cool').coolPlugin();
$('#cool_link').click(function(){
$('#cool_container').load('/anothercooldiv.html');
});
}
$(document).load(function(){ installStuff(); });
</script>
</body>
</html>
Of course, /anothercooldiv.html gives another <div class="cool"> .. etc ...</div> fragment.
So what's the best way to turn the fresh cool div into a coolPlugin without breaking everything (and writing some nasty hacks) ?
It'd would be great to be able to either:
Call installStuff with a default jQuery context '#cool_container', so I could call something like:
$.doThisInContext(function(){installStuff();}, $('#cool_container');
In the load callback.
Or, have an equivalent of 'live' (that would solve the problem of links if cool contains links), but on an element existence, that I could use like that in my function installStuff:
$('.cool').exists(function(what){ what.coolPlugin() };
Then the coolPlugin would be installed on all cool elements now and in the future.
I'd suggest the .livequery() plugin for this still:
$(function() {
$('.cool').livequery(function() {
$(this).coolPlugin();
});
$('#cool_link').click(function(){
$('#cool_container').load('/anothercooldiv.html');
});
});
The important bit:
$('.cool').livequery(function() {
$(this).coolPlugin();
});
Will run for every current and future .cool element as they're added, running the plugin on each.
Applying the plugin to the newly ajax loaded content shouldn't be too tricky:
$('#cool_container').load('/anothercooldiv.html', function() {
$(this).coolPlugin();
});