Why this won't be fired? - javascript

I tried to make a button to start playing video on player.
Player is showing up and works fine if I press "Playing" on control bar.
But My a href link to start playing won't work.
play() won't be fired. why?
<script>
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("myytplayer");
}
function play() {
if (ytplayer) {
ytplayer.playVideo();
}
}
</script>
<script type="text/javascript" src="swfobject.js"></script>
<div id="ytapiplayer">
You need Flash player 8+ and JavaScript enabled to view this video.
</div>
<script type="text/javascript">
var params = { allowScriptAccess: "always" };
var atts = { id: "myytplayer" };
swfobject.embedSWF("http://www.youtube.com/v/P5_GlAOCHyE?enablejsapi=1&playerapiid=ytplayer",
"ytapiplayer", "425", "356", "8", null, null, params, atts);
</script>
Play

Talking to Flash objects can be difficult. Here's the code I use to send messages:
function runFlashFunction( flashName, funcName ) {
var
od = document[flashName],
ow = window[flashName];
// flash isn't happy with o=func;o(); syntax
try {
if( od && !!(od[funcName]) ) {
return document[flashName][funcName]( );
}
if( ow && !!(ow[funcName]) ) {
return window[flashName][funcName]( );
}
if( ow && ow.length && !!(ow[0]) && !!(ow[0][funcName]) ) {
return window[flashName][0][funcName]( );
}
return void 0;
} catch( ex ) {
return void 0;
}
}
Why all that? because some browsers use different ways to access the flash content. The last one probably isn't needed, but I include it to be sure.
Also your link uses a style which isn't recommended. This is better:
Play
Or even better: assign the callback in the JavaScript, not the HTML:
$(function(){
$('#playLink').click(function(){ // name the link playLink (or whatever)
play();
return false;
});
});

Try not to use a global variable
var ytplayer = null;
function onYouTubePlayerReady(playerId) {
ytplayer = document.getElementById("myytplayer");
}
function play() {
if (ytplayer) {
ytplayer.playVideo();
}
}

Related

using YouTube iFrame API within jQuery event

