Print data instead of alert - javascript

I use the javascript to get some data from facebook using javascript sdk:
window.fbAsyncInit = function() {
FB.init({appId: '111164862286924', status: true, cookie: true,
xfbml: true});
/****************************************/
FB.api('/f8', function(response) {
alert(response.company_overview);
});
/****************************************/
};
(function() {
var e = document.createElement('script'); e.async = true;
e.src = document.location.protocol +
'//connect.facebook.net/en_US/all.js';
document.getElementById('fb-root').appendChild(e);
}());
This code works fine but if I change alert with documen.write to print the data instead of showing it inside the popup window it doesn't seem to work any more. It doesn't print anything. Can anyone please tell what could be the reason?
Thanks in advance

You can't use document.write after the initial parse of the page is complete. Fortunately, though, there's no particular reason to.
If you have an element on the page and you wish to append to it, you can do this:
var parent = document.getElementById('theId');
var p = document.createElement('p');
p.innerHTML = "This is the <em>new content</em>.";
parent.appendChild(p);
Live example (It doesn't have to be an p element, it can be a div or span or anything else that's a valid child of the parent element.)
Note that if you just want to append to the bottom of the document (relatively rare, but hey), you can just use document.body in place of parent:
var p = document.createElement('p');
p.innerHTML = "This is the new content.";
document.body.appendChild(p);
Similarly, if you want to replace the content of an element, just get a reference to it (using getElementById is a convenient way if the element has an ID, but there are other ways) and update it, rather than append to it:
var target = document.getElementById('targetId');
target.innerHTML = "This is the <em>updated content</em>.";
More re document.write: document.write actually writes to the HTML stream being parsed by the HTML parser. Naturally, once the page rendering is complete, there's no longer an HTML stream being parsed. But the DOM methods above are available for manipulating content on the page after the page is rendered.
Off-topic: DOM manipulation and DOM searching (finding elements to update) are both made easier (and in particular made easier cross-browser) if you use a library like jQuery, Prototype, YUI, Closure, or any of several others which will have syntactic sugar and workarounds for browser eccentricities, etc.

If you are looking to just output the value for testing. I recommend Console.JS for IE and Firebug for Firefox. They support a function called console.log() which will trace output to a debugging window.

Related

Locate and check script (within webpage) is correct using nightwatchjs

I'm using nightwatchjs as my testing tool and I need to test that an injected script is correctly displayed on a page, and that the script is correctly populated.
So, the following script html is to be tested (to ensure that it is correctly displayed):
<script type="text/javascript">
(function() {
window.dm = window.dm ||{ AjaxData:[]};
window.dm.AjaxEvent = function(et, d, ssid, ad) {
dm.AjaxData.push({ et:et, d:d, ssid:ssid, ad:ad});
window.DotMetricsObj && DotMetricsObj.onAjaxDataUpdate();
};
var d = document, h = d.getElementsByTagName('head')[0], s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src='https://uk-script.dotmetrics.net/door.js?id=11373';
h.appendChild(s);
} ());
</script>
So firstly, I'd like to test that this script is present on the page, but in a way that is as less brittle as possible. I can test for /html/head/script[13]/text() but this is really brittle and far from ideal.
Is there something in the script itself that I can reference, so the test won't be as brittle?
Secondly, I want to ensure that the script details are correct. This can be a test that will check for the presence of the https://uk-script.dotmetrics.net part of the script for example.
However, I've tried to use my usual css and xpath ways of locating this part of the script but with no luck.
Any help would be appreciated. Thanks.
In line with the paradigm of "assert the what, not the how", the "what" here seems to be making sure that a script got injected into the page. You could use a selector like this one: script[src^="https://uk-script.dotmetrics.net/"], in conjunction with Nightwatch's element function. You could add more selectors to assert the script has the expected attributes like type and async.
In this way, you can skip the implementation detail (the presence of the injecting script) and focus on what I think you really care about (that a script with a correct URL got injected into the page).

Hijacking a variable with a userscript for Chrome

I'm trying to change the variable in a page using a userscript.
I know that in the source code there is a variable
var smilies = false;
In theory I should be able to change it like that:
unsafeWindow.smilies = true;
But it doesn't work. When I'm trying to alert or log the variable to the console without hijacking I get that it's undefined.
alert(unsafeWindow.smilies); // undefined !!!
EDIT: I'm using Chrome if it changes anything...
http://code.google.com/chrome/extensions/content_scripts.html says:
Content scripts execute in a special environment called an isolated
world. They have access to the DOM of the page they are injected into,
but not to any JavaScript variables or functions created by the page.
It looks to each content script as if there is no other JavaScript
executing on the page it is running on.
It's about Chrome Extensions but I guess it's the same story with Userscripts too?
Thank you, Rob W. So the working code for people who need it:
var scriptText = "smilies = true;";
var rwscript = document.createElement("script");
rwscript.type = "text/javascript";
rwscript.textContent = scriptText;
document.documentElement.appendChild(rwscript);
rwscript.parentNode.removeChild(rwscript);
In Content scripts (Chrome extensions), there's a strict separation between the page's global window object, and the content script's global object.
To inject the code, a script tag has to be injected.
Overwriting a variable is straightforward.
Overwriting a variable, with the intention of preventing the variable from being overwritten requires the use of Object.defineProperty Example + notes.
The final Content script's code:
// This function is going to be stringified, and injected in the page
var code = function() {
// window is identical to the page's window, since this script is injected
Object.defineProperty(window, 'smilies', {
value: true
});
// Or simply: window.smilies = true;
};
var script = document.createElement('script');
script.textContent = '(' + code + ')()';
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);

prevent script execution on load (or parsing) in jQuery

