Disclaimer. I am fairly new to JavaScript so if my workflow does not make sense at all or my vocabulary is yet not precise enough, please advise me of how I should do it differently.
Current Approach
I want to learn more about Javascript and external libraries. Thus, I created a snippet under the DevTools sources panel in Chrome, opened about:blank and executed the following code (which I copied and paste from different sources):
Code
(function(head) {
var newscript = document.createElement('script');
newscript.type = 'text/javascript';
newscript.async = true;
newscript.src = "https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js";
(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(newscript);
})(document.getElementsByTagName('head'));
function jQueryReady() {
if (window.jQuery) {
jQuery.noConflict();
my_code(jQuery);
} else {
setTimeout(jQueryReady, 100);
}
}
jQueryReady();
function my_code($) {
console.log("OK");
$('head').append($('script', {
type : 'text/javascript',
async: true,
src : 'https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.js'
}));
$('head').append($('link', {
rel : 'stylesheet',
href: 'https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.css'
}));
}
Results
When I then look at the source code of about:blank, I see that the jQuery script is correctly inserted into the head, I see that the console shows OK, but neither the spectrum JavaScript nor the CSS is inserted into the head.
Questions
Why is the code not added to the HTML file? What do I need to change to make it work?
If I run teh code from my_code directly in teh console everything seems to work fine? Why?
What is a proper way of playing around with JavaScript without writing an own html file? Does the approach via snippet and about:blank make sense? I need to reload about:blank whenever I make changes to the snippet, so I guess there is a more elegant way to do so. Any tipps on how to do that better?
I believe it is because in jQuery, when you want to create new elements, it is necessary to wrap tag name in "<>" signs like this:
$('head').append($('<script>', {
type: 'text/javascript',
async: true,
src: 'https://cdnjs.cloudflare.com/ajax/libs/spectrum/1.8.0/spectrum.js'
}));
In my opinion it is good idea to try sites like jsfiddle.net or codepen.io, where at least you can add libraries like jQuery easier without writing additional importing scripts and it is easier to maintain.
Related
I'm currently making my first effort into porting a webpage to Wordpress, so forgive my inexperience on the subject.
In my page, I have the following code:
function workLoad() {
$.ajaxSetup({ cache: false });
$('.thumb-unit').click(function() {
var $this = $(this),
newTitle = $this.find('strong').text(),
newFolder = $this.data('folder'),
spinner = 'Loading...',
newHTML = 'work/'+ newFolder +'.html';
$('.project-load').html(spinner).load(newHTML);
$('.project-title').text(newTitle);
});
}
In the past, this has worked fine hosted both locally and on Github. However, running my wordpress build locally through MAMP gives me the following error:
jquery-2.1.1.min.js:4 GET http://localhost/work/proj-1.html?_=1485348127113 404 (Not Found)
The URL should be fine, except for the part where it adds the ?_=(number). I'm not familiar with this behavior or what causes it. I tried changing work/ to /work/, since the dir is in the root folder, but that didn't solve it. I also have tried changing the variable to
newHTML = '< ?php bloginfo('template_directory')' + '/work/'+ newFolder +'.html';without the space after the opening bracket but to no avail. I also tried putting that bit in its own var, but it keeps adding ?_=1485348127113 to the URL of the html file I want to load, resulting in a 404 error.
What causes this? Thanks in advance for any advice you could share.
This timestamp is added for You to obtain the latest version of the file using ajax load.
If You want to disable this behaviour, You should set
$.ajaxSetup({
cache: true
});
This will enable caching and Your request would not contain the ?_=1485348127113 part anymore. This parameter should not cause the 404 not found error. Please check your path.
I have a JsFiddle here, and added Microsoft AJAX to be loaded through external JS/resource section. How can I tell whether or not my JS code is run after the AJAX file has finished loading?
Seems that the AJAX does not load either. :(
Here is the code in the JSFiddle:
Type.registerNamespace("Tutorial.Chapter1");
Tutorial.Chapter1.Person = function(firstName, lastName) {
this._firstName = firstName;
this._lastName = lastName;
};
Tutorial.Chapter1.Person.prototype = {
set_firstName: function(value) {
this._firstName = value;
},
get_firstName: function() {
return this._firstName;
},
set_lastName: function(value) {
this._lastName = value;
},
get_lastName: function() {
return this._lastName;
},
_firstName: "",
_lastName: "",
displayName: function() {
alert("Hi! " + this._firstName + " " + this._lastName);
}
};
Tutorial.Chapter1.Person.registerClass("Tutorial.Chapter1.Person", null);
The External Resources tab of jsFiddle is currently somewhat tricky and unstable to use.
The resources defined here are often not correctly included into the code. There seems to be an issue with the automatic recognition of JS and CSS resources. If this happens, the external resource is simply not added to the head section of the resulting code. You can check that by reviewing the source code of the Result frame of your jsFiddle. You will find that your MS AJAX resource is simply NOT mentioned in the resulting HTML code.
The correct recognition can actually be forced by adding a dummy value to the resource's URL like this (see –>jsFiddle docs for more info):
...&dummy=.js
Here is an example that shows how to add the external Google Maps API resource to a jsFiddle (mind the dummy parameter at the very end!):
https://maps.googleapis.com/maps/api/js?sensor=false&dummy=.js
Unfortunately this won't work for you as the MS AJAX URL will fail when additional parameters are appended.
A solution (and currently the safest way to load external resources) is to avoid the External Resources tab altogether and load external code manually in the first line(s) of jsFiddle's HTML window like this:
<script type='text/javascript' src="http://ajax.aspnetcdn.com/ajax/3.5/MicrosoftAjax.js"></script>
Here is your jsFiddle modified to use that method: http://jsfiddle.net/rEzW5/12/
It actually does not do a lot (I did not check what is wrong with the rest of your code), but at least it does not throw JavaScript errors anymore.
Open "Add Resources" section and add the url of your external script...
#Jpsy's approach no longer seems to work (see my comment under his answer).
For me, adding the resource under External Resources also didn't work. (According to the Firefox Debugger, it couldn't find the resource).
The only way I was able to get an external bit of JavaScript code (in my case jquery.backstretch.js) to work, was to use Google to find a Fiddle which used this resource (and worked), then Fork this Fiddle and copy/paste all my code into the HTML, CSS and JavaScript panels. Ugh!
#clayRay, You absolutely went thru a code surgery. Just resolved that by mentioning external source in plain html which in my case is
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
Using External Resources tab didn't help a bit...
Is there anyway by adding to this javascript I can ingore anything after the .com/ .net/ .org/ etc for tab.url.
So if tab.url = examplesite.com/blabla/blabla.html it will replace tab.url with examplesite.com/ and ignore anything after it.
Here's my background.html script.
<script type="text/javascript">
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.getSelected(null,function(tab) {
chrome.tabs.create( { url: "http://www.mysite.com/index.php?q=" +tab.url } );
});
});
</script>
Or do I need to program this into mysite to strip the Url? I was wondering if it is possible with Javascript... (not my forte.)
Thank you for any help you may be able to give me.
Unfortunately there is not parseUri function built into javascript but you could build what you're asking for using regular expressions. An example of this can be found here:
http://blog.stevenlevithan.com/archives/parseuri
Also, I've never tried to access it from a Chrome extension, but I suspect you have access to the window.location variable which is an object that contains broken down parts of the current page's url. Trying console.log(window.location) and look at the content of the object.
I need to load the Recaptcha library on demand, with javascript (using Prototype):
var captcha = new Element('script', { type: 'text/javascript', src: 'http://api.recaptcha.net/js/recaptcha_ajax.js' });
$$('head')[0].appendChild(captcha);
captcha.onload = function()
{
Recaptcha.create("dsfahsldkjfhlasdjfc","recaptcha_image", {theme: "custom"});
};
The problem here is with IE, of course. It seems that the captcha.onload wont work in IE. As usual, it works on other browsers.
So, how can I check that the script is loaded on IE, and call Recaptcha.create afterwards?
Is there an easier and cross-browser way of loading and evaluating external scripts with Prototype?
Thanks.
Looks like IE doesn't support onload, but DOES support onreadystatechange:
Sample code for onreadystatechange:
http://gist.github.com/461797
Post with some info, source of above link:
http://blog.andrewcantino.com/post/211671748/replacement-for-script-onload-in-ie
I find this excellent code, posted by aemkei as answers to this questions:
How do you dynamically load a javascript file? (Think C’s #include)
Use javascript to inject script references as needed?
You may write dynamic script tags
(using Prototype):
new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
The problem here is that we do not
know when the external script file is
fully loaded.
We often want our dependant code on
the very next line and like to write
something like:
if (iNeedSomeMore){
Script.load("myBigCodeLibrary.js"); // includes code for myFancyMethod();
myFancyMethod(); // cool, no need for callbacks!
}
There is a smart way to inject script
dependencies without the need of
callbacks. You simply have to pull the
script via a synchronous AJAX request
and eval the script on global level.
If you use Prototype the Script.load
method looks like this:
var Script = {
_loadedScripts: [],
include: function(script){
// include script only once
if (this._loadedScripts.include(script)){
return false;
}
// request file synchronous
var code = new Ajax.Request(script, {
asynchronous: false, method: "GET",
evalJS: false, evalJSON: false
}).transport.responseText;
// eval code on global level
if (Prototype.Browser.IE) {
window.execScript(code);
} else if (Prototype.Browser.WebKit){
$$("head").first().insert(Object.extend(
new Element("script", {type: "text/javascript"}), {text: code}
));
} else {
window.eval(code);
}
// remember included script
this._loadedScripts.push(script);
}
};
I found that, the code does not work on IE if the all of them is executed in 'file://' protocol, however, it is not the problem since its use case involved real web application.
I tried it once to include http://www.google-analytics.com/urchin.js by google, but from one of web page, but it looks like it cannot request javascript file from different domain.
How we could dynamically add javascript, just like what above scripts does, but from another domain?
You can use the onload and onreadystatechange event to understand when the <script> tag is loaded.
var script = new Element("script", {src: "myBigCodeLibrary.js", type: "text/javascript"});
script.onload = script.onreadystatechange = function(){
if (!this.readyState ||
this.readyState == "loaded" || this.readyState == "complete") {
//script is loaded
}
};
The security model in modern browsers prevents JavaScript from making cross-domain requests. That has holes (see every website exploit since the beginning of the internet), but using them is more than a little shady and it's only a matter of time before they're patched.
What Rex said is correct, although HTML5 has added cross domain messaging and xhr, which require a little bit of work on your part but should be usable to achieve this. Alas they're not yet present in all released browsers (i think the latest betas of safari, firefox, and IE have support for some of these features, but i'm not sure which browsers support which apis)