I have a page in which clicking a link opens a lightbox and embeds a YouTube video in an <iframe>. The lightbox and <iframe> markup are generate on the fly by Lity.
Following the example right out of the documentation, where the <iframe> is hard-coded into the page, it works as expected.
<iframe id="existing-iframe-example"
width="640" height="360"
src="https://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1"
frameborder="0"
style="border: solid 4px #37474F">
</iframe>
<script type="text/javascript">
var tag = document.createElement('script');
tag.id = 'iframe-demo';
tag.src = 'https://www.youtube.com/iframe_api';
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubeIframeAPIReady() {
console.log('api ready');
player = new YT.Player('existing-iframe-example', {
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
document.getElementById('existing-iframe-example').style.borderColor = '#FF6D00';
}
function changeBorderColor(playerStatus) {
var color;
if (playerStatus == -1) {
color = "#37474F"; // unstarted = gray
} else if (playerStatus == 0) {
color = "#FFFF00"; // ended = yellow
} else if (playerStatus == 1) {
color = "#33691E"; // playing = green
} else if (playerStatus == 2) {
color = "#DD2C00"; // paused = red
} else if (playerStatus == 3) {
color = "#AA00FF"; // buffering = purple
} else if (playerStatus == 5) {
color = "#FF6DOO"; // video cued = orange
}
if (color) {
document.getElementById('existing-iframe-example').style.borderColor = color;
}
}
function onPlayerStateChange(event) {
changeBorderColor(event.data);
}
</script>
See this Codepen
I'm trying to modify it to work with a dynamically generated <iframe> (which is how Lity handles YouTube videos). I can see that the YouTube API script is being added to the page, but the function onYouTubeIframeAPIReady does not ever seem to be called, which according to documentation is supposed to fire as soon as API script loads.
HTML (to open lightbox)
<a href="https://www.youtube.com/embed/M7lc1UVf-VE?enablejsapi=1" class="lity" data-lity>open</a>
JavaScript (fires after lightbox object is available in DOM)
$(document).on("lity:ready", function (event, instance) {
console.log("Lightbox ready");
$(".lity-youtube iframe").attr("id", "x");
if ($("iframe#x").length) {
console.log("ID added to <iframe>");
} else {
console.log("ID NOT added to <iframe>");
}
var tag = document.createElement("script");
tag.id = "iframe-demo";
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName("script")[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
if ($("#iframe-demo").length) {
console.log("api script added");
} else {
console.log("api script NOT added");
}
var player;
function onYouTubeIframeAPIReady() {
console.log("api ready");
player = new YT.Player("x", {
events: {
onReady: onPlayerReady,
onStateChange: onPlayerStateChange
}
});
}
function onPlayerReady(event) {
console.log("player ready");
document.getElementById("x").style.borderColor = "#FF6D00";
}
function changeBorderColor(playerStatus) {
var color;
if (playerStatus == -1) {
color = "#37474F"; // unstarted = gray
} else if (playerStatus == 0) {
color = "#FFFF00"; // ended = yellow
} else if (playerStatus == 1) {
color = "#33691E"; // playing = green
} else if (playerStatus == 2) {
color = "#DD2C00"; // paused = red
} else if (playerStatus == 3) {
color = "#AA00FF"; // buffering = purple
} else if (playerStatus == 5) {
color = "#FF6DOO"; // video cued = orange
}
if (color) {
document.getElementById("x").style.borderColor = color;
}
}
function onPlayerStateChange(event) {
console.log('state change');
changeBorderColor(event.data);
}
});
See this Codepen.
I tried pulling everything out of the lity:ready event handler with the same results....
Can anyone see what's going wrong?
EDIT/UPDATE
I tried running onYouTubeIframeAPIReady as a deferred object
var YTdeferred = $.Deferred();
window.onYouTubeIframeAPIReady = function() {
YTdeferred.resolve(window.YT);
};
and using it in the callback
var player;
YTdeferred.done(function (YT) {
console.log("api ready");
player = new YT.Player("x", {
events: {
//onReady: onPlayerReady,
//onStateChange: onPlayerStateChange
onReady: function () {
console.log("player ready from ananonymous");
},
onStateChange: onPlayerStateChange
}
});
console.log(player);
});
Now the YT.Player object is created (presumably on the iframe created by lity), but neither of the events (onReady and onStateChange) seem to be triggering. Also, it doesn't have access to any of the methods or properties that it should:
player.playVideo()
produces an error: player.playVideo is not a function`
Still stumped.
Codepen
ANOTHER EDIT/UPDATE
Now I'm very confused because i created a version that replicates what lity does (I think) and the events (onReady and onStateChange) do in fact fire as expected.
Codepen
Solution to a STUPID mistake
I can' believe I beat my head into the wall over this for so long... G'AAAAAAH!!
It's definitely a lity thing
When lity receives an argument (YouTube URL) formatted like
https://www.youtube.com/embed/XXXXXXXXX
or
http://youtu.be/XXXXXXXXX
it converts it to
https://www.youtube.com/embed/XXXXXXXXX?autoplay=1
If you try to pass query string arguments to to a similarly formatted URL (such as: https://www.youtube.com/embed/XXXXXXXXX?enablejsapi=1 (which is required for the API calls to work), it URLencodes the ?enablejsapi=1 and adds it to the end of the converted URL, so you get:
https://www.youtube.com/embed/XXXXXXXX?autoplay=1&%3Fenablejsapi=1
As a result the enablejsapi=1 is never read in and therefore the YT.Player is never attached to the <iframe> DOM element.
** SOLUTION **
Pass the URL to lity in a format that passes the video ID as a query string argument (and append enablejsapi=1):
https://www.youtube.com/watch?v=XXXXXXXX&enablejsapi=1
lity will now keep your argument(s) intact and convert to
https://www.youtube.com/embed/XXXXXXXX?autoplay=1&enablejsapi=1
Now the YT.Player call can read enablejsapi=1 and properly attach to the <iframe> element, and all is good in the universe.
<a href="https://www.youtube.com/watch?v=TJU-tBquzcM&enablejsapi=1" class="lity" data-lity>open lightbox with video</a>
Final Working CodePen
.
It looks like the "lity:ready" event is not fired in my case.
I changed
$(document).on("lity:ready", function (event, instance) {
to
$(document).ready(function (event, instance) {
using the jQuery ready event.
And most important, the function onYouTubeIframeAPIReady must be global (on window scope) to be detected by the youtube iFrame API (actually it was created inside an anonymous function() ). So I changed
function onYouTubeIframeAPIReady() {
to
window.onYouTubeIframeAPIReady=function() {
Codepen
EDIT:
To work on a global context inside an anonymous function. Other local functions created and referenced (onPlayerReady and onPlayerStateChange) must be declared in the global context using the window object.
window.onPlayerReady=function(event) {
console.log("player ready");
document.getElementById("x").style.borderColor = "#FF6D00";
}
window.changeBorderColor=function(playerStatus) {
var color;
if (playerStatus == -1) {
color = "#37474F"; // unstarted = gray
} else if (playerStatus == 0) {
color = "#FFFF00"; // ended = yellow
} else if (playerStatus == 1) {
color = "#33691E"; // playing = green
} else if (playerStatus == 2) {
color = "#DD2C00"; // paused = red
} else if (playerStatus == 3) {
color = "#AA00FF"; // buffering = purple
} else if (playerStatus == 5) {
color = "#FF6DOO"; // video cued = orange
}
if (color) {
document.getElementById("x").style.borderColor = color;
}
}
window.onPlayerStateChange=function(event) {
console.log('state change');
changeBorderColor(event.data);
}

Browser Full screen feature

Hi I have the below page where you simply click the button Full screen and the page browser takes up the full screen, the navigation controls are also hidden to - which is what I like. However if you page refresh (or in my case my page refreshes every 5 minutes) the navigation controls return and it is no longer the view as previous. How can I solve this so that when it refreshed the navigation etc doesn't return and it remains full screen?
<html>
<head>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" />
<script src="screenfull.js"></script>
<script>
$(function () {
$('#supported').text('Supported/allowed: ' + !!screenfull.enabled);
if (!screenfull.enabled) {
return false;
}
$('#request').click(function () {
screenfull.request($('#container')[0]);
// does not require jQuery, can be used like this too:
// screenfull.request(document.getElementById('container'));
});
$('#exit').click(function () {
screenfull.exit();
});
function fullscreenchange() {
var elem = screenfull.element;
$('#status').text('Is fullscreen: ' + screenfull.isFullscreen);
if (elem) {
$('#element').text('Element: ' + elem.localName + (elem.id ? '#' + elem.id : ''));
}
if (!screenfull.isFullscreen) {
$('#external-iframe').remove();
document.body.style.overflow = 'hidden';
}
}
document.addEventListener(screenfull.raw.fullscreenchange, fullscreenchange);
// set the initial values
fullscreenchange();
});
</script>
<button id="request"><i class="fa fa-arrows-alt"></i> Request</button>
<button id="exit">Exit</button>
</body>
(function () {
'use strict';
var isCommonjs = typeof module !== 'undefined' && module.exports;
var keyboardAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
var fn = (function () {
var val;
var valLength;
var fnMap = [
[
'requestFullscreen',
'exitFullscreen',
'fullscreenElement',
'fullscreenEnabled',
'fullscreenchange',
'fullscreenerror'
],
// new WebKit
[
'webkitRequestFullscreen',
'webkitExitFullscreen',
'webkitFullscreenElement',
'webkitFullscreenEnabled',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
// old WebKit (Safari 5.1)
[
'webkitRequestFullScreen',
'webkitCancelFullScreen',
'webkitCurrentFullScreenElement',
'webkitCancelFullScreen',
'webkitfullscreenchange',
'webkitfullscreenerror'
],
[
'mozRequestFullScreen',
'mozCancelFullScreen',
'mozFullScreenElement',
'mozFullScreenEnabled',
'mozfullscreenchange',
'mozfullscreenerror'
],
[
'msRequestFullscreen',
'msExitFullscreen',
'msFullscreenElement',
'msFullscreenEnabled',
'MSFullscreenChange',
'MSFullscreenError'
]
];
var i = 0;
var l = fnMap.length;
var ret = {};
for (; i < l; i++) {
val = fnMap[i];
if (val && val[1] in document) {
for (i = 0, valLength = val.length; i < valLength; i++) {
ret[fnMap[0][i]] = val[i];
}
return ret;
}
}
return false;
})();
var screenfull = {
request: function (elem) {
var request = fn.requestFullscreen;
elem = elem || document.documentElement;
// Work around Safari 5.1 bug: reports support for
// keyboard in fullscreen even though it doesn't.
// Browser sniffing, since the alternative with
// setTimeout is even worse.
if (/5\.1[\.\d]* Safari/.test(navigator.userAgent)) {
elem[request]();
} else {
elem[request](keyboardAllowed && Element.ALLOW_KEYBOARD_INPUT);
}
},
exit: function () {
document[fn.exitFullscreen]();
},
toggle: function (elem) {
if (this.isFullscreen) {
this.exit();
} else {
this.request(elem);
}
},
raw: fn
};
if (!fn) {
if (isCommonjs) {
module.exports = false;
} else {
window.screenfull = false;
}
return;
}
Object.defineProperties(screenfull, {
isFullscreen: {
get: function () {
return Boolean(document[fn.fullscreenElement]);
}
},
element: {
enumerable: true,
get: function () {
return document[fn.fullscreenElement];
}
},
enabled: {
enumerable: true,
get: function () {
// Coerce to boolean in case of old WebKit
return Boolean(document[fn.fullscreenEnabled]);
}
}
});
if (isCommonjs) {
module.exports = screenfull;
} else {
window.screenfull = screenfull;
}
})();
Online Demo : https://plnkr.co/edit/zx0rXwXpJbWdMvh3HQ25?p=preview
Make onepage website (ajax) (no refresh) Use history pushstate to save all your links so you can use history navigation and change your URL. (most of time I use this approach.)
Or you can use localstorage to save state.
Theoretically You can store an indication of what was the previews state (full-screen / normal) in the browser storage.
Then on page load, read the stored value and activate full-screen if necessary.
However, modern browsers require this to be an interactive user action (not automatically via script on load)
If you try to automate this, you'll get these type of warnings in the browser's console:
Alternatives
Avoid full refreshes
Workaround using custom browser extension to restore the fullscreen state

html5 audio bind timeupdate before element exists

im trying to bind the "timeupdate" event from an audio tag, which doesn't exist yet. I was used to do it this way:
$("body").on("click","#selector", function(e) {
});
I tried this with the audio tag:
$("body").on("timeupdate", ".audioPlayerJS audio", function(e) {
alert("test");
console.log($(".audioPlayerJS audio").prop("currentTime"));
$(".audioPlayerJS span.current-time").html($(".audioPlayerJS audio").prop("currentTime"));
});
This doesn't work though. Is this supposed to work? Or what am I doing wrong?
Any help is highly appreciated.
There is a fiddel for you: jsfiddel
Apparently media events( those specifically belonging to audio or video like play, pause, timeupdate, etc) do not get bubbled. you can find the explanation for that in the answer to this question.
So using their solution, I captured the timeupdate event,
$.createEventCapturing(['timeupdate']);
$('body').on('timeupdate', '.audioPlayerJS audio', updateTime); // now this would work.
JSFiddle demo
the code for event capturing( taken from the other SO answer):
$.createEventCapturing = (function () {
var special = $.event.special;
return function (names) {
if (!document.addEventListener) {
return;
}
if (typeof names == 'string') {
names = [names];
}
$.each(names, function (i, name) {
var handler = function (e) {
e = $.event.fix(e);
return $.event.dispatch.call(this, e);
};
special[name] = special[name] || {};
if (special[name].setup || special[name].teardown) {
return;
}
$.extend(special[name], {
setup: function () {
this.addEventListener(name, handler, true);
},
teardown: function () {
this.removeEventListener(name, handler, true);
}
});
});
};
})();

Trigger an actionscript function (in a flash object) from javascript

I have a flash (AS2.0) application with a function that i need to trigger from a html form link
The flash function only runs a gotoAndPlay('label name');
So my HTML is
<a href="" id="flashTrigger" />
and my flash function is
function myFunction(){
gotoAndPlay("myLabel");
}
Anyone know either how I can fire the flash function from the html link tag, OR run a "gotoAndPlay" from a Javascript function
Iv looked around and only seem to find how to fire a javascript function from flash
Here is the code I have so far - Im prob doing something stupid
Flash:
ExternalInterface.addCallback( "myExternalMethod", this, myFunction );
function myFunction(){
gotoAndPlay("fade");
}
Javascript
function executeFlash()
{
getObjectById("myFlashID").myExternalMethod();
}
function getObjectById(objectIdStr) {
var r = null;
var o = document.getElementById(objectIdStr);
if (o && o.nodeName == "OBJECT") {
if (typeof o.SetVariable != undefined) {
r = o;
}
else {
var n = o.getElementsByTagName(OBJECT)[0];
if (n) {
r = n;
}
}
}
return r;
}
$(function() {
$('#WhatDoesmean').click(function(){
executeFlash();
});
});
I have set myFlashID to the id of:
initial 'Object tag'
and IE only 'embed tag'
EDIT:
At the moment I am targeting the flash object fine, it's the external (flash side) function which is not working
- error message, myExternalMethod is not a function
You can use the external interface for this:
There is a working example at this location:
Flash to JS:
http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001655.html
JS to Flash:
http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001653.html
Hope this helps
Cheers
I used this a few years ago to capture the flash object:
var flashObj = getFlash("Flash_Name");
function getFlash(movieName)
{
if (window.document[movieName])
{
return (window.document[movieName]);
}
if (navigator.appName.indexOf("Microsoft Internet")==-1)
{
if (document.embeds && document.embeds[movieName])
{
return (document.embeds[movieName]);
}
}
else // if (navigator.appName.indexOf("Microsoft Internet")!=-1)
{
return (document.getElementById(movieName));
}
}
Then a flashObj.gotoAndPlay(); should work
In your flash file add a callback:
//**updated**
if (ExternalInterface.available)
{
trace("ExternalInterface= " + ExternalInterface.available);
flash.external.ExternalInterface.addCallback("myExternalMethod", null, myFunction);
}
function myFunction()
{
gotoAndPlay("myLabel");
}
In your javascript:
function executeFlash()
{
//**updated**
alert('JS call works fine!');
getObjectById("myFlashID").myExternalMethod(); // myFlashID = your SWF object ID
}
function getObjectById(objectIdStr) {
var r = null;
var o = getElementById(objectIdStr);
if (o && o.nodeName == "OBJECT") {
if (typeof o.SetVariable != UNDEF) {
r = o;
}
else {
var n = o.getElementsByTagName(OBJECT)[0];
if (n) {
r = n;
}
}
}
return r;
}
In your HTML (give your SWF object embedded in your HTML an id = myFlashID):
<a href="" id="flashTrigger" onclick="executeFlash()" />
Here is where you find the documentation for ExternalInterface http://flash-reference.icod.de/
I have managed to crack the problem by using SWFObject
Accessign the flash objects method was easy through SWFObject.js, however it just wasnt working without it. Not sure why though.
All the above suggestions work with SWFObject.js, but none seemed to work without it
Cheers for everyones suggestions
Andy

$(document).ready() source

I need to wait for document readyness in my JavaScript, to insert a div at the bottom of the body.
I want to:
make this JavaScript file as small as possible (compile it down to < 1kb if possible)
inline the code that provides the document readyness in a closure (without exporting it)
Inlining the whole jQuery source in my file would be too big, so I'm looking for other methods. window.onload would work, but I specifically want document readyness, and not wait for the window.onload event.
Does anyone know a JS snippet that can do this? Or should I just copy part of jQuery's source?
EDIT:
I managed to crawl the jQuery source and put together with the following snippet:
var ready = (function () {
var ready_event_fired = false;
var ready_event_listener = function (fn) {
// Create an idempotent version of the 'fn' function
var idempotent_fn = function () {
if (ready_event_fired) {
return;
}
ready_event_fired = true;
return fn();
}
// The DOM ready check for Internet Explorer
var do_scroll_check = function () {
if (ready_event_fired) {
return;
}
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
try {
document.documentElement.doScroll('left');
} catch(e) {
setTimeout(do_scroll_check, 1);
return;
}
// Execute any waiting functions
return idempotent_fn();
}
// If the browser ready event has already occured
if (document.readyState === "complete") {
return idempotent_fn()
}
// Mozilla, Opera and webkit nightlies currently support this event
if (document.addEventListener) {
// Use the handy event callback
document.addEventListener("DOMContentLoaded", idempotent_fn, false);
// A fallback to window.onload, that will always work
window.addEventListener("load", idempotent_fn, false);
// If IE event model is used
} else if (document.attachEvent) {
// ensure firing before onload; maybe late but safe also for iframes
document.attachEvent("onreadystatechange", idempotent_fn);
// A fallback to window.onload, that will always work
window.attachEvent("onload", idempotent_fn);
// If IE and not a frame: continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch (e) {}
if (document.documentElement.doScroll && toplevel) {
return do_scroll_check();
}
}
};
return ready_event_listener;
})();
// TEST
var ready_1 = function () {
alert("ready 1");
};
var ready_2 = function () {
alert("ready 2");
};
ready(function () {
ready_1();
ready_2();
});
Thank you very much for helping me find this in the jQuery source. I can now put all this in a closure and do my work without exporting any functions and polluting the global scope.
One option would be to just get the core.js jQuery file from github.
You could probably slim it down quite a bit for code you don't need. Then run it through YUI compressor, and it should be pretty small.
http://github.com/jquery/jquery/blob/1.4.2/src/core.js (jQuery core)
http://yui.2clics.net/ (YUI compressor online)
I tried it, and this code worked properly:
$(function() {
var newDiv = document.createElement('div');
document.getElementsByTagName('body')[0].appendChild(newDiv);
});
Update: This was as small as I got it. It is entirely from jQuery and is around 1,278 bytes (compressed). Should get smaller when you gzip.
Only difference is that you need to call it like:
$.fn.ready(function() {
// your code
});
YUI Compressed:
(function(){var e=function(i,j){},c=window.jQuery,h=window.$,d,g=false,f=[],b;e.fn={ready:function(i){e.bindReady();if(e.isReady){i.call(document,e)}else{if(f){f.push(i)}}return this}};e.isReady=false;e.ready=function(){if(!e.isReady){if(!document.body){return setTimeout(e.ready,13)}e.isReady=true;if(f){var k,j=0;while((k=f[j++])){k.call(document,e)}f=null}if(e.fn.triggerHandler){e(document).triggerHandler("ready")}}};e.bindReady=function(){if(g){return}g=true;if(document.readyState==="complete"){return e.ready()}if(document.addEventListener){document.addEventListener("DOMContentLoaded",b,false);window.addEventListener("load",e.ready,false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",b);window.attachEvent("onload",e.ready);var i=false;try{i=window.frameElement==null}catch(j){}if(document.documentElement.doScroll&&i){a()}}}};d=e(document);if(document.addEventListener){b=function(){document.removeEventListener("DOMContentLoaded",b,false);e.ready()}}else{if(document.attachEvent){b=function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",b);e.ready()}}}}function a(){if(e.isReady){return}try{document.documentElement.doScroll("left")}catch(i){setTimeout(a,1);return}e.ready()}window.jQuery=window.$=e})();
Full source (again, this is jQuery code):
(function() {
var jQuery = function( selector, context ) {
},
_jQuery = window.jQuery,
_$ = window.$,
rootjQuery,
readyBound = false,
readyList = [],
DOMContentLoaded;
jQuery.fn = {
ready: function( fn ) {
jQuery.bindReady();
if ( jQuery.isReady ) {
fn.call( document, jQuery );
} else if ( readyList ) {
readyList.push( fn );
}
return this;
}
};
jQuery.isReady = false;
jQuery.ready = function() {
if ( !jQuery.isReady ) {
if ( !document.body ) {
return setTimeout( jQuery.ready, 13 );
}
jQuery.isReady = true;
if ( readyList ) {
var fn, i = 0;
while ( (fn = readyList[ i++ ]) ) {
fn.call( document, jQuery );
}
readyList = null;
}
if ( jQuery.fn.triggerHandler ) {
jQuery( document ).triggerHandler( "ready" );
}
}
};
jQuery.bindReady = function() {
if ( readyBound ) {
return;
}
readyBound = true;
if ( document.readyState === "complete" ) {
return jQuery.ready();
}
if ( document.addEventListener ) {
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
window.addEventListener( "load", jQuery.ready, false );
} else if ( document.attachEvent ) {
document.attachEvent("onreadystatechange", DOMContentLoaded);
window.attachEvent( "onload", jQuery.ready );
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
};
rootjQuery = jQuery(document);
if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
jQuery.ready();
};
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
jQuery.ready();
}
};
}
function doScrollCheck() {
if ( jQuery.isReady ) {
return;
}
try {
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
jQuery.ready();
}
window.jQuery = window.$ = jQuery;
})();
I'm sure there are more bytes that could be removed.
Don't forget:
/*!
* jQuery JavaScript Library v1.4.2
* http://jquery.com/
*
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
There are several implementations for "DOMReady" functions but most that I can find seem a bit dated, so I don't know how they will behave with IE8 and such.
I would recommend using jQuery's ready() as I think it promises the most cross-browser compatibility. I'm not an expert in jQuery's source code, but this seems to be the right spot (lines 812-845 or search for function bindReady).
You can start with script: http://snipplr.com/view/6029/domreadyjs/, not optimized (but work) for latest Safari though (e.g. use timer instead of supported DOMContentLoaded).

Categories

Resources