i have an "ajax engine" based on jQuery. And after receiving the response i must manipulate the response before inserting in page. But I need the response as an jQuery object.
I do this with:
tmpActualResult = $( '<span/>' ).html( actualResult );
But at this time jQuery (or browser itself?) execute the scripts which are included in response - and exactly this shouldn't occur. I will execute the scripts manual later.
in particular I will:
parse response (get access to the tags/elements which are included)
insert the elements into page (DOM manipulating)
execute possible scripts (which are received)
in thanks
Edit:
If someone is interested too, i've created a more general solution by extending the jQuery.domManip function, as suggested in first answer.
(function($, oldDomManip) {
// Override the core domManip function
$.fn.domManip = function() {
function evalScript(i, elem) {
jQuery.globalEval(elem.text || elem.textContent || elem.innerHTML || "");
}
var scripts = [];
// let jQuery build the fragments
var results = jQuery.buildFragment(arguments[0], this, scripts);
// change parameter to created fragments
arguments[0] = results.fragment.childNodes;
// do what jQuery will do - without scripts
oldDomManip.apply(this, arguments);
if (scripts.length) {
// if connection is active
if (jQuery.active != 0) {
$(this).bind("ajaxStop.scriptCache", function() {
$.each(scripts, evalScript);
$(this).unbind("ajaxStop.scriptCache");
});
} else
$.each(scripts, evalScript);
}
return this;
};
})(jQuery, jQuery.fn.domManip);
it will not execute scripts before ajax request is completed. worked for me.
You can't prevent script execution of scripts that are part of a string of markup you're trying to add using .html() or .append(). At least not without extending the domManip function of jQuery. It extracts all scripts in html markup that you're trying to add using .html() or .append() and evals it.
You could, however, extract the script tags with their inner text (js) from the string yourself, add only the markup via .html() or .append() and then eval the scripts yourself when you need to.
Try this:
var container = document.createElement('div');
container.innerHTML = "<div> i am html with script tag <script type="text/javascript">alert('Script executed');</script>end</div>"
$(container).doSomething()

Invoking document.write()

This code does not work:
<div class="pix"><div id="addTimestamp"></div></div>
<script type="text/javascript">
(function () {
var date = new Date(),
timestamp = date.getTime(),
newScript = document.createElement("script");
newScript.type = 'text/javascript';
newScript.src = 'someUrl=' + timestamp + '?';
document.getElementById('addTimestamp').appendChild(newScript);
}())
</script>
The dynamic script adds document.write(someCode which loads banners). But in Firebug I have an error:
Invoking document.write() from asynchronously-loaded external script was ignored.
Add this:
newScript.async = false;
Your script needs to load synchronously for document.write() to work (see https://developer.mozilla.org/En/HTML/Element/Script#attr-async). As you have it now, the script will load whenever the browser has time for it - so you cannot know where your HTML from document.write() will be inserted. The browser decided to ignore your document.write() call to prevent worse issues.
document writing javascript causes the html parser to fail when seeing try
document.getElementById('addTimestamp').innerHTML = '<script type="text/javascript" src="someUrl=' + timestamp + '?"' + 'charset="utf-8"></sc' + 'ript>';
However if you want to insert a script tag in in the DOM you need to also be certain the DOM is loaded.
Levon, it seems like you are trying to overcome problems with page load speed (I don't see other reasons not to just insert script statically).
Wladimir's answer is good and valid, but see my comment to his answer.
Another approach, which works, but should be very carefully implemented, is to overwrite the document.write itself. It is very, very, subtle work, it need to be thoroughly tested, but it can be done, actually. Each call of document.write can store something to some sort of string buffer. Then, by deciding somehow that it is time to flush all the content, just insert all buffers content to some DOM element.
Works, but very pervy. The best option is not touse document.write at all. But, alas, it is not always the option.

Javascript doesn't work in IE8

I am trying to create this html elements dynamically on the onload of my page,however;when I run it the code wont work on IE8 but okay in firefox,safari,and others.
function getmovie() {
var container = document.getElementById("container");
if (!container)
return;
var object = document.createElement("object");
object.setAttribute("width", "512");
object.setAttribute("height", "296");
var param1 = document.createElement("param");
param1.setAttribute("name", "movie");
param1.setAttribute("value", "url");
var param2 = document.createElement("param");
param2.setAttribute("name", "allowFullScreen");
param2.setAttribute("value", "true");
var embed = document.createElement("embed");
embed.setAttribute("src", "my url");
embed.setAttribute("type", "application/x-shockwave-flash");
embed.setAttribute("allowFullScreen", "true");
embed.setAttribute("width", "512");
embed.setAttribute("height", "296");
object.appendChild(param1);
object.appendChild(param2);
object.appendChild(embed);
container.appendChild(object);
}
Can anyone correct my code?
Unless you have a really good reason to build your Flash including DOM elements manually, consider replacing the code with a single call to a framework like SWFObject that does all the "dirty work" for you.
swfobject.embedSWF("flashmovie.swf", "container", "512", "296", "9.0.0",
"expressInstall.swf", { allowFullScreen : true });
You can't set the name attribute of ANY element in IE by using .setAttribute('name', value);
You will need to use:
param1.name = 'movie';//works
param1.setAttribute("name", "movie");//will fail
Note: this bug was fixed in IE8 (as long as you are running in IE8 Standards Mode)
Could this be the reason?
IE7 breaks getElementById
If that is not the case, try setting the codebase and classid attributes of the object tag
object.
object.setAttribute("codebase", "http://fpdownload.macromedia.com/get/flashplayer/current/swflash.cab");
object.setAttribute("classid", "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000");

Categories

Resources