I'm creating dynamically some scripts like this:
var js1 = document.createElement('script');
js1.type = 'text/javascript';
js1.src = '/js-1.js';
docmuent.body.appendChild(js1);
js1.onload = function() {
var js2 = document.createElement('script');
js2.type = 'text/javascript';
js2.src = '/js-2.js';
document.body.appendChild(js2);
};
Here's my spec:
it('Tests inject script', function() {
expect($("script[src*='/js-1.js']").length).toBeGreaterThan(0);
expect($("script[src*='/js-2.js']").length).toBeGreaterThan(0);
});
The test on js-2 always fails. How can i spy js-1 onload event ?
I think the problem may be in your ordering. You should create the script tag, add it to the body, set the onload, and then set the src.
var js1 = document.createElement('script');
js1.type = 'text/javascript';
docmuent.body.appendChild(js1);
js1.onload = function() {
var js2 = document.createElement('script');
js2.type = 'text/javascript';
document.body.appendChild(js2);
js2.src = '/js-2.js';
};
js1.src = '/js-1.js';
You shouldn't add the tag creation code inside the onload event. If I'm not wrong IE will only start downloading the file as soon as the script tag is added to the DOM.
My suggestion is to move everything you have in the onload event outside and maybe have a handler function inside the onload event to know for sure when the file has finished loading.
This way your only problem will be testing the call of the function inside the onload event. You can do that by mocking document.createElement('script'); and return a fake object that you can use like "fakeObject.onload()" and spy if your inner helper function is called.
Related
I want to spy on a function used as a click handler. The function is defined within the constructor of a closure.
var viewModel = function(){
var viewModel = function(){
var _this = this;
_this.internalClickHandler = function(){
console.log('I handled a click');
}
}
return viewModel;
}();
var testViewModel = new viewModel();
var theSpy = spyOn(testViewModel, 'internalClickHandler');
Even though Jasmine is happy that 'internalClickHandler' exists and creates the spy, it never gets called. In fact the original function (internalClickHandler) gets call instead.
I've created examples in codepen.io that show the problem. The failing test is the one trying to spy on a function in the constructor.
My event handler needs to be in the constructor as it needs access to instance of the object and I do want to test that the correct handler has been fired not just that the click event was triggered.
Any help would be greatly received. Thanks
You will not be able to execute that test because of the following reasons:
Your clickHandler actually gets reassigned to a different variable
on the DOM Element onClick, see this line
document.getElementById('testLink').addEventListener('click',
_this.internalClickHandler);
When a click trigger gets invoked, it actually executes the function
onClick and NOT internalClickHandler, though they are in actuality(code wise)
the same but they are being referenced by two different variables
i.e onClick & internalClickHandler.
You are better off trying something like this.
it('should spy on a event binding defined in constructor', function() {
var testViewModel = new viewModel();
var tl = document.getElementById('testLink');
var theSpy = spyOn(t1, 'onclick');
//$('#testLink').trigger('click');
var event = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
tl.dispatchEvent(event);
expect(theSpy).toHaveBeenCalled();
tearDown();
});
Hope this helps.
I resolved this by using as the handler an anonymous function wrapping a reference to internalClickHandler. This way the original function still gets called and I'm able to spy on it.
var viewModel = function(){
var viewModel = function(){
var _this = this;
_this.internalClickHandler = function(){
console.log('I handled a click');
}
}
return viewModel;
}();
var theViewModel = new viewModel();
var theSpy = spyOn(testViewModel, 'internalClickHandler');
$('#testLink').on('click',
function(){
theViewModel.internalClickHandler(); //<-- The anonymous function calls internalClickHandler
});
Can anyone help me translate this to prototype
var btn = $('#onestepcheckout-button-place-order');
var btnTxt = $('#onestepcheckout-button-place-order span span span');
var fewSeconds = 10;
btn.click(function(){
btn.prop('disabled', true);
btnTxt.text('Even geduld A.U.B.');
btn.addClass('disabled');
setTimeout(function(){
btn.prop('disabled', false);
btnTxt.text('Bestelling plaatsen');
btn.removeClass('disabled');
}, fewSeconds*1000);
});
Prototype is confusing the sh*t out of me
Try this:
var btn = $('onestepcheckout-button-place-order');
var btnTxt = $$('onestepcheckout-button-place-order span span span')[0];
var fewSeconds = 10;
Event.observe(btn, 'click', function(){
btn.setAttribute('disabled', 'disabled');
btnTxt.innerHTML = 'Even geduld A.U.B.';
btn.addClassName('disabled');
setTimeout(function(){
btn.removeAttribute('disabled');
btnTxt.innerHTML = 'Bestelling plaatsen';
btn.removeClassName('disabled');
}, fewSeconds*1000);
});
I haven't tested it though.
I'm not going to give you the direct copypasta snippet for your problem but you only probably just need to do the following swaps:
$(selector) with $($$(selector))
prop to attr
addClass to addClassName
I'm omitting one more replacement so you can look for it yourself, for added challenge! Protip: search google for "Prototype to jQuery equivalent". So many resources!
Alternatively, you can just use jQuery in jQuery.noConflict mode and wrap the above in a jQuery closure.
(function($) {
// your code above goes here.
})(jQuery)
There is a dialog, and I define a function OnAccept() and call it like this: ondialogaccept:ondialogaccept="OnAccept()".
OnAccept():
function OnAccept() {
var windowManager = Components.classes["#mozilla.org/appshell/window-mediator;1"].getService();
var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator );
var topWindow = windowManagerInterface.getMostRecentWindow( "navigator:browser" );
if(topWindow)
{
var web = topWindow.document.getElementById("content");
web.selectedTab = web.addTab("http://www.google.com");
var newBrowserHandle = web.getBrowserForTab(web.selectedTab);
newBrowserHandle.addEventListener("load", function() { alert("111"); }, true);
}
}
But the addEventListener doesn't work. I don't know why.
There are some issues in your code that are probably just bad copy&paste: ondialogaccept:ondialogaccept="OnAccept()" should be ondialogaccept="OnAccept()" and OnAccept(): should be OnAccept: (without parentheses).
The main issue: the load event listener doesn't get propagated from content to chrome, you would need progress listeners to get that event. You can listen to the DOMContentLoaded event however, that one can be caught on the browser element. This event will fire when only the document content is loaded, not images and such - but maybe that's ok for you.
Is there a way i can put a jQuery ajax call inside of a variable so i can create a setTimeout for specific events and clearTimeout for specific events? for example if this makes any sense something like this:
var testEvent = function(){ $(this).load("info.php"); };
On specific event
setTimeout("testEvent()",3000);
On another specific event
clearTimeout("testEvent()");
How about a couple of nifty plugin functions to do the trick?
$.fn.loadLater = function (url, time) {
var me = this;
this.data('load-later-timer', setTimeout(function () {
me.load(url);
}, time));
};
$.fn.dontLoadLater = function () {
var timer = this.data('load-later-timer');
if (timer != null) clearTimeout(timer);
};
Use like so:
// Start timer
$(this).loadLater('info.php', 3000);
// Stop timer
$(this).dontLoadLater();
This absolutely makes sense, just do like this:
var id = setTimeout(function() {testEvent()}, 3000);
clearTimeout(id);
Make sure to keep id accessible for both event handlers.
EDIT: I've overseen that you're referring to this inside the testEvent. Assuming that this is some node you're locating using jQuery, the code may look like this:
var id = setTimeout(function() {
$('.your-selector').each(testEvent);
}, 3000);
I send GET data with AJAX to another file.And on the another file I have echo "<script>alert('Something');</script>";.This is displayed dynamicly with AJAX ,i.e
var ajaxDisplay = document.getElementById('edit');
ajaxDisplay.innerHTML = ajaxRequest.responseText;
puts the <script>alert('Something');</script> to div with name edit.
But it doesn't alert anything.
How to get it work?
I have mixed html/javascript.
Here is the code.
function ajaxFunctions(){
var ajaxRequest; // The variable that makes Ajax possible!
try{
// Opera 8.0+, Firefox, Safari
ajaxRequest = new XMLHttpRequest();
} catch (e){
// Internet Explorer Browsers
try{
ajaxRequest = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try{
ajaxRequest = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e){
// Something went wrong
alert("Your browser broke!");
return false;
}
}
}
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function(){
if(ajaxRequest.readyState == 4){
var ajaxDisplay = document.getElementById('edit');
ajaxDisplay.innerHTML = ajaxRequest.responseText;
}
}
var namef = document.getElementById('nameed').value;
var queryString = "?namef=" + namef;
ajaxRequest.open("GET", "try.php" + queryString, true);
ajaxRequest.send(null);
}
Maybe to find the script tags and to eval them?
But how to find the script tags?
Instead of trying to inject a script element in the DOM, just have your script return:
alert('Something');
And then use eval(response); to run it. Or you could add a script element with the src attribute pointing to the page that returns your JavaScript into the <head> (which is the preferred method).
function loadScript(url) {
var head = document.getElementsByTagName("head")[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
head.appendChild(script);
}
Keep in mind that this wont work for cross-domain requests--the script has to have the same origin as the page running your code. To get around this, you'll have to use a callback.
It looks like the only purpose of setting innerHTML is an attempt to get the JS to execute. But once the page is loaded, JS won't 'know' that it needs to parse and execute the new text you've changed, so your method won't work. In this case, what you want is a callback function:
http://api.jquery.com/jQuery.ajax/
I haven't used jQuery, but it looks like you'd simply add a 'complete' property to the settings object you pass to the .ajax() call, like so:
$.ajax({
// ......
complete: function(){
alert('Something');
}
// ......
});
In this case, the callback function would execute once the ajax call has completed. You can pick other events, such as on success, on failure, and so on, if you need to attach your code to a different event.
But how to find the script tags?
Well, parent.getElementsByTagName('script') and then evaling the data of the text node inside will do it.
However, inserting content that includes script tags is unreliable and works slightly differently across browsers. eg. IE will execute the script the first time the script node is inserted into any parent, inside the document or not, whilst Firefox will execute script the first time a subtree including the script is added to a node inside the document. So if you're not extremely careful, you can end up executing scripts twice on some browsers, or executing the script at the wrong time, following a further page manipulation.
So don't. Return script that you want to execute separately to any HTML content, eg. using a JSON object containing both the HTML and the JavaScript seperately.