Object from external script undefined in ie and firefox - javascript

I'm working on building a javascript widget that users will be able to include on their websites which will display data from our web application. The main file which a user will include w1.js contains the following:
var MYLIBRARY = MYLIBRARY || (function(){
var _args = {};
var jQuery;
function main(){
//simply display loaded jquery version as a test
jQuery('#mylibrary-w1-content').text(jQuery.fn.jquery);
}
function scriptLoadHandler(){
jQuery = window.jQuery.noConflict(true);
main();
}
return {
init: function(Args){
_args = Args;
if(window.jQuery === undefined || window.jQuery.fn.jquery !== '3.3.1'){
var script_tag = document.createElement('script');
script_tag.setAttribute("type", "text/javascript");
script_tag.setAttribute("src", "//ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js");
if(script_tag.readyState){
script_tag.onreadystatechange = function(){ // for old versions of ie
if(this.readyState === 'complete' || this.readyState === 'loaded'){
scriptLoadHandler();
}
};
} else {
script_tag.onload = scriptLoadHandler;
}
(document.getElementsByName("head")[0] || document.documentElement).appendChild(script_tag);
} else {
jQuery = window.jQuery;
main();
}
}
};
/* END OF LIBRARY
*******************************************************************************/
}());
The code which users include on their website is as follows:
<script src="//thewebsite.com/widgets/w1.js"></script>
<script>
window.addEventListener('load', function(){MYLIBRARY.init(["somevalue"]);}, false);
</script>
<div id="mylibrary-w1-content"></div>
Everything is functioning as expected in chrome, however ie and firefox (thought this was just an ie issue until it didn't work in firefox, thought that was odd) return an error message in the console ReferenceError: MYLIBRARY is not defined.
My initial thought was that w1.js had not completed loading before the call to MYLIBRARY, however the addEventListener('load') appears to be functioning as expected, unless I've missed something or am doing something incorrectly.
Any Ideas?

After a bit of additional troubleshooting I discovered what was causing this issue. It was not related to javascript. The url where w1.js was being loaded from is an internal test site which uses a self signed ssl cert. The reason this was not working in firefox or ie, is because exceptions for this certificate did not exist in firefox or ie, therefore when the call was made, the file was never returned. Adding the exceptions solved the issue.

Related

Wait until js script is loaded on the page

I'm trying to add js file to the page. How to check if that file is loaded?
javascript ga.js file:
this.event = function (value) {
this.value = value;
this.method = function() {
return "sometext";
};
};
Dart code:
ScriptElement ga = new ScriptElement()
..src = "/ga.js"
..async = true;
querySelector('body').append(ga);
bool exist = context.hasProperty('event');
JsObject event = null;
if (exist) {
print("event exist");
} else {
print("there is no event yet");
}
You can just add an onload event to any script element in HTML.
ga.onload = function(ev) { alert('loaded!') };
Since this is native HTMLScriptElement behaviour it should combine fine with Dart.
The way I found for now it's to use Future.
void checkEvent() {
bool exist = context.hasProperty('event');
JsObject event = null;
if (exist) {
print("event exist");
} else {
print("there is no event yet");
var future = new Future.delayed(const Duration(milliseconds: 10), checkEvent);
}
}
But it's if I now already that 'event' exist in that javascript file. Maybe there is some way to check when javascript loaded in html?
Most browsers with Developer tools like Chrome, Firefox, and even IE have a tab called Network. In these panels/tabs you can search for the file in question. If it has loaded it will be in that view.
As long as the JavaScript recognizes/attempts to load the .js file, the console will usually tell you if it couldn't load the file.
If you're planning on doing something on your page after the file has loaded then you would want to do something more along the lines of what Niels Keurentjes suggested.
More Information:
Chrome's Network Panel
Firefox's Network Panel
Internet Explorer's Network Panel
OnLoad Event

Waiting for a script object to load [duplicate]

This question already has answers here:
dynamic script loading synchronization
(6 answers)
Closed 8 years ago.
I'm trying to create a jquery script that will be run from the console of google chrome and will analyze a page.
My problem is that when I run the following code:
var jq = document.createElement('script');
jq.src = "http://code.jquery.com/jquery-latest.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
alert($('a'));
I get a message box with null (bad result)
But if I separate it to to executions like this:
step1:
var jq = document.createElement('script');
jq.src = "http://code.jquery.com/jquery-latest.min.js";
document.getElementsByTagName('head')[0].appendChild(jq);
step2:
alert($('a'));
It works great and I get [object] that is my desired result.
The question is what can I do to run this in a single batch?
In general, you need to attach a listener on the script nodes onload event. jQuery will not be available until its fully transfered and executed. Like
var jq = document.createElement('script'),
head = document.head || document.getElementsByTagName('head')[0] || document.documentElement;
jq.src = "http://code.jquery.com/jquery-latest.min.js";
jq.onload = jq.onreadystatechange = function() {
if(!jq.readyState || /loaded|complete/.test( jq.readyState ) ) {
jq.onload = jq.onreadystatechange = null;
jq = undefined;
}
}
head.insertBefore(jq, head.firstChild);
The above code is pretty much rocksolid and works in IE6+ aswell.
You could try something like this and check the ready state of the script:
jq.onreadystatechange = function() {
if (this.readyState == 'complete') {
alert($('a'));
}
}
If you want a solid way and tested listeners for a complete load of script, try third party libraries like:
http://yepnopejs.com/
Start a script loader from scratch is not recommended, not Today.

Use ctrl+enter to submit google+ reply but does not work sending a 'click' event to the submit button

I want to use Ctrl+Enter to submit the Google+ reply but it does not work when I send a 'Click' event to the submit button. This is a chrome plugin for plus.google.com.
document.onkeydown=function(e){
if(e.ctrlKey&&e.keyCode==13){
div_id=document.activeElement.id;
div_id=div_id.substr(0,3);
editorid=div_id.substr(0,2)+String.fromCharCode(div_id.charCodeAt(2)-1);
postbuttonid=editorid+'.post';
console.log(postbuttonid);
postbutton=document.getElementById(postbuttonid);
evt=document.createEvent("MouseEvents");
evt.initEvent("click", true, true);
postbutton.dispatchEvent(evt);
}
}
I suggest you use jQuery:
jQuery("#:2s.post").click();
The above code should work assuming that, as one of your comments describes, the button you want to click has the id ":2s.post".
I hope that works for you. If you're unable to include jQuery directly, you could try something like:
/*--- Create a proper unsafeWindow object on browsers where it doesn't exist
(Chrome, mainly).
Chrome now defines unsafeWindow, but does not give it the same access to
a page's javascript that a properly unsafe, unsafeWindow has.
This code remedies that.
*/
if (typeof unsafeWindow === "undefined") {
unsafeWindow = ( function () {
var dummyElem = document.createElement('p');
dummyElem.setAttribute ('onclick', 'return window;');
return dummyElem.onclick ();
} ) ();
if(typeof unsafeWindow === "undefined") {
unsafeWindow = window;
}
}
// END PROPER unsafeWindow
var script = unsafeWindow.document.createElement("SCRIPT");
script.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js';
script.type = 'text/javascript';
unsafeWindow.document.getElementsByTagName("head")[0].appendChild(script);
script.addEventListener('load', function(){
jQ = unsafeWindow['jQuery'];
$ = jQ.noConflict(true); // keep jQuery local so you don't accidentally override/overwrite any variables
requiresjQuery($);
}, false);
In which case, your code would actually look more like:
function requiresjQuery($) { // put any code in here that requires jQuery; I actually recommend putting all of your code in here.
$("#:2s.post").click();
}
try document.forms.yourForm.submit();

Override Ctrl+M hotkey of Facebook in Firefox

I'm working on a bookmarklet which will let users to write on any input fields in our language. We choose Ctrl+M for switching layout between default and our language (Inspired by Wikipedia). It was working fine in almost every website with chrome. When we started checking with Firefox we found that it only fails in Facebook.
Moreover, Facebook catches the Ctrl+M from outside the window
scope. Like, form the address bar, search bar, firebug console, etc.
I've tried with raw javascript, jQuery and also with the jQuery Hotkeys plugin by John Resig but no luck :(
Here is a version that I had tried. You can run it on your Firebug console for testing purpose -
(function(){
var noConflictMode = false;
if(typeof $ !== 'undefined') noConflictMode = true;
if(typeof jQuery === 'undefined') {
var root = (document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]);
var ns = document.createElementNS && document.documentElement.namespaceURI;
var script = ns ? document.createElementNS(ns, 'script') : document.createElement('script');
script.type = 'text/javascript';
script.onreadystatechange = function () {
if (this.readyState == 'complete') test();
}
script.onload= test;
script.src= 'https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.min.js';
root.appendChild(script);
} else {
test();
}
function test() {
if(noConflictMode) jQuery.noConflict();
jQuery(window).on('keydown keyup keypress', function(e){
e.preventDefault();
// For Firefox
e.stopPropagation();
// Extra effort :|
e.stopImmediatePropagation()
e.cancelBubble = true;
console.log(e);
return false;
});
}
})();
You can NOT do that on client-side web for security reasons, you can code anything in JS or JQ or any language you want but MOZ never will take care of your code.
Take care, one thing is that the browser "compile" your code and work with it, and another thing is that you can change the browser itself. For that reasons there's the "add-on".
For example, you can't change the kernel of Visual Studio programming in V.S. :D
BUT...
... you can ask to the user re-bind the keys, you have 3 ways to do that:
1) installing a MOZ add-on (or your own addon)
2) Working with: http://mxr.mozilla.org/seamonkey/source/dom/public/idl/events/nsIDOMKeyEvent.idl
3) installing a shortcut keyb at OS level with higher priority than the App (in this case, MOZ) (you can do it with C#). Alt+tab combination is an example of high level shortcut, or "Prnt Scrn"
There is NO way to do that with about:config, neither.
Maybe this url can help you, but i suggest you try asking for changes in MOZ and not asking for Javascript code.
http://www-archive.mozilla.org/unix/customizing.html#keys

What is my script src URL?

Is there a simple and reliable way to determine the URL of the currently-executing JavaScript file (inside a web page)?
My only thought on this is to scan the DOM for all the script src attributes to find how the current file was referenced and then figure out the absolute URL by applying it to document.location. Anyone have other ideas, is there some super-easy method I completely overlooked?
UPDATE: Script elements accessed via the DOM already have a src property which contains the full URL. I don't know how ubiquitous/standard that is, but alternatively you can use getAttribute("src") which will return whatever raw attribute value is in the [X]HTML.
Put this in the js file that needs to know it's own url.
Fully Qualified (eg http://www.example.com/js/main.js):
var scriptSource = (function(scripts) {
var scripts = document.getElementsByTagName('script'),
script = scripts[scripts.length - 1];
if (script.getAttribute.length !== undefined) {
return script.src
}
return script.getAttribute('src', -1)
}());
Or
As it appears in source (eg /js/main.js):
var scriptSource = (function() {
var scripts = document.getElementsByTagName('script'),
script = scripts[scripts.length - 1];
if (script.getAttribute.length !== undefined) {
return script.getAttribute('src')
}
return script.getAttribute('src', 2)
}());
See http://www.glennjones.net/Post/809/getAttributehrefbug.htm for explanation of the getAttribute parameter being used (it's an IE bug).
For recent browsers, you can use document.currentScript to get this information.
var mySource = document.currentScript.src;
The upside is that it's more reliable for scripts that are loaded asynchronously. The downside is that it's not, as best I know, universally supported. It should work on Chrome >= 29, FireFox >= 4, Opera >= 16. Like many useful things, it doesn't seem to work in IE.
When I need to get a script path, I check to see if document.currentScript is defined, and, if not, use the method described in the accepted answer.
if (document.currentScript) {
mySource = document.currentScript.src;
} else {
// code omitted for brevity
}
https://developer.mozilla.org/en-US/docs/Web/API/document.currentScript
As it appears in source (e.g. /js/main.js), this is cross-browser:
var scriptSource = (function()
{
var scripts = document.getElementsByTagName('script'),
script = scripts[scripts.length - 1];
//No need to perform the same test we do for the Fully Qualified
return script.getAttribute('src', 2); //this works in all browser even in FF/Chrome/Safari
}());
Fully Qualified (e.g. http://www.example.com/js/main.js):
After some tests it seems hard to get the fully qualified one in a cross-browser way. The solution suggested by Crescent Fresh does not work in IE8 to get the fully qualified, even if it works in IE7
This method work with defer, async and lazy loading
Since you know the filename of your script, and if it will be unique
/* see
* http://stackoverflow.com/questions/984510/what-is-my-script-src-url/984656#984656
* http://www.glennjones.net/Post/809/getAttributehrefbug.htm
*
* iterate all script to find script with right filename
* this work with async and defer (but your script MUST have a unique filemane)
* mozilla support document.currentScript and we use it, if is set
*
* this will not work with local script loaded by jQuery.getScript(),
* since there is no script tag added into the dom. the script is only evaluated in global space.
* http://api.jquery.com/jQuery.getScript/
*
* to fix this odd, you can add a reference in meta ( meta[name=srcipt][content=url] )
* when you load the script
*/
var scriptFilename = 'jquery.plugins.template.js'; // don't forget to set the filename
var scriptUrl = (function() {
if (document.currentScript) { // support defer & async (mozilla only)
return document.currentScript.src;
} else {
var ls,s;
var getSrc = function (ls, attr) {
var i, l = ls.length, nf, s;
for (i = 0; i < l; i++) {
s = null;
if (ls[i].getAttribute.length !== undefined) {
s = ls[i].getAttribute(attr, 2);
}
if (!s) continue; // tag with no src
nf = s;
nf = nf.split('?')[0].split('/').pop(); // get script filename
if (nf === scriptFilename) {
return s;
}
}
};
ls = document.getElementsByTagName('script');
s = getSrc(ls, 'src');
if ( !s ) { // search reference of script loaded by jQuery.getScript() in meta[name=srcipt][content=url]
ls = document.getElementsByTagName('meta');
s = getSrc(ls, 'content');
}
if ( s ) return s;
}
return '';
})();
var scriptPath = scriptUrl.substring(0, scriptUrl.lastIndexOf('/'))+"/";
a jquery plugin template with it:
https://github.com/mkdgs/mkdgs-snippet/blob/master/javascript/jquery.plugins.template.js
note: this will not work with local script loaded by jQuery.getScript(), since there is no script tag added into the dom. the script is only evaluated in global space.
http://api.jquery.com/jQuery.getScript/
to fix it you can do something like:
function loadScript(url,callback) {
if ( $('[src="'+url+'"]').length ) return true; // is already loaded
// make a reference of the loaded script
if ( $('meta[content="'+url+'"]', $("head")).length ) return true; // is already loaded
var meta = document.createElement('meta');
meta.content = url;
meta.name = 'script';
$("head").append(meta);
return $.ajax({
cache: true,
url: u,
dataType: 'script',
async: false,
success : function (script) {
try {
if ( typeof callback == 'function' ) callback();
} catch (error) {
//console.log(error);
}
}
});
}
If this is a strictly client solution, yours sounds pretty good.
If you are writing code on the server, you could probably just populate a div/hidden field/(insert your fave HTML element here) with the fully resolved URL to the script, and pick that up with your javascript on the clientside.
You may want to have a look at https://addons.mozilla.org/en-US/firefox/addon/10345 if you're interested in learning which functions (and thus which file) are executing on a page you don't control.
If you're interested in figuring out which of your scripts is executing, then there are a number of ways. With Firebug you could console.log() the information. Even just putting alert statements in your code (while annoying) can help debug in a low-tech way. You could also raise errors and catch them, then process using properties of the error (see: https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error)
However, why would this be important? If the script is causing errors already then it's easy enough to determine where the error is occurring. If it's not about errors at all, then what's the advantage in knowing which file it comes from?

Categories