I am making a cross domain request using script tag hack and jsonp. In the callback function, I want to write the data received to DOM using document.write().
I know that I should use appendChild/innerHTML instead of doc.write(). My constraint is I do not have a class/id hook to the element I want to write to. I can only rely on document.write() to write "in place".
Following code is included in HTML div in a script tag.:
function request_jsonp(){
var script = document.createElement('script');
var server_path = 'http://somedomain.com/?q=querystring&callback=request_callback';
script.setAttribute('src', server_path);
document.getElementsByTagName('head')[0].appendChild(script);
console.log('data requested');
// document.write('hello world'); // this gets written
}
function request_callback(data){
console.log('data received');
document.write(data);
}
request_jsonp();
window.onload = function(){
console.log('onload fired');
}
/*
above code prints
data requested
data received
onload fired
*/
Basically document.write does not work even with a static string inside the callback function. I thought that if document.write is called before onload, it inserts text in the page as noted here JavaScript and HTML Script Tags
What is preventing the document.write() to write to DOM? Also, is there a better approach to do this?
You should note that document.write(); calls an implicit document.open();, thus, in effect, clearing everything you have had in the document so far.
It is impossible to add content to a document using document.write();. It is, however, possible to use document.write(); to write an entire document.
You have several possible solutions:
You can pass the target element as a GET parameter, as #kirilloid noted.
You can insert an IFrame object at the desired place, and use myIFrame.document.write(); to update its content.
This is basically happening because you are updating the content of a container that is the parent to your script code, and as such, is not closed yet.
Either that, or I'm entirely off track here which, let's face it, is entirely possible. ;-)
Related
I have a file which contains lots of tags like follows
<script type="text/template" id="template-1">
</script>
<script type="text/template" id="template-2">
</script>
I want to load the file and than load all the content inside the script tags in memory.
I am trying the below code but its not working.
tpl = {
// Hash of preloaded templates for the app
templates : {},
loadTemplates : function(name) {
var that = this;
$.get(name, function(data) {
$(data).find('script').each(function (_, entry) {
that.templates[$(this).attr('id')] = $(this).text();
});
});
},
// Get template by name from hash of preloaded templates
get : function(name) {
return this.templates[name];
}
};
any help?
call is made like this
tpl.loadTemplates('/templates/templates-home.html');
In general you seem like you're on the right track. The browser will load (but ignore) script tags marked with type=text/template and you can later select the contents of those tags and process them with javascript.
I think your problem is likely with the order of your procedure.
You haven't posted the javascript that uses your templates so I can only assume. I suspect your trying to load the templates before the document is ready, thus, the script tags aren't actually on the page when you load them. To fix, your can move your javascripts below the templates in the document OR execute your code in a window.onLoad handler.
EDIT
Okay, now I have a better idea of what you're trying to do. You still haven't told me what part of this is broken, but my gut tells me that this bit is the problem: $(data).find('script'). jQuery expects to be traversing the DOM. At this point in time, data is just a string returned from the server, it's not actually loaded in the DOM. So jQuery won't actually find ANY script tags. Try appending your result to the body before querying the DOM for script elements. Maybe something like this:
$('body').append(data);
$('script[type="text/template"]').each ...
I'm not really thrilled about that though. Can you just inject them into the page on the server side? Why do you need to delay the loading?
EDIT 2
If you don't want your script tags to be visible in the html document, then I suggest you don't use them. Instead you can have your template endpoint just return a bundle of javascript and evaluate it directly. Something like:
$.get(name, function(data) {
// data is a string that sets up your window.template variable
eval(data);
});
I have a script that loads the code dynamically. It is kind of a search engine. When I press a search button, the action gets triggered and a new page opens with many parameters.
I want to override one of the parameters generated with the script in the new URL. JS code is quite big and hard to read, but I have found the important part in the Firebug DOM editor.
This is the pattern of the URL generated when you perform the search:
http://www.example.com/...?ParameterOne=123&ParameterTwo=Two&ThisParameter=Sth&ParameterFour=Four...
What I want to edit is "ThisParameter" and change its value. This is the part edited in the DOM that does what I want:
Foobar = {
_options: [],
...
var options = {"ParameterOne":123,"ParameterTwo":"Two","ThisParameter":"ABC","ParameterFour":Four,...}
...
And this is the output of "ThisParameter" when you choose "Copy path" in Firebug's DOM tab:
_options[0].ThisParameter
I am wondering it this is possible at all. What makes me think that it is, is the fact that I can change this parameter in Firebug and it works perfectly. So, if Firebug can edit it, there should be a way to influence it with another script.
Looking forward to any suggestions, thank you in advance!
Since you cannot edit the dynamic script you have the following options:
You have to try to give the script the correct input and hope it uses your value.
Add a script to the results page which will read the url and arguments, change it and redirect, as we discussed here. (If you put everything in functions it should not conflict with the dynamic script if the functions are uniquely named.)
You could try adding something like this jQuery code to the page with the search button:
$('input[name=search_button_name]').click(function(e) {
e.preventDefault();
var form_search = $('#search_form_id');
$('<input>').attr({
type: 'hidden',
name: 'ThisParameter',
value: 'SomethingElse'
}).appendTo(form_search);
f.submit();
});
You can override any js function and method, or wrap you code around it. The easiest thing would be to look at the code you get and once it gets loaded, you re-declare a method with your own functionality.
I you are trying to replace a parameter in a specific jquery request, you can even wrap around the jquerys ajax method:
var jquery_ajax = $.ajax
$.ajax = function(options){
// parse only a specific occurence
if(options.url.indexOf("example.com") > -1) {
// change the url/params object - depending on where the parameter is
options.params.ThisParameter = "My Custom value"
}
// call the original jquery ajax function
jquery_ajax(options);
}
But it would be a lot cleaner to override the method that builds the ajax request rather than the ajax request itself.
I would investigate further on the scope of the variable options (var options), is it global? i.e. if you type 'options' in the Firebug console, does it display its properties?
If so, you could then access it via your own script and change is value, e.g.
options.ThisParameter = 'my-own-value';
You might hook your script to the click event of the search button.
I hope this helps, it could be more specific maybe if you have some sample code somewhere.
So I have a simple setup going here where I load up a file (A blender .obj file) and display it. Then I call this function:
function parseFile(){
var fileText = $('#file').html();
var fileLine = fileText.split("\r\n");
$('#file').html(fileLine[5]);
}
Which should make it so it displays the 6th line of the file, but it still displays the whole file. How do I make it split the lines like they are in the actual file?
Edit: Just so everyone know's I'm loading the file like this: $('#file').load('model.obj');
The call to .load() is asynchronous. The method will return, but the content will be available somewhen in the future. You'll need to use a callback:
$('#file').load('model.obj', function(response, status) {
alert("Now the file is loaded");
parseFile();
});
alert("Loading the file just began, nothing available by now");
Or more narrative, using the deferred interface:
$('#file').load('model.obj').then(parseFile);
If you need/want to parse the server response anyway, it might be a better to use $.ajax() directly instead of loading it into a innerHTML and reading from there... You even could use a dedicated dataFilter for the blender.obj file type.
Maybe it is only a problem with '\n'
Try this :
var fileLine = fileText.split("\n");
Try wrapping your call like this $(parseFile()); and make sure your HTML actually contains an element with the id of file.
There is a similar post Retrieving HTTP status code from loaded iframe with Javascript but the solution requires the server-side to return javascript calling a function within the iframe. Instead, I would simply like to check the HTTP status code of the iframe without having to call a function within the iframe itself since my app either returns the full site through HTML or the single object as JSON. Essentially I've been trying to implement a callback method which returns success|failure dependent upon the HTTP status code.
Currently I have uploadFrame.onLoad = function() { ... so far pretty empty ... } and I am unsure what to check for when looking for HTTP status codes. Up until now, I've mainly relied upon jQuery's $.ajax() to handle success|failure but would like to further understand the mechanics behind XHR calls and iframe use. Thanks ahead of time.
UPDATE
The solution I came up with using jQuery
form.submit(function() {
uploadFrame.load(function() {
//using eval because the return data is JSON
eval( '(' + uploadFrame[0].contentDocument.body.children[0].innerHTML + ')' );
//code goes here
});
});
I think the best solution is injecting <script> tag into your iframe <head> and insert your "detecting" javascript code there.
something like this:
$('#iframeHolderDivId').html($.get('myPage.php'));
$('#iframeHolderDivId iframe head').delay(1000).append($('<script/>').text('your js function to detect load status'));
Maybe it's not the best solution but I think it works
I have following workflow
div on the page is used
on users operation request is done
to server side page whose html is
retrived using ajax and dumped into
the div
With html markup some JavaScript is
also dumped however that is not
getting executed.
Why is so ? What could be the possible fix ?
Though i avoid doing things like this but in some old code implementations like these are very common.
Scripts added using .innerHTML will not be executed, so you will have to handle this your self.
One easy way is to extract the scripts and execute them
var response = "html\<script type=\"text/javascript\">alert(\"foo\");<\/script>html";
var reScript = /\<script.*?>(.*)<\/script>/mg;
response = response.replace(reScript, function(m,m1) {
eval(m1); //will run alert("foo");
return "";
});
alert(response); // will alert "htmlhtml"
This will extract the scripts, execute them and replace them with "" in the original data.