How can i write dynamic MULTIPLE script loader with complete handler like google
google.load("http://script1");
google.load("http://script2");
google.setOnLoadCallback(function(){});
thanks
My advise is not to bother with script loading yourself, unless you take a look at how some frameworks do it because there can be security risks for your application with that sort of thing. In fact, I would redirect you to JQuery instead as it does have that functionality implemented (see here).
There are open source js which will ease your problem.
You can use LABJS or RequreJS plugins.
Script loaders like LABJS, RequireJS will improve the speed and quality of your code. Additionally it will load scripts dynamically.
I wrote like that
myApp.Loader = function(){
var queries = [];
var q = 0;
var p = 0;
var started = false;
var _callback = function(){};
var start = function(){
if(queries.length > 0 && !started){
started = true;
load(queries.shift());
} else if(queries.length > 0 && started){
load(queries.shift());
} else if(queries.length == 0 && started){
started = false;
if(q > 0 && q == p){
callback();
}
}
};
var load = function(fullUrl){
$.getScript(fullUrl, function() {
p++;
start();
});
};
var callback = function(){
_callback();
};
this.setCallback = function(fnc){
_callback = fnc;
if(q > 0 && q == p){
callback();
}
};
this.addQuery = function(query){
queries.push(query);
q++;
if(!started) {
start();
}
};
return this;
}
var Loader = new myApp.Loader();
myApp.load = function(fullUrl){
Loader.addQuery(fullUrl);
}
myApp.setOnLoadCallback = function(fnc){
Loader.setCallback(fnc);
}
and call it
myApp.load("http://script1");
myApp.load("http://script2");
myApp.load("http://script3");
myApp.setOnLoadCallback(function(){
// complete script load handling
});
Related
I'm trying to change my image size with javascript to be 500x375 instead of 130x98. If there is no 500x37 for that image, than I would like it to fallback to 130x98.
So far, I have the code below. It changes my images to 500x375, but the ones that do not have that size it appears broken instead of falling back to 130x98. Any ideas on how to fix this?
function ImageExists(selector) {
var imageFound = $(selector);
if (imageFound.height() === 0) {
console.log('no height');
return false;
}
return true;
}
$('div.photo > a > img').each(function(k, v) {
var x = v.src;
v.src = x.replace('130x98', '500x375');
if (!ImageExists(v)) {
console.log(v.src);
v.src = x.replace('500x375', '130x98')
}
});
You can try this code
$(document).ready(function(){
var src1 = '130x98';
var src2 = '500x375';
$('div.photo > a > img').each(function(){
var changeSrc;
var Image = $(this);
var GetSrc = $(this).attr('src');
Image.error(function() {
if(GetSrc.indexOf(src1) !== -1 ){
changeSrc = GetSrc.replace(src1 , src2);
}else if(GetSrc.indexOf(src2) !== -1 ){
changeSrc = GetSrc.replace(src2 , src1);
}
Image.attr("src", changeSrc);
});
})
});
DEMO
Are you missing semicolon in v.src = x.replace('500x375', '130x98'):in this line??
try putting alert();function in which line you doubted... alert(); will not work if any previous line is in error
$('div.photo > a > img').each(function (k, v) {
var x = v.src;
v.src = x.replace('130x98', '500x375');
if (!ImageExists(v)) {
console.log(v.src);
v.src = x.replace('500x375', '130x98');
};
How about trying the on error event instead of your ImageExists method:
$("img").error(function () {
//load in your default image dimensions.
});
When there's an error loading the image this will be triggered.
You might also want to unbind this event the first time it us run in case it continuously loops.
I am trying to work with Disqus api and I need to run some javascript code that modify Disqus comments thread.
How to run the javascript code after Disqus thread has loaded?
I ran into a similar issue. The only working solution I was able to come up with was to run setInterval() to check the height of the Disqus container div.
Example:
var editable = true; // set a flag
setInterval(function() {
// Initially Disqus renders this div with the height of 0px prior to the comments being loaded. So run a check to see if the comments have been loaded yet.
var disqusHeight = $('#dsq-2').height();
if ( disqusHeight > 0 ) {
if (editable) { // To make sure that the changes you want to make only happen once check to see if the flag has been changed, if not run the changes and update the flag.
editable = false;
// Your code here...
}
}
}, 100);
Try this:
function disqus_config() {
this.callbacks.onReady.push(function () {
// your code
});
}
Here is modifyed code of Brandon Morse for new version Disqus and script stops when Disqus is loaded comments.
var interval = setInterval(function() {
var $ = jQuery;
var disqusHeight = $('#disqus_thread').height();
if ( disqusHeight > 52 ) { // height 52px is header of Disqus, more than 52px means that disqus load comments
// Your code
clearInterval(interval); // after loaded comment we stop this script
}
}, 100);
Use flag to avoid loop:
evento.add(window, "load", function () {
var w = window,
d = document,
a = d.getElementById("disqus_thread") || "",
disqus_shortname = a ? (a.dataset.shortname || "") : "",
embed_js_src = ("https:" == w.location.protocol ? "https" : "http") + "://" + disqus_shortname + ".disqus.com/embed.js",
g = ".grid",
h = ".grid-item",
k = ".grid-sizer",
grid = d.querySelector(g) || "";
function build_layout() {
if (grid) {
if (w.Packery) {
var pckry = new Packery(grid, {
itemSelector : h,
gutter : 0
});
} else if (w.Masonry) {
var msnry = new Masonry(grid, {
itemSelector : h,
columnWidth : k
});
}
}
}
build_layout();
if (a && disqus_shortname) {
w.loadJS && loadJS(embed_js_src, function () {
if (grid) {
var f = !1;
setInterval(function () {
var disqus_thread_height = a.clientHeight || a.offsetHeight || "";
if (108 < disqus_thread_height && !1 === f) {
/* alert(disqus_thread_height); */
build_layout();
f = !0;
}
}, 100);
}
});
}
});
`<script>
var disqus_config = function () {
this.callbacks.onReady = [function(data) {
//your code here
}];
this.callbacks.afterRender= [function(data) {
//your code here
}];
this.callbacks.beforeComment= [function(data) {
//your code here
}];
this.callbacks.onInit= [function(data) {
//your code here
}];
this.callbacks.onNewComment= [function(data) {
//your code here
}];
this.callbacks.onPaginate= [function(data) {
//your code here
}];
this.callbacks.preData= [function(data) {
//your code here
}];
this.callbacks.preInit= [function(data) {
//your code here
}];
this.callbacks.preReset= [function(data) {
//your code here
}];
};
</script>`
How would I have the h1 change for each iteration of the loop? This code now only displays the h1 text after everything is done.
for (i=0; i<array.length; i++) {
$("body > h1").text("Processing #" + i);
// things that take a while to do
}
Additional info: if I resize the window as it loops, the html updates.
var array = ['one', 'two', 'three']
var i = 0;
var refreshIntervalId = setInterval(function() {
length = array.length;
if (i < (array.length +1)) {
$("h1").text("Processing #" + i);
} else {
clearInterval(refreshIntervalId);
}
i++
}, 1000);
http://jsfiddle.net/3fj9E/
Use a setInterval with a one-millisecond delay:
var i=0, j=array.length;
var iv = setInterval(function() {
$("h1").text("Processing #" + i);
// things that take a while to do
if (++i>=j) clearInterval(iv);
}, 1);
http://jsfiddle.net/mblase75/sP9p7/
Sometimes you can force a render by forcing a recalculation of layout
for (i=0; i<array.length; i++) {
$("body > h1").text("Processing #" + i)
.width(); // force browser to recalculate layout
// things that take a while to do
}
It might not work in all browsers.
A better way, that does not block the browser so much:
function doThings(array) {
var queueWork,
i = -1,
work = function () {
// do work for array[i]
// ...
queueWork();
};
queueWork = function () {
if (++i < array.length) {
$("body > h1").text("Processing #" + i);
setTimeout(work, 0); // yield to browser
}
};
}
doThings(yourArray);
DEMO
I've spent a bit of time working out a jquery function that seems to solve this. Basically, it's a process handler that you can add any number of processes to and then call run to sequentially call these in a asynchronous way.
$.fn.LongProcess = function () {
var _this = this;
this.notifications = [];
this.actions = [];
this.add = function (_notification, _action) {
this.notifications.push(_notification);
this.actions.push(_action);
};
this.run = function () {
if (!_this.actions && !_this.notifications) {
return "Empty";
}
//******************************************************************
//This section makes the actions lag one step behind the notifications.
var notification = null;
if (_this.notifications.length > 0) notification = _this.notifications.shift();
var action = null;
if ((_this.actions.length >= _this.notifications.length + 2) || (_this.actions.length > 0 && _this.notifications.length == 0))
action = _this.actions.shift();
//****************************************************************
if (!action && !notification) {
return "Completed";
}
if (action) action();
if (notification) notification();
setTimeout(_this.run, 1000);
//setTimeout(_this.run,1); //set to 1 after you've entered your actual long running process. The 1000 is there to just show the delay.
}
return this;
};
How to use with <h1 class="processStatus"></h1>:
$(function () {
var process = $().LongProcess();
//process.add(notification function, action function);
process.add(function () {
$(".processStatus").text("process1");
}, function () {
//..long process stuff
alert("long process 1");
});
process.add(function () {
$(".processStatus").text("process2");
}, function () {
//..long process stuff
alert("long process 2");
});
process.add(function () {
$(".processStatus").text("process3");
}, function () {
//..long process stuff
alert("long process 3");
});
process.run();
});
if the process is very long you can use this script which shows every notification for a specific time interval.
here is the code..
html
<div id="ccNotificationBox"></div>
css
#ccNotificationBox{
-webkit-animation-name:;
-webkit-animation-duration:2s;/*Notification duration*/
box-sizing:border-box;
border-radius:16px;
padding:16px;
background-color:rgba(0,0,0,0.7);
top:-100%;
right:16px;
position:fixed;
color:#fff;
}
#ccNotificationBox.active{
-webkit-animation-name:note;
top:16px;
}
#-webkit-keyframes note{
0% {opacity:0;}
20% {opacity:1;}
80% {opacity:1;}
100% {opacity:0;}
}
javascript
var coccoNotification=(function(){
var
nA=[],
nB,
rdy=true;
function nP(a){
nA.push(a);
!rdy||(nR(),rdy=false);
}
function nR(){
nB.innerHTML=nA[0];console.log(nA[0]);
nB.offsetWidth=nB.offsetWidth;//reflow ios
nB.classList.add('active');
}
function nC(){
nB.classList.remove('active');
nB.innerHTML='';
nA.shift();
nA.length>0?nR():(rdy=true);
}
function init(){
nB=document.getElementById('ccNotificationBox');
nB.addEventListener('webkitAnimationEnd',nC,false);
window.removeEventListener('load',init,false);
}
window.addEventListener('load',init,false);
return nP
})();
usage
coccoNotification('notification 1');
example
http://jsfiddle.net/f6dkE/1/
info
the example above is perfect for external js as you use just one global variable which is the name of the function ... in my case coccoNotification
here is a different approach but it does the same
http://jsfiddle.net/ZXL4q/11/
I need to check whether the browser is supported by my application and I do this the following way:
main.js (main require.js module)
define(['underscore', 'backbone', 'views/mainView', 'views/oldBrowser', 'ui', function(_, Backbone, mainView, oldBrowser){
var _browserHandshaking = function(){
var browserSupportedCookie = $.cookie('browserSupported');
var browserNameCookie = $.cookie('browserName');
var browserVersionCookie = $.cookie('browserVersion');
if(browserSupportedCookie === null){
if(/Chrome[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
$.ui.browserName = 'chrome';
} else if(/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
$.ui.browserName = 'opera';
/Version[\/\s](\d+\.\d+)/.test(navigator.userAgent);
} else if(/MSIE (\d+\.\d+);/.test(navigator.userAgent)){
$.ui.browserName = 'ie';
} else if(/Safari[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
$.ui.browserName = 'safari';
/Version[\/\s](\d+\.\d+)/.test(navigator.userAgent);
} else if(/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
$.ui.browserName = 'firefox';
} else if(/webOS/i.test(navigator.userAgent)){
$.ui.browserName = 'webos';
} else if(/Android/i.test(navigator.userAgent)){
$.ui.browserName = 'android'
} else if(/iPhone/i.test(navigator.userAgent)){
$.ui.browserName = 'iphone';
} else if(/iPod/i.test(navigator.userAgent)){
$.ui.browserName = 'ipod';
} else if(/BlackBerry/i.test(navigator.userAgent)){
$.ui.browserName = 'blackberry';
}
if($.ui.browserName !== false){
// Set browser version.
if(!$.ui.browserVersion){
$.ui.browserVersion = parseFloat(new Number(RegExp.$1));
}
for(var browserName in $.ui.supportedBrowsers){
if($.ui.browserName === browserName){
if($.ui.browserVersion >= $.ui.supportedBrowsers[browserName]){
$.ui.browserSupported = true;
break;
}
}
}
$.cookie('browserVersion', $.ui.browserVersion, { expires: 7 });
$.cookie('browserName', $.ui.browserName, { expires: 7 });
$.cookie('browserSupported', $.ui.browserSupported, { expires: 7 });
}
} else {
$.ui.browserSupported = browserSupportedCookie;
$.ui.browserName = browserNameCookie;
$.ui.browserVersion = browserVersionCookie;
}
};
_browserHandshaking.call(this);
var Router = Backbone.Router.extend({
routes: {
"old-browser": "oldBrowser",
"*actions": "main",
},
oldBrowser: function(){
oldBrowser.render();
},
main: function(){
mainView.render();
}
});
$.ui.router = new Router();
// Start routing.
Backbone.history.start({
pushState: true,
root: $.ui.rootDir
});
});
Is there a function in Backbone.js that triggers at every action, there I could easily implement this:
preRouting: function(){
if(!$.ui.browserSupported){
return false;
}
return true;
}
I just need to check, if the browser is supported, and if it is supported it can call the mainView, else the oldBrowser view should be triggered, I just don't want to do this at each route function call.
Someone has a better solution for this? And does someone know if it is possible to create a check that is basically a prelimiter for a route function call.
Thanks for help :)
Based on comments, you can check for push state with: (from Can use pushState )
var hasPushstate = !!(window.history && history.pushState);
css3 animations with: ( from Detect css transitions using javascript (and without modernizr)? )
function supportsTransitions() {
var b = document.body || document.documentElement;
var s = b.style;
var p = 'transition';
if(typeof s[p] == 'string') {return true; }
// Tests for vendor specific prop
v = ['Moz', 'Webkit', 'Khtml', 'O', 'ms'],
p = p.charAt(0).toUpperCase() + p.substr(1);
for(var i=0; i<v.length; i++) {
if(typeof s[v[i] + p] == 'string') { return true; }
}
return false;
}
var hasCSS3Transitions = supportsTransitions();
There's no need to check the browser name/version if you can simply check to see if the browser has the functionality your application needs.
I'm currently looking for a way to load in multiple scripts/plugins without having a laundry list listed out in the header.
To simply have a load.js have everything load in would be very elegant to me.
$(function() {
var scripts = ['scripts/jquery1.5.js','scripts/easing.js','scripts/scroll.js','scripts/main.js'];
for(var i = 0; i < scripts.length; i++) {
$.getScript(scripts[i]);
}
})
I currently have something like this but can't get it to work for some reason. Any ideas?
Have you looked at head.js?
Here is my conclusion for head.js, I have done some benchmarks myself:
http://blog.feronovak.com/2011/03/headjs-script-is-it-really-necessary.html
It is subjective opinion and benchmarks are not by any means scientific.
This is my solution : check if file is added (stored in array) and then load one file after another. Works perfectly!
var filesadded = "" //list of files already added
function loadJSQueue(array, success) {
if (array.length != 0) {
if (filesadded.indexOf("[" + array[0] + "]") == -1) {
filesadded += "[" + array[0] + "]" //List of files added in the form "[filename1],[filename2],etc"
oHead = document.getElementsByTagName('head')[0];
var oScript = document.createElement('script');
oScript.type = 'text/javascript';
oScript.src = array[0];
array.shift();
oScript.onreadystatechange = function () {
if (this.readyState == 'complete') {
loadJSQueue(array, success);
}
}
oHead.appendChild(oScript);
}
else {
array.shift();
loadJSQueue(array, success);
}
}
else {
success();
}
}
call it with
loadJSQueue(["../../JavaScript/plupload/js/jquery.plupload.queue/jquery.plupload.queue.js",
"../../JavaScript/plupload/js/plupload.js",
"../../JavaScript/plupload/js/plupload.html4.js"
], function(){alert("success");})
loadScripts(['script1.js','script2.js'], function(){ alert('scripts loaded'); }
function loadScripts(scripts, callback){
var scripts = scripts || new Array();
var callback = callback || function(){};
for(var i = 0; i < scripts.length; i++){
(function(i) {
$.getScript(scripts[i], function() {
if(i + 1 == scripts.length){
callback();
}
});
})(i);
}
}