diff --git a/.DS_Store b/.DS_Store
index 8075e3ec..59e937cb 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/ClickToPlugin.fr.safariextension/.DS_Store b/ClickToPlugin.fr.safariextension/.DS_Store
index 10fb7ec1..5d3c2697 100644
Binary files a/ClickToPlugin.fr.safariextension/.DS_Store and b/ClickToPlugin.fr.safariextension/.DS_Store differ
diff --git a/ClickToPlugin.fr.safariextension/ClickToPlugin.js b/ClickToPlugin.fr.safariextension/ClickToPlugin.js
index 387ae0dc..47e4da4c 100644
--- a/ClickToPlugin.fr.safariextension/ClickToPlugin.js
+++ b/ClickToPlugin.fr.safariextension/ClickToPlugin.js
@@ -1,45 +1,45 @@
-/*
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-NOTE TO SELF
-ALWAYS ALWAYS ALWAYS ALWAYS USE the 'var' keyword in 'for' loops!!!!!!!!!!
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-*/
-
-
/****************************
ClickToPlugin class definition
*****************************/
function ClickToPlugin() {
- this.blockedElements = new Array();// array containing the Flash HTML elements
+ this.blockedElements = new Array();// array containing the blocked HTML elements
this.placeholderElements = new Array();// array containing the corresponding placeholder elements
- this.mediaPlayers = new Array();// array containing the HTML5 media players
+ this.mediaPlayers = new Array();// array containing the HTML5 media players
+
+ /*
+ Each item in blockedElement will acquire 3 additional properties:
+ -> tag: 'embed', 'object', or 'applet'
+ -> plugin: the name of the plugin that would handle the element
+ -> info: an object; info.src is the source of the embedded content
+ */
this.settings = null;
this.instance = null;
this.numberOfBlockedElements = 0;
- this.numberOfUnblockedElements = 0;
- this.location = window.location.href;
+ this.numberOfUnblockedElements = 0;
+
+ var _this = this;
- var _this = this;
-
- this.respondToMessageTrampoline = function(event) {
+ this.respondToMessageTrampoline = function(event) {
_this.respondToMessage(event);
};
-
- this.handleEventTrampoline = function(event) {
- _this.handleEvent(event);
- };
+
+ this.handleEventTrampoline = function(event) {
+ _this.handleEvent(event);
+ };
- safari.self.addEventListener("message", this.respondToMessageTrampoline, false);
- document.addEventListener("beforeload", this.handleEventTrampoline, true);
+ safari.self.addEventListener("message", this.respondToMessageTrampoline, false);
+ document.addEventListener("beforeload", this.handleEventTrampoline, true);
+ // HTML applet elements fire no beforeload event
+ // bug filed: https://bugs.webkit.org/show_bug.cgi?id=44023
+ // Unsatisfactory workaround (Java will run anyway):
document.addEventListener("DOMContentLoaded", this.handleEventTrampoline, false);
- document.addEventListener("DOMNodeInserted", this.handleEventTrampoline, false);
- //document.addEventListener("DOMNodeInsertedIntoDocument", this.handleEventTrampoline, false);
+ document.addEventListener("DOMNodeInserted", this.handleEventTrampoline, false);
document.oncontextmenu = function(event) {
- safari.self.tab.setContextMenuEventUserInfo(event, {"location": _this.location, "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements});
+ safari.self.tab.setContextMenuEventUserInfo(event, {"location": window.location.href, "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements});
};
}
@@ -50,31 +50,41 @@ ClickToPlugin.prototype.clearAll = function(elementID) {
};
ClickToPlugin.prototype.respondToMessage = function(event) {
- if (event.name == "mediaData") {
- if(event.message.CTPInstance != this.instance) return; // ignore message from other CTP instances
- this.prepMedia(event.message);
- } else if (event.name == "loadContent") {
- var loadData = event.message.split(","); // [0] CTPInstance, [1] elementID, [2] message
- if (loadData[0] != this.instance) return; // ignore message from other CTP instances
- if (loadData[2] == "plugin") {
- this.loadPluginForElement(loadData[1]);
- } else if (loadData[2] == "video") {
- this.loadMediaForElement(loadData[1]);
- } else if (loadData[2] == "reloadPlugin") {
- this.loadInPlugin(loadData[1]);
- } else if (loadData[2] == "remove") {
- this.removeElement(loadData[1]);
- } else if (loadData[2] == "qtp") {
- this.launchInQuickTimePlayer(loadData[1]);
- } else if (loadData[2] == "show") {
- alert(document.HTMLToString(this.blockedElements[loadData[1]]));
- }
- } else if (event.name == "updateVolume") {
- this.setVolumeTo(event.message);
- } else if (event.name == "updateOpacity") {
- this.setOpacityTo(event.message);
- } else if(event.name == "loadAll") {
- this.loadAll();
+ switch(event.name) {
+ case "mediaData":
+ if(event.message.instance != this.instance) return; // ignore message from other CTP instances
+ this.prepMedia(event.message);
+ break;
+ case "loadContent":
+ var loadData = event.message.split(","); // [0] instance, [1] elementID, [2] message
+ if (loadData[0] != this.instance) return; // ignore message from other CTP instances
+ switch(loadData[2]) {
+ case "plugin":
+ this.loadPluginForElement(loadData[1]);
+ break;
+ case "remove":
+ this.removeElement(loadData[1]);
+ break;
+ case "reload":
+ this.reloadInPlugin(loadData[1]);
+ break;
+ case "qtp":
+ this.launchInQuickTimePlayer(loadData[1]);
+ break;
+ case "show":
+ alert(document.HTMLToString(this.blockedElements[loadData[1]]));
+ break;
+ }
+ break;
+ case "loadAll":
+ this.loadAll();
+ break;
+ case "updateVolume":
+ this.setVolumeTo(event.message);
+ break;
+ case "updateOpacity":
+ this.setOpacityTo(event.message);
+ break;
}
};
@@ -82,9 +92,8 @@ ClickToPlugin.prototype.respondToMessage = function(event) {
According to the W3C HTML5 spec, to activate a plugin,
-> an 'embed' element must have either the 'src' or the 'type' attribute with nonempty value
-> an 'object' element must have either the 'data' or the 'type' attribute with nonempty value.
-In the real world, however, (AS IS RECOMMANDED ON ADOBE'S WEBSITE, BY THE WAY!)
-one often finds an 'object' with neither 'data' nor 'type', with an 'embed' element
-as child with 'src' and/or 'type' attribute set.
+In the real world, however, one often finds an 'object' with neither 'data' nor 'type',
+with an 'embed' element as child with 'src' and/or 'type' attribute set.
*/
ClickToPlugin.prototype.handleEvent = function(event) {
@@ -102,21 +111,35 @@ ClickToPlugin.prototype.handleEvent = function(event) {
ClickToPlugin.prototype.handleDOMContentEvent = function(event) {
if(event.target.nodeType != 1 && event.target.nodeType != 9) return; // the node is not an HTML Element nor the document
const applets = event.target.getElementsByTagName("applet");
+ if(applets.length == 0) return;
+
// Convert NodeList to Array
var appletElements = new Array();
for(var i = 0; i < applets.length; i++) {
appletElements.push(applets[i]);
}
+ var tmpAnchor = document.createElement("a");
for(var i = 0; i < appletElements.length; i++) {
if(appletElements[i].allowedToLoad) continue;
appletElements[i].tag = "applet";
- appletElements[i].source = getSrcOf(appletElements[i]);
+ appletElements[i].info = new Object();
+
+ // Get source of applet
+ if(appletElements[i].code) {
+ tmpAnchor.href = appletElements[i].code;
+ appletElements[i].info.src = tmpAnchor.href;
+ } else if(appletElements[i].hasAttribute("archive")) {
+ tmpAnchor.href = appletElements[i].getAttribute("archive");
+ appletElements[i].info.src = tmpAnchor.href;
+ } else {
+ appletElements[i].info.src = "";
+ }
- var pluginName = safari.self.tab.canLoad(event, {"src": appletElements[i].source, "type": "application/x-java-applet", "classid": "", "params": "", "location": this.location, "width": appletElements[i].offsetWidth, "height": appletElements[i].offsetHeight, "otherInfo": null});
+ var pluginName = safari.self.tab.canLoad(event, {"src": appletElements[i].info.src, "type": "application/x-java-applet", "location": window.location.href, "width": appletElements[i].offsetWidth, "height": appletElements[i].offsetHeight});
if(!pluginName) continue; // whitelisted
- appletElements[i].plugin = pluginName;
+ appletElements[i].plugin = "Java";
if(this.settings == null) {
this.settings = safari.self.tab.canLoad(event, "getSettings");
@@ -125,15 +148,21 @@ ClickToPlugin.prototype.handleDOMContentEvent = function(event) {
this.instance = safari.self.tab.canLoad(event, "getInstance");
}
var elementID = this.numberOfBlockedElements++;
- this.processBlockedElement(appletElements[i], elementID); // this removes appletElements[0] from the document
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ if(!confirm("ClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
+ }
+ // END DEBUG
+
+ this.processBlockedElement(appletElements[i], elementID);
}
};
ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
- const element = event.target;
-
+ const element = event.target;
+
// deal with sIFR script first
- if(element instanceof HTMLScriptElement && element.getAttribute("src").indexOf("sifr.js") != (-1)) {
+ if(element instanceof HTMLScriptElement && element.src.indexOf("sifr.js") != (-1)) {
var sIFRData = safari.self.tab.canLoad(event, "sIFR");
if(!sIFRData.canLoad) {
// BEGIN DEBUG
@@ -151,7 +180,8 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
// the beforeload event is fired again but this time the
// flash element must not be blocked
if (element.allowedToLoad) return;
- if (element instanceof HTMLEmbedElement) {
+
+ if (element instanceof HTMLEmbedElement) {
element.tag = "embed";
} else if (element instanceof HTMLObjectElement) {
element.tag = "object";
@@ -159,29 +189,20 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
return;
}
+ element.info = getInfo(element, event.url);
+
+ var pluginName = safari.self.tab.canLoad(event, {"src": element.info.src, "type": getTypeOf(element), "classid": element.getAttribute("classid"), "location": window.location.href, "width": element.offsetWidth, "height": element.offsetHeight, "launchInQTP": element.info.target == "quicktimeplayer" ? element.info.href : null});
+ if(!pluginName) return; // whitelisted
+
// Load the user settings
if(this.settings == null) {
this.settings = safari.self.tab.canLoad(event, "getSettings");
}
- // Give an address to this CTP instance to receive messages
- if(this.instance == null) {
- this.instance = safari.self.tab.canLoad(event, "getInstance");
- }
-
- element.otherInfo = new Object();
- element.source = getSrcOf(element);
-
- var pluginName = safari.self.tab.canLoad(event, {"src": element.source, "type": getTypeOf(element), "classid": element.getAttribute("classid"), "params": this.settings["useH264"] ? getParamsOf(element) : "", "location": this.location, "width": element.offsetWidth, "height": element.offsetHeight, "otherInfo": element.otherInfo});
- if(!pluginName) return; // whitelisted
- //alert(pluginName);
-
-
-
- // if useh264...
+ // if useh264...
// Deal with sIFR Flash
- if (element.className == "sIFR-flash" || element.getAttribute("sifr")) {
+ if (element.className == "sIFR-flash" || element.hasAttribute("sifr")) {
if (this.settings["sifrReplacement"] == "autoload") {
// BEGIN DEBUG
if(this.settings["debug"]) {
@@ -193,13 +214,17 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
}
// At this point we know we have to block 'element' from loading
+ var elementID = this.numberOfBlockedElements++;
element.plugin = pluginName;
- var elementID = this.numberOfBlockedElements++;
+
+ // Give an address to this CTP instance to receive messages
+ if(this.instance == null) {
+ this.instance = safari.self.tab.canLoad(event, "getInstance");
+ }
// BEGIN DEBUG
if(this.settings["debug"]) {
- if(!confirm(window.location.href + "\n" + window.top.location.href + "\nClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
- //alert(element.source + "\n -- \n" + event.url);
+ if(!confirm("ClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
}
// END DEBUG
@@ -209,38 +234,37 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
ClickToPlugin.prototype.prepMedia = function(mediaData) {
if(mediaData.playlist.length == 0 || !mediaData.playlist[0].mediaURL) return;
- if(!this.mediaPlayers[mediaData.elementID]) {
- this.mediaPlayers[mediaData.elementID] = new mediaPlayer(mediaData.isAudio ? "audio" : "video");
- }
- if(mediaData.loadAfter) { // just adding stuff to the playlist
- // BEGIN DEBUG
- if(this.settings["debug"]) {
- if(!confirm("Preparing to add " + mediaData.playlist.length + " tracks to the playlist for element " + this.instance +"."+ mediaData.elementID)) return;
- }
- // END DEBUG
- this.mediaPlayers[mediaData.elementID].playlistLength -= mediaData.missed;
- this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist);
- return;
- }
- // BEGIN DEBUG
- if(this.settings["debug"]) {
- var showPlaylist = "(" + mediaData.playlist.length + " track" + (mediaData.playlist.length > 1 ? "s" : "") + ")";
+ if(!this.mediaPlayers[mediaData.elementID]) {
+ this.mediaPlayers[mediaData.elementID] = new mediaPlayer(mediaData.isAudio ? "audio" : "video");
+ }
+ if(mediaData.loadAfter) { // just adding stuff to the playlist
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ if(!confirm("Preparing to add " + mediaData.playlist.length + " tracks to the playlist for element " + this.instance +"."+ mediaData.elementID)) return;
+ }
+ // END DEBUG
+ this.mediaPlayers[mediaData.elementID].playlistLength -= mediaData.missed;
+ this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist);
+ return;
+ }
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ var showPlaylist = "(" + mediaData.playlist.length + " track" + (mediaData.playlist.length > 1 ? "s" : "");
+ if(mediaData.playlistLength) showPlaylist += ", expecting " + mediaData.playlistLength;
+ showPlaylist += ")";
for (var i = 0; i < mediaData.playlist.length; i++) {
- showPlaylist += "\n[" + (i + 1) + "] (" + mediaData.playlist[i].mediaType + ")" + (mediaData.playlist[i].mediaType == "video" ? ("\nposterURL: " + mediaData.playlist[i].posterURL) : "") + "\nmediaURL: " + mediaData.playlist[i].mediaURL + "\n";
+ showPlaylist += "\n[" + (i + 1) + "] (" + mediaData.playlist[i].mediaType + ")" + "\nposterURL: " + mediaData.playlist[i].posterURL + "\nmediaURL: " + mediaData.playlist[i].mediaURL + "\n";
}
if(!confirm("Preparing media for element " + this.instance +"."+ mediaData.elementID +
":\n\nbadgeLabel: " + mediaData.badgeLabel + "\n\nPLAYLIST " + showPlaylist)) return;
}
// END DEBUG
-
- // do it backward just in case a loadAfter came first
- // can happen for embedded playlists
-
- this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist, true);
- this.mediaPlayers[mediaData.elementID].playlistLength = mediaData.playlistLength ? mediaData.playlistLength : mediaData.playlist.length;
- this.mediaPlayers[mediaData.elementID].startTrack = mediaData.startTrack ? mediaData.startTrack : 0;
-
- this.mediaPlayers[mediaData.elementID].usePlaylistControls = this.settings["usePlaylists"] && !mediaData.noPlaylistControls && this.mediaPlayers[mediaData.elementID].playlistLength > 1;
+
+ this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist, true);
+ this.mediaPlayers[mediaData.elementID].playlistLength = mediaData.playlistLength ? mediaData.playlistLength : mediaData.playlist.length;
+ this.mediaPlayers[mediaData.elementID].startTrack = mediaData.startTrack ? mediaData.startTrack : 0;
+
+ this.mediaPlayers[mediaData.elementID].usePlaylistControls = this.settings["usePlaylists"] && !mediaData.noPlaylistControls && this.mediaPlayers[mediaData.elementID].playlistLength > 1;
// Check if we should load video at once
if(this.settings["H264autoload"]) {
@@ -249,17 +273,17 @@ ClickToPlugin.prototype.prepMedia = function(mediaData) {
}
var badgeLabel = mediaData.badgeLabel;
if(!badgeLabel) badgeLabel = "Video";
-
+
this.displayBadge(badgeLabel, mediaData.elementID);
};
ClickToPlugin.prototype.loadPluginForElement = function(elementID) {
var placeholderElement = this.placeholderElements[elementID];
- var element = this.blockedElements[elementID];
- element.allowedToLoad = true;
+ var element = this.blockedElements[elementID];
+ element.allowedToLoad = true;
if(placeholderElement.parentNode) {
placeholderElement.parentNode.replaceChild(element, placeholderElement);
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
this.clearAll(elementID);
}
};
@@ -271,14 +295,14 @@ ClickToPlugin.prototype.loadAll = function() {
this.loadPluginForElement(i);
}
}
- this.numberOfUnblockedElements = this.numberOfBlockedElements;
+ this.numberOfUnblockedElements = this.numberOfBlockedElements;
};
-ClickToPlugin.prototype.loadInPlugin = function(elementID) {
+ClickToPlugin.prototype.reloadInPlugin = function(elementID) {
var containerElement = this.mediaPlayers[elementID].containerElement;
- var element = this.blockedElements[elementID];
- element.allowedToLoad = true;
- containerElement.parentNode.replaceChild(element, containerElement);
+ var element = this.blockedElements[elementID];
+ element.allowedToLoad = true;
+ containerElement.parentNode.replaceChild(element, containerElement);
this.clearAll(elementID);
};
@@ -286,56 +310,54 @@ ClickToPlugin.prototype.loadMediaForElement = function(elementID) {
var placeholderElement = this.placeholderElements[elementID];
var contextInfo = {
- "CTPInstance": this.instance,
+ "instance": this.instance,
"elementID": elementID,
"isH264": true,
"plugin": this.blockedElements[elementID].plugin
- //"blocked": this.numberOfBlockedElements - this.numberOfUnblockedElements
+ //"blocked": this.numberOfBlockedElements - this.numberOfUnblockedElements
};
- // Initialize player
- var w = parseInt(placeholderElement.style.width.replace("px",""));
- var h = parseInt(placeholderElement.style.height.replace("px",""));
- this.mediaPlayers[elementID].initialize(this.settings["H264behavior"], w, h, this.settings["volume"], contextInfo);
- //mediaElement.allowedToLoad = true; // not used for now
-
- // Load first track
- this.mediaPlayers[elementID].loadTrack(0);
+ // Initialize player
+ var w = parseInt(placeholderElement.style.width.replace("px",""));
+ var h = parseInt(placeholderElement.style.height.replace("px",""));
+ this.mediaPlayers[elementID].initialize(this.settings["H264behavior"], w, h, this.settings["volume"], contextInfo);
+ // mediaElement.allowedToLoad = true; // not used
- // Replace placeholder
- placeholderElement.parentNode.replaceChild(this.mediaPlayers[elementID].containerElement, placeholderElement);
- this.numberOfUnblockedElements++;
+ // Replace placeholder and load first track
+ placeholderElement.parentNode.replaceChild(this.mediaPlayers[elementID].containerElement, placeholderElement);
+ this.mediaPlayers[elementID].loadTrack(0);
+ this.numberOfUnblockedElements++;
this.placeholderElements[elementID] = null;
};
ClickToPlugin.prototype.launchInQuickTimePlayer = function(elementID) {
- var track = this.mediaPlayers[elementID].currentTrack;
- var element = null;
- if(track == null) {
- track = 0;
- element = this.placeholderElements[elementID];
- } else {
- element = this.mediaPlayers[elementID].containerElement;
- }
+ var track = this.mediaPlayers[elementID].currentTrack;
+ var element = null;
+ if(track == null) {
+ track = 0;
+ element = this.placeholderElements[elementID];
+ } else {
+ element = this.mediaPlayers[elementID].containerElement;
+ }
var mediaURL = this.mediaPlayers[elementID].playlist[track].mediaURL;
- var QTObject = document.createElement("embed");
- QTObject.allowedToLoad = true;
- QTObject.className = "CTFQTObject";
- QTObject.setAttribute("type", "video/quicktime");
- QTObject.setAttribute("width", "0");
- QTObject.setAttribute("height", "0");
- // need an external URL for source, since QT plugin doesn't accept safari-extension:// protocol
- // Apple has a small 1px image for this exact purpose
- QTObject.setAttribute("src", "http://images.apple.com/apple-events/includes/qtbutton.mov");
- QTObject.setAttribute("href", mediaURL);
- QTObject.setAttribute("target", "quicktimeplayer");
- QTObject.setAttribute("autohref", "true");
- QTObject.setAttribute("controller", "false");
- //QTObject.setAttribute("postdomevents", "true");
- element.appendChild(QTObject);
- // There doesn't seem to exist an appropriate event, so we just wait a bit...
- setTimeout(function() {element.removeChild(QTObject);}, 100);
+ var QTObject = document.createElement("embed");
+ QTObject.allowedToLoad = true;
+ QTObject.className = "CTFQTObject";
+ QTObject.setAttribute("type", "video/quicktime");
+ QTObject.setAttribute("width", "0");
+ QTObject.setAttribute("height", "0");
+ // need an external URL for source, since QT plugin doesn't accept safari-extension:// protocol
+ // Apple has a small 1px image for this exact purpose
+ QTObject.setAttribute("src", "http://images.apple.com/apple-events/includes/qtbutton.mov");
+ QTObject.setAttribute("href", mediaURL);
+ QTObject.setAttribute("target", "quicktimeplayer");
+ QTObject.setAttribute("autohref", "true");
+ QTObject.setAttribute("controller", "false");
+ // QTObject.setAttribute("postdomevents", "true");
+ element.appendChild(QTObject);
+ // There doesn't seem to exist an appropriate event, so we just wait a bit...
+ setTimeout(function() {element.removeChild(QTObject);}, 100);
};
ClickToPlugin.prototype.setVolumeTo = function(volume) {
@@ -356,7 +378,7 @@ ClickToPlugin.prototype.removeElement = function(elementID) {
element = element.parentNode;
}
element.parentNode.removeChild(element);
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
this.clearAll(elementID);
};
@@ -376,11 +398,11 @@ ClickToPlugin.prototype.displayBadge = function(badgeLabel, elementID) {
this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild.className = "logoContainer hidden";
this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild.childNodes[1].className = "logo tmp";
- this.unhideLogo(elementID);
+ this.unhideLogo(elementID, 0);
};
// NOTE: this function should never be called directly (use displayBadge instead)
-ClickToPlugin.prototype.unhideLogo = function(elementID) {
+ClickToPlugin.prototype.unhideLogo = function(elementID, i) {
var logoContainer = this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild;
var w0 = this.placeholderElements[elementID].offsetWidth;
var h0 = this.placeholderElements[elementID].offsetHeight;
@@ -390,10 +412,11 @@ ClickToPlugin.prototype.unhideLogo = function(elementID) {
var h2 = logoContainer.childNodes[1].offsetHeight;
if(w2 == 0 || h2 == 0 || w1 == 0 || h1 == 0 || w0 == 0 || h0 == 0) {
+ if(i > 9) return;
// 2 options: leave the logo hidden (no big deal, and rarely happens),
- // or run unhideLogo again later (this might cause unexpected results due to asynchronicity)
+ // or run unhideLogo again later <- THIS
var _this = this;
- setTimeout(function() {_this.unhideLogo(elementID);}, 100); // there's no hurry here
+ setTimeout(function() {_this.unhideLogo(elementID, ++i);}, 100); // there's no hurry here
return;
}
@@ -418,22 +441,22 @@ ClickToPlugin.prototype.unhideLogo = function(elementID) {
};
ClickToPlugin.prototype.clickPlaceholder = function(elementID) {
- if (this.mediaPlayers[elementID] && this.mediaPlayers[elementID].startTrack != null) {
- this.loadMediaForElement(elementID);
- } else {
+ if (this.mediaPlayers[elementID] && this.mediaPlayers[elementID].startTrack != null) {
+ this.loadMediaForElement(elementID);
+ } else {
this.loadPluginForElement(elementID);
- }
+ }
};
ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
// Creating the placeholder element
- var placeholderElement = document.createElement("div");
- placeholderElement.style.width = element.offsetWidth + "px";
- placeholderElement.style.height = element.offsetHeight + "px";
- placeholderElement.style.opacity = this.settings["opacity"];
+ var placeholderElement = document.createElement("div");
+ placeholderElement.style.width = element.offsetWidth + "px";
+ placeholderElement.style.height = element.offsetHeight + "px";
+ placeholderElement.style.opacity = this.settings["opacity"];
- placeholderElement.className = "clickToFlashPlaceholder";
+ placeholderElement.className = "clickToFlashPlaceholder";
// Replacing element by placeholderElement
if (element.parentNode) {
@@ -445,54 +468,54 @@ ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
alert("Ignoring duplicate element " + this.instance + "." + elementID + ".");
}
// END DEBUG
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
return;
}
- var _this = this;
- placeholderElement.onclick = function(event){_this.clickPlaceholder(elementID);};
- placeholderElement.oncontextmenu = function(event) {
- var contextInfo = {
- "CTPInstance": _this.instance,
+ var _this = this;
+ placeholderElement.onclick = function(event){_this.clickPlaceholder(elementID);};
+ placeholderElement.oncontextmenu = function(event) {
+ var contextInfo = {
+ "instance": _this.instance,
"elementID": elementID,
- "src": element.source,
+ "src": element.info.src,
"plugin": element.plugin,
- "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements
+ //"blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements
};
if (_this.mediaPlayers[elementID] && _this.mediaPlayers[elementID].startTrack != null) {
- contextInfo.hasH264 = true;
+ contextInfo.hasH264 = true;
_this.mediaPlayers[elementID].setContextInfo(event, contextInfo);
} else {
- contextInfo.hasH264 = false;
- safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
- event.stopPropagation();
+ contextInfo.hasH264 = false;
+ safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
+ event.stopPropagation();
}
- };
+ };
// Building the placeholder
- var container = document.createElement("div");
- container.className = "clickToFlashPlaceholderContainer";
- placeholderElement.appendChild(container);
-
- var verticalPositionElement = document.createElement("div");
- verticalPositionElement.className = "logoVerticalPosition";
- container.appendChild(verticalPositionElement);
-
- var horizontalPositionElement = document.createElement("div");
- horizontalPositionElement.className = "logoHorizontalPosition";
- verticalPositionElement.appendChild(horizontalPositionElement);
-
- var logoContainer = document.createElement("div");
- logoContainer.className = "logoContainer nodisplay"; // keep the logo hidden at first
- horizontalPositionElement.appendChild(logoContainer);
-
- var logoElement = document.createElement("div");
- logoElement.className = "logo";
- logoContainer.appendChild(logoElement);
-
- var logoInsetElement = document.createElement("div");
- logoInsetElement.className = "logo inset";
- logoContainer.appendChild(logoInsetElement);
+ var container = document.createElement("div");
+ container.className = "clickToFlashPlaceholderContainer";
+ placeholderElement.appendChild(container);
+
+ var verticalPositionElement = document.createElement("div");
+ verticalPositionElement.className = "logoVerticalPosition";
+ container.appendChild(verticalPositionElement);
+
+ var horizontalPositionElement = document.createElement("div");
+ horizontalPositionElement.className = "logoHorizontalPosition";
+ verticalPositionElement.appendChild(horizontalPositionElement);
+
+ var logoContainer = document.createElement("div");
+ logoContainer.className = "logoContainer nodisplay"; // keep the logo hidden at first
+ horizontalPositionElement.appendChild(logoContainer);
+
+ var logoElement = document.createElement("div");
+ logoElement.className = "logo";
+ logoContainer.appendChild(logoElement);
+
+ var logoInsetElement = document.createElement("div");
+ logoInsetElement.className = "logo inset";
+ logoContainer.appendChild(logoInsetElement);
// Filling the main arrays
this.blockedElements[elementID] = element;
@@ -503,14 +526,14 @@ ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
if(this.settings["useH264"]) {
if(!this.directKill(elementID)) {
var elementData = {
+ "instance": this.instance,
+ "elementID": elementID,
"plugin": element.plugin,
- "src": element.source,
- "presrc": element.presource, // TEMP!!
+ "src": element.info.href ? element.info.href : element.info.src,
+ "presrc": element.info.href ? element.info.src : "",
+ "image": element.info.image,
"params": getParamsOf(element),
- "elementID": elementID,
- "CTPInstance": this.instance,
- "location": this.location,
- "image": element.image
+ "location": window.location.href
};
safari.self.tab.dispatchMessage("killPlugin", elementData);
}
@@ -549,7 +572,7 @@ ClickToPlugin.prototype.directKill = function(elementID) {
var mediaData = {
"elementID": elementID,
"playlist": [{"mediaType": mediaType, "posterURL": mediaElements[0].getAttribute("poster"), "mediaURL": mediaURL}],
- "badgeLabel": "Video"
+ "badgeLabel": mediaType == "audio" ? "Audio" : "Video"
};
this.prepMedia(mediaData);
return true;
diff --git a/ClickToPlugin.fr.safariextension/Info.plist b/ClickToPlugin.fr.safariextension/Info.plist
index 61b74786..278f2668 100644
--- a/ClickToPlugin.fr.safariextension/Info.plist
+++ b/ClickToPlugin.fr.safariextension/Info.plist
@@ -2,56 +2,56 @@
- Author
- Marc Hoyois
- CFBundleDisplayName
- ClickToPlugin
- CFBundleIdentifier
- com.hoyois.safari.clicktoplugin.fr
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleShortVersionString
- 1.3.3
- CFBundleVersion
- 1.3.3
- Chrome
-
- Global Page
- global.html
-
- Content
-
- Scripts
-
- Start
-
- functions.js
- mediaPlayer.js
- ClickToPlugin.js
-
-
- Stylesheets
-
- styles.css
-
-
- Description
- Empêche l'exécution automatique des plugins
- ExtensionInfoDictionaryVersion
- 1.0
- Permissions
-
- Website Access
-
- Include Secure Pages
-
- Level
- All
-
-
- Update Manifest URL
- http://hoyois.github.com/safariextensions/updates.plist
- Website
- http://hoyois.github.com/safariextensions/clicktoplugin/
+ Author
+ Marc Hoyois
+ CFBundleDisplayName
+ ClickToPlugin
+ CFBundleIdentifier
+ com.hoyois.safari.clicktoplugin.fr
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleShortVersionString
+ 1.3.3
+ CFBundleVersion
+ 1.3.3
+ Chrome
+
+ Global Page
+ global.html
+
+ Content
+
+ Scripts
+
+ Start
+
+ functions.js
+ mediaPlayer.js
+ ClickToPlugin.js
+
+
+ Stylesheets
+
+ styles.css
+
+
+ Description
+ Empêche l'exécution automatique des plugins
+ ExtensionInfoDictionaryVersion
+ 1.0
+ Permissions
+
+ Website Access
+
+ Include Secure Pages
+
+ Level
+ All
+
+
+ Update Manifest URL
+ http://hoyois.github.com/safariextensions/updates.plist
+ Website
+ http://hoyois.github.com/safariextensions/clicktoplugin/
diff --git a/ClickToPlugin.fr.safariextension/Settings.plist b/ClickToPlugin.fr.safariextension/Settings.plist
index 1c013f63..7dd957e3 100644
--- a/ClickToPlugin.fr.safariextension/Settings.plist
+++ b/ClickToPlugin.fr.safariextension/Settings.plist
@@ -2,437 +2,437 @@
-
- Title
- Options MIME
- Type
- Group
-
-
- DefaultValue
- blockAll
- Key
- block
- Title
- Bloquer
- Titles
-
- tous les types MIME
- tous sauf ceux de la liste verte
- seulement ceux de la liste rouge
-
- Type
- RadioButtons
- Values
-
- blockAll
- useGreenlist
- useRedlist
-
-
-
- DefaultValue
-
- Key
- greenlist
- Title
- Liste verte
- Type
- TextField
-
-
- DefaultValue
- flash, futuresplash, silverlight
- Key
- redlist
- Title
- Liste rouge
- Type
- TextField
-
-
- DefaultValue
-
- Key
- allowQT
- Title
- Autoriser le plugin QuickTime                         Â
- Type
- CheckBox
-
-
- Title
- Options vidéo
- Type
- Group
-
-
- DefaultValue
-
- Key
- useH264
- Title
- Rechercher des vidéos pour remplacer            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceFlash
- Title
- Flash                                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceSL
- Title
- Silverlight                                     Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceQT
- Title
- QuickTime                                   Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceWM
- Title
- Windows Media                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- usePlaylists
- Title
- Utiliser les listes de lecture                              Â
- Titles
-
- Ne pas utiliser
- N'utiliser qu'en dernier recours
- Utiliser sans restrictions
-
- Type
- CheckBox
- Values
-
- 1
- 2
- 3
-
-
-
- DefaultValue
-
- Key
- H264autoload
- Title
- Effectuer les remplacements automatiquement
- Type
- CheckBox
-
-
- DefaultValue
- autoplay
- Key
- H264behavior
- Title
- Une fois effectués
- Titles
-
- Attendre avant de télécharger
- Commencer le téléchargement
- Commencer la lecture automatiquement
-
- Type
- PopUpButton
- Values
-
- none
- buffer
- autoplay
-
-
-
- DefaultValue
- 2
- Key
- QTbehavior
- Title
- Codecs non natifs
- Titles
-
- Ne pas utiliser
- N'utiliser qu'en dernier recours
- Utiliser sans restrictions
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 3
-
-
-
- DefaultValue
- 3
- Key
- maxresolution
- Title
- Résolution max
- Titles
-
- 480p
- 720p
- 1080p
- 4K
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 3
- 4
-
-
-
- DefaultValue
- 0.5
- Key
- volume
- MaximumValue
- 1
- StepValue
- 0.01
- Title
- Volume sonore
- Type
- Slider
-
-
- Title
- Liste blanche
- Type
- Group
-
-
- DefaultValue
-
- Key
- uselocWhitelist
- Title
- Autoriser les plugins si l'adresse de la page    Â
- Type
- CheckBox
-
-
- DefaultValue
- www.example.com, www.example2.com
- Key
- locwhitelist
- Title
- contient
- Type
- TextField
-
-
- DefaultValue
-
- Key
- locblacklist
- Title
- ne contient pas
- Type
- TextField
-
-
- DefaultValue
-
- Key
- usesrcWhitelist
- Title
- Autoriser les plugins si l'adresse de l'objet      Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- srcwhitelist
- Title
- contient
- Type
- TextField
-
-
- DefaultValue
-
- Key
- srcblacklist
- Title
- ne contient pas
- Type
- TextField
-
-
- Title
- Éléments invisibles
- Type
- Group
-
-
- DefaultValue
-
- Key
- loadInvisible
- Title
- Autoriser les éléments aux dimensions           Â
- Type
- CheckBox
-
-
- DefaultValue
- 1
- Key
- maxinvdim
- Title
- n'excédant pas
- Titles
-
- 1 x 1 px
- 2 x 2 px
- 4 x 4 px
- 8 x 8 px
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 4
- 8
-
-
-
- Title
- Menu contextuel
- Type
- Group
-
-
- DefaultValue
-
- Key
- useWLcontext
- Title
- Ajouter à la liste blanche                                 Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useLAcontext
- Title
- Débloquer tous les plugins                              Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useVScontext
- Title
- Voir la vidéo sur le site                                    Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useQTcontext
- Title
- Ouvrir dans QuickTime Player                          Â
- Type
- CheckBox
-
-
- Type
- Separator
-
-
- DefaultValue
- textonly
- Key
- sifrReplacement
- Title
- Texte sIFR
- Titles
-
- N'afficher que le texte
- Considérer comme Flash
- Autoriser
-
- Type
- PopUpButton
- Values
-
- textonly
- normal
- autoload
-
-
-
- DefaultValue
- 1
- Key
- opacity
- MaximumValue
- 1
- Secure
-
- StepValue
- 0.01
- Title
- Opacité
- Type
- Slider
-
-
- DefaultValue
-
- Key
- debug
- Title
- Activer le mode de débogage                          Â
- Type
- Hidden
-
+
+ Title
+ Options MIME
+ Type
+ Group
+
+
+ DefaultValue
+ blockAll
+ Key
+ block
+ Title
+ Bloquer
+ Titles
+
+ tous les types MIME
+ tous sauf ceux de la liste verte
+ seulement ceux de la liste rouge
+
+ Type
+ RadioButtons
+ Values
+
+ blockAll
+ useGreenlist
+ useRedlist
+
+
+
+ DefaultValue
+
+ Key
+ greenlist
+ Title
+ Liste verte
+ Type
+ TextField
+
+
+ DefaultValue
+ flash, futuresplash, silverlight
+ Key
+ redlist
+ Title
+ Liste rouge
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ allowQT
+ Title
+ Autoriser le plugin QuickTime                         Â
+ Type
+ CheckBox
+
+
+ Title
+ Options vidéo
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ useH264
+ Title
+ Rechercher des vidéos pour remplacer            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceFlash
+ Title
+ Flash                                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceSL
+ Title
+ Silverlight                                     Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceQT
+ Title
+ QuickTime                                   Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceWM
+ Title
+ Windows Media                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ usePlaylists
+ Title
+ Utiliser les listes de lecture                              Â
+ Titles
+
+ Ne pas utiliser
+ N'utiliser qu'en dernier recours
+ Utiliser sans restrictions
+
+ Type
+ CheckBox
+ Values
+
+ 1
+ 2
+ 3
+
+
+
+ DefaultValue
+
+ Key
+ H264autoload
+ Title
+ Effectuer les remplacements automatiquement
+ Type
+ CheckBox
+
+
+ DefaultValue
+ autoplay
+ Key
+ H264behavior
+ Title
+ Une fois effectués
+ Titles
+
+ Attendre avant de télécharger
+ Commencer le téléchargement
+ Commencer la lecture automatiquement
+
+ Type
+ PopUpButton
+ Values
+
+ none
+ buffer
+ autoplay
+
+
+
+ DefaultValue
+ 2
+ Key
+ QTbehavior
+ Title
+ Codecs non natifs
+ Titles
+
+ Ne pas utiliser
+ N'utiliser qu'en dernier recours
+ Utiliser sans restrictions
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 3
+
+
+
+ DefaultValue
+ 3
+ Key
+ maxresolution
+ Title
+ Résolution max
+ Titles
+
+ 480p
+ 720p
+ 1080p
+ 4K
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 3
+ 4
+
+
+
+ DefaultValue
+ 0.5
+ Key
+ volume
+ MaximumValue
+ 1
+ StepValue
+ 0.01
+ Title
+ Volume sonore
+ Type
+ Slider
+
+
+ Title
+ Liste blanche
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ uselocWhitelist
+ Title
+ Autoriser les plugins si l'adresse de la page    Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+ www.example.com, www.example2.com
+ Key
+ locwhitelist
+ Title
+ contient
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ locblacklist
+ Title
+ ne contient pas
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ usesrcWhitelist
+ Title
+ Autoriser les plugins si l'adresse de l'objet      Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ srcwhitelist
+ Title
+ contient
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ srcblacklist
+ Title
+ ne contient pas
+ Type
+ TextField
+
+
+ Title
+ Éléments invisibles
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ loadInvisible
+ Title
+ Autoriser les éléments aux dimensions           Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+ 1
+ Key
+ maxinvdim
+ Title
+ n'excédant pas
+ Titles
+
+ 1 x 1 px
+ 2 x 2 px
+ 4 x 4 px
+ 8 x 8 px
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 4
+ 8
+
+
+
+ Title
+ Menu contextuel
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ useWLcontext
+ Title
+ Ajouter à la liste blanche                                 Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useLAcontext
+ Title
+ Débloquer tous les plugins                              Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useVScontext
+ Title
+ Voir la vidéo sur le site                                    Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useQTcontext
+ Title
+ Ouvrir dans QuickTime Player                          Â
+ Type
+ CheckBox
+
+
+ Type
+ Separator
+
+
+ DefaultValue
+ textonly
+ Key
+ sifrReplacement
+ Title
+ Texte sIFR
+ Titles
+
+ N'afficher que le texte
+ Considérer comme Flash
+ Autoriser
+
+ Type
+ PopUpButton
+ Values
+
+ textonly
+ normal
+ autoload
+
+
+
+ DefaultValue
+ 1
+ Key
+ opacity
+ MaximumValue
+ 1
+ Secure
+
+ StepValue
+ 0.01
+ Title
+ Opacité
+ Type
+ Slider
+
+
+ DefaultValue
+
+ Key
+ debug
+ Title
+ Activer le mode de débogage                          Â
+ Type
+ Hidden
+
diff --git a/ClickToPlugin.fr.safariextension/functions.js b/ClickToPlugin.fr.safariextension/functions.js
index 3b440fac..ad40eb3a 100644
--- a/ClickToPlugin.fr.safariextension/functions.js
+++ b/ClickToPlugin.fr.safariextension/functions.js
@@ -1,91 +1,63 @@
-function getSrcOf(element) {
+function getInfo(element, url) {
+ // gathers attributes of the element that might be needed later on
+ // Done by a single function so that we only loop once through the children
+ var info = new Object();
var tmpAnchor = document.createElement("a");
switch (element.tag) {
case "embed":
+ if(element.hasAttribute("qtsrc")) {
+ tmpAnchor.href = element.getAttribute("qtsrc");
+ info.src = tmpAnchor.href;
+ }
+ if(element.hasAttribute("href")) {
+ tmpAnchor.href = element.getAttribute("href");
+ info.href = tmpAnchor.href;
+ }
+ if(element.hasAttribute("target")) {
+ info.target = element.getAttribute("target");
+ }
if(element.hasAttribute("previewimage")) {
tmpAnchor.href = element.getAttribute("previewimage");
- element.image = tmpAnchor.href;
+ info.image = tmpAnchor.href;
}
- if(element.src) tmpAnchor.href = element.src;
- if(element.hasAttribute("qtsrc")) tmpAnchor.href = element.getAttribute("qtsrc");
- element.presource = tmpAnchor.href;
- if(element.hasAttribute("target")) element.otherInfo.target = element.getAttribute("target");
- if(element.hasAttribute("href")) {
- tmpAnchor.href = element.getAttribute("href");
- } else {
- delete element.presource;
- if(!element.src) return "";
- }
- return tmpAnchor.href;
break;
case "object":
- // NOTE: For silverlight objects element.data is used for something else than the source
- // and a param named 'source' is used for the source. So we look for that before
- // using element.data
var paramElements = element.getElementsByTagName("param");
- var srcParam = null; var qtsrcParam = null;
for (i = 0; i < paramElements.length; i++) {
- if(!paramElements[i].hasAttribute("value")) continue;
+ if(!paramElements[i].hasAttribute("value")) continue;
var paramName = paramElements[i].getAttribute("name").toLowerCase(); // name attribute is mandatory!
- // this is a bit shaky...
- // maybe should check first for mimetype and then let getSrcOf depend on type
- // eg source for silverlight; src for flash, qt, realplayer; filename for wm...
- // this would require 2 successive canLoads? or just use the type attribute??
- // it seems to always be specified for SL, but not QT (uses classid instead)
- // damn... maybe better to pass the whole HTMLToString(element) to the global page after all?
- if(paramName == "previewimage") {
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.image = tmpAnchor2.href;
- } else if(paramName == "src") {
- srcParam = i;
- if(!element.presource) {
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.presource = tmpAnchor2.href;
- }
- //element.otherInfo.src = paramElements[i].getAttribute("value");
- } else if (paramName == "qtsrc") {
- qtsrcParam = i;
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.presource = tmpAnchor2.href;
- //element.otherInfo.qtsrc = paramElements[i].getAttribute("value");
- } else if (paramName == "target") element.otherInfo.target = paramElements[i].getAttribute("value");
- else if(paramName == "movie" || paramName == "source" || paramName == "href" || paramName == "filename") { //|| paramName == "url") { // for oleobject, not supported on Safari (what about the Win version?)
- tmpAnchor.href = paramElements[i].getAttribute("value");
+ switch(paramName) {
+ case "source": // Silverlight true source
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.src = tmpAnchor.href;
+ break;
+ case "qtsrc": // QuickTime true source
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.src = tmpAnchor.href;
+ break;
+ case "href": // QuickTime
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.href = tmpAnchor.href;
+ break;
+ case "target": // QuickTime
+ info.target = paramElements[i].getAttribute("value");
+ break;
+ case "previewimage": // DivX
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.image = tmpAnchor.href;
+ break;
}
}
- if(tmpAnchor.href) return tmpAnchor.href;
- if(qtsrcParam != null) {
- element.presource = null;
- tmpAnchor.href = paramElements[qtsrcParam].getAttribute("value");
- return tmpAnchor.href;
- } else if(srcParam != null) {
- element.presource = null;
- tmpAnchor.href = paramElements[srcParam].getAttribute("value");
- return tmpAnchor.href;
- }
- if(element.data) {
- tmpAnchor.href = element.data;
- return tmpAnchor.href;
- } else {
- var embedElements = element.getElementsByTagName("embed");
- if(embedElements.length == 0) return "";
- embedElements[0].tag = "embed";
- return getSrcOf(embedElements[0]);
- }
- return "";
- break;
- case "applet":
- if(element.code) {
- tmpAnchor.href = element.code;
- } else if(element.hasAttribute("archive")) {
- tmpAnchor.href = element.getAttribute("archive");
- } else return "";
- return tmpAnchor.href;
break;
}
+ if(!info.src) {
+ if(!url) info.src = "";
+ else {
+ tmpAnchor.href = url;
+ info.src = tmpAnchor.href;
+ }
+ }
+ return info;
}
function getParamsOf(element) {
@@ -132,7 +104,7 @@ function getTypeOf(element) {
var paramElements = element.getElementsByTagName("param");
for (i = 0; i < paramElements.length; i++) {
if(paramElements[i].getAttribute("name").toLowerCase() == "type") {
- return paramElements[i].getAttribute("value");
+ return paramElements[i].getAttribute("value");
}
}
var embedChildren = element.getElementsByTagName("embed");
diff --git a/ClickToPlugin.fr.safariextension/global.html b/ClickToPlugin.fr.safariextension/global.html
index 90e01f3e..034769de 100644
--- a/ClickToPlugin.fr.safariextension/global.html
+++ b/ClickToPlugin.fr.safariextension/global.html
@@ -1,9 +1,10 @@
-
- Global HTML
+
+ Global HTML
+
-
+
@@ -13,6 +14,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/global.js b/ClickToPlugin.fr.safariextension/global.js
index 4e0abdb5..b58bf3b5 100644
--- a/ClickToPlugin.fr.safariextension/global.js
+++ b/ClickToPlugin.fr.safariextension/global.js
@@ -1,81 +1,19 @@
var CTP_instance = 0; // incremented by one whenever a ClickToPlugin instance with content is created
const killers = [new YouTubeKiller(), new VimeoKiller(), new DailymotionKiller(), new VeohKiller(), new JWKiller(), new SLKiller(), new QTKiller(), new WMKiller(), new DivXKiller()];
-function pluginName(plugin) {
- if(plugin.name == "Shockwave Flash") return "Flash";
- if(plugin.name == "Silverlight Plug-In") return "Silverlight";
- if(plugin.name.match("Java")) return "Java";
- if(plugin.name.match("QuickTime")) return "QuickTime";
- if(plugin.name.match("Flip4Mac")) return "WM";
- if(plugin.name == "iPhotoPhotocast") return "iPhoto";
- if(plugin.name == "Quartz Composer Plug-In") return "Quartz";
- if(plugin.name == "VideoLAN VLC Plug-in") return "VLC";
- if(plugin.name == "DivX Web Player") return "DivX";
- if(plugin.name == ("RealPlayer Plugin.plugin")) return "RealPlayer";
- return plugin.name;
- /*switch (plugin.name) {
- case "Flip4Mac Windows Media Web Plugin 2.3.4": return "WM";
- case "Flip4Mac Windows Media Plugin 2.3.4": return "WM";
- case "Silverlight Plug-In": return "Silverlight";
- case "Shockwave Flash": return "Flash";
- case "Switchable Java Plug-in for WebKit": return "Java";
- case "Java Plug-In 2 for NPAPI Browsers": return "Java";
- case "iPhotoPhotocast": return "iPhoto";
- case "QuickTime Plug-in 7.6.6": return "QuickTime";
- case "Quartz Composer Plug-In": return "Quartz";
- default: return plugin.name;
- }*/
-}
-
-/*
-LIST OF CLASSID (What is this stuff anyway?)
-QuickTime: 02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
-WMP 6: 22d6f312-b0f6-11d0-94ab-0080c74c7e95
-WMP >6: 6BF52A52-394A-11D3-B153-00C04F79FAA6
-Flash: d27cdb6e-ae6d-11cf-96b8-444553540000
-Real Player: CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA
-?? calendar: 8E27C92B-1264-101C-8A2F-040224009C02
-?? graphics: 369303C2-D7AC-11D0-89D5-00A0C90833E6
-?? slider: F08DF954-8592-11D1-B16A-00C0F0283628
-DivX: 67DABFBF-D0AB-41fa-9C46-CC0F21721616
-*/
-
-
-function getPluginForType(MIMEType) { // MIMEType is a string
- for(var i = 0; i < navigator.plugins.length; i++) {
- for(var j = 0; j < navigator.plugins[i].length; j++) {
- if(navigator.plugins[i][j].type == MIMEType) return navigator.plugins[i];
- }
- }
- return null;
-}
-
-function getPluginAndTypeForExt(ext) {
- var suffixes = null;
- for(var i = 0; i < navigator.plugins.length; i++) {
- for(var j = 0; j < navigator.plugins[i].length; j++) {
- suffixes = navigator.plugins[i][j].suffixes.split(",");
- for(var k = 0; k < suffixes.length; k++) {
- if(ext == suffixes[k]) return {"plugin": navigator.plugins[i], "type": navigator.plugins[i][j].type};
- }
- }
- }
- return {"plugin": null, "type": null};
-}
-
function blockOrAllow(data) { // returns null if element can be loaded, the name of the plugin otherwise
// no source and no type -> must allow, it's probably going to pass through here again after being modified by a script
if(!data.src && !data.type && !data.classid) return null;
// native Safari support
- var ext = extractExt(data.src); // used later as well
- if(data.type) {
- if(isNativeType(data.type)) return null;
- } else {
- if(isNativeExt(ext)) return null;
- }
-
+ var ext = extractExt(data.src); // used later as well
+ if(data.type) {
+ if(isNativeType(data.type)) return null;
+ } else {
+ if(isNativeExt(ext)) return null;
+ }
+
// try not to block objects created by other extensions
if(data.src.substring(0,19) == "safari-extension://") return null;
@@ -87,55 +25,55 @@ function blockOrAllow(data) { // returns null if element can be loaded, the name
}
// Deal with whitelisted content
- if(safari.extension.settings["uselocWhitelist"]) {
+ if(safari.extension.settings["uselocWhitelist"]) {
var locwhitelist = safari.extension.settings["locwhitelist"].replace(/\s+/g,"");
var locblacklist = safari.extension.settings["locblacklist"].replace(/\s+/g,"");
- if(locwhitelist) {
- locwhitelist = locwhitelist.split(/,(?![^\(]*\))/);
+ if(locwhitelist) {
+ locwhitelist = locwhitelist.split(/,(?![^\(]*\))/); // matches all , except those in parentheses (used in regexp)
if(matchList(locwhitelist, data.location)) return null;
- }
- if(locblacklist) {
- locblacklist = locblacklist.split(/,(?![^\(]*\))/);
- if(!matchList(locblacklist, data.location)) return null;
- }
+ }
+ if(locblacklist) {
+ locblacklist = locblacklist.split(/,(?![^\(]*\))/);
+ if(!matchList(locblacklist, data.location)) return null;
+ }
}
- if(safari.extension.settings["usesrcWhitelist"]) {
- var srcwhitelist = safari.extension.settings["srcwhitelist"].replace(/\s+/g,"");
+ if(safari.extension.settings["usesrcWhitelist"]) {
+ var srcwhitelist = safari.extension.settings["srcwhitelist"].replace(/\s+/g,"");
var srcblacklist = safari.extension.settings["srcblacklist"].replace(/\s+/g,"");
- if(srcwhitelist) {
- srcwhitelist = srcwhitelist.split(/,(?![^\(]*\))/);
+ if(srcwhitelist) {
+ srcwhitelist = srcwhitelist.split(/,(?![^\(]*\))/);
if(matchList(srcwhitelist, data.src)) return null;
- }
- if(locblacklist) {
- srcblacklist = srcblacklist.split(/,(?![^\(]*\))/);
- if(!matchList(srcblacklist, data.src)) return null;
- }
- }
-
+ }
+ if(locblacklist) {
+ srcblacklist = srcblacklist.split(/,(?![^\(]*\))/);
+ if(!matchList(srcblacklist, data.src)) return null;
+ }
+ }
+
// We use a 'soft' method to get the MIME type
// It is not necessarily correct, but always returns a MIME type handled by the correct plugin
// To get the correct MIME type an AJAX request would be needed, out of the question here!
var plugin = null;
- var MIMEType = data.type.replace(/\s+/g,"");
- var badgeLabel = "?";
- if(MIMEType) {
- badgeLabel = MIMEType.split(";")[0].split("/")[1]; // temporary unless no plugin can be found to play MIMEType
- plugin = getPluginForType(MIMEType);
- }
+ var MIMEType = data.type;
+ var pluginName = "?";
+ if(MIMEType) plugin = getPluginForType(MIMEType);
if(!plugin && data.src) {
var x = getPluginAndTypeForExt(ext);
plugin = x.plugin;
MIMEType = x.type;
}
- if(plugin) badgeLabel = pluginName(plugin);
+ if(plugin) pluginName = getPluginNameFromPlugin(plugin);
+ else if(MIMEType) pluginName = getPluginNameFromType(MIMEType);
+ else if(data.classid) pluginName = getPluginNameFromClassid(data.classid.replace("clsid:", ""));
- if(safari.extension.settings["allowQT"] && badgeLabel == "QuickTime") return null;
+ if(safari.extension.settings["allowQT"] && pluginName == "QuickTime") return null;
+ // Use greenlist/redlist
if(MIMEType) {
if(safari.extension.settings["block"] == "useRedlist") {
var redlist = safari.extension.settings["redlist"].replace(/\s+/g,"");
if(!redlist) return null;
- redlist = redlist.split(/,(?![^\(]*\))/); // matches all , except those in parentheses (used in regexp)
+ redlist = redlist.split(/,(?![^\(]*\))/);
if(!matchList(redlist, MIMEType, true)) return null;
} else if(safari.extension.settings["block"] == "useGreenlist") {
var greenlist = safari.extension.settings["greenlist"].replace(/\s+/g,"");
@@ -145,18 +83,16 @@ function blockOrAllow(data) { // returns null if element can be loaded, the name
}
}
}
- // At this point we know we'll have to block the element
+ // At this point we know we should block the element
- for(var key in data.otherInfo) {
- if(key == "target" && data.otherInfo.target == "quicktimeplayer") {
- // A quicktime object that would launch QTP
- if(confirm("Un objet QuickTime voudrait lancer le lecture de\n\n" + data.src + "\n\ndans QuickTime Player. Voulez-vous l'autoriser?")) {
- return null;
- }
+ // Exception: ask the user what to do if a QT object would launch QTP
+ if(data.launchInQTP) {
+ if(confirm("Un objet QuickTime voudrait lancer le lecture de\n\n" + data.launchInQTP + "\n\ndans QuickTime Player. Voulez-vous l'autoriser?")) {
+ return null;
}
}
- return badgeLabel;
+ return pluginName;
}
@@ -174,11 +110,6 @@ function respondToMessage(event) {
case "killPlugin":
killPlugin(event.message);
break;
- //case "downloadMedia":
- //var newTab = safari.application.activeBrowserWindow.openTab("foreground");
- //newTab.url = event.message + ".zip";
- //prompt("Copy the following URL and paste it into the Downloads window.", event.message);
- //break;
}
}
@@ -197,73 +128,60 @@ function respondToCanLoad(message) {
}
}
-function printMedia(mediaType) {
- switch(mediaType) {
- case "video": return "Video";
- case "audio": return "Audio";
- default: return "Video";
- }
-}
-
-function printPlugin(pluginName) {
- if(/[A-Z]/.test(pluginName)) return pluginName;
- return "Plugin";
-}
-
function handleContextMenu(event) {
- if(!event.userInfo.CTPInstance) {
- if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 0) event.contextMenu.appendContextMenuItem("loadall", "Débloquer tous les plugins (" + event.userInfo.blocked + ")");
+ if(!event.userInfo.instance) {
+ if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 0) event.contextMenu.appendContextMenuItem("loadall", "Débloquer tous les plugins (" + event.userInfo.blocked + ")");
if(safari.extension.settings["useWLcontext"]) {
- event.contextMenu.appendContextMenuItem("locwhitelist", "Ajouter à la liste blanche\u2026");
+ event.contextMenu.appendContextMenuItem("locwhitelist", "Ajouter à la liste blanche\u2026");
}
return;
}
+ var pluginName = /[A-Z]/.test(event.userInfo.plugin) ? event.userInfo.plugin : "Plugin";
if(event.userInfo.isH264) {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",reloadPlugin", "Relancer avec " + event.userInfo.plugin);
- if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",qtp", "Ouvrir dans QuickTime Player");
- if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "Voir la vidéo sur " + event.userInfo.siteInfo.name);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",reload", "Relancer avec " + pluginName);
+ if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",qtp", "Ouvrir avec QuickTime Player");
+ if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "Voir la vidéo sur " + event.userInfo.siteInfo.name);
} else {
if(event.userInfo.hasH264) {
- //event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",video", "Load " + printMedia(event.userInfo.mediaType));
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",plugin", "Lancer " + printPlugin(event.userInfo.plugin));
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",remove", "Supprimer " + printPlugin(event.userInfo.plugin));
- //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
- if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",qtp", "Ouvrir dans QuickTime Player");
- if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "Voir la vidéo sur " + event.userInfo.siteInfo.name);
- } else {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",remove", "Supprimer " + printPlugin(event.userInfo.plugin));
- //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
- }
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",plugin", "Lancer " + pluginName);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",remove", "Supprimer " + pluginName);
+ //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
+ if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",qtp", "Ouvrir avec QuickTime Player");
+ if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "Voir la vidéo sur " + event.userInfo.siteInfo.name);
+ } else {
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",remove", "Supprimer " + pluginName);
+ //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
+ }
if(safari.extension.settings["useWLcontext"]) {
- event.contextMenu.appendContextMenuItem("srcwhitelist", "Ajouter à la liste blanche\u2026");
+ event.contextMenu.appendContextMenuItem("srcwhitelist", "Ajouter à la liste blanche\u2026");
}
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",show", "Voir l'élément " + event.userInfo.CTPInstance + "." + event.userInfo.elementID);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",show", "Voir l'élément " + event.userInfo.instance + "." + event.userInfo.elementID);
}
//END DEBUG
}
}
function doCommand(event) {
- switch(event.command) {
- case "gotosite":
- var newTab = safari.application.activeBrowserWindow.openTab("foreground");
- newTab.url = event.userInfo.siteInfo.url;
- break;
- case "locwhitelist":
- handleWhitelisting(true, event.userInfo.location);
- break;
- case "srcwhitelist":
- handleWhitelisting(false, event.userInfo.src);
- break;
- case "loadall":
- safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadAll", "");
- break;
- default:
- safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadContent", event.command);
- break;
- }
+ switch(event.command) {
+ case "gotosite":
+ var newTab = safari.application.activeBrowserWindow.openTab("foreground");
+ newTab.url = event.userInfo.siteInfo.url;
+ break;
+ case "locwhitelist":
+ handleWhitelisting(true, event.userInfo.location);
+ break;
+ case "srcwhitelist":
+ handleWhitelisting(false, event.userInfo.src);
+ break;
+ case "loadall":
+ safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadAll", "");
+ break;
+ default:
+ safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadContent", event.command);
+ break;
+ }
}
function handleWhitelisting (type, url) {
@@ -281,25 +199,23 @@ function handleWhitelisting (type, url) {
function handleChangeOfSettings(event) {
if(event.key == "volume") {
- // send to all pages or just the active one??
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("updateVolume", event.newValue);
} else if(event.key = "opacity") {
- dispatchMessageToAllPages("updateOpacity", event.newValue);
- }
+ dispatchMessageToAllPages("updateOpacity", event.newValue);
+ }
}
-function getSettings() {
- var settings = new Object();
- settings.useH264 = safari.extension.settings["useH264"];
- settings.usePlaylists = safari.extension.settings["usePlaylists"];
- //settings.maxres = safari.extension.settings["maxresolution"];
+function getSettings() { // return the settings injected scripts need
+ var settings = new Object();
+ settings.useH264 = safari.extension.settings["useH264"];
+ settings.usePlaylists = safari.extension.settings["usePlaylists"];
settings.H264autoload = safari.extension.settings["H264autoload"];
settings.H264behavior = safari.extension.settings["H264behavior"];
settings.volume = safari.extension.settings["volume"];
settings.sifrReplacement = safari.extension.settings["sifrReplacement"];
- settings.opacity = safari.extension.settings["opacity"];
+ settings.opacity = safari.extension.settings["opacity"];
settings.debug = safari.extension.settings["debug"];
- return settings;
+ return settings;
}
function killPlugin(data) {
@@ -307,21 +223,21 @@ function killPlugin(data) {
if(killerID == null) return;
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
- if(!confirm("Killer '" + killers[killerID].name + "' thinks it might be able to process target " + data.CTPInstance +"."+ data.elementID + ".")) return;
+ if(!confirm("Killer '" + killers[killerID].name + "' thinks it might be able to process target " + data.instance +"."+ data.elementID + ".")) return;
}
// END DEBUG
var callback = function(mediaData) {
mediaData.elementID = data.elementID;
- mediaData.CTPInstance = data.CTPInstance;
+ mediaData.instance = data.instance;
// the following messsage must be dispatched to all pages to make sure that
- // pages or tabs loading in the background get their videoData
+ // pages or tabs loading in the background get their mediaData
dispatchMessageToAllPages("mediaData", mediaData);
};
killers[killerID].processElement(data, callback);
}
function findKillerFor(data) {
- for (i = 0; i < killers.length; i++) {
+ for (i = 0; i < killers.length; i++) {
if(killers[i].canKill(data)) return i;
}
return null;
diff --git a/ClickToPlugin.fr.safariextension/globalfunctions.js b/ClickToPlugin.fr.safariextension/globalfunctions.js
index 1bc5ad5d..01a68cab 100644
--- a/ClickToPlugin.fr.safariextension/globalfunctions.js
+++ b/ClickToPlugin.fr.safariextension/globalfunctions.js
@@ -1,40 +1,37 @@
-function makeAbsoluteURI(url) {
+function makeAbsoluteURI(url, location) {
if(!url) return "";
- var tmpAnchor = document.createElement("a");
- tmpAnchor.href = url;
- return tmpAnchor.href;
+ if(/\/\//.test(url)) return url; // already absolute
+ location = location.replace(/\/[^\/]*$/, "/");
+ if(url[0]=="/") url = url.substring(1);
+ if(url[0]=="/") {
+ url = url.substring(1);
+ location = location.replace(/\/\/.*$/,"//");
+ }
+ return location + url;
}
-// This function returns false if the url shoudl not be proposed
-// as a video replacement, according to the user's settings
-/*function getMediaTypeOf(url) {
- if (url.match(/(.mp4)|(.mpe{0,1}g)/i) || (safari.extension.settings["QTbehavior"] > 1 && url.match(/(.flv)/i))) return "video";
- if(url.match(/(.mp3)|(.wav)|(.aiff)|(.aac)/i) || (safari.extension.settings["QTbehavior"] > 1 && url.match(/.wma/i))) return "audio";
- return false;
-}*/
-
function getFlashVariable(flashvars, key) {
- if (!flashvars) return "";
- var flashVarsArray = flashvars.split("&");
- for (var i = 0; i < flashVarsArray.length; i++) {
- var keyValuePair = flashVarsArray[i].split("=");
- if (keyValuePair[0] == key) {
- return keyValuePair[1];
- }
- }
- return "";
+ if (!flashvars) return "";
+ var flashVarsArray = flashvars.split("&");
+ for (var i = 0; i < flashVarsArray.length; i++) {
+ var keyValuePair = flashVarsArray[i].split("=");
+ if (keyValuePair[0] == key) {
+ return keyValuePair[1];
+ }
+ }
+ return "";
}
function getSLVariable(initParams, key) {
- if (!initParams) return "";
- var initParamsArray = initParams.split(",");
- for (var i = 0; i < initParamsArray.length; i++) {
- var keyValuePair = initParamsArray[i].split("=");
- if (keyValuePair[0].toLowerCase() == key) {
- return keyValuePair[1];
- }
- }
- return "";
+ if (!initParams) return "";
+ var initParamsArray = initParams.split(",");
+ for (var i = 0; i < initParamsArray.length; i++) {
+ var keyValuePair = initParamsArray[i].split("=");
+ if (keyValuePair[0].toLowerCase() == key) {
+ return keyValuePair[1];
+ }
+ }
+ return "";
}
function getMIMEType(resourceURL, handleMIMEType) {
@@ -85,10 +82,10 @@ function matchList(list, string, lowerCase) { // set lowerCase to true if 'strin
// if s is enclosed in parenthesis, interpret as regexp
if (s[0] == "(" && s[s.length - 1] == ")") {
try{
- s = new RegExp(s, (lowerCase ? "i" : ""));
- } catch (err) { // invalid regexp, just ignore
- continue;
- }
+ s = new RegExp(s, (lowerCase ? "i" : ""));
+ } catch (err) { // invalid regexp, just ignore
+ continue;
+ }
} else if(lowerCase) {
s = s.toLowerCase();
}
@@ -97,4 +94,80 @@ function matchList(list, string, lowerCase) { // set lowerCase to true if 'strin
}
}
return false;
-}
\ No newline at end of file
+}
+
+/***********************
+Plugin detection methods
+***********************/
+
+function getPluginForType(MIMEType) { // MIMEType is a string
+ for(var i = 0; i < navigator.plugins.length; i++) {
+ for(var j = 0; j < navigator.plugins[i].length; j++) {
+ if(navigator.plugins[i][j].type == MIMEType) return navigator.plugins[i];
+ }
+ }
+ return null;
+}
+
+function getPluginAndTypeForExt(ext) {
+ var suffixes = null;
+ for(var i = 0; i < navigator.plugins.length; i++) {
+ for(var j = 0; j < navigator.plugins[i].length; j++) {
+ suffixes = navigator.plugins[i][j].suffixes.split(",");
+ for(var k = 0; k < suffixes.length; k++) {
+ if(ext == suffixes[k]) return {"plugin": navigator.plugins[i], "type": navigator.plugins[i][j].type};
+ }
+ }
+ }
+ return {"plugin": null, "type": null};
+}
+
+function getPluginNameFromPlugin(plugin) {
+ if(plugin.name == "Shockwave Flash") return "Flash";
+ if(plugin.name == "Silverlight Plug-In") return "Silverlight";
+ if(plugin.name.match("Java")) return "Java";
+ if(plugin.name.match("QuickTime")) return "QuickTime";
+ if(plugin.name.match("Flip4Mac")) return "WM";
+ if(plugin.name == "iPhotoPhotocast") return "iPhoto";
+ if(plugin.name == "Quartz Composer Plug-In") return "Quartz";
+ if(plugin.name == "VideoLAN VLC Plug-in") return "VLC";
+ if(plugin.name == "DivX Web Player") return "DivX";
+ if(plugin.name == ("RealPlayer Plugin.plugin")) return "Real";
+ return plugin.name;
+}
+
+function getPluginNameFromType(type) { // only used if no installed plugin is found
+ if(/shockwave-flash/.test(type) || /futuresplash/.test(type)) return "Flash";
+ if(/silverlight/.test(type)) return "Silverlight";
+ if(/x-java/.test(type)) return "Java";
+ if(/x-ms/.test(type)) return "WM";
+ if(/x-pn/.test(type)) return "Real";
+ type = type.split(";")[0];
+ if(type == "video/divx") return "DivX";
+ return type.split("/")[1];
+}
+
+function getPluginNameFromClassid(classid) { // last resort
+ switch(classid.toLowerCase()) {
+ case "d27cdb6e-ae6d-11cf-96b8-444553540000": return "Flash";
+ case "22d6f312-b0f6-11d0-94ab-0080c74c7e95": return "WM";
+ case "6bf52a52-394a-11d3-b153-00c04f79faa6": return "WM";
+ case "02bf25d5-8c17-4b23-bc80-d3488abddc6b": return "QuickTime";
+ case "cfcdaa03-8be4-11cf-b84b-0020afbbccfa": return "Real";
+ case "67dabfbf-d0ab-41fa-9c46-cc0f21721616": return "DivX";
+ default: return "?";
+ }
+}
+
+/*
+LIST OF CLASSIDs
+QuickTime: 02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
+WMP 6: 22d6f312-b0f6-11d0-94ab-0080c74c7e95
+WMP >6: 6BF52A52-394A-11D3-B153-00C04F79FAA6
+Flash: d27cdb6e-ae6d-11cf-96b8-444553540000
+Real Player: CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA
+?? calendar: 8E27C92B-1264-101C-8A2F-040224009C02
+?? graphics: 369303C2-D7AC-11D0-89D5-00A0C90833E6
+?? slider: F08DF954-8592-11D1-B16A-00C0F0283628
+DivX: 67DABFBF-D0AB-41fa-9C46-CC0F21721616
+*/
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/DailymotionKiller.js b/ClickToPlugin.fr.safariextension/killers/DailymotionKiller.js
index cee66d97..03fc92ef 100644
--- a/ClickToPlugin.fr.safariextension/killers/DailymotionKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/DailymotionKiller.js
@@ -3,7 +3,7 @@ function DailymotionKiller() {
}
DailymotionKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (data.src.match("/dmplayerv4/") || data.src.match("www.dailymotion.com"));
};
@@ -23,7 +23,7 @@ DailymotionKiller.prototype.processElement = function(data, callback) {
DailymotionKiller.prototype.processElementFromSequence = function(sequence, callback) {
var posterURL = null;
- var videoURL = null;
+ var videoURL = null;
var badgeLabel = "H.264";
if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV) {
var URLindex = sequence.indexOf("sdURL");
@@ -33,7 +33,7 @@ DailymotionKiller.prototype.processElementFromSequence = function(sequence, call
videoURL = s.replace(/\\\//g,"/");
}
}
- var URLindex = sequence.indexOf("hqURL"); // there's also an sdURL but it is an FLV video
+ var URLindex = sequence.indexOf("hqURL");
if (URLindex != -1) {
var s = sequence.substring(URLindex+8);
s = s.substring(0,s.indexOf("\""));
@@ -48,12 +48,11 @@ DailymotionKiller.prototype.processElementFromSequence = function(sequence, call
videoURL = s.replace(/\\\//g,"/");
}
}
- URLindex = sequence.indexOf("videoPreviewURL");
+ URLindex = sequence.indexOf("videoPreviewURL");
if (URLindex != -1) {
var s = sequence.substring(URLindex+18);
s = s.substring(0,s.indexOf("\""));
posterURL = s.replace(/\\\//g,"/");
- //alert(posterURL);
}
var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
@@ -69,10 +68,10 @@ DailymotionKiller.prototype.processElementFromVideoID = function(videoID, callba
req.open("GET", "http://www.dailymotion.com/video/" + videoID, true);
req.onload = function() {
var sequence = req.responseText.match(toMatch)[0];
- var callbackForEmbed = function(videoData) {
- videoData.playlist[0].siteInfo = {"name": "Dailymotion", "url": "http://www.dailymotion.com/video/" + videoID};
- callback(videoData);
- }
+ var callbackForEmbed = function(videoData) {
+ videoData.playlist[0].siteInfo = {"name": "Dailymotion", "url": "http://www.dailymotion.com/video/" + videoID};
+ callback(videoData);
+ }
if(sequence) {_this.processElementFromSequence(unescape(sequence), callbackForEmbed);}
};
// BEGIN DEBUG
diff --git a/ClickToPlugin.fr.safariextension/killers/DivXKiller.js b/ClickToPlugin.fr.safariextension/killers/DivXKiller.js
index 80232ccc..6a4185c8 100644
--- a/ClickToPlugin.fr.safariextension/killers/DivXKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/DivXKiller.js
@@ -1,5 +1,5 @@
function DivXKiller() {
- this.name = "DivXKiller";
+ this.name = "DivXKiller";
}
@@ -9,9 +9,9 @@ DivXKiller.prototype.canKill = function(data) {
DivXKiller.prototype.processElement = function(data, callback) {
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "posterURL": data.image, "mediaURL": data.src}],
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/JWKiller.js b/ClickToPlugin.fr.safariextension/killers/JWKiller.js
index d380792d..b6e0fe9e 100644
--- a/ClickToPlugin.fr.safariextension/killers/JWKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/JWKiller.js
@@ -1,93 +1,96 @@
function JWKiller() {
- this.name = "JWKiller";
+ this.name = "JWKiller";
}
JWKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
- return (getFlashVariable(data.params, "file") || getFlashVariable(data.params, "playlistfile"));
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ // streams are not supported
+ return (!getFlashVariable(data.params, "streamer") && (getFlashVariable(data.params, "file") || getFlashVariable(data.params, "playlistfile")));
};
JWKiller.prototype.processElement = function(data, callback) {
- var playlistURL = getFlashVariable(data.params, "playlistfile");
+ var playlistURL = getFlashVariable(data.params, "playlistfile");
var sourceURL = getFlashVariable(data.params, "file");
- var posterURL = getFlashVariable(data.params, "image");
-
- if(safari.extension.settings["usePlaylists"]) {
- if(playlistURL) {
- this.processElementFromPlaylist(playlistURL, getFlashVariable(data.params, "item"), posterURL, callback);
- return;
- }
- if(sourceURL.match(".xml")) {
- this.processElementFromPlaylist(sourceURL, getFlashVariable(data.params, "item"), posterURL, callback);
- return;
- }
- }
+ var posterURL = getFlashVariable(data.params, "image");
- var sourceURL2 = getFlashVariable(data.params, "real_file");
- if(sourceURL2) sourceURL = sourceURL2;
-
- var mediaType = checkSrc(sourceURL);
- if(!mediaType) return;
+ if(safari.extension.settings["usePlaylists"]) {
+ if(playlistURL) {
+ this.processElementFromPlaylist(playlistURL, data.location, getFlashVariable(data.params, "item"), posterURL, callback);
+ return;
+ }
+ if(/.xml($|\?)/i.test(sourceURL)) {
+ this.processElementFromPlaylist(sourceURL, data.location, getFlashVariable(data.params, "item"), posterURL, callback);
+ return;
+ }
+ }
+
+ var sourceURL2 = getFlashVariable(data.params, "real_file");
+ if(sourceURL2) sourceURL = sourceURL2;
+
+ var mediaType = checkSrc(sourceURL);
+ if(!mediaType) return;
- var mediaData = {
- "playlist": [{"mediaType": mediaType, "posterURL": makeAbsoluteURI(posterURL), "mediaURL": makeAbsoluteURI(sourceURL)}],
+ var mediaData = {
+ "playlist": [{"mediaType": mediaType, "posterURL": makeAbsoluteURI(posterURL, data.location), "mediaURL": makeAbsoluteURI(sourceURL, data.location)}],
"badgeLabel": (mediaType == "video") ? "Video" : "Audio"
};
- callback(mediaData);
+ callback(mediaData);
};
// put a more complete function in globalfunctions.js
function checkSrc(sourceURL) {
- if (sourceURL.match(/(.mp4)|(.mpe{0,1}g)/i)) return "video";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && sourceURL.match(/.flv/i)) return "video";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/(.wmv)|(.asf)/i)) return "video";
- if(sourceURL.match(/(.mp3)|(.wav)|(.aiff)|(.aac)/i)) return "audio";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wma/i)) return "audio";
- return false;
+ if (sourceURL.match(/.mp4|.mpe{0,1}g|.mov/i)) return "video";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && sourceURL.match(/.flv/i)) return "video";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wmv|.asf/i)) return "video";
+ if(sourceURL.match(/.mp3|.wav|.aiff|.aac/i)) return "audio";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wma/i)) return "audio";
+ return false;
};
-JWKiller.prototype.processElementFromPlaylist = function(playlistURL, track, posterURL, callback) {
- var req = new XMLHttpRequest();
- var startTrack = track;
- playlistURL = makeAbsoluteURI(playlistURL);
+JWKiller.prototype.processElementFromPlaylist = function(playlistURL, location, track, posterURL, callback) {
+ var req = new XMLHttpRequest();
+ var startTrack = track;
+ playlistURL = makeAbsoluteURI(playlistURL, location);
req.open('GET', playlistURL, true);
req.onload = function() {
+ var isAudio = true;
var x = req.responseXML.getElementsByTagName("track");
- if(!(track >= 0 && track < x.length)) track = 0;
- var playlist = new Array();
- var url = "";
- var list = null;
- var title = "";
- var poster = null;
- for(var i = 0; i < x.length; i++) {
- list = x[(i + track) % x.length].getElementsByTagName("location");
- if(list.length > 0) url = list[0].firstChild.nodeValue;
- else url = "";
- list = x[(i + track) % x.length].getElementsByTagName("title");
- if(list.length > 0) title = list[0].firstChild.nodeValue;
- else title = "";
- list = x[(i + track) % x.length].getElementsByTagName("image");
- if(list.length > 0) poster = list[0].firstChild.nodeValue;
- else poster = "";
- var mediaType = checkSrc(url);
- if(mediaType) {
- playlist.push({"title": title, "mediaType": mediaType, "posterURL": makeAbsoluteURI(poster), "mediaURL": makeAbsoluteURI(url)});
- if(mediaType == "video") isAudio = false;
- } else {
- if(i >= x.length - track) --startTrack;
- }
- }
- if(playlist.length == 0) return;
- if(!playlist[0].posterURL) playlist[0].posterURL = makeAbsoluteURI(posterURL);
+ if(!(track >= 0 && track < x.length)) track = 0;
+ var playlist = new Array();
+ var url = "";
+ var list = null;
+ var title = "";
+ var poster = null;
+ for(var i = 0; i < x.length; i++) {
+ list = x[(i + track) % x.length].getElementsByTagName("location");
+ if(list.length > 0) url = list[0].firstChild.nodeValue;
+ else if(i == 0) return;
+ else continue;
+ list = x[(i + track) % x.length].getElementsByTagName("title");
+ if(list.length > 0) title = list[0].firstChild.nodeValue;
+ else title = "";
+ list = x[(i + track) % x.length].getElementsByTagName("image");
+ if(list.length > 0) poster = list[0].firstChild.nodeValue;
+ else poster = "";
+ var mediaType = checkSrc(url);
+ if(mediaType) {
+ playlist.push({"title": title, "mediaType": mediaType, "posterURL": makeAbsoluteURI(poster, location), "mediaURL": makeAbsoluteURI(url, location)});
+ if(mediaType == "video") isAudio = false;
+ } else {
+ if(i == 0) return;
+ if(i >= x.length - track) --startTrack;
+ }
+ }
+ if(!playlist[0].posterURL) playlist[0].posterURL = makeAbsoluteURI(posterURL, location);
var mediaData = {
- "startTrack": startTrack,
- "isAudio": isAudio,
- "playlist": playlist,
- "badgeLabel": isAudio ? "Audio" : "Video"
- };
- callback(mediaData);
+ "startTrack": startTrack,
+ "isAudio": isAudio,
+ "playlist": playlist,
+ "badgeLabel": playlist[0].mediaType == "audio" ? "Audio" : "Video"
+ };
+ callback(mediaData);
};
- // BEGIN DEBUG
+ // BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + playlistURL)) return;
}
diff --git a/ClickToPlugin.fr.safariextension/killers/QTKiller.js b/ClickToPlugin.fr.safariextension/killers/QTKiller.js
index f7e83ad5..297914bf 100644
--- a/ClickToPlugin.fr.safariextension/killers/QTKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/QTKiller.js
@@ -1,5 +1,5 @@
function QTKiller() {
- this.name = "QTKiller";
+ this.name = "QTKiller";
}
@@ -13,11 +13,11 @@ QTKiller.prototype.processElement = function(data, callback) {
var playlist = null;
if(data.presrc) playlist = [{"mediaType": "video", "mediaURL": data.presrc}, {"mediaType": "video", "mediaURL": data.src}];
else playlist = [{"mediaType": "video", "mediaURL": data.src}];
- var videoData = {
- "noPlaylistControls": true,
+ var videoData = {
+ "noPlaylistControls": true,
"playlist": playlist,
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/SLKiller.js b/ClickToPlugin.fr.safariextension/killers/SLKiller.js
index 958b0d74..1b1538b0 100644
--- a/ClickToPlugin.fr.safariextension/killers/SLKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/SLKiller.js
@@ -1,5 +1,5 @@
function SLKiller() {
- this.name = "SLKiller";
+ this.name = "SLKiller";
}
@@ -14,9 +14,9 @@ SLKiller.prototype.processElement = function(data, callback) {
if(!videoURL.match(/\.((wm(?!x))|(asf))/)) return;
var posterURL = getSLVariable(data.params, "thumbnail");
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": "Video"
}
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/VeohKiller.js b/ClickToPlugin.fr.safariextension/killers/VeohKiller.js
index e2e4535a..72beda1c 100644
--- a/ClickToPlugin.fr.safariextension/killers/VeohKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/VeohKiller.js
@@ -1,39 +1,38 @@
function VeohKiller() {
- this.name = "VeohKiller";
+ this.name = "VeohKiller";
}
VeohKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && data.src.match("veoh.com/static/swf/webplayer"));
};
VeohKiller.prototype.processElement = function(data, callback) {
var videoID = null;
- var isEmbed = false;
+ var isEmbed = false;
if(data.params) videoID = getFlashVariable(data.params, "permalinkId");
else { // embedded video
- isEmbed = true;
+ isEmbed = true;
var matches = data.src.match(/permalinkId=([^&]*)(?=&)/);
if(matches) videoID = matches[0].replace("permalinkId=","");
}
var posterURL = null;
var videoURL = null;
- var request = new XMLHttpRequest();
- request.open('GET', "http://www.veoh.com/rest/video/" + videoID + "/details", true);
+ var request = new XMLHttpRequest();
+ request.open('GET', "http://www.veoh.com/rest/video/" + videoID + "/details", true);
request.onload = function() {
var element = request.responseXML.getElementsByTagName("video")[0];
if(element) {
videoURL = element.getAttribute("fullPreviewHashPath"); //"fullPreviewHashLowPath"
posterURL = element.getAttribute("fullHighResImagePath");
- //alert(element.getAttribute("previewHash") + "\n" + element.getAttribute("fullPreviewHashPath") + "\n\n" + element.getAttribute("previewHashLow") + "\n" + element.getAttribute("fullPreviewHashLowPath"));
}
var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": "Video" // There's no HD on Veoh, as far as I see, despite what they say. It's < 360p! Am I doing something wrong??
}
- if(isEmbed) videoData.playlist[0].siteInfo = {"name": "Veoh", "url": "http://www.veoh.com/browse/videos#watch%3D" + videoID};
+ if(isEmbed) videoData.playlist[0].siteInfo = {"name": "Veoh", "url": "http://www.veoh.com/browse/videos#watch%3D" + videoID};
callback(videoData);
};
// BEGIN DEBUG
@@ -41,5 +40,5 @@ VeohKiller.prototype.processElement = function(data, callback) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + "http://www.veoh.com/rest/video/" + videoID + "/details")) return;
}
// END DEBUG
- request.send(null);
+ request.send(null);
};
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/VimeoKiller.js b/ClickToPlugin.fr.safariextension/killers/VimeoKiller.js
index 6a2e54ea..26f1c9d4 100644
--- a/ClickToPlugin.fr.safariextension/killers/VimeoKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/VimeoKiller.js
@@ -3,7 +3,7 @@ function VimeoKiller() {
}
VimeoKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return !!data.src.match("moogaloop");
};
@@ -17,40 +17,38 @@ VimeoKiller.prototype.processElement = function(data, callback) {
if(!videoID) return;
var posterURL = null;
- var videoURL = null;
+ var videoURL = null;
var badgeLabel = "H.264";
- var request = new XMLHttpRequest();
- request.open('GET', "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/", false);
- //alert("sending AJAX request...");
+ var req = new XMLHttpRequest();
+ // this request needs to be synchronous, otherwise Vimeo scripts cause errors
+ req.open('GET', "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/", false);
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send a synchronous AJAX request to:\n\n" + "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/")) return;
}
// END DEBUG
- request.send(null);
- //alert("request sent! Answer:\n\n" + request.responseText);
- var responseXML = new DOMParser().parseFromString(request.responseText,"text/xml");
+ req.send(null);
if (safari.extension.settings["maxresolution"] > 1) {
- if(responseXML.getElementsByTagName("isHD").length > 0) {
- if(responseXML.getElementsByTagName("isHD")[0].childNodes[0].nodeValue == "1") badgeLabel = "HD H.264";
+ if(req.responseXML.getElementsByTagName("isHD").length > 0) {
+ if(req.responseXML.getElementsByTagName("isHD")[0].childNodes[0].nodeValue == "1") badgeLabel = "HD H.264";
}
}
- if(responseXML.getElementsByTagName("request_signature").length > 0 && responseXML.getElementsByTagName("request_signature_expires").length > 0) {
- videoURL = "http://www.vimeo.com/moogaloop/play/clip:" + videoID + "/" + responseXML.getElementsByTagName("request_signature")[0].childNodes[0].nodeValue+ "/" + responseXML.getElementsByTagName("request_signature_expires")[0].childNodes[0].nodeValue+"/?q=" + ((badgeLabel == "H.264") ? "mobile" : "hd");
- }
- if(responseXML.getElementsByTagName("thumbnail").length > 0) {
- posterURL = responseXML.getElementsByTagName("thumbnail")[0].childNodes[0].nodeValue;
+ if(req.responseXML.getElementsByTagName("request_signature").length > 0 && req.responseXML.getElementsByTagName("request_signature_expires").length > 0) {
+ videoURL = "http://www.vimeo.com/moogaloop/play/clip:" + videoID + "/" + req.responseXML.getElementsByTagName("request_signature")[0].childNodes[0].nodeValue+ "/" + req.responseXML.getElementsByTagName("request_signature_expires")[0].childNodes[0].nodeValue+"/?q=" + ((badgeLabel == "H.264") ? "mobile" : "hd");
}
- var siteInfo = null;
- if(!data.location.match("vimeo.com/")) siteInfo = {"name": "Vimeo", "url": "http://vimeo.com/" + videoID};
+ if(req.responseXML.getElementsByTagName("thumbnail").length > 0) {
+ posterURL = req.responseXML.getElementsByTagName("thumbnail")[0].childNodes[0].nodeValue;
+ }
+ var siteInfo = null;
+ if(!data.location.match("vimeo.com/") || data.location == "http://vimeo.com/") siteInfo = {"name": "Vimeo", "url": "http://vimeo.com/" + videoID};
var videoData = {
"playlist": [{"siteInfo": siteInfo, "mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": badgeLabel
};
- // Some videos on Vimeo are FLV; need to check that this is not the case, cause Safari can't handle them
+ // Some videos on Vimeo are FLV; need to check that this is not the case if user doesn't want them
if(videoURL) {
if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV) {
callback(videoData);
@@ -63,7 +61,7 @@ VimeoKiller.prototype.processElement = function(data, callback) {
// BEGIN DEBUG
else if(safari.extension.settings["debug"]) {
alert("Video found by killer 'VimeoKiller' has MIME type " + MIMEType + " and cannot be played natively by QuickTime.");
- }
+ }
// END DEBUD
};
// BEGIN DEBUG
@@ -72,30 +70,5 @@ VimeoKiller.prototype.processElement = function(data, callback) {
}
// END DEBUG
getMIMEType(videoURL, handleMIMEType);
- /*request = new XMLHttpRequest();
- request.open('HEAD', videoURL, true);
- var gotContentType = false;
- request.onreadystatechange = function () {
- if(!gotContentType && request.getResponseHeader('Content-Type')) {
- gotContentType = true;
- if(request.getResponseHeader('Content-Type') != "video/x-flv") {
- callback(videoData);
- }
- // BEGIN DEBUG
- else if(safari.extension.settings["debug"]) {
- alert("Video found by killer 'VimeoKiller' has MIME type " + request.getResponseHeader('Content-Type') + " and cannot be played by Safari.");
- }
- // END DEBUD
- request.abort();
- }
- };
- // BEGIN DEBUG
- if(safari.extension.settings["debug"]) {
- if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + videoURL)) return;
- }
- // END DEBUG
- request.send(null);*/
- //alert(request.responseText);
- //alert(req.getResponseHeader('Content-Type').split(';')[0]);
}
};
diff --git a/ClickToPlugin.fr.safariextension/killers/WMKiller.js b/ClickToPlugin.fr.safariextension/killers/WMKiller.js
index c9001c1d..e4361592 100644
--- a/ClickToPlugin.fr.safariextension/killers/WMKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/WMKiller.js
@@ -1,17 +1,17 @@
function WMKiller() {
- this.name = "WMKiller";
+ this.name = "WMKiller";
}
WMKiller.prototype.canKill = function(data) {
- return (data.plugin == "WM" && safari.extension.settings["replaceWM"] && safari.extension.settings["QTbehavior"] > 1 && canPlayWM && data.src.match(/\.((wm(?!x))|(asf))/i));
+ return (data.plugin == "WM" && safari.extension.settings["replaceWM"] && safari.extension.settings["QTbehavior"] > 1 && canPlayWM && data.src.match(/\.((wm(?!x)|asf))/i));
};
// should check media type...
WMKiller.prototype.processElement = function(data, callback) {
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "mediaURL": data.src}],
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.fr.safariextension/killers/YouTubeKiller.js b/ClickToPlugin.fr.safariextension/killers/YouTubeKiller.js
index 547e00d7..397e18aa 100644
--- a/ClickToPlugin.fr.safariextension/killers/YouTubeKiller.js
+++ b/ClickToPlugin.fr.safariextension/killers/YouTubeKiller.js
@@ -1,181 +1,162 @@
function YouTubeKiller() {
- this.name = "YouTubeKiller";
+ this.name = "YouTubeKiller";
}
YouTubeKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (data.src.match("ytimg.com") || data.src.match("youtube.com") || data.src.match("youtube-nocookie.com"));
};
YouTubeKiller.prototype.processElement = function(data, callback) {
if(data.params) {
- if(safari.extension.settings["usePlaylists"]) {
- // see http://apiblog.youtube.com/2010/03/upcoming-change-to-youtube-video-page.html
- // these new YT urls break everything!!!! Video data is loaded dynamically
- // after the Flash has been loaded... no more flashvars :(
- var URLvars = data.location.split("?")[1];
- var playlistID = null;
- if(URLvars) {
- URLvars = URLvars.split("&");
- for (var i = 0; i < URLvars.length; i++) {
- var keyValuePair = URLvars[i].split("=");
- if (keyValuePair[0] == "p") {
- playlistID = keyValuePair[1];
- break;
- }
- }
- }
- if(playlistID) {
- this.buildVideoIDList(data.params, playlistID, 0, new Array(), callback);
- } else this.processElementFromFlashVars(data.params, callback);
- } else this.processElementFromFlashVars(data.params, callback);
+ if(safari.extension.settings["usePlaylists"]) {
+ var URLvars = data.location.split(/#!|\?/)[1];
+ var playlistID = null;
+ if(URLvars) {
+ URLvars = URLvars.split("&");
+ for (var i = 0; i < URLvars.length; i++) {
+ var keyValuePair = URLvars[i].split("=");
+ if (keyValuePair[0] == "p") {
+ playlistID = keyValuePair[1];
+ break;
+ }
+ }
+ }
+ if(playlistID) {
+ this.buildVideoIDList(data.params, data.location, playlistID, 0, new Array(), callback);
+ } else this.processElementFromFlashVars(data.params, data.location, callback);
+ } else this.processElementFromFlashVars(data.params, data.location, callback);
return;
}
// The vid has no flashvars... Only hope is that it is a YouTube /v/ embed
var index = data.src.indexOf(".com/v/");
if(index == -1) {
- if(safari.extension.settings["usePlaylists"]) {
- index = data.src.indexOf(".com/p/");
- if(index == -1) return;
- var playlistID = data.src.substring(index + 7);
- index = playlistID.indexOf(".com/p/");
- if(index != -1) playlistID = playlistID.substring(index + 7);
- index = playlistID.search(/\?|&/);
- if(index != -1) playlistID = playlistID.substring(0,index);
- this.buildVideoIDList(null, playlistID, 0, new Array(), callback);
- }
- return;
- }
+ if(safari.extension.settings["usePlaylists"]) {
+ index = data.src.indexOf(".com/p/");
+ if(index == -1) return;
+ var playlistID = data.src.substring(index + 7);
+ index = playlistID.indexOf(".com/p/");
+ if(index != -1) playlistID = playlistID.substring(index + 7);
+ index = playlistID.search(/\?|&/);
+ if(index != -1) playlistID = playlistID.substring(0,index);
+ this.buildVideoIDList(null, data.location, playlistID, 0, new Array(), callback);
+ }
+ return;
+ }
var videoID = data.src.substring(index + 7);
- index = videoID.indexOf(".com/v/");
- if(index != -1) videoID = videoID.substring(index + 7);
+ index = videoID.indexOf(".com/v/");
+ if(index != -1) videoID = videoID.substring(index + 7);
index = videoID.search(/\?|&/);
if(index != -1) videoID = videoID.substring(0,index);
this.processElementFromVideoID(videoID, callback);
};
-/*YouTubeKiller.prototype.processElementFromPlaylist = function(videoID, plaslistID, callback) {
- var playlistURL = function(i) {
- return "feed://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50"
- };
- var isEmpty = false;
- var i = 0;
- var req = null;
- while(!isEmpty) {
- req = new XMLHttpRequest();
- req.open('GET', playlistURL(i), true);
- req.onload()
- }
-};*/
-
-// this function adds playlist data
-YouTubeKiller.prototype.buildVideoIDList = function(flashvars, playlistID, i, videoIDList, callback) {
- req = new XMLHttpRequest();
- req.open('GET', "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50", true);
- var _this = this;
- req.onload = function() {
- //alert(req.responseText);
- var entries = req.responseXML.getElementsByTagName("entry");
- // this is not always the correct number!!
- //if(!imax) imax = parseInt(responseXML.getElementsByTagNameNS("http://a9.com/-/spec/opensearchrss/1.0/", "totalResults")[0].firstChild.nodeValue);
- for(var j = 0; j < entries.length; j++) {
- try{
- videoIDList.push(entries[j].getElementsByTagNameNS("http://search.yahoo.com/mrss/", "player")[0].getAttribute("url").match(/\?v=[^(&|\?)]*(?=(&|\?))/)[0].replace("?v=",""));
- } catch(err) {}
- }
- if(entries.length < 50) {// we've got the whole list of videoIDs
- var track = 0;
- var length = videoIDList.length;
- if(flashvars) {
- var videoID = getFlashVariable(flashvars, "video_id");
- for(var j = 0; j < videoIDList.length; j++) {
- if(videoIDList[0] == videoID) {track = j; break;}
- videoIDList.push(videoIDList.shift());
- }
- //alert(videoIDList.length + " tracks\n\n" + videoIDList.join("\n"));
- // load the first video at once
- }
- var callbackForPlaylist = function(videoData) {
- videoData.playlistLength = length;
- videoData.startTrack = track;
- if(videoData.playlist[0].siteInfo) videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
- callback(videoData);
- };
- if(flashvars) _this.processElementFromFlashVars(flashvars, callbackForPlaylist);
- else _this.processElementFromVideoID(videoIDList[0], callbackForPlaylist);
- videoIDList.shift();
- _this.buildPlaylist(videoIDList, playlistID, true, 3, callback);
- return;
- }
- _this.buildVideoIDList(flashvars, playlistID, ++i, videoIDList, callback);
- };
- // BEGIN DEBUG
+YouTubeKiller.prototype.buildVideoIDList = function(flashvars, location, playlistID, i, videoIDList, callback) {
+ req = new XMLHttpRequest();
+ req.open('GET', "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50", true);
+ var _this = this;
+ req.onload = function() {
+ var entries = req.responseXML.getElementsByTagName("entry");
+ for(var j = 0; j < entries.length; j++) {
+ try{
+ videoIDList.push(entries[j].getElementsByTagNameNS("http://search.yahoo.com/mrss/", "player")[0].getAttribute("url").match(/\?v=[^(&|\?)]*(?=(&|\?))/)[0].replace("?v=",""));
+ } catch(err) {}
+ }
+ if(entries.length < 50) {// we've got the whole list of videoIDs
+ var track = 0;
+ var length = videoIDList.length;
+ if(flashvars) {
+ var videoID = getFlashVariable(flashvars, "video_id");
+ if(!videoID) { // new YT AJAX player
+ var matches = location.match(/(!|&)v=[^&]+(&|$)/);
+ if(!matches) return;
+ videoID = matches[0].substring(3).replace("&", "");
+ flashvars = null;
+ }
+ for(var j = 0; j < videoIDList.length; j++) {
+ if(videoIDList[0] == videoID) {track = j; break;}
+ videoIDList.push(videoIDList.shift());
+ }
+ }
+ var callbackForPlaylist = function(videoData) {
+ videoData.playlistLength = length;
+ videoData.startTrack = track;
+ if(videoData.playlist[0].siteInfo) videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
+ callback(videoData);
+ };
+ // load the first video at once
+ if(flashvars) _this.processElementFromFlashVars(flashvars, location, callbackForPlaylist);
+ else _this.processElementFromVideoID(videoIDList[0], callbackForPlaylist);
+ videoIDList.shift();
+ // load the rest of the playlist 3 by 3
+ _this.buildPlaylist(videoIDList, playlistID, true, 3, callback);
+ return;
+ }
+ _this.buildVideoIDList(flashvars, location, playlistID, ++i, videoIDList, callback);
+ };
+ // BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50")) return;
}
// END DEBUG
- req.send(null);
+ req.send(null);
};
YouTubeKiller.prototype.buildPlaylist = function(videoIDList, playlistID, isFirst, n, callback) {
- if(videoIDList.length == 0) return;
- var j = 0;
- var jmax = videoIDList.length;
- if(isFirst) --n;
- if(jmax > n) jmax = n; // load by groups of n
- if(isFirst) ++n;
- var mediaData = {"loadAfter": true, "missed": 0, "playlist": []};
- var _this = this;
- var next = function(videoData) {
- // this actually works!!
- if(videoData.playlist.length > 0) {
- videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
- mediaData.playlist.push(videoData.playlist[0]);
- } else {// playlist is 1 shorter than announced
- ++mediaData.missed;
- }
- ++j;
- //alert(mediaData.playlist.length);
- if(j == jmax) {
- callback(mediaData);
- // continue building
- _this.buildPlaylist(videoIDList, playlistID, false, n, callback);
- } else _this.processElementFromVideoID(videoIDList.shift(), next);
- };
- this.processElementFromVideoID(videoIDList.shift(), next);
- return;
+ if(videoIDList.length == 0) return;
+ var j = 0;
+ var jmax = videoIDList.length;
+ if(isFirst) --n;
+ if(jmax > n) jmax = n; // load by groups of n
+ if(isFirst) ++n;
+ var mediaData = {"loadAfter": true, "missed": 0, "playlist": []};
+ var _this = this;
+ var next = function(videoData) {
+ // this actually works!!
+ if(videoData.playlist.length > 0) {
+ videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
+ mediaData.playlist.push(videoData.playlist[0]);
+ } else { // playlist is 1 shorter than announced
+ ++mediaData.missed;
+ }
+ ++j;
+ if(j == jmax) {
+ callback(mediaData);
+ _this.buildPlaylist(videoIDList, playlistID, false, n, callback);
+ } else _this.processElementFromVideoID(videoIDList.shift(), next);
+ };
+ this.processElementFromVideoID(videoIDList.shift(), next);
+ return;
};
YouTubeKiller.prototype.getMediaDataFromURLMap = function(videoID, videoHash, urlMap) {
- var availableFormats = [];
+ var availableFormats = [];
var formatInfo = urlMap.split(",");
- // alert(formatInfo);
- for (var i = 0; i < formatInfo.length; i++) {
+ for (var i = 0; i < formatInfo.length; i++) {
var format = formatInfo[i].split("|");
- availableFormats[format[0]] = format[1];
- }
-
- var posterURL = "http://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg";
- // this is the 360p video URL
- var videoURL = "http://www.youtube.com/get_video?fmt=18&asv=&video_id=" + videoID + "&t=" + videoHash;
- var badgeLabel = "H.264";
+ availableFormats[format[0]] = format[1];
+ }
- // Get the highest-quality version set by the user
- //var format = 18;
+ var posterURL = "http://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg";
+ // this is the 360p MP4 video URL, always available
+ var videoURL = "http://www.youtube.com/get_video?fmt=18&asv=&video_id=" + videoID + "&t=" + videoHash;
+ var badgeLabel = "H.264";
- //alert(req.responseText);
- // Only 18, 22, 37, and 38 are h264 playable without plugin in Safari.
- // Other container are FLV (0, 5, 6, 34, 35, although the latter two are H.264 360p and 480p), 3GP (13,17), or WebM (43,45) and cannot play natively (even with Perian)
- if (availableFormats[38] && safari.extension.settings["maxresolution"] > 3) {// 4K @_@
+ /*
+ Only 18, 22, 37, and 38 are MP4 playable nativey by QuickTime.
+ Other containers are FLV (0, 5, 6, 34, 35, the latter two are H.264 360p and 480p),
+ 3GP (13,17), or WebM (43,45)
+ */
+ if (availableFormats[38] && safari.extension.settings["maxresolution"] > 3) {// 4K @_@
badgeLabel = "4K H.264";
- videoURL = availableFormats[38];
+ videoURL = availableFormats[38];
} else if (availableFormats[37] && safari.extension.settings["maxresolution"] > 2) {// 1080p
badgeLabel = "HD H.264";
- videoURL = availableFormats[37];
- } else if (availableFormats[22] && safari.extension.settings["maxresolution"] > 1) {// 720p
+ videoURL = availableFormats[37];
+ } else if (availableFormats[22] && safari.extension.settings["maxresolution"] > 1) {// 720p
badgeLabel = "HD H.264";
- videoURL = availableFormats[22];
- } else if (safari.extension.settings["QTbehavior"] > 2 && canPlayFLV) {
+ videoURL = availableFormats[22];
+ } else if (safari.extension.settings["QTbehavior"] > 2 && canPlayFLV) {
if (availableFormats[35]) { // 480p FLV
videoURL = availableFormats[35];
}
@@ -194,20 +175,28 @@ YouTubeKiller.prototype.getMediaDataFromURLMap = function(videoID, videoHash, ur
this.getSDH264FromFmt18(posterURL, videoID, callback); return;
// NOTE: possibility 2 seems to always work, so possibility 1 is never needed
}*/
- return {"posterURL": posterURL, "videoURL": videoURL, "badgeLabel": badgeLabel};
+ return {"posterURL": posterURL, "videoURL": videoURL, "badgeLabel": badgeLabel};
};
-YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, callback) {
- var title = unescape(getFlashVariable(flashvars, "rec_title")).substring(3).replace(/\+/g, " ");
+YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, location, callback) {
var videoID = getFlashVariable(flashvars, "video_id");
+ // see http://apiblog.youtube.com/2010/03/upcoming-change-to-youtube-video-page.html:
+ if(!videoID) { // new YT AJAX player (not yet used?)
+ var matches = location.match(/(!|&)v=[^&]+(&|$)/);
+ if(!matches) return;
+ videoID = matches[0].substring(3).replace("&", "");
+ this.processElementFromVideoID(videoID, callback);
+ return;
+ }
var videoHash = getFlashVariable(flashvars, "t");
if(!videoHash) {
this.processElementFromVideoID(videoID, callback);
return;
}
- var urlMap = unescape(getFlashVariable(flashvars, "fmt_url_map"));
+ var title = unescape(getFlashVariable(flashvars, "rec_title")).substring(3).replace(/\+/g, " ");
+ var urlMap = unescape(getFlashVariable(flashvars, "fmt_url_map"));
var x = this.getMediaDataFromURLMap(videoID, videoHash, urlMap);
- var videoData = {
+ var videoData = {
"playlist": [{"title": title, "mediaType": "video", "posterURL": x.posterURL, "mediaURL": x.videoURL}],
"badgeLabel": x.badgeLabel
};
@@ -215,36 +204,35 @@ YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, callba
};
YouTubeKiller.prototype.processElementFromVideoID = function(videoID, callback) {
- if(!videoID) return; // needed!
+ if(!videoID) return; // needed!
var toMatch = /\"fmt_url_map\":\s\"[^\"]*\"/; //"// works for both Flash and HTML5 Beta player pages
var toMatch2 = /\"t\":\s\"[^\"]*\"/; //"//
var _this = this;
var req = new XMLHttpRequest ();
req.open("GET", "http://www.youtube.com/watch?v=" + videoID, true);
req.onload = function() {
- var title = "";
- if(safari.extension.settings["usePlaylists"]) {
- var toMatchTitle = / 1;
- if(this.usePlaylistControls) {
- this.initializePlaylistControls();
- } else {
- this.initializeDownloadControls();
- }
+ }
+
+ // Set dimensions
+ this.width = width;
+ this.height = height;
+ this.containerElement.style.width = width + "px";
+ this.containerElement.style.height = height + "px";
+
+ // Set volume
+ this.mediaElement.volume = volume;
+
+ // Set listeners
+ var _this = this; // need anonymous function in listeners otherwise the 'this' will refer to the mediaElement!
+ this.mediaElement.addEventListener("contextmenu", function(event) {_this.setContextInfo(event, contextInfo);}, false);
+ this.mediaElement.addEventListener("loadedmetadata", function() {_this.fixAspectRatio();}, false);
+ this.mediaElement.addEventListener("ended", function() {_this.nextTrack();}, false);
+ this.mediaElement.ondblclick = function() {
+ _this.switchLoop();
+ };
+
+ if(this.usePlaylistControls) {
+ this.initializePlaylistControls();
+ } else {
+ this.initializeDownloadControls();
+ }
};
mediaPlayer.prototype.initializePlaylistControls = function() {
- this.playlistControls = document.createElement("div");
- this.playlistControls.className = "CTFplaylistControls";
-
- var trackTitle = document.createElement("div");
- trackTitle.className = "CTFtrackTitle";
- this.playlistControls.appendChild(trackTitle);
-
- var trackSelect = document.createElement("div");
- trackSelect.className = "CTFtrackSelect";
- this.playlistControls.appendChild(trackSelect);
-
- var trackTitleText = document.createElement("div");
- trackTitleText.className = "CTFtrackTitleText";
- trackTitle.appendChild(trackTitleText);
-
- var trackTitleTextP = document.createElement("p");
- trackTitleText.appendChild(trackTitleTextP);
-
- var prevButton = document.createElement("div");
- prevButton.className = "CTFprevButton";
- trackSelect.appendChild(prevButton);
-
- var trackInput = document.createElement("form");
- trackInput.className = "CTFtrackInput";
- trackSelect.appendChild(trackInput);
-
- var nextButton = document.createElement("div");
- nextButton.className = "CTFnextButton";
- trackSelect.appendChild(nextButton);
+ this.playlistControls = document.createElement("div");
+ this.playlistControls.className = "CTFplaylistControls";
+
+ var trackTitle = document.createElement("div");
+ trackTitle.className = "CTFtrackTitle";
+ this.playlistControls.appendChild(trackTitle);
+
+ var trackSelect = document.createElement("div");
+ trackSelect.className = "CTFtrackSelect";
+ this.playlistControls.appendChild(trackSelect);
+
+ var trackTitleText = document.createElement("div");
+ trackTitleText.className = "CTFtrackTitleText";
+ trackTitle.appendChild(trackTitleText);
+
+ var trackTitleTextP = document.createElement("p");
+ trackTitleText.appendChild(trackTitleTextP);
+
+ var prevButton = document.createElement("div");
+ prevButton.className = "CTFprevButton";
+ trackSelect.appendChild(prevButton);
+
+ var trackInput = document.createElement("form");
+ trackInput.className = "CTFtrackInput";
+ trackSelect.appendChild(trackInput);
+
+ var nextButton = document.createElement("div");
+ nextButton.className = "CTFnextButton";
+ trackSelect.appendChild(nextButton);
- trackInput.innerHTML = "/" + normalize(this.playlist.length, this.playlistLength) + "";
-
- var _this = this;
- this.mediaElement.onmouseover = function(event) {
- this.focus = true;
- if(!this.paused && this.readyState > 1) _this.fadeIn(.05);
- };
- this.playlistControls.onmouseover = function(event) {
- _this.mediaElement.focus = true;
- if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeIn(0);
- };
- this.mediaElement.onmouseout = function(event) {
- // prevents the default controls from disappearing
- if(event.relatedTarget && (event.relatedTarget == prevButton || event.relatedTarget == nextButton || event.relatedTarget == trackInput.firstChild || event.relatedTarget == trackTitleTextP.lastChild || event.relatedTarget.hasAttribute("precision"))) {
- event.preventDefault();
- } else {
- this.focus = false;
- if(!this.paused && this.readyState > 1) _this.fadeOut(0);
- }
- };
- this.playlistControls.onmouseout = function(event) {
- _this.mediaElement.focus = false;
- if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeOut(.1);
- };
- this.mediaElement.focus = false;
- this.mediaElement.addEventListener("pause", function(){_this.fadeIn(0);}, false);
- this.mediaElement.addEventListener("play", function(){if(!_this.mediaElement.focus) _this.fadeOut(0);}, false);
-
- trackInput.onsubmit = function(event) {
- event.preventDefault();
- var track = this.getElementsByTagName("input")[0].value;
- if(!(/^\d+$/.test(track))) return;
- track = parseInt(track);
- if(track < 1 || track > _this.playlistLength) return;
- track = (track - _this.startTrack - 1 + _this.playlistLength) % _this.playlistLength;
- if(track == _this.currentTrack) return;
- if(track < _this.playlist.length) {
- _this.loadTrack(track, true);
- }
- };
- prevButton.onclick = function() {
- if(_this.playlist.length == 1) return;
- _this.loadTrack(_this.currentTrack - 1, true);
- };
- nextButton.onclick = function() {
- if(_this.playlist.length == 1) return;
- _this.loadTrack(_this.currentTrack + 1, true);
- };
-
- // If the controls are shown at once a webkit bug will mess up font smoothing
- // when the video starts playing.
- // The only way I was able to prevent this is to show controls on loadedmetadata
- this.playlistControls.style.opacity = "0";
- this.containerElement.appendChild(this.playlistControls);
+ trackInput.innerHTML = "/" + normalize(this.playlist.length, this.playlistLength) + "";
+
+ var _this = this;
+ this.mediaElement.onmouseover = function(event) {
+ this.focus = true;
+ if(!this.paused && this.readyState > 1) _this.fadeIn(.05);
+ };
+ this.playlistControls.onmouseover = function(event) {
+ _this.mediaElement.focus = true;
+ if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeIn(0);
+ };
+ this.mediaElement.onmouseout = function(event) {
+ // prevents the default controls from disappearing
+ if(event.relatedTarget && (event.relatedTarget == prevButton || event.relatedTarget == nextButton || event.relatedTarget == trackInput.firstChild || event.relatedTarget == trackTitleTextP.lastChild || event.relatedTarget.hasAttribute("precision"))) {
+ event.preventDefault();
+ } else {
+ this.focus = false;
+ if(!this.paused && this.readyState > 1) _this.fadeOut(0);
+ }
+ };
+ this.playlistControls.onmouseout = function(event) {
+ _this.mediaElement.focus = false;
+ if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeOut(.1);
+ };
+ this.mediaElement.focus = false;
+ this.mediaElement.addEventListener("pause", function(){_this.fadeIn(0);}, false);
+ this.mediaElement.addEventListener("play", function(){if(!_this.mediaElement.focus) _this.fadeOut(0);}, false);
+
+ trackInput.onsubmit = function(event) {
+ event.preventDefault();
+ var track = this.getElementsByTagName("input")[0].value;
+ if(!(/^\d+$/.test(track))) return;
+ track = parseInt(track);
+ if(track < 1 || track > _this.playlistLength) return;
+ track = (track - _this.startTrack - 1 + _this.playlistLength) % _this.playlistLength;
+ if(track == _this.currentTrack) return;
+ if(track < _this.playlist.length) {
+ _this.loadTrack(track, true);
+ }
+ };
+ prevButton.onclick = function() {
+ if(_this.playlist.length == 1) return;
+ _this.loadTrack(_this.currentTrack - 1, true);
+ };
+ nextButton.onclick = function() {
+ if(_this.playlist.length == 1) return;
+ _this.loadTrack(_this.currentTrack + 1, true);
+ };
+
+ this.playlistControls.style.opacity = "1";
+ this.containerElement.appendChild(this.playlistControls);
};
mediaPlayer.prototype.initializeDownloadControls = function() {
- this.playlistControls = document.createElement("div");
- this.playlistControls.className = "CTFplaylistControls";
-
- var hoverElement = document.createElement("div");
- hoverElement.className = "CTFhoverElement";
- this.playlistControls.innerHTML = "";
-
- this.playlistControls.appendChild(hoverElement);
-
- var _this = this;
-
- this.playlistControls.firstChild.onmouseout = function(event) {
- this.nextSibling.style.display = "block";
- _this.fadeOut(0)
- };
-
- this.playlistControls.firstChild.onmouseover = function(event) {
- if(event.relatedTarget && event.relatedTarget.className == "CTFhoverElement") {
- this.nextSibling.style.display = "none";
- _this.fadeIn(0)
- }
- };
- hoverElement.onmouseover = function(event) {
- this.previousSibling.style.display ="block";
- }
-
- hoverElement.onmouseout = function(event) {
- if(!event.relatedTarget || event.relatedTarget.className != "CTFtitleText") {
- this.previousSibling.style.display ="none";
- }
- };
-
- this.mediaElement.onmouseout = function(event) {
- if(event.relatedTarget && (event.relatedTarget == hoverElement || event.relatedTarget.className == "CTFtitleText")) {
- event.preventDefault();
- }
- }
-
- this.playlistControls.addEventListener("webkitTransitionEnd", function() {if(this.style.opacity == "0") this.firstChild.style.display = "none";}, false);
-
- this.playlistControls.style.opacity = "0";
- this.playlistControls.firstChild.style.display = "none";
- //this.playlistControls.firstChild.style.pointerEvents = "auto";
-
- this.containerElement.appendChild(this.playlistControls);
+ this.playlistControls = document.createElement("div");
+ this.playlistControls.className = "CTFplaylistControls";
+
+ var hoverElement = document.createElement("div");
+ hoverElement.className = "CTFhoverElement";
+ this.playlistControls.innerHTML = "";
+
+ this.playlistControls.appendChild(hoverElement);
+
+ var _this = this;
+
+ this.playlistControls.firstChild.onmouseout = function(event) {
+ this.nextSibling.style.display = "block";
+ _this.fadeOut(0)
+ };
+
+ this.playlistControls.firstChild.onmouseover = function(event) {
+ if(event.relatedTarget && event.relatedTarget.className == "CTFhoverElement") {
+ this.nextSibling.style.display = "none";
+ _this.fadeIn(0)
+ }
+ };
+ hoverElement.onmouseover = function(event) {
+ this.previousSibling.style.display ="block";
+ }
+
+ hoverElement.onmouseout = function(event) {
+ if(!event.relatedTarget || event.relatedTarget.className != "CTFtitleText") {
+ this.previousSibling.style.display ="none";
+ }
+ };
+
+ this.mediaElement.onmouseout = function(event) {
+ if(event.relatedTarget && (event.relatedTarget == hoverElement || event.relatedTarget.className == "CTFtitleText")) {
+ event.preventDefault();
+ }
+ }
+
+ this.playlistControls.addEventListener("webkitTransitionEnd", function() {if(this.style.opacity == "0") this.firstChild.style.display = "none";}, false);
+
+ this.playlistControls.style.opacity = "0";
+ this.playlistControls.firstChild.style.display = "none";
+
+ this.containerElement.appendChild(this.playlistControls);
};
mediaPlayer.prototype.fadeOut = function(delay) {
- this.playlistControls.style.WebkitTransition = "opacity .4s linear " + delay + "s";
- this.playlistControls.style.opacity = "0";
+ this.playlistControls.style.WebkitTransition = "opacity .4s linear " + delay + "s";
+ this.playlistControls.style.opacity = "0";
};
mediaPlayer.prototype.fadeIn = function(delay) {
- this.playlistControls.style.WebkitTransition = "opacity .05s linear " + delay + "s";
- this.playlistControls.style.opacity = "0.93";
+ this.playlistControls.style.WebkitTransition = "opacity .05s linear " + delay + "s";
+ this.playlistControls.style.opacity = "0.93";
};
mediaPlayer.prototype.fixAspectRatio = function() {
- var w = this.mediaElement.videoWidth;
- var h = this.mediaElement.videoHeight;
- if(w == 0 || h == 0) { // audio source
+ var w = this.mediaElement.videoWidth;
+ var h = this.mediaElement.videoHeight;
+ if(w == 0 || h == 0) { // audio source
//this.mediaElement.style.height = "24px"; // the height of the controls
this.mediaElement.style.width = this.width + "px"; this.mediaElement.style.height = this.height + "px";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
} else if (w/h > this.width/this.height) {
this.mediaElement.style.width = this.width + "px"; this.mediaElement.style.height = "";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
} else {
this.mediaElement.style.height = this.height + "px"; this.mediaElement.style.width = "";
- // Apparently webkit uses floor, not round
- if(this.playlistControls) this.playlistControls.style.width = Math.floor(w/h*this.height) + "px";
+ if(this.playlistControls) {
+ // Apparently QuickTime uses floor, not round
+ var width = Math.floor(w/h*this.height);
+ this.playlistControls.style.width = width + "px";
+ if(this.usePlaylistControls) this.playlistControls.getElementsByTagName("p")[0].style.width = (width - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth - 12) + "px";
+ }
+ }
+ if(this.usePlaylistControls) {
+ // need this otherwise a webkit bug messes up font smoothing
+ this.fadeIn(.05);
}
- if(this.usePlaylistControls) {
- this.fadeIn(.05);
- }
-
+
};
mediaPlayer.prototype.resetAspectRatio = function() {
- this.mediaElement.style.width = this.width + "px";
- this.mediaElement.style.height = this.height + "px";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
+ this.mediaElement.style.width = this.width + "px";
+ this.mediaElement.style.height = this.height + "px";
+ if(this.playlistControls) {
+ this.playlistControls.style.width = this.width + "px";
+ if(this.usePlaylistControls) this.playlistControls.getElementsByTagName("p")[0].style.width = (this.width - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth - 12) + "px";
+ }
};
mediaPlayer.prototype.switchLoop = function() {
- if(this.mediaElement.hasAttribute("loop")) this.mediaElement.removeAttribute("loop");
- else this.mediaElement.setAttribute("loop", "true");
+ if(this.mediaElement.hasAttribute("loop")) this.mediaElement.removeAttribute("loop");
+ else this.mediaElement.setAttribute("loop", "true");
}
mediaPlayer.prototype.nextTrack = function() {
- if(!this.mediaElement.hasAttribute("loop")) {
- if(this.currentTrack + this.startTrack + 1 == this.playlistLength) return;
- this.loadTrack(this.currentTrack + 1, true);
- }
+ if(!this.mediaElement.hasAttribute("loop")) {
+ if(this.currentTrack + this.startTrack + 1 == this.playlistLength) return;
+ this.loadTrack(this.currentTrack + 1, true);
+ }
};
mediaPlayer.prototype.loadTrack = function(track, autoplay) {
- track = track % this.playlist.length;
+ track = track % this.playlist.length;
if(track < 0) track += this.playlist.length; // weird JS behavior
- this.resetAspectRatio();
+ this.resetAspectRatio();
this.mediaElement.src = this.playlist[track].mediaURL;
- // If src is not set before poster, poster is not shown. Webkit bug?
- if(this.playlist[track].posterURL) {
- if(this.playlist[track].mediaType == "video") {
- this.mediaElement.poster = this.playlist[track].posterURL;
- this.mediaElement.style.background = "";
- // this.mediaElement.style.backgroundSize = "";
- } else {
- if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
- this.mediaElement.style.backgroundImage = "url('" + this.playlist[track].posterURL + "')";
- this.mediaElement.style.backgroundRepeat = "no-repeat";
- this.mediaElement.style.backgroundPosition = "center center";
- // this.mediaElement.style.backgroundSize = "100 %";
- }
- } else {
- if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
- this.mediaElement.style.background = "";
- }
- this.currentTrack = track;
- if(autoplay) {
+ // If src is not set before poster, poster is not shown. Webkit bug?
+ if(this.playlist[track].posterURL) {
+ if(this.playlist[track].mediaType == "video") {
+ this.mediaElement.poster = this.playlist[track].posterURL;
+ this.mediaElement.style.background = "";
+ // this.mediaElement.style.backgroundSize = "";
+ } else {
+ if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
+ this.mediaElement.style.backgroundImage = "url('" + this.playlist[track].posterURL + "')";
+ this.mediaElement.style.backgroundRepeat = "no-repeat";
+ this.mediaElement.style.backgroundPosition = "center center";
+ // this.mediaElement.style.backgroundSize = "100 %";
+ }
+ } else {
+ if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
+ this.mediaElement.style.background = "";
+ }
+ this.currentTrack = track;
+ if(autoplay) {
this.mediaElement.setAttribute("preload", "auto");
this.mediaElement.setAttribute("autoplay", "autoplay");
}
- if(this.usePlaylistControls) {
- var title = this.playlist[track].title;
- if(!title) title = "(no title)";
- title = "" + title + "";
- this.playlistControls.getElementsByTagName("p")[0].innerHTML = ((track + this.startTrack) % this.playlistLength + 1) + ". " + title;
- var inputField = this.playlistControls.getElementsByTagName("input")[0];
- var newInputField = document.createElement("input");
- newInputField.setAttribute("type", "text");
- newInputField.setAttribute("value", (track + this.startTrack) % this.playlistLength + 1);
- newInputField.style.width = (8 * this.playlistLength.toString().length) + "px";
- // simply changing the value does not update if user has used the field
- this.playlistControls.getElementsByTagName("form")[0].replaceChild(newInputField, inputField);
- //this.playlistControls.getElementsByTagName("input")[0].setAttribute("value", track + this.startTrack + 1);
- } else {
- var title = "Télécharger " + (this.playlist[track].mediaType == "audio" ? "l'audio" : "la vidéo");
- title = "" + title + "";
- this.playlistControls.getElementsByTagName("p")[0].innerHTML = title;
- }
+ if(this.usePlaylistControls) {
+ var title = this.playlist[track].title;
+ if(!title) title = "(no title)";
+ title = "" + title + "";
+ this.playlistControls.getElementsByTagName("p")[0].innerHTML = ((track + this.startTrack) % this.playlistLength + 1) + ". " + title;
+ var inputField = this.playlistControls.getElementsByTagName("input")[0];
+ var newInputField = document.createElement("input");
+ newInputField.setAttribute("type", "text");
+ newInputField.setAttribute("value", (track + this.startTrack) % this.playlistLength + 1);
+ newInputField.style.width = (8 * this.playlistLength.toString().length) + "px";
+ // simply changing the value does not update if user has used the field
+ this.playlistControls.getElementsByTagName("form")[0].replaceChild(newInputField, inputField);
+ // this.playlistControls.getElementsByTagName("input")[0].setAttribute("value", track + this.startTrack + 1);
+ } else {
+ var title = "Télécharger " + (this.playlist[track].mediaType == "audio" ? "l'audio" : "la vidéo");
+ title = "" + title + "";
+ this.playlistControls.getElementsByTagName("p")[0].innerHTML = title;
+ }
};
mediaPlayer.prototype.setContextInfo = function(event, contextInfo) {
- var track = this.currentTrack;
- if(track == null) track = 0;
- contextInfo.mediaType = this.playlist[track].mediaType;
- contextInfo.siteInfo = this.playlist[track].siteInfo;
- //if(this.mediaElement) contextInfo.loop = this.mediaElement.hasAttribute("loop");
- // contextInfo.isPlaylist = (this.playlist.length > 1); // not used
- safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
- event.stopPropagation();
+ var track = this.currentTrack;
+ if(track == null) track = 0;
+ contextInfo.mediaType = this.playlist[track].mediaType;
+ contextInfo.siteInfo = this.playlist[track].siteInfo;
+ // if(this.mediaElement) contextInfo.loop = this.mediaElement.hasAttribute("loop");
+ // contextInfo.isPlaylist = (this.playlist.length > 1); // not used
+ safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
+ event.stopPropagation();
};
mediaPlayer.prototype.addToPlaylist = function(playlist, init) {
- if(init) this.playlist = playlist.concat(this.playlist);
- else this.playlist = this.playlist.concat(playlist);
- if(this.usePlaylistControls && this.playlistControls) {
- this.playlistControls.getElementsByTagName("span")[0].innerHTML = "/" + normalize(this.playlist.length + this.startTrack, this.playlistLength);
- var width = this.playlistControls.offsetWidth - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth;
- this.playlistControls.getElementsByTagName("p")[0].style.width = (width - 7) + "px";
- }
+ if(init) this.playlist = playlist.concat(this.playlist);
+ else this.playlist = this.playlist.concat(playlist);
+ if(this.usePlaylistControls && this.playlistControls) {
+ this.playlistControls.getElementsByTagName("span")[0].innerHTML = "/" + normalize(this.playlist.length + this.startTrack, this.playlistLength);
+ }
};
function normalize(n,m) {
- if(n > m) return m.toString();
- var string = n.toString();
- while(string.length < m.toString().length) {
- string = "0" + string;
- }
- return string;
+ if(n > m) return m.toString();
+ var string = n.toString();
+ while(string.length < m.toString().length) {
+ string = "0" + string;
+ }
+ return string;
}
diff --git a/ClickToPlugin.fr.safariextension/next.png b/ClickToPlugin.fr.safariextension/next.png
index 0cea8b02..72e161b6 100644
Binary files a/ClickToPlugin.fr.safariextension/next.png and b/ClickToPlugin.fr.safariextension/next.png differ
diff --git a/ClickToPlugin.fr.safariextension/next_active.png b/ClickToPlugin.fr.safariextension/next_active.png
index 3ec0a0ca..4c0fd79d 100644
Binary files a/ClickToPlugin.fr.safariextension/next_active.png and b/ClickToPlugin.fr.safariextension/next_active.png differ
diff --git a/ClickToPlugin.fr.safariextension/prev.png b/ClickToPlugin.fr.safariextension/prev.png
index a8f8888b..b79a46b6 100644
Binary files a/ClickToPlugin.fr.safariextension/prev.png and b/ClickToPlugin.fr.safariextension/prev.png differ
diff --git a/ClickToPlugin.fr.safariextension/prev_active.png b/ClickToPlugin.fr.safariextension/prev_active.png
index fcbd8c5b..1b41e105 100644
Binary files a/ClickToPlugin.fr.safariextension/prev_active.png and b/ClickToPlugin.fr.safariextension/prev_active.png differ
diff --git a/ClickToPlugin.fr.safariextension/styles.css b/ClickToPlugin.fr.safariextension/styles.css
index 63aa3f6b..1a17ac7d 100644
--- a/ClickToPlugin.fr.safariextension/styles.css
+++ b/ClickToPlugin.fr.safariextension/styles.css
@@ -1,11 +1,11 @@
/* Reset random stuff that might be set by the parent page */
.clickToFlashPlaceholder * {
- margin: 0 !important;
- padding: 0 !important;
- border: 0 !important;
- border-radius: 0 !important;
- text-align: left !important;
- background: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ border: 0 !important;
+ border-radius: 0 !important;
+ text-align: left !important;
+ background: none !important;
}
/*********************
@@ -13,11 +13,11 @@
*********************/
.clickToFlashPlaceholder {
- background: -webkit-gradient(linear, left top, left bottom, from(rgba(235, 235, 235, 1)), to(rgba(190, 190, 190, 1))) !important;
- border: 1px solid rgba(0, 0, 0, 0.5) !important;
- -webkit-user-select: none !important;
- display: inline-block !important;
- -webkit-box-sizing: border-box !important;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgba(235, 235, 235, 1)), to(rgba(190, 190, 190, 1))) !important;
+ border: 1px solid rgba(0, 0, 0, 0.5) !important;
+ -webkit-user-select: none !important;
+ display: inline-block !important;
+ -webkit-box-sizing: border-box !important;
}
.clickToFlashPlaceholder.notable {
@@ -29,39 +29,39 @@
}
.clickToFlashPlaceholder:active {
- background: -webkit-gradient(linear, left bottom, left top, from(rgba(225, 225, 225, 1)), to(rgba(200, 200, 200, 1))) !important;
+ background: -webkit-gradient(linear, left bottom, left top, from(rgba(225, 225, 225, 1)), to(rgba(200, 200, 200, 1))) !important;
}
.clickToFlashPlaceholderContainer {
- position: relative !important;
- width: inherit !important;
- height: inherit !important;
- margin: -1px !important;
+ position: relative !important;
+ width: inherit !important;
+ height: inherit !important;
+ margin: -1px !important;
overflow: visible !important;
}
div.logoVerticalPosition {
- display: table-cell !important;
- vertical-align: middle !important;
- width: inherit !important;
- height: inherit !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ width: inherit !important;
+ height: inherit !important;
}
.logoHorizontalPosition {
- float: left !important;
- position: relative !important;
- left: 50% !important;
- height: auto !important;
- width: auto !important;
+ float: left !important;
+ position: relative !important;
+ left: 50% !important;
+ height: auto !important;
+ width: auto !important;
overflow: visible !important;
}
.clickToFlashPlaceholder .logoContainer {
- float: left !important;
- position: relative !important;
- left: -50% !important;
- width: auto !important;
- height: auto !important;
+ float: left !important;
+ position: relative !important;
+ left: -50% !important;
+ width: auto !important;
+ height: auto !important;
overflow: visible !important;
}
@@ -75,40 +75,41 @@ div.logoVerticalPosition {
}
.clickToFlashPlaceholder .logo {
- border-radius: 8px !important;
- border: 4px solid rgba(0, 0, 0, 0.3) !important;
- font-size: 20px !important;
+ border-radius: 8px !important;
+ border: 4px solid rgba(0, 0, 0, 0.3) !important;
+ font-size: 20px !important;
font-style: normal !important;
- width: auto !important;
+ width: auto !important;
margin: 0 !important;
- color: rgba(0, 0, 0, 0.5) !important;
- font-weight: bold !important;
- padding: 14px 5px 7px 5px !important;
- -webkit-user-select: none !important;
- cursor: default !important;
- background: none !important;
- position: relative !important;
- height: auto !important;
- line-height: 0 !important;
+ color: rgba(0, 0, 0, 0.5) !important;
+ font-weight: bold !important;
+ padding: 14px 5px 7px 5px !important;
+ -webkit-user-select: none !important;
+ white-space: nowrap !important;
+ cursor: default !important;
+ background: none !important;
+ position: relative !important;
+ height: auto !important;
+ line-height: 0 !important;
font-family: "Helvetica Neue", Helvetica, sans-serif !important;
}
.clickToFlashPlaceholder .logo.inset {
- color: rgba(255, 255, 255, 0.45) !important;
- border-color: rgba(255, 255, 255, 0.45) !important;
- position: absolute !important;
- top: 1px !important;
+ color: rgba(255, 255, 255, 0.45) !important;
+ border-color: rgba(255, 255, 255, 0.45) !important;
+ position: absolute !important;
+ top: 1px !important;
font-family: "Helvetica Neue", Helvetica, sans-serif !important;
}
.clickToFlashPlaceholder .logoContainer.mini .logo,
.clickToFlashPlaceholder .logoContainer.hidden .logo.tmp {
color: rgba(50, 50, 50, 0.4) !important;
- font-size: 10px !important;
+ font-size: 10px !important;
font-style: normal !important;
- border: 2px solid rgba(50, 50, 50, 0.2) !important;
- padding: 7px 2px 4px 2px !important;
- border-radius: 4px !important;
+ border: 2px solid rgba(50, 50, 50, 0.2) !important;
+ padding: 7px 2px 4px 2px !important;
+ border-radius: 4px !important;
}
.clickToFlashPlaceholder .logoContainer.hidden .logo.tmp {
@@ -116,182 +117,182 @@ div.logoVerticalPosition {
}
.clickToFlashPlaceholder .logoContainer.mini .logo.inset {
- color: rgba(255, 255, 255, 0.25) !important;
- border-color: rgba(255, 255, 255, 0.25) !important;
+ color: rgba(255, 255, 255, 0.25) !important;
+ border-color: rgba(255, 255, 255, 0.25) !important;
}
.CTFvideoContainer {
- position: relative !important;
- display: inline-block !important;
- margin: 0 !important;
- padding: 0 !important;
+ position: relative !important;
+ display: inline-block !important;
+ margin: 0 !important;
+ padding: 0 !important;
}
.CTFvideoElement {
- display: block !important;
- position: relative !important;
- margin: 0px auto 0px auto !important;
+ display: block !important;
+ position: relative !important;
+ margin: 0px auto 0px auto !important;
}
.CTFQTObject {
- position: absolute !important;
- width: 0px !important;
- height: 0px !important;
+ position: absolute !important;
+ width: 0px !important;
+ height: 0px !important;
}
/* PLAYLIST CONTROLS */
.CTFplaylistControls {
- z-index: 1 !important;
- -webkit-user-select: none !important;
- display: block !important;
- position: relative !important;
- bottom: 48px !important;
- margin: 0px auto 0px auto !important;
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- padding: 0px !important;
- height: 24px !important;
- background-image: url('controls_background.png') !important;
- background-repeat: repeat-x !important;
- /*opacity: 0 !important;*/
- /*-webkit-transition: opacity .5s linear !important;*/
- pointer-events: none !important;
- text-rendering: auto !important;
+ z-index: 1 !important;
+ -webkit-user-select: none !important;
+ display: block !important;
+ position: relative !important;
+ bottom: 48px !important;
+ margin: 0px auto 0px auto !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ padding: 0px !important;
+ height: 24px !important;
+ background-image: url('controls_background.png') !important;
+ background-repeat: repeat-x !important;
+ /*opacity: 0 !important;*/
+ /*-webkit-transition: opacity .5s linear !important;*/
+ pointer-events: none !important;
+ text-rendering: auto !important;
}
.CTFtitleText {
- color: white !important;
- pointer-events: auto !important;
- text-decoration: none !important;
- border: 0 !important;
+ color: white !important;
+ pointer-events: auto !important;
+ text-decoration: none !important;
+ border: 0 !important;
}
.CTFtitleText:hover {
- text-decoration: underline !important;
+ text-decoration: underline !important;
}
/*:hover.CTFplaylistControls {
- opacity: 1 !important;
+ opacity: 1 !important;
}*/
.CTFplaylistControls div {
- height: inherit !important;
+ height: inherit !important;
}
.CTFtrackSelect div.CTFprevButton {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- margin: 0 !important;
- padding: 0 !important;
- width: 35px !important;
- background-image: url('prev.png') !important;
- background-repeat: no-repeat !important;
- background-position: center center !important;
- pointer-events: auto !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 37px !important;
+ background-image: url('prev.png') !important;
+ background-repeat: no-repeat !important;
+ background-position: center center !important;
+ pointer-events: auto !important;
}
.CTFtrackSelect div.CTFprevButton:active {
- background-image: url('prev_active.png') !important;
+ background-image: url('prev_active.png') !important;
}
.CTFtrackSelect form.CTFtrackInput {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- padding: 0 !important;
- margin: 0 !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ padding: 0 !important;
+ margin: 0 !important;
}
.CTFtrackSelect div.CTFnextButton {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- margin: 0 0 0 0 !important;
- padding: 0 0 0 0 !important;
- width: 35px !important;
- background-image: url('next.png') !important;
- background-repeat: no-repeat !important;
- background-position: center center !important;
- pointer-events: auto !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ margin: 0 0 0 0 !important;
+ padding: 0 0 0 0 !important;
+ width: 37px !important;
+ background-image: url('next.png') !important;
+ background-repeat: no-repeat !important;
+ background-position: center center !important;
+ pointer-events: auto !important;
}
.CTFtrackSelect div.CTFnextButton:active {
- background-image: url('next_active.png') !important;
+ background-image: url('next_active.png') !important;
}
.CTFtrackTitle {
- position: absolute !important;
- top: 0px !important;
- left: 0px !important;
- height: 24px !important;
+ position: absolute !important;
+ top: 0px !important;
+ left: 0px !important;
+ height: 24px !important;
}
.CTFtrackSelect {
- position: absolute !important;
- top: 0px !important;
- right: 6px !important;
- /*margin: 0 2px 0 0 !important;*/
+ position: absolute !important;
+ top: 0px !important;
+ right: 4px !important;
+ /*margin: 0 2px 0 0 !important;*/
}
.CTFtrackTitle div.CTFtrackTitleText {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- padding: 0 5px 0 7px !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ padding: 0 5px 0 7px !important;
}
.CTFtrackTitle div.CTFtrackTitleText p {
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- margin: 0 !important;
- padding: 0 !important;
- white-space: nowrap !important;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- text-align: left !important;
- line-height: normal !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ text-align: left !important;
+ line-height: normal !important;
}
.CTFtrackSelect input {
- background-color: rgba(255, 255, 255, 0.1) !important;
- border: 1px solid rgba(0, 0, 0, 1) !important;
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- margin: 0 !important;
- padding: 0 !important;
- text-align: right !important;
- pointer-events: auto !important;
- height: 12px !important;
- line-height: 1 !important;
+ background-color: rgba(255, 255, 255, 0.1) !important;
+ border: 1px solid rgba(0, 0, 0, 1) !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ text-align: right !important;
+ pointer-events: auto !important;
+ height: 12px !important;
+ line-height: 1 !important;
}
.CTFtrackSelect span {
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- line-height: 1 !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ line-height: 1 !important;
}
/*need the specificity*/
div.CTFplaylistControls div.CTFhoverElement {
- position: absolute !important;
- left: 28px !important;
- top: 18px !important;
- width: 24px !important;
- height: 6px !important;
- pointer-events: auto !important;
+ position: absolute !important;
+ left: 28px !important;
+ top: 18px !important;
+ width: 24px !important;
+ height: 6px !important;
+ pointer-events: auto !important;
}
diff --git a/ClickToPlugin.safariextension/.DS_Store b/ClickToPlugin.safariextension/.DS_Store
index 10fb7ec1..5d3c2697 100644
Binary files a/ClickToPlugin.safariextension/.DS_Store and b/ClickToPlugin.safariextension/.DS_Store differ
diff --git a/ClickToPlugin.safariextension/ClickToPlugin.js b/ClickToPlugin.safariextension/ClickToPlugin.js
index 387ae0dc..47e4da4c 100644
--- a/ClickToPlugin.safariextension/ClickToPlugin.js
+++ b/ClickToPlugin.safariextension/ClickToPlugin.js
@@ -1,45 +1,45 @@
-/*
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-NOTE TO SELF
-ALWAYS ALWAYS ALWAYS ALWAYS USE the 'var' keyword in 'for' loops!!!!!!!!!!
-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-*/
-
-
/****************************
ClickToPlugin class definition
*****************************/
function ClickToPlugin() {
- this.blockedElements = new Array();// array containing the Flash HTML elements
+ this.blockedElements = new Array();// array containing the blocked HTML elements
this.placeholderElements = new Array();// array containing the corresponding placeholder elements
- this.mediaPlayers = new Array();// array containing the HTML5 media players
+ this.mediaPlayers = new Array();// array containing the HTML5 media players
+
+ /*
+ Each item in blockedElement will acquire 3 additional properties:
+ -> tag: 'embed', 'object', or 'applet'
+ -> plugin: the name of the plugin that would handle the element
+ -> info: an object; info.src is the source of the embedded content
+ */
this.settings = null;
this.instance = null;
this.numberOfBlockedElements = 0;
- this.numberOfUnblockedElements = 0;
- this.location = window.location.href;
+ this.numberOfUnblockedElements = 0;
+
+ var _this = this;
- var _this = this;
-
- this.respondToMessageTrampoline = function(event) {
+ this.respondToMessageTrampoline = function(event) {
_this.respondToMessage(event);
};
-
- this.handleEventTrampoline = function(event) {
- _this.handleEvent(event);
- };
+
+ this.handleEventTrampoline = function(event) {
+ _this.handleEvent(event);
+ };
- safari.self.addEventListener("message", this.respondToMessageTrampoline, false);
- document.addEventListener("beforeload", this.handleEventTrampoline, true);
+ safari.self.addEventListener("message", this.respondToMessageTrampoline, false);
+ document.addEventListener("beforeload", this.handleEventTrampoline, true);
+ // HTML applet elements fire no beforeload event
+ // bug filed: https://bugs.webkit.org/show_bug.cgi?id=44023
+ // Unsatisfactory workaround (Java will run anyway):
document.addEventListener("DOMContentLoaded", this.handleEventTrampoline, false);
- document.addEventListener("DOMNodeInserted", this.handleEventTrampoline, false);
- //document.addEventListener("DOMNodeInsertedIntoDocument", this.handleEventTrampoline, false);
+ document.addEventListener("DOMNodeInserted", this.handleEventTrampoline, false);
document.oncontextmenu = function(event) {
- safari.self.tab.setContextMenuEventUserInfo(event, {"location": _this.location, "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements});
+ safari.self.tab.setContextMenuEventUserInfo(event, {"location": window.location.href, "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements});
};
}
@@ -50,31 +50,41 @@ ClickToPlugin.prototype.clearAll = function(elementID) {
};
ClickToPlugin.prototype.respondToMessage = function(event) {
- if (event.name == "mediaData") {
- if(event.message.CTPInstance != this.instance) return; // ignore message from other CTP instances
- this.prepMedia(event.message);
- } else if (event.name == "loadContent") {
- var loadData = event.message.split(","); // [0] CTPInstance, [1] elementID, [2] message
- if (loadData[0] != this.instance) return; // ignore message from other CTP instances
- if (loadData[2] == "plugin") {
- this.loadPluginForElement(loadData[1]);
- } else if (loadData[2] == "video") {
- this.loadMediaForElement(loadData[1]);
- } else if (loadData[2] == "reloadPlugin") {
- this.loadInPlugin(loadData[1]);
- } else if (loadData[2] == "remove") {
- this.removeElement(loadData[1]);
- } else if (loadData[2] == "qtp") {
- this.launchInQuickTimePlayer(loadData[1]);
- } else if (loadData[2] == "show") {
- alert(document.HTMLToString(this.blockedElements[loadData[1]]));
- }
- } else if (event.name == "updateVolume") {
- this.setVolumeTo(event.message);
- } else if (event.name == "updateOpacity") {
- this.setOpacityTo(event.message);
- } else if(event.name == "loadAll") {
- this.loadAll();
+ switch(event.name) {
+ case "mediaData":
+ if(event.message.instance != this.instance) return; // ignore message from other CTP instances
+ this.prepMedia(event.message);
+ break;
+ case "loadContent":
+ var loadData = event.message.split(","); // [0] instance, [1] elementID, [2] message
+ if (loadData[0] != this.instance) return; // ignore message from other CTP instances
+ switch(loadData[2]) {
+ case "plugin":
+ this.loadPluginForElement(loadData[1]);
+ break;
+ case "remove":
+ this.removeElement(loadData[1]);
+ break;
+ case "reload":
+ this.reloadInPlugin(loadData[1]);
+ break;
+ case "qtp":
+ this.launchInQuickTimePlayer(loadData[1]);
+ break;
+ case "show":
+ alert(document.HTMLToString(this.blockedElements[loadData[1]]));
+ break;
+ }
+ break;
+ case "loadAll":
+ this.loadAll();
+ break;
+ case "updateVolume":
+ this.setVolumeTo(event.message);
+ break;
+ case "updateOpacity":
+ this.setOpacityTo(event.message);
+ break;
}
};
@@ -82,9 +92,8 @@ ClickToPlugin.prototype.respondToMessage = function(event) {
According to the W3C HTML5 spec, to activate a plugin,
-> an 'embed' element must have either the 'src' or the 'type' attribute with nonempty value
-> an 'object' element must have either the 'data' or the 'type' attribute with nonempty value.
-In the real world, however, (AS IS RECOMMANDED ON ADOBE'S WEBSITE, BY THE WAY!)
-one often finds an 'object' with neither 'data' nor 'type', with an 'embed' element
-as child with 'src' and/or 'type' attribute set.
+In the real world, however, one often finds an 'object' with neither 'data' nor 'type',
+with an 'embed' element as child with 'src' and/or 'type' attribute set.
*/
ClickToPlugin.prototype.handleEvent = function(event) {
@@ -102,21 +111,35 @@ ClickToPlugin.prototype.handleEvent = function(event) {
ClickToPlugin.prototype.handleDOMContentEvent = function(event) {
if(event.target.nodeType != 1 && event.target.nodeType != 9) return; // the node is not an HTML Element nor the document
const applets = event.target.getElementsByTagName("applet");
+ if(applets.length == 0) return;
+
// Convert NodeList to Array
var appletElements = new Array();
for(var i = 0; i < applets.length; i++) {
appletElements.push(applets[i]);
}
+ var tmpAnchor = document.createElement("a");
for(var i = 0; i < appletElements.length; i++) {
if(appletElements[i].allowedToLoad) continue;
appletElements[i].tag = "applet";
- appletElements[i].source = getSrcOf(appletElements[i]);
+ appletElements[i].info = new Object();
+
+ // Get source of applet
+ if(appletElements[i].code) {
+ tmpAnchor.href = appletElements[i].code;
+ appletElements[i].info.src = tmpAnchor.href;
+ } else if(appletElements[i].hasAttribute("archive")) {
+ tmpAnchor.href = appletElements[i].getAttribute("archive");
+ appletElements[i].info.src = tmpAnchor.href;
+ } else {
+ appletElements[i].info.src = "";
+ }
- var pluginName = safari.self.tab.canLoad(event, {"src": appletElements[i].source, "type": "application/x-java-applet", "classid": "", "params": "", "location": this.location, "width": appletElements[i].offsetWidth, "height": appletElements[i].offsetHeight, "otherInfo": null});
+ var pluginName = safari.self.tab.canLoad(event, {"src": appletElements[i].info.src, "type": "application/x-java-applet", "location": window.location.href, "width": appletElements[i].offsetWidth, "height": appletElements[i].offsetHeight});
if(!pluginName) continue; // whitelisted
- appletElements[i].plugin = pluginName;
+ appletElements[i].plugin = "Java";
if(this.settings == null) {
this.settings = safari.self.tab.canLoad(event, "getSettings");
@@ -125,15 +148,21 @@ ClickToPlugin.prototype.handleDOMContentEvent = function(event) {
this.instance = safari.self.tab.canLoad(event, "getInstance");
}
var elementID = this.numberOfBlockedElements++;
- this.processBlockedElement(appletElements[i], elementID); // this removes appletElements[0] from the document
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ if(!confirm("ClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
+ }
+ // END DEBUG
+
+ this.processBlockedElement(appletElements[i], elementID);
}
};
ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
- const element = event.target;
-
+ const element = event.target;
+
// deal with sIFR script first
- if(element instanceof HTMLScriptElement && element.getAttribute("src").indexOf("sifr.js") != (-1)) {
+ if(element instanceof HTMLScriptElement && element.src.indexOf("sifr.js") != (-1)) {
var sIFRData = safari.self.tab.canLoad(event, "sIFR");
if(!sIFRData.canLoad) {
// BEGIN DEBUG
@@ -151,7 +180,8 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
// the beforeload event is fired again but this time the
// flash element must not be blocked
if (element.allowedToLoad) return;
- if (element instanceof HTMLEmbedElement) {
+
+ if (element instanceof HTMLEmbedElement) {
element.tag = "embed";
} else if (element instanceof HTMLObjectElement) {
element.tag = "object";
@@ -159,29 +189,20 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
return;
}
+ element.info = getInfo(element, event.url);
+
+ var pluginName = safari.self.tab.canLoad(event, {"src": element.info.src, "type": getTypeOf(element), "classid": element.getAttribute("classid"), "location": window.location.href, "width": element.offsetWidth, "height": element.offsetHeight, "launchInQTP": element.info.target == "quicktimeplayer" ? element.info.href : null});
+ if(!pluginName) return; // whitelisted
+
// Load the user settings
if(this.settings == null) {
this.settings = safari.self.tab.canLoad(event, "getSettings");
}
- // Give an address to this CTP instance to receive messages
- if(this.instance == null) {
- this.instance = safari.self.tab.canLoad(event, "getInstance");
- }
-
- element.otherInfo = new Object();
- element.source = getSrcOf(element);
-
- var pluginName = safari.self.tab.canLoad(event, {"src": element.source, "type": getTypeOf(element), "classid": element.getAttribute("classid"), "params": this.settings["useH264"] ? getParamsOf(element) : "", "location": this.location, "width": element.offsetWidth, "height": element.offsetHeight, "otherInfo": element.otherInfo});
- if(!pluginName) return; // whitelisted
- //alert(pluginName);
-
-
-
- // if useh264...
+ // if useh264...
// Deal with sIFR Flash
- if (element.className == "sIFR-flash" || element.getAttribute("sifr")) {
+ if (element.className == "sIFR-flash" || element.hasAttribute("sifr")) {
if (this.settings["sifrReplacement"] == "autoload") {
// BEGIN DEBUG
if(this.settings["debug"]) {
@@ -193,13 +214,17 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
}
// At this point we know we have to block 'element' from loading
+ var elementID = this.numberOfBlockedElements++;
element.plugin = pluginName;
- var elementID = this.numberOfBlockedElements++;
+
+ // Give an address to this CTP instance to receive messages
+ if(this.instance == null) {
+ this.instance = safari.self.tab.canLoad(event, "getInstance");
+ }
// BEGIN DEBUG
if(this.settings["debug"]) {
- if(!confirm(window.location.href + "\n" + window.top.location.href + "\nClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
- //alert(element.source + "\n -- \n" + event.url);
+ if(!confirm("ClickToPlugin is about to block embedded content " + this.instance + "." + elementID + ":\n\n" + document.HTMLToString(element))) return;
}
// END DEBUG
@@ -209,38 +234,37 @@ ClickToPlugin.prototype.handleBeforeLoadEvent = function(event) {
ClickToPlugin.prototype.prepMedia = function(mediaData) {
if(mediaData.playlist.length == 0 || !mediaData.playlist[0].mediaURL) return;
- if(!this.mediaPlayers[mediaData.elementID]) {
- this.mediaPlayers[mediaData.elementID] = new mediaPlayer(mediaData.isAudio ? "audio" : "video");
- }
- if(mediaData.loadAfter) { // just adding stuff to the playlist
- // BEGIN DEBUG
- if(this.settings["debug"]) {
- if(!confirm("Preparing to add " + mediaData.playlist.length + " tracks to the playlist for element " + this.instance +"."+ mediaData.elementID)) return;
- }
- // END DEBUG
- this.mediaPlayers[mediaData.elementID].playlistLength -= mediaData.missed;
- this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist);
- return;
- }
- // BEGIN DEBUG
- if(this.settings["debug"]) {
- var showPlaylist = "(" + mediaData.playlist.length + " track" + (mediaData.playlist.length > 1 ? "s" : "") + ")";
+ if(!this.mediaPlayers[mediaData.elementID]) {
+ this.mediaPlayers[mediaData.elementID] = new mediaPlayer(mediaData.isAudio ? "audio" : "video");
+ }
+ if(mediaData.loadAfter) { // just adding stuff to the playlist
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ if(!confirm("Preparing to add " + mediaData.playlist.length + " tracks to the playlist for element " + this.instance +"."+ mediaData.elementID)) return;
+ }
+ // END DEBUG
+ this.mediaPlayers[mediaData.elementID].playlistLength -= mediaData.missed;
+ this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist);
+ return;
+ }
+ // BEGIN DEBUG
+ if(this.settings["debug"]) {
+ var showPlaylist = "(" + mediaData.playlist.length + " track" + (mediaData.playlist.length > 1 ? "s" : "");
+ if(mediaData.playlistLength) showPlaylist += ", expecting " + mediaData.playlistLength;
+ showPlaylist += ")";
for (var i = 0; i < mediaData.playlist.length; i++) {
- showPlaylist += "\n[" + (i + 1) + "] (" + mediaData.playlist[i].mediaType + ")" + (mediaData.playlist[i].mediaType == "video" ? ("\nposterURL: " + mediaData.playlist[i].posterURL) : "") + "\nmediaURL: " + mediaData.playlist[i].mediaURL + "\n";
+ showPlaylist += "\n[" + (i + 1) + "] (" + mediaData.playlist[i].mediaType + ")" + "\nposterURL: " + mediaData.playlist[i].posterURL + "\nmediaURL: " + mediaData.playlist[i].mediaURL + "\n";
}
if(!confirm("Preparing media for element " + this.instance +"."+ mediaData.elementID +
":\n\nbadgeLabel: " + mediaData.badgeLabel + "\n\nPLAYLIST " + showPlaylist)) return;
}
// END DEBUG
-
- // do it backward just in case a loadAfter came first
- // can happen for embedded playlists
-
- this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist, true);
- this.mediaPlayers[mediaData.elementID].playlistLength = mediaData.playlistLength ? mediaData.playlistLength : mediaData.playlist.length;
- this.mediaPlayers[mediaData.elementID].startTrack = mediaData.startTrack ? mediaData.startTrack : 0;
-
- this.mediaPlayers[mediaData.elementID].usePlaylistControls = this.settings["usePlaylists"] && !mediaData.noPlaylistControls && this.mediaPlayers[mediaData.elementID].playlistLength > 1;
+
+ this.mediaPlayers[mediaData.elementID].addToPlaylist(mediaData.playlist, true);
+ this.mediaPlayers[mediaData.elementID].playlistLength = mediaData.playlistLength ? mediaData.playlistLength : mediaData.playlist.length;
+ this.mediaPlayers[mediaData.elementID].startTrack = mediaData.startTrack ? mediaData.startTrack : 0;
+
+ this.mediaPlayers[mediaData.elementID].usePlaylistControls = this.settings["usePlaylists"] && !mediaData.noPlaylistControls && this.mediaPlayers[mediaData.elementID].playlistLength > 1;
// Check if we should load video at once
if(this.settings["H264autoload"]) {
@@ -249,17 +273,17 @@ ClickToPlugin.prototype.prepMedia = function(mediaData) {
}
var badgeLabel = mediaData.badgeLabel;
if(!badgeLabel) badgeLabel = "Video";
-
+
this.displayBadge(badgeLabel, mediaData.elementID);
};
ClickToPlugin.prototype.loadPluginForElement = function(elementID) {
var placeholderElement = this.placeholderElements[elementID];
- var element = this.blockedElements[elementID];
- element.allowedToLoad = true;
+ var element = this.blockedElements[elementID];
+ element.allowedToLoad = true;
if(placeholderElement.parentNode) {
placeholderElement.parentNode.replaceChild(element, placeholderElement);
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
this.clearAll(elementID);
}
};
@@ -271,14 +295,14 @@ ClickToPlugin.prototype.loadAll = function() {
this.loadPluginForElement(i);
}
}
- this.numberOfUnblockedElements = this.numberOfBlockedElements;
+ this.numberOfUnblockedElements = this.numberOfBlockedElements;
};
-ClickToPlugin.prototype.loadInPlugin = function(elementID) {
+ClickToPlugin.prototype.reloadInPlugin = function(elementID) {
var containerElement = this.mediaPlayers[elementID].containerElement;
- var element = this.blockedElements[elementID];
- element.allowedToLoad = true;
- containerElement.parentNode.replaceChild(element, containerElement);
+ var element = this.blockedElements[elementID];
+ element.allowedToLoad = true;
+ containerElement.parentNode.replaceChild(element, containerElement);
this.clearAll(elementID);
};
@@ -286,56 +310,54 @@ ClickToPlugin.prototype.loadMediaForElement = function(elementID) {
var placeholderElement = this.placeholderElements[elementID];
var contextInfo = {
- "CTPInstance": this.instance,
+ "instance": this.instance,
"elementID": elementID,
"isH264": true,
"plugin": this.blockedElements[elementID].plugin
- //"blocked": this.numberOfBlockedElements - this.numberOfUnblockedElements
+ //"blocked": this.numberOfBlockedElements - this.numberOfUnblockedElements
};
- // Initialize player
- var w = parseInt(placeholderElement.style.width.replace("px",""));
- var h = parseInt(placeholderElement.style.height.replace("px",""));
- this.mediaPlayers[elementID].initialize(this.settings["H264behavior"], w, h, this.settings["volume"], contextInfo);
- //mediaElement.allowedToLoad = true; // not used for now
-
- // Load first track
- this.mediaPlayers[elementID].loadTrack(0);
+ // Initialize player
+ var w = parseInt(placeholderElement.style.width.replace("px",""));
+ var h = parseInt(placeholderElement.style.height.replace("px",""));
+ this.mediaPlayers[elementID].initialize(this.settings["H264behavior"], w, h, this.settings["volume"], contextInfo);
+ // mediaElement.allowedToLoad = true; // not used
- // Replace placeholder
- placeholderElement.parentNode.replaceChild(this.mediaPlayers[elementID].containerElement, placeholderElement);
- this.numberOfUnblockedElements++;
+ // Replace placeholder and load first track
+ placeholderElement.parentNode.replaceChild(this.mediaPlayers[elementID].containerElement, placeholderElement);
+ this.mediaPlayers[elementID].loadTrack(0);
+ this.numberOfUnblockedElements++;
this.placeholderElements[elementID] = null;
};
ClickToPlugin.prototype.launchInQuickTimePlayer = function(elementID) {
- var track = this.mediaPlayers[elementID].currentTrack;
- var element = null;
- if(track == null) {
- track = 0;
- element = this.placeholderElements[elementID];
- } else {
- element = this.mediaPlayers[elementID].containerElement;
- }
+ var track = this.mediaPlayers[elementID].currentTrack;
+ var element = null;
+ if(track == null) {
+ track = 0;
+ element = this.placeholderElements[elementID];
+ } else {
+ element = this.mediaPlayers[elementID].containerElement;
+ }
var mediaURL = this.mediaPlayers[elementID].playlist[track].mediaURL;
- var QTObject = document.createElement("embed");
- QTObject.allowedToLoad = true;
- QTObject.className = "CTFQTObject";
- QTObject.setAttribute("type", "video/quicktime");
- QTObject.setAttribute("width", "0");
- QTObject.setAttribute("height", "0");
- // need an external URL for source, since QT plugin doesn't accept safari-extension:// protocol
- // Apple has a small 1px image for this exact purpose
- QTObject.setAttribute("src", "http://images.apple.com/apple-events/includes/qtbutton.mov");
- QTObject.setAttribute("href", mediaURL);
- QTObject.setAttribute("target", "quicktimeplayer");
- QTObject.setAttribute("autohref", "true");
- QTObject.setAttribute("controller", "false");
- //QTObject.setAttribute("postdomevents", "true");
- element.appendChild(QTObject);
- // There doesn't seem to exist an appropriate event, so we just wait a bit...
- setTimeout(function() {element.removeChild(QTObject);}, 100);
+ var QTObject = document.createElement("embed");
+ QTObject.allowedToLoad = true;
+ QTObject.className = "CTFQTObject";
+ QTObject.setAttribute("type", "video/quicktime");
+ QTObject.setAttribute("width", "0");
+ QTObject.setAttribute("height", "0");
+ // need an external URL for source, since QT plugin doesn't accept safari-extension:// protocol
+ // Apple has a small 1px image for this exact purpose
+ QTObject.setAttribute("src", "http://images.apple.com/apple-events/includes/qtbutton.mov");
+ QTObject.setAttribute("href", mediaURL);
+ QTObject.setAttribute("target", "quicktimeplayer");
+ QTObject.setAttribute("autohref", "true");
+ QTObject.setAttribute("controller", "false");
+ // QTObject.setAttribute("postdomevents", "true");
+ element.appendChild(QTObject);
+ // There doesn't seem to exist an appropriate event, so we just wait a bit...
+ setTimeout(function() {element.removeChild(QTObject);}, 100);
};
ClickToPlugin.prototype.setVolumeTo = function(volume) {
@@ -356,7 +378,7 @@ ClickToPlugin.prototype.removeElement = function(elementID) {
element = element.parentNode;
}
element.parentNode.removeChild(element);
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
this.clearAll(elementID);
};
@@ -376,11 +398,11 @@ ClickToPlugin.prototype.displayBadge = function(badgeLabel, elementID) {
this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild.className = "logoContainer hidden";
this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild.childNodes[1].className = "logo tmp";
- this.unhideLogo(elementID);
+ this.unhideLogo(elementID, 0);
};
// NOTE: this function should never be called directly (use displayBadge instead)
-ClickToPlugin.prototype.unhideLogo = function(elementID) {
+ClickToPlugin.prototype.unhideLogo = function(elementID, i) {
var logoContainer = this.placeholderElements[elementID].firstChild.firstChild.firstChild.firstChild;
var w0 = this.placeholderElements[elementID].offsetWidth;
var h0 = this.placeholderElements[elementID].offsetHeight;
@@ -390,10 +412,11 @@ ClickToPlugin.prototype.unhideLogo = function(elementID) {
var h2 = logoContainer.childNodes[1].offsetHeight;
if(w2 == 0 || h2 == 0 || w1 == 0 || h1 == 0 || w0 == 0 || h0 == 0) {
+ if(i > 9) return;
// 2 options: leave the logo hidden (no big deal, and rarely happens),
- // or run unhideLogo again later (this might cause unexpected results due to asynchronicity)
+ // or run unhideLogo again later <- THIS
var _this = this;
- setTimeout(function() {_this.unhideLogo(elementID);}, 100); // there's no hurry here
+ setTimeout(function() {_this.unhideLogo(elementID, ++i);}, 100); // there's no hurry here
return;
}
@@ -418,22 +441,22 @@ ClickToPlugin.prototype.unhideLogo = function(elementID) {
};
ClickToPlugin.prototype.clickPlaceholder = function(elementID) {
- if (this.mediaPlayers[elementID] && this.mediaPlayers[elementID].startTrack != null) {
- this.loadMediaForElement(elementID);
- } else {
+ if (this.mediaPlayers[elementID] && this.mediaPlayers[elementID].startTrack != null) {
+ this.loadMediaForElement(elementID);
+ } else {
this.loadPluginForElement(elementID);
- }
+ }
};
ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
// Creating the placeholder element
- var placeholderElement = document.createElement("div");
- placeholderElement.style.width = element.offsetWidth + "px";
- placeholderElement.style.height = element.offsetHeight + "px";
- placeholderElement.style.opacity = this.settings["opacity"];
+ var placeholderElement = document.createElement("div");
+ placeholderElement.style.width = element.offsetWidth + "px";
+ placeholderElement.style.height = element.offsetHeight + "px";
+ placeholderElement.style.opacity = this.settings["opacity"];
- placeholderElement.className = "clickToFlashPlaceholder";
+ placeholderElement.className = "clickToFlashPlaceholder";
// Replacing element by placeholderElement
if (element.parentNode) {
@@ -445,54 +468,54 @@ ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
alert("Ignoring duplicate element " + this.instance + "." + elementID + ".");
}
// END DEBUG
- this.numberOfUnblockedElements++;
+ this.numberOfUnblockedElements++;
return;
}
- var _this = this;
- placeholderElement.onclick = function(event){_this.clickPlaceholder(elementID);};
- placeholderElement.oncontextmenu = function(event) {
- var contextInfo = {
- "CTPInstance": _this.instance,
+ var _this = this;
+ placeholderElement.onclick = function(event){_this.clickPlaceholder(elementID);};
+ placeholderElement.oncontextmenu = function(event) {
+ var contextInfo = {
+ "instance": _this.instance,
"elementID": elementID,
- "src": element.source,
+ "src": element.info.src,
"plugin": element.plugin,
- "blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements
+ //"blocked": _this.numberOfBlockedElements - _this.numberOfUnblockedElements
};
if (_this.mediaPlayers[elementID] && _this.mediaPlayers[elementID].startTrack != null) {
- contextInfo.hasH264 = true;
+ contextInfo.hasH264 = true;
_this.mediaPlayers[elementID].setContextInfo(event, contextInfo);
} else {
- contextInfo.hasH264 = false;
- safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
- event.stopPropagation();
+ contextInfo.hasH264 = false;
+ safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
+ event.stopPropagation();
}
- };
+ };
// Building the placeholder
- var container = document.createElement("div");
- container.className = "clickToFlashPlaceholderContainer";
- placeholderElement.appendChild(container);
-
- var verticalPositionElement = document.createElement("div");
- verticalPositionElement.className = "logoVerticalPosition";
- container.appendChild(verticalPositionElement);
-
- var horizontalPositionElement = document.createElement("div");
- horizontalPositionElement.className = "logoHorizontalPosition";
- verticalPositionElement.appendChild(horizontalPositionElement);
-
- var logoContainer = document.createElement("div");
- logoContainer.className = "logoContainer nodisplay"; // keep the logo hidden at first
- horizontalPositionElement.appendChild(logoContainer);
-
- var logoElement = document.createElement("div");
- logoElement.className = "logo";
- logoContainer.appendChild(logoElement);
-
- var logoInsetElement = document.createElement("div");
- logoInsetElement.className = "logo inset";
- logoContainer.appendChild(logoInsetElement);
+ var container = document.createElement("div");
+ container.className = "clickToFlashPlaceholderContainer";
+ placeholderElement.appendChild(container);
+
+ var verticalPositionElement = document.createElement("div");
+ verticalPositionElement.className = "logoVerticalPosition";
+ container.appendChild(verticalPositionElement);
+
+ var horizontalPositionElement = document.createElement("div");
+ horizontalPositionElement.className = "logoHorizontalPosition";
+ verticalPositionElement.appendChild(horizontalPositionElement);
+
+ var logoContainer = document.createElement("div");
+ logoContainer.className = "logoContainer nodisplay"; // keep the logo hidden at first
+ horizontalPositionElement.appendChild(logoContainer);
+
+ var logoElement = document.createElement("div");
+ logoElement.className = "logo";
+ logoContainer.appendChild(logoElement);
+
+ var logoInsetElement = document.createElement("div");
+ logoInsetElement.className = "logo inset";
+ logoContainer.appendChild(logoInsetElement);
// Filling the main arrays
this.blockedElements[elementID] = element;
@@ -503,14 +526,14 @@ ClickToPlugin.prototype.processBlockedElement = function(element, elementID) {
if(this.settings["useH264"]) {
if(!this.directKill(elementID)) {
var elementData = {
+ "instance": this.instance,
+ "elementID": elementID,
"plugin": element.plugin,
- "src": element.source,
- "presrc": element.presource, // TEMP!!
+ "src": element.info.href ? element.info.href : element.info.src,
+ "presrc": element.info.href ? element.info.src : "",
+ "image": element.info.image,
"params": getParamsOf(element),
- "elementID": elementID,
- "CTPInstance": this.instance,
- "location": this.location,
- "image": element.image
+ "location": window.location.href
};
safari.self.tab.dispatchMessage("killPlugin", elementData);
}
@@ -549,7 +572,7 @@ ClickToPlugin.prototype.directKill = function(elementID) {
var mediaData = {
"elementID": elementID,
"playlist": [{"mediaType": mediaType, "posterURL": mediaElements[0].getAttribute("poster"), "mediaURL": mediaURL}],
- "badgeLabel": "Video"
+ "badgeLabel": mediaType == "audio" ? "Audio" : "Video"
};
this.prepMedia(mediaData);
return true;
diff --git a/ClickToPlugin.safariextension/Settings.plist b/ClickToPlugin.safariextension/Settings.plist
index 3fef5130..3a358c00 100644
--- a/ClickToPlugin.safariextension/Settings.plist
+++ b/ClickToPlugin.safariextension/Settings.plist
@@ -2,421 +2,421 @@
-
- Title
- MIME Settings
- Type
- Group
-
-
- DefaultValue
- blockAll
- Key
- block
- Title
- Block
- Titles
-
- all MIME types
- all MIME types not matching the greenlist
- only the MIME types matching the redlist
-
- Type
- RadioButtons
- Values
-
- blockAll
- useGreenlist
- useRedlist
-
-
-
- DefaultValue
-
- Key
- greenlist
- Title
- Greenlist
- Type
- TextField
-
-
- DefaultValue
- flash, futuresplash, silverlight
- Key
- redlist
- Title
- Redlist
- Type
- TextField
-
-
- DefaultValue
-
- Key
- allowQT
- Title
- Allow QuickTime plugin                                Â
- Type
- CheckBox
-
-
- Title
- Video Settings
- Type
- Group
-
-
- DefaultValue
-
- Key
- useH264
- Title
- Look for video replacements to                    Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceFlash
- Title
- Flash                                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceSL
- Title
- Silverlight                                     Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceQT
- Title
- QuickTime                                   Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- replaceWM
- Title
- Windows Media                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- usePlaylists
- Title
- Use playlists                                                  Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- H264autoload
- Title
- Load the video player automatically             Â
- Type
- CheckBox
-
-
- DefaultValue
- autoplay
- Key
- H264behavior
- Title
- Once loaded
- Titles
-
- Do not buffer
- Start buffering
- Start buffering and play automatically
-
- Type
- PopUpButton
- Values
-
- none
- buffer
- autoplay
-
-
-
- DefaultValue
- 2
- Key
- QTbehavior
- Title
- Nonnative codecs
- Titles
-
- Do not use
- Use only as a last resort
- Use freely
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 3
-
-
-
- DefaultValue
- 3
- Key
- maxresolution
- Title
- Max resolution
- Titles
-
- 480p
- 720p
- 1080p
- 4K
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 3
- 4
-
-
-
- DefaultValue
- 0.5
- Key
- volume
- MaximumValue
- 1
- StepValue
- 0.01
- Title
- Sound volume
- Type
- Slider
-
-
- Title
- Whitelist
- Type
- Group
-
-
- DefaultValue
-
- Key
- uselocWhitelist
- Title
- Allow embedded content on locations          Â
- Type
- CheckBox
-
-
- DefaultValue
- www.example.com, www.example2.com
- Key
- locwhitelist
- Title
- matching
- Type
- TextField
-
-
- DefaultValue
-
- Key
- locblacklist
- Title
- not matching
- Type
- TextField
-
-
- DefaultValue
-
- Key
- usesrcWhitelist
- Title
- Allow embedded content from sources        Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- srcwhitelist
- Title
- matching
- Type
- TextField
-
-
- DefaultValue
-
- Key
- srcblacklist
- Title
- not matching
- Type
- TextField
-
-
- Title
- Invisible elements
- Type
- Group
-
-
- DefaultValue
-
- Key
- loadInvisible
- Title
- Allow elements to load if                              Â
- Type
- CheckBox
-
-
- DefaultValue
- 1
- Key
- maxinvdim
- Title
- size is at most
- Titles
-
- 1 x 1 px
- 2 x 2 px
- 4 x 4 px
- 8 x 8 px
-
- Type
- PopUpButton
- Values
-
- 1
- 2
- 4
- 8
-
-
-
- Title
- Contextual Menu Items
- Type
- Group
-
-
- DefaultValue
-
- Key
- useWLcontext
- Title
- Add to Whitelist                                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useLAcontext
- Title
- Load All Plugins                                            Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useVScontext
- Title
- View on Site                                                  Â
- Type
- CheckBox
-
-
- DefaultValue
-
- Key
- useQTcontext
- Title
- View in QuickTime Player                              Â
- Type
- CheckBox
-
-
- Type
- Separator
-
-
- DefaultValue
- textonly
- Key
- sifrReplacement
- Title
- sIFR Text
- Titles
-
- Show text only
- Treat as regular Flash
- Load automatically
-
- Type
- PopUpButton
- Values
-
- textonly
- normal
- autoload
-
-
-
- DefaultValue
- 1
- Key
- opacity
- MaximumValue
- 1
- Secure
-
- StepValue
- 0.01
- Title
- Opacity
- Type
- Slider
-
-
- DefaultValue
-
- Key
- debug
-
+
+ Title
+ MIME Settings
+ Type
+ Group
+
+
+ DefaultValue
+ blockAll
+ Key
+ block
+ Title
+ Block
+ Titles
+
+ all MIME types
+ all MIME types not matching the greenlist
+ only the MIME types matching the redlist
+
+ Type
+ RadioButtons
+ Values
+
+ blockAll
+ useGreenlist
+ useRedlist
+
+
+
+ DefaultValue
+
+ Key
+ greenlist
+ Title
+ Greenlist
+ Type
+ TextField
+
+
+ DefaultValue
+ flash, futuresplash, silverlight
+ Key
+ redlist
+ Title
+ Redlist
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ allowQT
+ Title
+ Allow QuickTime plugin                                Â
+ Type
+ CheckBox
+
+
+ Title
+ Video Settings
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ useH264
+ Title
+ Look for video replacements to                    Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceFlash
+ Title
+ Flash                                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceSL
+ Title
+ Silverlight                                     Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceQT
+ Title
+ QuickTime                                   Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ replaceWM
+ Title
+ Windows Media                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ usePlaylists
+ Title
+ Use playlists                                                  Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ H264autoload
+ Title
+ Load the video player automatically             Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+ autoplay
+ Key
+ H264behavior
+ Title
+ Once loaded
+ Titles
+
+ Do not buffer
+ Start buffering
+ Start buffering and play automatically
+
+ Type
+ PopUpButton
+ Values
+
+ none
+ buffer
+ autoplay
+
+
+
+ DefaultValue
+ 2
+ Key
+ QTbehavior
+ Title
+ Nonnative codecs
+ Titles
+
+ Do not use
+ Use only as a last resort
+ Use freely
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 3
+
+
+
+ DefaultValue
+ 3
+ Key
+ maxresolution
+ Title
+ Max resolution
+ Titles
+
+ 480p
+ 720p
+ 1080p
+ 4K
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 3
+ 4
+
+
+
+ DefaultValue
+ 0.5
+ Key
+ volume
+ MaximumValue
+ 1
+ StepValue
+ 0.01
+ Title
+ Sound volume
+ Type
+ Slider
+
+
+ Title
+ Whitelist
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ uselocWhitelist
+ Title
+ Allow embedded content on locations          Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+ www.example.com, www.example2.com
+ Key
+ locwhitelist
+ Title
+ matching
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ locblacklist
+ Title
+ not matching
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ usesrcWhitelist
+ Title
+ Allow embedded content from sources        Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ srcwhitelist
+ Title
+ matching
+ Type
+ TextField
+
+
+ DefaultValue
+
+ Key
+ srcblacklist
+ Title
+ not matching
+ Type
+ TextField
+
+
+ Title
+ Invisible elements
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ loadInvisible
+ Title
+ Allow elements to load if                              Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+ 1
+ Key
+ maxinvdim
+ Title
+ size is at most
+ Titles
+
+ 1 x 1 px
+ 2 x 2 px
+ 4 x 4 px
+ 8 x 8 px
+
+ Type
+ PopUpButton
+ Values
+
+ 1
+ 2
+ 4
+ 8
+
+
+
+ Title
+ Contextual Menu Items
+ Type
+ Group
+
+
+ DefaultValue
+
+ Key
+ useWLcontext
+ Title
+ Add to Whitelist                                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useLAcontext
+ Title
+ Load All Plugins                                            Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useVScontext
+ Title
+ View on Site                                                  Â
+ Type
+ CheckBox
+
+
+ DefaultValue
+
+ Key
+ useQTcontext
+ Title
+ View in QuickTime Player                              Â
+ Type
+ CheckBox
+
+
+ Type
+ Separator
+
+
+ DefaultValue
+ textonly
+ Key
+ sifrReplacement
+ Title
+ sIFR Text
+ Titles
+
+ Show text only
+ Treat as regular Flash
+ Load automatically
+
+ Type
+ PopUpButton
+ Values
+
+ textonly
+ normal
+ autoload
+
+
+
+ DefaultValue
+ 1
+ Key
+ opacity
+ MaximumValue
+ 1
+ Secure
+
+ StepValue
+ 0.01
+ Title
+ Opacity
+ Type
+ Slider
+
+
+ DefaultValue
+
+ Key
+ debug
+
diff --git a/ClickToPlugin.safariextension/functions.js b/ClickToPlugin.safariextension/functions.js
index 3b440fac..ad40eb3a 100644
--- a/ClickToPlugin.safariextension/functions.js
+++ b/ClickToPlugin.safariextension/functions.js
@@ -1,91 +1,63 @@
-function getSrcOf(element) {
+function getInfo(element, url) {
+ // gathers attributes of the element that might be needed later on
+ // Done by a single function so that we only loop once through the children
+ var info = new Object();
var tmpAnchor = document.createElement("a");
switch (element.tag) {
case "embed":
+ if(element.hasAttribute("qtsrc")) {
+ tmpAnchor.href = element.getAttribute("qtsrc");
+ info.src = tmpAnchor.href;
+ }
+ if(element.hasAttribute("href")) {
+ tmpAnchor.href = element.getAttribute("href");
+ info.href = tmpAnchor.href;
+ }
+ if(element.hasAttribute("target")) {
+ info.target = element.getAttribute("target");
+ }
if(element.hasAttribute("previewimage")) {
tmpAnchor.href = element.getAttribute("previewimage");
- element.image = tmpAnchor.href;
+ info.image = tmpAnchor.href;
}
- if(element.src) tmpAnchor.href = element.src;
- if(element.hasAttribute("qtsrc")) tmpAnchor.href = element.getAttribute("qtsrc");
- element.presource = tmpAnchor.href;
- if(element.hasAttribute("target")) element.otherInfo.target = element.getAttribute("target");
- if(element.hasAttribute("href")) {
- tmpAnchor.href = element.getAttribute("href");
- } else {
- delete element.presource;
- if(!element.src) return "";
- }
- return tmpAnchor.href;
break;
case "object":
- // NOTE: For silverlight objects element.data is used for something else than the source
- // and a param named 'source' is used for the source. So we look for that before
- // using element.data
var paramElements = element.getElementsByTagName("param");
- var srcParam = null; var qtsrcParam = null;
for (i = 0; i < paramElements.length; i++) {
- if(!paramElements[i].hasAttribute("value")) continue;
+ if(!paramElements[i].hasAttribute("value")) continue;
var paramName = paramElements[i].getAttribute("name").toLowerCase(); // name attribute is mandatory!
- // this is a bit shaky...
- // maybe should check first for mimetype and then let getSrcOf depend on type
- // eg source for silverlight; src for flash, qt, realplayer; filename for wm...
- // this would require 2 successive canLoads? or just use the type attribute??
- // it seems to always be specified for SL, but not QT (uses classid instead)
- // damn... maybe better to pass the whole HTMLToString(element) to the global page after all?
- if(paramName == "previewimage") {
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.image = tmpAnchor2.href;
- } else if(paramName == "src") {
- srcParam = i;
- if(!element.presource) {
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.presource = tmpAnchor2.href;
- }
- //element.otherInfo.src = paramElements[i].getAttribute("value");
- } else if (paramName == "qtsrc") {
- qtsrcParam = i;
- var tmpAnchor2 = document.createElement("a");
- tmpAnchor2.href = paramElements[i].getAttribute("value");
- element.presource = tmpAnchor2.href;
- //element.otherInfo.qtsrc = paramElements[i].getAttribute("value");
- } else if (paramName == "target") element.otherInfo.target = paramElements[i].getAttribute("value");
- else if(paramName == "movie" || paramName == "source" || paramName == "href" || paramName == "filename") { //|| paramName == "url") { // for oleobject, not supported on Safari (what about the Win version?)
- tmpAnchor.href = paramElements[i].getAttribute("value");
+ switch(paramName) {
+ case "source": // Silverlight true source
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.src = tmpAnchor.href;
+ break;
+ case "qtsrc": // QuickTime true source
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.src = tmpAnchor.href;
+ break;
+ case "href": // QuickTime
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.href = tmpAnchor.href;
+ break;
+ case "target": // QuickTime
+ info.target = paramElements[i].getAttribute("value");
+ break;
+ case "previewimage": // DivX
+ tmpAnchor.href = paramElements[i].getAttribute("value");
+ info.image = tmpAnchor.href;
+ break;
}
}
- if(tmpAnchor.href) return tmpAnchor.href;
- if(qtsrcParam != null) {
- element.presource = null;
- tmpAnchor.href = paramElements[qtsrcParam].getAttribute("value");
- return tmpAnchor.href;
- } else if(srcParam != null) {
- element.presource = null;
- tmpAnchor.href = paramElements[srcParam].getAttribute("value");
- return tmpAnchor.href;
- }
- if(element.data) {
- tmpAnchor.href = element.data;
- return tmpAnchor.href;
- } else {
- var embedElements = element.getElementsByTagName("embed");
- if(embedElements.length == 0) return "";
- embedElements[0].tag = "embed";
- return getSrcOf(embedElements[0]);
- }
- return "";
- break;
- case "applet":
- if(element.code) {
- tmpAnchor.href = element.code;
- } else if(element.hasAttribute("archive")) {
- tmpAnchor.href = element.getAttribute("archive");
- } else return "";
- return tmpAnchor.href;
break;
}
+ if(!info.src) {
+ if(!url) info.src = "";
+ else {
+ tmpAnchor.href = url;
+ info.src = tmpAnchor.href;
+ }
+ }
+ return info;
}
function getParamsOf(element) {
@@ -132,7 +104,7 @@ function getTypeOf(element) {
var paramElements = element.getElementsByTagName("param");
for (i = 0; i < paramElements.length; i++) {
if(paramElements[i].getAttribute("name").toLowerCase() == "type") {
- return paramElements[i].getAttribute("value");
+ return paramElements[i].getAttribute("value");
}
}
var embedChildren = element.getElementsByTagName("embed");
diff --git a/ClickToPlugin.safariextension/global.html b/ClickToPlugin.safariextension/global.html
index 90e01f3e..034769de 100644
--- a/ClickToPlugin.safariextension/global.html
+++ b/ClickToPlugin.safariextension/global.html
@@ -1,9 +1,10 @@
-
- Global HTML
+
+ Global HTML
+
-
+
@@ -13,6 +14,6 @@
-
-
+
+
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/global.js b/ClickToPlugin.safariextension/global.js
index cd607e89..51c5f9e2 100644
--- a/ClickToPlugin.safariextension/global.js
+++ b/ClickToPlugin.safariextension/global.js
@@ -1,81 +1,19 @@
var CTP_instance = 0; // incremented by one whenever a ClickToPlugin instance with content is created
const killers = [new YouTubeKiller(), new VimeoKiller(), new DailymotionKiller(), new VeohKiller(), new JWKiller(), new SLKiller(), new QTKiller(), new WMKiller(), new DivXKiller()];
-function pluginName(plugin) {
- if(plugin.name == "Shockwave Flash") return "Flash";
- if(plugin.name == "Silverlight Plug-In") return "Silverlight";
- if(plugin.name.match("Java")) return "Java";
- if(plugin.name.match("QuickTime")) return "QuickTime";
- if(plugin.name.match("Flip4Mac")) return "WM";
- if(plugin.name == "iPhotoPhotocast") return "iPhoto";
- if(plugin.name == "Quartz Composer Plug-In") return "Quartz";
- if(plugin.name == "VideoLAN VLC Plug-in") return "VLC";
- if(plugin.name == "DivX Web Player") return "DivX";
- if(plugin.name == ("RealPlayer Plugin.plugin")) return "RealPlayer";
- return plugin.name;
- /*switch (plugin.name) {
- case "Flip4Mac Windows Media Web Plugin 2.3.4": return "WM";
- case "Flip4Mac Windows Media Plugin 2.3.4": return "WM";
- case "Silverlight Plug-In": return "Silverlight";
- case "Shockwave Flash": return "Flash";
- case "Switchable Java Plug-in for WebKit": return "Java";
- case "Java Plug-In 2 for NPAPI Browsers": return "Java";
- case "iPhotoPhotocast": return "iPhoto";
- case "QuickTime Plug-in 7.6.6": return "QuickTime";
- case "Quartz Composer Plug-In": return "Quartz";
- default: return plugin.name;
- }*/
-}
-
-/*
-LIST OF CLASSID (What is this stuff anyway?)
-QuickTime: 02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
-WMP 6: 22d6f312-b0f6-11d0-94ab-0080c74c7e95
-WMP >6: 6BF52A52-394A-11D3-B153-00C04F79FAA6
-Flash: d27cdb6e-ae6d-11cf-96b8-444553540000
-Real Player: CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA
-?? calendar: 8E27C92B-1264-101C-8A2F-040224009C02
-?? graphics: 369303C2-D7AC-11D0-89D5-00A0C90833E6
-?? slider: F08DF954-8592-11D1-B16A-00C0F0283628
-DivX: 67DABFBF-D0AB-41fa-9C46-CC0F21721616
-*/
-
-
-function getPluginForType(MIMEType) { // MIMEType is a string
- for(var i = 0; i < navigator.plugins.length; i++) {
- for(var j = 0; j < navigator.plugins[i].length; j++) {
- if(navigator.plugins[i][j].type == MIMEType) return navigator.plugins[i];
- }
- }
- return null;
-}
-
-function getPluginAndTypeForExt(ext) {
- var suffixes = null;
- for(var i = 0; i < navigator.plugins.length; i++) {
- for(var j = 0; j < navigator.plugins[i].length; j++) {
- suffixes = navigator.plugins[i][j].suffixes.split(",");
- for(var k = 0; k < suffixes.length; k++) {
- if(ext == suffixes[k]) return {"plugin": navigator.plugins[i], "type": navigator.plugins[i][j].type};
- }
- }
- }
- return {"plugin": null, "type": null};
-}
-
function blockOrAllow(data) { // returns null if element can be loaded, the name of the plugin otherwise
// no source and no type -> must allow, it's probably going to pass through here again after being modified by a script
if(!data.src && !data.type && !data.classid) return null;
// native Safari support
- var ext = extractExt(data.src); // used later as well
- if(data.type) {
- if(isNativeType(data.type)) return null;
- } else {
- if(isNativeExt(ext)) return null;
- }
-
+ var ext = extractExt(data.src); // used later as well
+ if(data.type) {
+ if(isNativeType(data.type)) return null;
+ } else {
+ if(isNativeExt(ext)) return null;
+ }
+
// try not to block objects created by other extensions
if(data.src.substring(0,19) == "safari-extension://") return null;
@@ -87,55 +25,55 @@ function blockOrAllow(data) { // returns null if element can be loaded, the name
}
// Deal with whitelisted content
- if(safari.extension.settings["uselocWhitelist"]) {
+ if(safari.extension.settings["uselocWhitelist"]) {
var locwhitelist = safari.extension.settings["locwhitelist"].replace(/\s+/g,"");
var locblacklist = safari.extension.settings["locblacklist"].replace(/\s+/g,"");
- if(locwhitelist) {
- locwhitelist = locwhitelist.split(/,(?![^\(]*\))/);
+ if(locwhitelist) {
+ locwhitelist = locwhitelist.split(/,(?![^\(]*\))/); // matches all , except those in parentheses (used in regexp)
if(matchList(locwhitelist, data.location)) return null;
- }
- if(locblacklist) {
- locblacklist = locblacklist.split(/,(?![^\(]*\))/);
- if(!matchList(locblacklist, data.location)) return null;
- }
+ }
+ if(locblacklist) {
+ locblacklist = locblacklist.split(/,(?![^\(]*\))/);
+ if(!matchList(locblacklist, data.location)) return null;
+ }
}
- if(safari.extension.settings["usesrcWhitelist"]) {
- var srcwhitelist = safari.extension.settings["srcwhitelist"].replace(/\s+/g,"");
+ if(safari.extension.settings["usesrcWhitelist"]) {
+ var srcwhitelist = safari.extension.settings["srcwhitelist"].replace(/\s+/g,"");
var srcblacklist = safari.extension.settings["srcblacklist"].replace(/\s+/g,"");
- if(srcwhitelist) {
- srcwhitelist = srcwhitelist.split(/,(?![^\(]*\))/);
+ if(srcwhitelist) {
+ srcwhitelist = srcwhitelist.split(/,(?![^\(]*\))/);
if(matchList(srcwhitelist, data.src)) return null;
- }
- if(locblacklist) {
- srcblacklist = srcblacklist.split(/,(?![^\(]*\))/);
- if(!matchList(srcblacklist, data.src)) return null;
- }
- }
-
+ }
+ if(locblacklist) {
+ srcblacklist = srcblacklist.split(/,(?![^\(]*\))/);
+ if(!matchList(srcblacklist, data.src)) return null;
+ }
+ }
+
// We use a 'soft' method to get the MIME type
// It is not necessarily correct, but always returns a MIME type handled by the correct plugin
// To get the correct MIME type an AJAX request would be needed, out of the question here!
var plugin = null;
- var MIMEType = data.type.replace(/\s+/g,"");
- var badgeLabel = "?";
- if(MIMEType) {
- badgeLabel = MIMEType.split(";")[0].split("/")[1]; // temporary unless no plugin can be found to play MIMEType
- plugin = getPluginForType(MIMEType);
- }
+ var MIMEType = data.type;
+ var pluginName = "?";
+ if(MIMEType) plugin = getPluginForType(MIMEType);
if(!plugin && data.src) {
var x = getPluginAndTypeForExt(ext);
plugin = x.plugin;
MIMEType = x.type;
}
- if(plugin) badgeLabel = pluginName(plugin);
+ if(plugin) pluginName = getPluginNameFromPlugin(plugin);
+ else if(MIMEType) pluginName = getPluginNameFromType(MIMEType);
+ else if(data.classid) pluginName = getPluginNameFromClassid(data.classid.replace("clsid:", ""));
- if(safari.extension.settings["allowQT"] && badgeLabel == "QuickTime") return null;
+ if(safari.extension.settings["allowQT"] && pluginName == "QuickTime") return null;
+ // Use greenlist/redlist
if(MIMEType) {
if(safari.extension.settings["block"] == "useRedlist") {
var redlist = safari.extension.settings["redlist"].replace(/\s+/g,"");
if(!redlist) return null;
- redlist = redlist.split(/,(?![^\(]*\))/); // matches all , except those in parentheses (used in regexp)
+ redlist = redlist.split(/,(?![^\(]*\))/);
if(!matchList(redlist, MIMEType, true)) return null;
} else if(safari.extension.settings["block"] == "useGreenlist") {
var greenlist = safari.extension.settings["greenlist"].replace(/\s+/g,"");
@@ -145,18 +83,16 @@ function blockOrAllow(data) { // returns null if element can be loaded, the name
}
}
}
- // At this point we know we'll have to block the element
+ // At this point we know we should block the element
- for(var key in data.otherInfo) {
- if(key == "target" && data.otherInfo.target == "quicktimeplayer") {
- // A quicktime object that would launch QTP
- if(confirm("A QuickTime object would like to play\n\n" + data.src + "\n\nin QuickTime Player. Do you want to allow it?")) {
- return null;
- }
+ // Exception: ask the user what to do if a QT object would launch QTP
+ if(data.launchInQTP) {
+ if(confirm("A QuickTime object would like to play\n\n" + data.launchInQTP + "\n\nin QuickTime Player. Do you want to allow it?")) {
+ return null;
}
}
- return badgeLabel;
+ return pluginName;
}
@@ -174,11 +110,6 @@ function respondToMessage(event) {
case "killPlugin":
killPlugin(event.message);
break;
- //case "downloadMedia":
- //var newTab = safari.application.activeBrowserWindow.openTab("foreground");
- //newTab.url = event.message + ".zip";
- //prompt("Copy the following URL and paste it into the Downloads window.", event.message);
- //break;
}
}
@@ -197,73 +128,60 @@ function respondToCanLoad(message) {
}
}
-function printMedia(mediaType) {
- switch(mediaType) {
- case "video": return "Video";
- case "audio": return "Audio";
- default: return "Video";
- }
-}
-
-function printPlugin(pluginName) {
- if(/[A-Z]/.test(pluginName)) return pluginName;
- return "Plugin";
-}
-
function handleContextMenu(event) {
- if(!event.userInfo.CTPInstance) {
- if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 0) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
+ if(!event.userInfo.instance) {
+ if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 0) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
if(safari.extension.settings["useWLcontext"]) {
event.contextMenu.appendContextMenuItem("locwhitelist", "Add Location to Whitelist\u2026");
}
return;
}
+ var pluginName = /[A-Z]/.test(event.userInfo.plugin) ? event.userInfo.plugin : "Plugin";
if(event.userInfo.isH264) {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",reloadPlugin", "Reload in " + event.userInfo.plugin);
- if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",qtp", "View in QuickTime Player");
- if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "View on " + event.userInfo.siteInfo.name);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",reload", "Reload in " + pluginName);
+ if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",qtp", "View in QuickTime Player");
+ if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "View on " + event.userInfo.siteInfo.name);
} else {
if(event.userInfo.hasH264) {
- //event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",video", "Load " + printMedia(event.userInfo.mediaType));
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",plugin", "Load " + printPlugin(event.userInfo.plugin));
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",remove", "Hide " + printPlugin(event.userInfo.plugin));
- //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
- if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",qtp", "View in QuickTime Player");
- if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "View on " + event.userInfo.siteInfo.name);
- } else {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",remove", "Hide " + printPlugin(event.userInfo.plugin));
- //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
- }
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",plugin", "Load " + pluginName);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",remove", "Hide " + pluginName);
+ //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
+ if(safari.extension.settings["useQTcontext"]) event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",qtp", "View in QuickTime Player");
+ if(event.userInfo.siteInfo && safari.extension.settings["useVScontext"]) event.contextMenu.appendContextMenuItem("gotosite", "View on " + event.userInfo.siteInfo.name);
+ } else {
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",remove", "Hide " + pluginName);
+ //if(safari.extension.settings["useLAcontext"] && event.userInfo.blocked > 1) event.contextMenu.appendContextMenuItem("loadall", "Load All Plugins (" + event.userInfo.blocked + ")");
+ }
if(safari.extension.settings["useWLcontext"]) {
event.contextMenu.appendContextMenuItem("srcwhitelist", "Add Source to Whitelist\u2026");
}
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
- event.contextMenu.appendContextMenuItem(event.userInfo.CTPInstance + "," + event.userInfo.elementID + ",show", "Show Element " + event.userInfo.CTPInstance + "." + event.userInfo.elementID);
+ event.contextMenu.appendContextMenuItem(event.userInfo.instance + "," + event.userInfo.elementID + ",show", "Show Element " + event.userInfo.instance + "." + event.userInfo.elementID);
}
//END DEBUG
}
}
function doCommand(event) {
- switch(event.command) {
- case "gotosite":
- var newTab = safari.application.activeBrowserWindow.openTab("foreground");
- newTab.url = event.userInfo.siteInfo.url;
- break;
- case "locwhitelist":
- handleWhitelisting(true, event.userInfo.location);
- break;
- case "srcwhitelist":
- handleWhitelisting(false, event.userInfo.src);
- break;
- case "loadall":
- safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadAll", "");
- break;
- default:
- safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadContent", event.command);
- break;
- }
+ switch(event.command) {
+ case "gotosite":
+ var newTab = safari.application.activeBrowserWindow.openTab("foreground");
+ newTab.url = event.userInfo.siteInfo.url;
+ break;
+ case "locwhitelist":
+ handleWhitelisting(true, event.userInfo.location);
+ break;
+ case "srcwhitelist":
+ handleWhitelisting(false, event.userInfo.src);
+ break;
+ case "loadall":
+ safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadAll", "");
+ break;
+ default:
+ safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("loadContent", event.command);
+ break;
+ }
}
function handleWhitelisting (type, url) {
@@ -281,25 +199,23 @@ function handleWhitelisting (type, url) {
function handleChangeOfSettings(event) {
if(event.key == "volume") {
- // send to all pages or just the active one??
safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("updateVolume", event.newValue);
} else if(event.key = "opacity") {
- dispatchMessageToAllPages("updateOpacity", event.newValue);
- }
+ dispatchMessageToAllPages("updateOpacity", event.newValue);
+ }
}
-function getSettings() {
- var settings = new Object();
- settings.useH264 = safari.extension.settings["useH264"];
- settings.usePlaylists = safari.extension.settings["usePlaylists"];
- //settings.maxres = safari.extension.settings["maxresolution"];
+function getSettings() { // return the settings injected scripts need
+ var settings = new Object();
+ settings.useH264 = safari.extension.settings["useH264"];
+ settings.usePlaylists = safari.extension.settings["usePlaylists"];
settings.H264autoload = safari.extension.settings["H264autoload"];
settings.H264behavior = safari.extension.settings["H264behavior"];
settings.volume = safari.extension.settings["volume"];
settings.sifrReplacement = safari.extension.settings["sifrReplacement"];
- settings.opacity = safari.extension.settings["opacity"];
+ settings.opacity = safari.extension.settings["opacity"];
settings.debug = safari.extension.settings["debug"];
- return settings;
+ return settings;
}
function killPlugin(data) {
@@ -307,21 +223,21 @@ function killPlugin(data) {
if(killerID == null) return;
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
- if(!confirm("Killer '" + killers[killerID].name + "' thinks it might be able to process target " + data.CTPInstance +"."+ data.elementID + ".")) return;
+ if(!confirm("Killer '" + killers[killerID].name + "' thinks it might be able to process target " + data.instance +"."+ data.elementID + ".")) return;
}
// END DEBUG
var callback = function(mediaData) {
mediaData.elementID = data.elementID;
- mediaData.CTPInstance = data.CTPInstance;
+ mediaData.instance = data.instance;
// the following messsage must be dispatched to all pages to make sure that
- // pages or tabs loading in the background get their videoData
+ // pages or tabs loading in the background get their mediaData
dispatchMessageToAllPages("mediaData", mediaData);
};
killers[killerID].processElement(data, callback);
}
function findKillerFor(data) {
- for (i = 0; i < killers.length; i++) {
+ for (i = 0; i < killers.length; i++) {
if(killers[i].canKill(data)) return i;
}
return null;
diff --git a/ClickToPlugin.safariextension/globalfunctions.js b/ClickToPlugin.safariextension/globalfunctions.js
index 1bc5ad5d..01a68cab 100644
--- a/ClickToPlugin.safariextension/globalfunctions.js
+++ b/ClickToPlugin.safariextension/globalfunctions.js
@@ -1,40 +1,37 @@
-function makeAbsoluteURI(url) {
+function makeAbsoluteURI(url, location) {
if(!url) return "";
- var tmpAnchor = document.createElement("a");
- tmpAnchor.href = url;
- return tmpAnchor.href;
+ if(/\/\//.test(url)) return url; // already absolute
+ location = location.replace(/\/[^\/]*$/, "/");
+ if(url[0]=="/") url = url.substring(1);
+ if(url[0]=="/") {
+ url = url.substring(1);
+ location = location.replace(/\/\/.*$/,"//");
+ }
+ return location + url;
}
-// This function returns false if the url shoudl not be proposed
-// as a video replacement, according to the user's settings
-/*function getMediaTypeOf(url) {
- if (url.match(/(.mp4)|(.mpe{0,1}g)/i) || (safari.extension.settings["QTbehavior"] > 1 && url.match(/(.flv)/i))) return "video";
- if(url.match(/(.mp3)|(.wav)|(.aiff)|(.aac)/i) || (safari.extension.settings["QTbehavior"] > 1 && url.match(/.wma/i))) return "audio";
- return false;
-}*/
-
function getFlashVariable(flashvars, key) {
- if (!flashvars) return "";
- var flashVarsArray = flashvars.split("&");
- for (var i = 0; i < flashVarsArray.length; i++) {
- var keyValuePair = flashVarsArray[i].split("=");
- if (keyValuePair[0] == key) {
- return keyValuePair[1];
- }
- }
- return "";
+ if (!flashvars) return "";
+ var flashVarsArray = flashvars.split("&");
+ for (var i = 0; i < flashVarsArray.length; i++) {
+ var keyValuePair = flashVarsArray[i].split("=");
+ if (keyValuePair[0] == key) {
+ return keyValuePair[1];
+ }
+ }
+ return "";
}
function getSLVariable(initParams, key) {
- if (!initParams) return "";
- var initParamsArray = initParams.split(",");
- for (var i = 0; i < initParamsArray.length; i++) {
- var keyValuePair = initParamsArray[i].split("=");
- if (keyValuePair[0].toLowerCase() == key) {
- return keyValuePair[1];
- }
- }
- return "";
+ if (!initParams) return "";
+ var initParamsArray = initParams.split(",");
+ for (var i = 0; i < initParamsArray.length; i++) {
+ var keyValuePair = initParamsArray[i].split("=");
+ if (keyValuePair[0].toLowerCase() == key) {
+ return keyValuePair[1];
+ }
+ }
+ return "";
}
function getMIMEType(resourceURL, handleMIMEType) {
@@ -85,10 +82,10 @@ function matchList(list, string, lowerCase) { // set lowerCase to true if 'strin
// if s is enclosed in parenthesis, interpret as regexp
if (s[0] == "(" && s[s.length - 1] == ")") {
try{
- s = new RegExp(s, (lowerCase ? "i" : ""));
- } catch (err) { // invalid regexp, just ignore
- continue;
- }
+ s = new RegExp(s, (lowerCase ? "i" : ""));
+ } catch (err) { // invalid regexp, just ignore
+ continue;
+ }
} else if(lowerCase) {
s = s.toLowerCase();
}
@@ -97,4 +94,80 @@ function matchList(list, string, lowerCase) { // set lowerCase to true if 'strin
}
}
return false;
-}
\ No newline at end of file
+}
+
+/***********************
+Plugin detection methods
+***********************/
+
+function getPluginForType(MIMEType) { // MIMEType is a string
+ for(var i = 0; i < navigator.plugins.length; i++) {
+ for(var j = 0; j < navigator.plugins[i].length; j++) {
+ if(navigator.plugins[i][j].type == MIMEType) return navigator.plugins[i];
+ }
+ }
+ return null;
+}
+
+function getPluginAndTypeForExt(ext) {
+ var suffixes = null;
+ for(var i = 0; i < navigator.plugins.length; i++) {
+ for(var j = 0; j < navigator.plugins[i].length; j++) {
+ suffixes = navigator.plugins[i][j].suffixes.split(",");
+ for(var k = 0; k < suffixes.length; k++) {
+ if(ext == suffixes[k]) return {"plugin": navigator.plugins[i], "type": navigator.plugins[i][j].type};
+ }
+ }
+ }
+ return {"plugin": null, "type": null};
+}
+
+function getPluginNameFromPlugin(plugin) {
+ if(plugin.name == "Shockwave Flash") return "Flash";
+ if(plugin.name == "Silverlight Plug-In") return "Silverlight";
+ if(plugin.name.match("Java")) return "Java";
+ if(plugin.name.match("QuickTime")) return "QuickTime";
+ if(plugin.name.match("Flip4Mac")) return "WM";
+ if(plugin.name == "iPhotoPhotocast") return "iPhoto";
+ if(plugin.name == "Quartz Composer Plug-In") return "Quartz";
+ if(plugin.name == "VideoLAN VLC Plug-in") return "VLC";
+ if(plugin.name == "DivX Web Player") return "DivX";
+ if(plugin.name == ("RealPlayer Plugin.plugin")) return "Real";
+ return plugin.name;
+}
+
+function getPluginNameFromType(type) { // only used if no installed plugin is found
+ if(/shockwave-flash/.test(type) || /futuresplash/.test(type)) return "Flash";
+ if(/silverlight/.test(type)) return "Silverlight";
+ if(/x-java/.test(type)) return "Java";
+ if(/x-ms/.test(type)) return "WM";
+ if(/x-pn/.test(type)) return "Real";
+ type = type.split(";")[0];
+ if(type == "video/divx") return "DivX";
+ return type.split("/")[1];
+}
+
+function getPluginNameFromClassid(classid) { // last resort
+ switch(classid.toLowerCase()) {
+ case "d27cdb6e-ae6d-11cf-96b8-444553540000": return "Flash";
+ case "22d6f312-b0f6-11d0-94ab-0080c74c7e95": return "WM";
+ case "6bf52a52-394a-11d3-b153-00c04f79faa6": return "WM";
+ case "02bf25d5-8c17-4b23-bc80-d3488abddc6b": return "QuickTime";
+ case "cfcdaa03-8be4-11cf-b84b-0020afbbccfa": return "Real";
+ case "67dabfbf-d0ab-41fa-9c46-cc0f21721616": return "DivX";
+ default: return "?";
+ }
+}
+
+/*
+LIST OF CLASSIDs
+QuickTime: 02BF25D5-8C17-4B23-BC80-D3488ABDDC6B
+WMP 6: 22d6f312-b0f6-11d0-94ab-0080c74c7e95
+WMP >6: 6BF52A52-394A-11D3-B153-00C04F79FAA6
+Flash: d27cdb6e-ae6d-11cf-96b8-444553540000
+Real Player: CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA
+?? calendar: 8E27C92B-1264-101C-8A2F-040224009C02
+?? graphics: 369303C2-D7AC-11D0-89D5-00A0C90833E6
+?? slider: F08DF954-8592-11D1-B16A-00C0F0283628
+DivX: 67DABFBF-D0AB-41fa-9C46-CC0F21721616
+*/
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/DailymotionKiller.js b/ClickToPlugin.safariextension/killers/DailymotionKiller.js
index cee66d97..03fc92ef 100644
--- a/ClickToPlugin.safariextension/killers/DailymotionKiller.js
+++ b/ClickToPlugin.safariextension/killers/DailymotionKiller.js
@@ -3,7 +3,7 @@ function DailymotionKiller() {
}
DailymotionKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (data.src.match("/dmplayerv4/") || data.src.match("www.dailymotion.com"));
};
@@ -23,7 +23,7 @@ DailymotionKiller.prototype.processElement = function(data, callback) {
DailymotionKiller.prototype.processElementFromSequence = function(sequence, callback) {
var posterURL = null;
- var videoURL = null;
+ var videoURL = null;
var badgeLabel = "H.264";
if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV) {
var URLindex = sequence.indexOf("sdURL");
@@ -33,7 +33,7 @@ DailymotionKiller.prototype.processElementFromSequence = function(sequence, call
videoURL = s.replace(/\\\//g,"/");
}
}
- var URLindex = sequence.indexOf("hqURL"); // there's also an sdURL but it is an FLV video
+ var URLindex = sequence.indexOf("hqURL");
if (URLindex != -1) {
var s = sequence.substring(URLindex+8);
s = s.substring(0,s.indexOf("\""));
@@ -48,12 +48,11 @@ DailymotionKiller.prototype.processElementFromSequence = function(sequence, call
videoURL = s.replace(/\\\//g,"/");
}
}
- URLindex = sequence.indexOf("videoPreviewURL");
+ URLindex = sequence.indexOf("videoPreviewURL");
if (URLindex != -1) {
var s = sequence.substring(URLindex+18);
s = s.substring(0,s.indexOf("\""));
posterURL = s.replace(/\\\//g,"/");
- //alert(posterURL);
}
var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
@@ -69,10 +68,10 @@ DailymotionKiller.prototype.processElementFromVideoID = function(videoID, callba
req.open("GET", "http://www.dailymotion.com/video/" + videoID, true);
req.onload = function() {
var sequence = req.responseText.match(toMatch)[0];
- var callbackForEmbed = function(videoData) {
- videoData.playlist[0].siteInfo = {"name": "Dailymotion", "url": "http://www.dailymotion.com/video/" + videoID};
- callback(videoData);
- }
+ var callbackForEmbed = function(videoData) {
+ videoData.playlist[0].siteInfo = {"name": "Dailymotion", "url": "http://www.dailymotion.com/video/" + videoID};
+ callback(videoData);
+ }
if(sequence) {_this.processElementFromSequence(unescape(sequence), callbackForEmbed);}
};
// BEGIN DEBUG
diff --git a/ClickToPlugin.safariextension/killers/DivXKiller.js b/ClickToPlugin.safariextension/killers/DivXKiller.js
index 80232ccc..6a4185c8 100644
--- a/ClickToPlugin.safariextension/killers/DivXKiller.js
+++ b/ClickToPlugin.safariextension/killers/DivXKiller.js
@@ -1,5 +1,5 @@
function DivXKiller() {
- this.name = "DivXKiller";
+ this.name = "DivXKiller";
}
@@ -9,9 +9,9 @@ DivXKiller.prototype.canKill = function(data) {
DivXKiller.prototype.processElement = function(data, callback) {
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "posterURL": data.image, "mediaURL": data.src}],
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/JWKiller.js b/ClickToPlugin.safariextension/killers/JWKiller.js
index d380792d..b6e0fe9e 100644
--- a/ClickToPlugin.safariextension/killers/JWKiller.js
+++ b/ClickToPlugin.safariextension/killers/JWKiller.js
@@ -1,93 +1,96 @@
function JWKiller() {
- this.name = "JWKiller";
+ this.name = "JWKiller";
}
JWKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
- return (getFlashVariable(data.params, "file") || getFlashVariable(data.params, "playlistfile"));
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ // streams are not supported
+ return (!getFlashVariable(data.params, "streamer") && (getFlashVariable(data.params, "file") || getFlashVariable(data.params, "playlistfile")));
};
JWKiller.prototype.processElement = function(data, callback) {
- var playlistURL = getFlashVariable(data.params, "playlistfile");
+ var playlistURL = getFlashVariable(data.params, "playlistfile");
var sourceURL = getFlashVariable(data.params, "file");
- var posterURL = getFlashVariable(data.params, "image");
-
- if(safari.extension.settings["usePlaylists"]) {
- if(playlistURL) {
- this.processElementFromPlaylist(playlistURL, getFlashVariable(data.params, "item"), posterURL, callback);
- return;
- }
- if(sourceURL.match(".xml")) {
- this.processElementFromPlaylist(sourceURL, getFlashVariable(data.params, "item"), posterURL, callback);
- return;
- }
- }
+ var posterURL = getFlashVariable(data.params, "image");
- var sourceURL2 = getFlashVariable(data.params, "real_file");
- if(sourceURL2) sourceURL = sourceURL2;
-
- var mediaType = checkSrc(sourceURL);
- if(!mediaType) return;
+ if(safari.extension.settings["usePlaylists"]) {
+ if(playlistURL) {
+ this.processElementFromPlaylist(playlistURL, data.location, getFlashVariable(data.params, "item"), posterURL, callback);
+ return;
+ }
+ if(/.xml($|\?)/i.test(sourceURL)) {
+ this.processElementFromPlaylist(sourceURL, data.location, getFlashVariable(data.params, "item"), posterURL, callback);
+ return;
+ }
+ }
+
+ var sourceURL2 = getFlashVariable(data.params, "real_file");
+ if(sourceURL2) sourceURL = sourceURL2;
+
+ var mediaType = checkSrc(sourceURL);
+ if(!mediaType) return;
- var mediaData = {
- "playlist": [{"mediaType": mediaType, "posterURL": makeAbsoluteURI(posterURL), "mediaURL": makeAbsoluteURI(sourceURL)}],
+ var mediaData = {
+ "playlist": [{"mediaType": mediaType, "posterURL": makeAbsoluteURI(posterURL, data.location), "mediaURL": makeAbsoluteURI(sourceURL, data.location)}],
"badgeLabel": (mediaType == "video") ? "Video" : "Audio"
};
- callback(mediaData);
+ callback(mediaData);
};
// put a more complete function in globalfunctions.js
function checkSrc(sourceURL) {
- if (sourceURL.match(/(.mp4)|(.mpe{0,1}g)/i)) return "video";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && sourceURL.match(/.flv/i)) return "video";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/(.wmv)|(.asf)/i)) return "video";
- if(sourceURL.match(/(.mp3)|(.wav)|(.aiff)|(.aac)/i)) return "audio";
- if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wma/i)) return "audio";
- return false;
+ if (sourceURL.match(/.mp4|.mpe{0,1}g|.mov/i)) return "video";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && sourceURL.match(/.flv/i)) return "video";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wmv|.asf/i)) return "video";
+ if(sourceURL.match(/.mp3|.wav|.aiff|.aac/i)) return "audio";
+ if(safari.extension.settings["QTbehavior"] > 1 && canPlayWM && sourceURL.match(/.wma/i)) return "audio";
+ return false;
};
-JWKiller.prototype.processElementFromPlaylist = function(playlistURL, track, posterURL, callback) {
- var req = new XMLHttpRequest();
- var startTrack = track;
- playlistURL = makeAbsoluteURI(playlistURL);
+JWKiller.prototype.processElementFromPlaylist = function(playlistURL, location, track, posterURL, callback) {
+ var req = new XMLHttpRequest();
+ var startTrack = track;
+ playlistURL = makeAbsoluteURI(playlistURL, location);
req.open('GET', playlistURL, true);
req.onload = function() {
+ var isAudio = true;
var x = req.responseXML.getElementsByTagName("track");
- if(!(track >= 0 && track < x.length)) track = 0;
- var playlist = new Array();
- var url = "";
- var list = null;
- var title = "";
- var poster = null;
- for(var i = 0; i < x.length; i++) {
- list = x[(i + track) % x.length].getElementsByTagName("location");
- if(list.length > 0) url = list[0].firstChild.nodeValue;
- else url = "";
- list = x[(i + track) % x.length].getElementsByTagName("title");
- if(list.length > 0) title = list[0].firstChild.nodeValue;
- else title = "";
- list = x[(i + track) % x.length].getElementsByTagName("image");
- if(list.length > 0) poster = list[0].firstChild.nodeValue;
- else poster = "";
- var mediaType = checkSrc(url);
- if(mediaType) {
- playlist.push({"title": title, "mediaType": mediaType, "posterURL": makeAbsoluteURI(poster), "mediaURL": makeAbsoluteURI(url)});
- if(mediaType == "video") isAudio = false;
- } else {
- if(i >= x.length - track) --startTrack;
- }
- }
- if(playlist.length == 0) return;
- if(!playlist[0].posterURL) playlist[0].posterURL = makeAbsoluteURI(posterURL);
+ if(!(track >= 0 && track < x.length)) track = 0;
+ var playlist = new Array();
+ var url = "";
+ var list = null;
+ var title = "";
+ var poster = null;
+ for(var i = 0; i < x.length; i++) {
+ list = x[(i + track) % x.length].getElementsByTagName("location");
+ if(list.length > 0) url = list[0].firstChild.nodeValue;
+ else if(i == 0) return;
+ else continue;
+ list = x[(i + track) % x.length].getElementsByTagName("title");
+ if(list.length > 0) title = list[0].firstChild.nodeValue;
+ else title = "";
+ list = x[(i + track) % x.length].getElementsByTagName("image");
+ if(list.length > 0) poster = list[0].firstChild.nodeValue;
+ else poster = "";
+ var mediaType = checkSrc(url);
+ if(mediaType) {
+ playlist.push({"title": title, "mediaType": mediaType, "posterURL": makeAbsoluteURI(poster, location), "mediaURL": makeAbsoluteURI(url, location)});
+ if(mediaType == "video") isAudio = false;
+ } else {
+ if(i == 0) return;
+ if(i >= x.length - track) --startTrack;
+ }
+ }
+ if(!playlist[0].posterURL) playlist[0].posterURL = makeAbsoluteURI(posterURL, location);
var mediaData = {
- "startTrack": startTrack,
- "isAudio": isAudio,
- "playlist": playlist,
- "badgeLabel": isAudio ? "Audio" : "Video"
- };
- callback(mediaData);
+ "startTrack": startTrack,
+ "isAudio": isAudio,
+ "playlist": playlist,
+ "badgeLabel": playlist[0].mediaType == "audio" ? "Audio" : "Video"
+ };
+ callback(mediaData);
};
- // BEGIN DEBUG
+ // BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + playlistURL)) return;
}
diff --git a/ClickToPlugin.safariextension/killers/QTKiller.js b/ClickToPlugin.safariextension/killers/QTKiller.js
index f7e83ad5..297914bf 100644
--- a/ClickToPlugin.safariextension/killers/QTKiller.js
+++ b/ClickToPlugin.safariextension/killers/QTKiller.js
@@ -1,5 +1,5 @@
function QTKiller() {
- this.name = "QTKiller";
+ this.name = "QTKiller";
}
@@ -13,11 +13,11 @@ QTKiller.prototype.processElement = function(data, callback) {
var playlist = null;
if(data.presrc) playlist = [{"mediaType": "video", "mediaURL": data.presrc}, {"mediaType": "video", "mediaURL": data.src}];
else playlist = [{"mediaType": "video", "mediaURL": data.src}];
- var videoData = {
- "noPlaylistControls": true,
+ var videoData = {
+ "noPlaylistControls": true,
"playlist": playlist,
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/SLKiller.js b/ClickToPlugin.safariextension/killers/SLKiller.js
index 958b0d74..1b1538b0 100644
--- a/ClickToPlugin.safariextension/killers/SLKiller.js
+++ b/ClickToPlugin.safariextension/killers/SLKiller.js
@@ -1,5 +1,5 @@
function SLKiller() {
- this.name = "SLKiller";
+ this.name = "SLKiller";
}
@@ -14,9 +14,9 @@ SLKiller.prototype.processElement = function(data, callback) {
if(!videoURL.match(/\.((wm(?!x))|(asf))/)) return;
var posterURL = getSLVariable(data.params, "thumbnail");
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": "Video"
}
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/VeohKiller.js b/ClickToPlugin.safariextension/killers/VeohKiller.js
index e2e4535a..72beda1c 100644
--- a/ClickToPlugin.safariextension/killers/VeohKiller.js
+++ b/ClickToPlugin.safariextension/killers/VeohKiller.js
@@ -1,39 +1,38 @@
function VeohKiller() {
- this.name = "VeohKiller";
+ this.name = "VeohKiller";
}
VeohKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (safari.extension.settings["QTbehavior"] > 1 && canPlayFLV && data.src.match("veoh.com/static/swf/webplayer"));
};
VeohKiller.prototype.processElement = function(data, callback) {
var videoID = null;
- var isEmbed = false;
+ var isEmbed = false;
if(data.params) videoID = getFlashVariable(data.params, "permalinkId");
else { // embedded video
- isEmbed = true;
+ isEmbed = true;
var matches = data.src.match(/permalinkId=([^&]*)(?=&)/);
if(matches) videoID = matches[0].replace("permalinkId=","");
}
var posterURL = null;
var videoURL = null;
- var request = new XMLHttpRequest();
- request.open('GET', "http://www.veoh.com/rest/video/" + videoID + "/details", true);
+ var request = new XMLHttpRequest();
+ request.open('GET', "http://www.veoh.com/rest/video/" + videoID + "/details", true);
request.onload = function() {
var element = request.responseXML.getElementsByTagName("video")[0];
if(element) {
videoURL = element.getAttribute("fullPreviewHashPath"); //"fullPreviewHashLowPath"
posterURL = element.getAttribute("fullHighResImagePath");
- //alert(element.getAttribute("previewHash") + "\n" + element.getAttribute("fullPreviewHashPath") + "\n\n" + element.getAttribute("previewHashLow") + "\n" + element.getAttribute("fullPreviewHashLowPath"));
}
var videoData = {
"playlist": [{"mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": "Video" // There's no HD on Veoh, as far as I see, despite what they say. It's < 360p! Am I doing something wrong??
}
- if(isEmbed) videoData.playlist[0].siteInfo = {"name": "Veoh", "url": "http://www.veoh.com/browse/videos#watch%3D" + videoID};
+ if(isEmbed) videoData.playlist[0].siteInfo = {"name": "Veoh", "url": "http://www.veoh.com/browse/videos#watch%3D" + videoID};
callback(videoData);
};
// BEGIN DEBUG
@@ -41,5 +40,5 @@ VeohKiller.prototype.processElement = function(data, callback) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + "http://www.veoh.com/rest/video/" + videoID + "/details")) return;
}
// END DEBUG
- request.send(null);
+ request.send(null);
};
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/VimeoKiller.js b/ClickToPlugin.safariextension/killers/VimeoKiller.js
index 6a2e54ea..26f1c9d4 100644
--- a/ClickToPlugin.safariextension/killers/VimeoKiller.js
+++ b/ClickToPlugin.safariextension/killers/VimeoKiller.js
@@ -3,7 +3,7 @@ function VimeoKiller() {
}
VimeoKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return !!data.src.match("moogaloop");
};
@@ -17,40 +17,38 @@ VimeoKiller.prototype.processElement = function(data, callback) {
if(!videoID) return;
var posterURL = null;
- var videoURL = null;
+ var videoURL = null;
var badgeLabel = "H.264";
- var request = new XMLHttpRequest();
- request.open('GET', "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/", false);
- //alert("sending AJAX request...");
+ var req = new XMLHttpRequest();
+ // this request needs to be synchronous, otherwise Vimeo scripts cause errors
+ req.open('GET', "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/", false);
// BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send a synchronous AJAX request to:\n\n" + "http://www.vimeo.com/moogaloop/load/clip:" + videoID + "/")) return;
}
// END DEBUG
- request.send(null);
- //alert("request sent! Answer:\n\n" + request.responseText);
- var responseXML = new DOMParser().parseFromString(request.responseText,"text/xml");
+ req.send(null);
if (safari.extension.settings["maxresolution"] > 1) {
- if(responseXML.getElementsByTagName("isHD").length > 0) {
- if(responseXML.getElementsByTagName("isHD")[0].childNodes[0].nodeValue == "1") badgeLabel = "HD H.264";
+ if(req.responseXML.getElementsByTagName("isHD").length > 0) {
+ if(req.responseXML.getElementsByTagName("isHD")[0].childNodes[0].nodeValue == "1") badgeLabel = "HD H.264";
}
}
- if(responseXML.getElementsByTagName("request_signature").length > 0 && responseXML.getElementsByTagName("request_signature_expires").length > 0) {
- videoURL = "http://www.vimeo.com/moogaloop/play/clip:" + videoID + "/" + responseXML.getElementsByTagName("request_signature")[0].childNodes[0].nodeValue+ "/" + responseXML.getElementsByTagName("request_signature_expires")[0].childNodes[0].nodeValue+"/?q=" + ((badgeLabel == "H.264") ? "mobile" : "hd");
- }
- if(responseXML.getElementsByTagName("thumbnail").length > 0) {
- posterURL = responseXML.getElementsByTagName("thumbnail")[0].childNodes[0].nodeValue;
+ if(req.responseXML.getElementsByTagName("request_signature").length > 0 && req.responseXML.getElementsByTagName("request_signature_expires").length > 0) {
+ videoURL = "http://www.vimeo.com/moogaloop/play/clip:" + videoID + "/" + req.responseXML.getElementsByTagName("request_signature")[0].childNodes[0].nodeValue+ "/" + req.responseXML.getElementsByTagName("request_signature_expires")[0].childNodes[0].nodeValue+"/?q=" + ((badgeLabel == "H.264") ? "mobile" : "hd");
}
- var siteInfo = null;
- if(!data.location.match("vimeo.com/")) siteInfo = {"name": "Vimeo", "url": "http://vimeo.com/" + videoID};
+ if(req.responseXML.getElementsByTagName("thumbnail").length > 0) {
+ posterURL = req.responseXML.getElementsByTagName("thumbnail")[0].childNodes[0].nodeValue;
+ }
+ var siteInfo = null;
+ if(!data.location.match("vimeo.com/") || data.location == "http://vimeo.com/") siteInfo = {"name": "Vimeo", "url": "http://vimeo.com/" + videoID};
var videoData = {
"playlist": [{"siteInfo": siteInfo, "mediaType": "video", "posterURL": posterURL, "mediaURL": videoURL}],
"badgeLabel": badgeLabel
};
- // Some videos on Vimeo are FLV; need to check that this is not the case, cause Safari can't handle them
+ // Some videos on Vimeo are FLV; need to check that this is not the case if user doesn't want them
if(videoURL) {
if(safari.extension.settings["QTbehavior"] > 1 && canPlayFLV) {
callback(videoData);
@@ -63,7 +61,7 @@ VimeoKiller.prototype.processElement = function(data, callback) {
// BEGIN DEBUG
else if(safari.extension.settings["debug"]) {
alert("Video found by killer 'VimeoKiller' has MIME type " + MIMEType + " and cannot be played natively by QuickTime.");
- }
+ }
// END DEBUD
};
// BEGIN DEBUG
@@ -72,30 +70,5 @@ VimeoKiller.prototype.processElement = function(data, callback) {
}
// END DEBUG
getMIMEType(videoURL, handleMIMEType);
- /*request = new XMLHttpRequest();
- request.open('HEAD', videoURL, true);
- var gotContentType = false;
- request.onreadystatechange = function () {
- if(!gotContentType && request.getResponseHeader('Content-Type')) {
- gotContentType = true;
- if(request.getResponseHeader('Content-Type') != "video/x-flv") {
- callback(videoData);
- }
- // BEGIN DEBUG
- else if(safari.extension.settings["debug"]) {
- alert("Video found by killer 'VimeoKiller' has MIME type " + request.getResponseHeader('Content-Type') + " and cannot be played by Safari.");
- }
- // END DEBUD
- request.abort();
- }
- };
- // BEGIN DEBUG
- if(safari.extension.settings["debug"]) {
- if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + videoURL)) return;
- }
- // END DEBUG
- request.send(null);*/
- //alert(request.responseText);
- //alert(req.getResponseHeader('Content-Type').split(';')[0]);
}
};
diff --git a/ClickToPlugin.safariextension/killers/WMKiller.js b/ClickToPlugin.safariextension/killers/WMKiller.js
index c9001c1d..e4361592 100644
--- a/ClickToPlugin.safariextension/killers/WMKiller.js
+++ b/ClickToPlugin.safariextension/killers/WMKiller.js
@@ -1,17 +1,17 @@
function WMKiller() {
- this.name = "WMKiller";
+ this.name = "WMKiller";
}
WMKiller.prototype.canKill = function(data) {
- return (data.plugin == "WM" && safari.extension.settings["replaceWM"] && safari.extension.settings["QTbehavior"] > 1 && canPlayWM && data.src.match(/\.((wm(?!x))|(asf))/i));
+ return (data.plugin == "WM" && safari.extension.settings["replaceWM"] && safari.extension.settings["QTbehavior"] > 1 && canPlayWM && data.src.match(/\.((wm(?!x)|asf))/i));
};
// should check media type...
WMKiller.prototype.processElement = function(data, callback) {
- var videoData = {
+ var videoData = {
"playlist": [{"mediaType": "video", "mediaURL": data.src}],
"badgeLabel": "Video"
};
- callback(videoData);
+ callback(videoData);
};
\ No newline at end of file
diff --git a/ClickToPlugin.safariextension/killers/YouTubeKiller.js b/ClickToPlugin.safariextension/killers/YouTubeKiller.js
index 547e00d7..397e18aa 100644
--- a/ClickToPlugin.safariextension/killers/YouTubeKiller.js
+++ b/ClickToPlugin.safariextension/killers/YouTubeKiller.js
@@ -1,181 +1,162 @@
function YouTubeKiller() {
- this.name = "YouTubeKiller";
+ this.name = "YouTubeKiller";
}
YouTubeKiller.prototype.canKill = function(data) {
- if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
+ if(data.plugin != "Flash" || !safari.extension.settings["replaceFlash"]) return false;
return (data.src.match("ytimg.com") || data.src.match("youtube.com") || data.src.match("youtube-nocookie.com"));
};
YouTubeKiller.prototype.processElement = function(data, callback) {
if(data.params) {
- if(safari.extension.settings["usePlaylists"]) {
- // see http://apiblog.youtube.com/2010/03/upcoming-change-to-youtube-video-page.html
- // these new YT urls break everything!!!! Video data is loaded dynamically
- // after the Flash has been loaded... no more flashvars :(
- var URLvars = data.location.split("?")[1];
- var playlistID = null;
- if(URLvars) {
- URLvars = URLvars.split("&");
- for (var i = 0; i < URLvars.length; i++) {
- var keyValuePair = URLvars[i].split("=");
- if (keyValuePair[0] == "p") {
- playlistID = keyValuePair[1];
- break;
- }
- }
- }
- if(playlistID) {
- this.buildVideoIDList(data.params, playlistID, 0, new Array(), callback);
- } else this.processElementFromFlashVars(data.params, callback);
- } else this.processElementFromFlashVars(data.params, callback);
+ if(safari.extension.settings["usePlaylists"]) {
+ var URLvars = data.location.split(/#!|\?/)[1];
+ var playlistID = null;
+ if(URLvars) {
+ URLvars = URLvars.split("&");
+ for (var i = 0; i < URLvars.length; i++) {
+ var keyValuePair = URLvars[i].split("=");
+ if (keyValuePair[0] == "p") {
+ playlistID = keyValuePair[1];
+ break;
+ }
+ }
+ }
+ if(playlistID) {
+ this.buildVideoIDList(data.params, data.location, playlistID, 0, new Array(), callback);
+ } else this.processElementFromFlashVars(data.params, data.location, callback);
+ } else this.processElementFromFlashVars(data.params, data.location, callback);
return;
}
// The vid has no flashvars... Only hope is that it is a YouTube /v/ embed
var index = data.src.indexOf(".com/v/");
if(index == -1) {
- if(safari.extension.settings["usePlaylists"]) {
- index = data.src.indexOf(".com/p/");
- if(index == -1) return;
- var playlistID = data.src.substring(index + 7);
- index = playlistID.indexOf(".com/p/");
- if(index != -1) playlistID = playlistID.substring(index + 7);
- index = playlistID.search(/\?|&/);
- if(index != -1) playlistID = playlistID.substring(0,index);
- this.buildVideoIDList(null, playlistID, 0, new Array(), callback);
- }
- return;
- }
+ if(safari.extension.settings["usePlaylists"]) {
+ index = data.src.indexOf(".com/p/");
+ if(index == -1) return;
+ var playlistID = data.src.substring(index + 7);
+ index = playlistID.indexOf(".com/p/");
+ if(index != -1) playlistID = playlistID.substring(index + 7);
+ index = playlistID.search(/\?|&/);
+ if(index != -1) playlistID = playlistID.substring(0,index);
+ this.buildVideoIDList(null, data.location, playlistID, 0, new Array(), callback);
+ }
+ return;
+ }
var videoID = data.src.substring(index + 7);
- index = videoID.indexOf(".com/v/");
- if(index != -1) videoID = videoID.substring(index + 7);
+ index = videoID.indexOf(".com/v/");
+ if(index != -1) videoID = videoID.substring(index + 7);
index = videoID.search(/\?|&/);
if(index != -1) videoID = videoID.substring(0,index);
this.processElementFromVideoID(videoID, callback);
};
-/*YouTubeKiller.prototype.processElementFromPlaylist = function(videoID, plaslistID, callback) {
- var playlistURL = function(i) {
- return "feed://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50"
- };
- var isEmpty = false;
- var i = 0;
- var req = null;
- while(!isEmpty) {
- req = new XMLHttpRequest();
- req.open('GET', playlistURL(i), true);
- req.onload()
- }
-};*/
-
-// this function adds playlist data
-YouTubeKiller.prototype.buildVideoIDList = function(flashvars, playlistID, i, videoIDList, callback) {
- req = new XMLHttpRequest();
- req.open('GET', "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50", true);
- var _this = this;
- req.onload = function() {
- //alert(req.responseText);
- var entries = req.responseXML.getElementsByTagName("entry");
- // this is not always the correct number!!
- //if(!imax) imax = parseInt(responseXML.getElementsByTagNameNS("http://a9.com/-/spec/opensearchrss/1.0/", "totalResults")[0].firstChild.nodeValue);
- for(var j = 0; j < entries.length; j++) {
- try{
- videoIDList.push(entries[j].getElementsByTagNameNS("http://search.yahoo.com/mrss/", "player")[0].getAttribute("url").match(/\?v=[^(&|\?)]*(?=(&|\?))/)[0].replace("?v=",""));
- } catch(err) {}
- }
- if(entries.length < 50) {// we've got the whole list of videoIDs
- var track = 0;
- var length = videoIDList.length;
- if(flashvars) {
- var videoID = getFlashVariable(flashvars, "video_id");
- for(var j = 0; j < videoIDList.length; j++) {
- if(videoIDList[0] == videoID) {track = j; break;}
- videoIDList.push(videoIDList.shift());
- }
- //alert(videoIDList.length + " tracks\n\n" + videoIDList.join("\n"));
- // load the first video at once
- }
- var callbackForPlaylist = function(videoData) {
- videoData.playlistLength = length;
- videoData.startTrack = track;
- if(videoData.playlist[0].siteInfo) videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
- callback(videoData);
- };
- if(flashvars) _this.processElementFromFlashVars(flashvars, callbackForPlaylist);
- else _this.processElementFromVideoID(videoIDList[0], callbackForPlaylist);
- videoIDList.shift();
- _this.buildPlaylist(videoIDList, playlistID, true, 3, callback);
- return;
- }
- _this.buildVideoIDList(flashvars, playlistID, ++i, videoIDList, callback);
- };
- // BEGIN DEBUG
+YouTubeKiller.prototype.buildVideoIDList = function(flashvars, location, playlistID, i, videoIDList, callback) {
+ req = new XMLHttpRequest();
+ req.open('GET', "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50", true);
+ var _this = this;
+ req.onload = function() {
+ var entries = req.responseXML.getElementsByTagName("entry");
+ for(var j = 0; j < entries.length; j++) {
+ try{
+ videoIDList.push(entries[j].getElementsByTagNameNS("http://search.yahoo.com/mrss/", "player")[0].getAttribute("url").match(/\?v=[^(&|\?)]*(?=(&|\?))/)[0].replace("?v=",""));
+ } catch(err) {}
+ }
+ if(entries.length < 50) {// we've got the whole list of videoIDs
+ var track = 0;
+ var length = videoIDList.length;
+ if(flashvars) {
+ var videoID = getFlashVariable(flashvars, "video_id");
+ if(!videoID) { // new YT AJAX player
+ var matches = location.match(/(!|&)v=[^&]+(&|$)/);
+ if(!matches) return;
+ videoID = matches[0].substring(3).replace("&", "");
+ flashvars = null;
+ }
+ for(var j = 0; j < videoIDList.length; j++) {
+ if(videoIDList[0] == videoID) {track = j; break;}
+ videoIDList.push(videoIDList.shift());
+ }
+ }
+ var callbackForPlaylist = function(videoData) {
+ videoData.playlistLength = length;
+ videoData.startTrack = track;
+ if(videoData.playlist[0].siteInfo) videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
+ callback(videoData);
+ };
+ // load the first video at once
+ if(flashvars) _this.processElementFromFlashVars(flashvars, location, callbackForPlaylist);
+ else _this.processElementFromVideoID(videoIDList[0], callbackForPlaylist);
+ videoIDList.shift();
+ // load the rest of the playlist 3 by 3
+ _this.buildPlaylist(videoIDList, playlistID, true, 3, callback);
+ return;
+ }
+ _this.buildVideoIDList(flashvars, location, playlistID, ++i, videoIDList, callback);
+ };
+ // BEGIN DEBUG
if(safari.extension.settings["debug"]) {
if(!confirm("Killer '" + this.name + "' is about to send an asynchronous AJAX request to:\n\n" + "http://gdata.youtube.com/feeds/api/playlists/" + playlistID + "?start-index=" + (50*i + 1) + "&max-results=50")) return;
}
// END DEBUG
- req.send(null);
+ req.send(null);
};
YouTubeKiller.prototype.buildPlaylist = function(videoIDList, playlistID, isFirst, n, callback) {
- if(videoIDList.length == 0) return;
- var j = 0;
- var jmax = videoIDList.length;
- if(isFirst) --n;
- if(jmax > n) jmax = n; // load by groups of n
- if(isFirst) ++n;
- var mediaData = {"loadAfter": true, "missed": 0, "playlist": []};
- var _this = this;
- var next = function(videoData) {
- // this actually works!!
- if(videoData.playlist.length > 0) {
- videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
- mediaData.playlist.push(videoData.playlist[0]);
- } else {// playlist is 1 shorter than announced
- ++mediaData.missed;
- }
- ++j;
- //alert(mediaData.playlist.length);
- if(j == jmax) {
- callback(mediaData);
- // continue building
- _this.buildPlaylist(videoIDList, playlistID, false, n, callback);
- } else _this.processElementFromVideoID(videoIDList.shift(), next);
- };
- this.processElementFromVideoID(videoIDList.shift(), next);
- return;
+ if(videoIDList.length == 0) return;
+ var j = 0;
+ var jmax = videoIDList.length;
+ if(isFirst) --n;
+ if(jmax > n) jmax = n; // load by groups of n
+ if(isFirst) ++n;
+ var mediaData = {"loadAfter": true, "missed": 0, "playlist": []};
+ var _this = this;
+ var next = function(videoData) {
+ // this actually works!!
+ if(videoData.playlist.length > 0) {
+ videoData.playlist[0].siteInfo.url += "&p=" + playlistID;
+ mediaData.playlist.push(videoData.playlist[0]);
+ } else { // playlist is 1 shorter than announced
+ ++mediaData.missed;
+ }
+ ++j;
+ if(j == jmax) {
+ callback(mediaData);
+ _this.buildPlaylist(videoIDList, playlistID, false, n, callback);
+ } else _this.processElementFromVideoID(videoIDList.shift(), next);
+ };
+ this.processElementFromVideoID(videoIDList.shift(), next);
+ return;
};
YouTubeKiller.prototype.getMediaDataFromURLMap = function(videoID, videoHash, urlMap) {
- var availableFormats = [];
+ var availableFormats = [];
var formatInfo = urlMap.split(",");
- // alert(formatInfo);
- for (var i = 0; i < formatInfo.length; i++) {
+ for (var i = 0; i < formatInfo.length; i++) {
var format = formatInfo[i].split("|");
- availableFormats[format[0]] = format[1];
- }
-
- var posterURL = "http://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg";
- // this is the 360p video URL
- var videoURL = "http://www.youtube.com/get_video?fmt=18&asv=&video_id=" + videoID + "&t=" + videoHash;
- var badgeLabel = "H.264";
+ availableFormats[format[0]] = format[1];
+ }
- // Get the highest-quality version set by the user
- //var format = 18;
+ var posterURL = "http://i.ytimg.com/vi/" + videoID + "/hqdefault.jpg";
+ // this is the 360p MP4 video URL, always available
+ var videoURL = "http://www.youtube.com/get_video?fmt=18&asv=&video_id=" + videoID + "&t=" + videoHash;
+ var badgeLabel = "H.264";
- //alert(req.responseText);
- // Only 18, 22, 37, and 38 are h264 playable without plugin in Safari.
- // Other container are FLV (0, 5, 6, 34, 35, although the latter two are H.264 360p and 480p), 3GP (13,17), or WebM (43,45) and cannot play natively (even with Perian)
- if (availableFormats[38] && safari.extension.settings["maxresolution"] > 3) {// 4K @_@
+ /*
+ Only 18, 22, 37, and 38 are MP4 playable nativey by QuickTime.
+ Other containers are FLV (0, 5, 6, 34, 35, the latter two are H.264 360p and 480p),
+ 3GP (13,17), or WebM (43,45)
+ */
+ if (availableFormats[38] && safari.extension.settings["maxresolution"] > 3) {// 4K @_@
badgeLabel = "4K H.264";
- videoURL = availableFormats[38];
+ videoURL = availableFormats[38];
} else if (availableFormats[37] && safari.extension.settings["maxresolution"] > 2) {// 1080p
badgeLabel = "HD H.264";
- videoURL = availableFormats[37];
- } else if (availableFormats[22] && safari.extension.settings["maxresolution"] > 1) {// 720p
+ videoURL = availableFormats[37];
+ } else if (availableFormats[22] && safari.extension.settings["maxresolution"] > 1) {// 720p
badgeLabel = "HD H.264";
- videoURL = availableFormats[22];
- } else if (safari.extension.settings["QTbehavior"] > 2 && canPlayFLV) {
+ videoURL = availableFormats[22];
+ } else if (safari.extension.settings["QTbehavior"] > 2 && canPlayFLV) {
if (availableFormats[35]) { // 480p FLV
videoURL = availableFormats[35];
}
@@ -194,20 +175,28 @@ YouTubeKiller.prototype.getMediaDataFromURLMap = function(videoID, videoHash, ur
this.getSDH264FromFmt18(posterURL, videoID, callback); return;
// NOTE: possibility 2 seems to always work, so possibility 1 is never needed
}*/
- return {"posterURL": posterURL, "videoURL": videoURL, "badgeLabel": badgeLabel};
+ return {"posterURL": posterURL, "videoURL": videoURL, "badgeLabel": badgeLabel};
};
-YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, callback) {
- var title = unescape(getFlashVariable(flashvars, "rec_title")).substring(3).replace(/\+/g, " ");
+YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, location, callback) {
var videoID = getFlashVariable(flashvars, "video_id");
+ // see http://apiblog.youtube.com/2010/03/upcoming-change-to-youtube-video-page.html:
+ if(!videoID) { // new YT AJAX player (not yet used?)
+ var matches = location.match(/(!|&)v=[^&]+(&|$)/);
+ if(!matches) return;
+ videoID = matches[0].substring(3).replace("&", "");
+ this.processElementFromVideoID(videoID, callback);
+ return;
+ }
var videoHash = getFlashVariable(flashvars, "t");
if(!videoHash) {
this.processElementFromVideoID(videoID, callback);
return;
}
- var urlMap = unescape(getFlashVariable(flashvars, "fmt_url_map"));
+ var title = unescape(getFlashVariable(flashvars, "rec_title")).substring(3).replace(/\+/g, " ");
+ var urlMap = unescape(getFlashVariable(flashvars, "fmt_url_map"));
var x = this.getMediaDataFromURLMap(videoID, videoHash, urlMap);
- var videoData = {
+ var videoData = {
"playlist": [{"title": title, "mediaType": "video", "posterURL": x.posterURL, "mediaURL": x.videoURL}],
"badgeLabel": x.badgeLabel
};
@@ -215,36 +204,35 @@ YouTubeKiller.prototype.processElementFromFlashVars = function(flashvars, callba
};
YouTubeKiller.prototype.processElementFromVideoID = function(videoID, callback) {
- if(!videoID) return; // needed!
+ if(!videoID) return; // needed!
var toMatch = /\"fmt_url_map\":\s\"[^\"]*\"/; //"// works for both Flash and HTML5 Beta player pages
var toMatch2 = /\"t\":\s\"[^\"]*\"/; //"//
var _this = this;
var req = new XMLHttpRequest ();
req.open("GET", "http://www.youtube.com/watch?v=" + videoID, true);
req.onload = function() {
- var title = "";
- if(safari.extension.settings["usePlaylists"]) {
- var toMatchTitle = / 1;
- if(this.usePlaylistControls) {
- this.initializePlaylistControls();
- } else {
- this.initializeDownloadControls();
- }
+ }
+
+ // Set dimensions
+ this.width = width;
+ this.height = height;
+ this.containerElement.style.width = width + "px";
+ this.containerElement.style.height = height + "px";
+
+ // Set volume
+ this.mediaElement.volume = volume;
+
+ // Set listeners
+ var _this = this; // need anonymous function in listeners otherwise the 'this' will refer to the mediaElement!
+ this.mediaElement.addEventListener("contextmenu", function(event) {_this.setContextInfo(event, contextInfo);}, false);
+ this.mediaElement.addEventListener("loadedmetadata", function() {_this.fixAspectRatio();}, false);
+ this.mediaElement.addEventListener("ended", function() {_this.nextTrack();}, false);
+ this.mediaElement.ondblclick = function() {
+ _this.switchLoop();
+ };
+
+ if(this.usePlaylistControls) {
+ this.initializePlaylistControls();
+ } else {
+ this.initializeDownloadControls();
+ }
};
mediaPlayer.prototype.initializePlaylistControls = function() {
- this.playlistControls = document.createElement("div");
- this.playlistControls.className = "CTFplaylistControls";
-
- var trackTitle = document.createElement("div");
- trackTitle.className = "CTFtrackTitle";
- this.playlistControls.appendChild(trackTitle);
-
- var trackSelect = document.createElement("div");
- trackSelect.className = "CTFtrackSelect";
- this.playlistControls.appendChild(trackSelect);
-
- var trackTitleText = document.createElement("div");
- trackTitleText.className = "CTFtrackTitleText";
- trackTitle.appendChild(trackTitleText);
-
- var trackTitleTextP = document.createElement("p");
- trackTitleText.appendChild(trackTitleTextP);
-
- var prevButton = document.createElement("div");
- prevButton.className = "CTFprevButton";
- trackSelect.appendChild(prevButton);
-
- var trackInput = document.createElement("form");
- trackInput.className = "CTFtrackInput";
- trackSelect.appendChild(trackInput);
-
- var nextButton = document.createElement("div");
- nextButton.className = "CTFnextButton";
- trackSelect.appendChild(nextButton);
+ this.playlistControls = document.createElement("div");
+ this.playlistControls.className = "CTFplaylistControls";
+
+ var trackTitle = document.createElement("div");
+ trackTitle.className = "CTFtrackTitle";
+ this.playlistControls.appendChild(trackTitle);
+
+ var trackSelect = document.createElement("div");
+ trackSelect.className = "CTFtrackSelect";
+ this.playlistControls.appendChild(trackSelect);
+
+ var trackTitleText = document.createElement("div");
+ trackTitleText.className = "CTFtrackTitleText";
+ trackTitle.appendChild(trackTitleText);
+
+ var trackTitleTextP = document.createElement("p");
+ trackTitleText.appendChild(trackTitleTextP);
+
+ var prevButton = document.createElement("div");
+ prevButton.className = "CTFprevButton";
+ trackSelect.appendChild(prevButton);
+
+ var trackInput = document.createElement("form");
+ trackInput.className = "CTFtrackInput";
+ trackSelect.appendChild(trackInput);
+
+ var nextButton = document.createElement("div");
+ nextButton.className = "CTFnextButton";
+ trackSelect.appendChild(nextButton);
- trackInput.innerHTML = "/" + normalize(this.playlist.length, this.playlistLength) + "";
-
- var _this = this;
- this.mediaElement.onmouseover = function(event) {
- this.focus = true;
- if(!this.paused && this.readyState > 1) _this.fadeIn(.05);
- };
- this.playlistControls.onmouseover = function(event) {
- _this.mediaElement.focus = true;
- if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeIn(0);
- };
- this.mediaElement.onmouseout = function(event) {
- // prevents the default controls from disappearing
- if(event.relatedTarget && (event.relatedTarget == prevButton || event.relatedTarget == nextButton || event.relatedTarget == trackInput.firstChild || event.relatedTarget == trackTitleTextP.lastChild || event.relatedTarget.hasAttribute("precision"))) {
- event.preventDefault();
- } else {
- this.focus = false;
- if(!this.paused && this.readyState > 1) _this.fadeOut(0);
- }
- };
- this.playlistControls.onmouseout = function(event) {
- _this.mediaElement.focus = false;
- if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeOut(.1);
- };
- this.mediaElement.focus = false;
- this.mediaElement.addEventListener("pause", function(){_this.fadeIn(0);}, false);
- this.mediaElement.addEventListener("play", function(){if(!_this.mediaElement.focus) _this.fadeOut(0);}, false);
-
- trackInput.onsubmit = function(event) {
- event.preventDefault();
- var track = this.getElementsByTagName("input")[0].value;
- if(!(/^\d+$/.test(track))) return;
- track = parseInt(track);
- if(track < 1 || track > _this.playlistLength) return;
- track = (track - _this.startTrack - 1 + _this.playlistLength) % _this.playlistLength;
- if(track == _this.currentTrack) return;
- if(track < _this.playlist.length) {
- _this.loadTrack(track, true);
- }
- };
- prevButton.onclick = function() {
- if(_this.playlist.length == 1) return;
- _this.loadTrack(_this.currentTrack - 1, true);
- };
- nextButton.onclick = function() {
- if(_this.playlist.length == 1) return;
- _this.loadTrack(_this.currentTrack + 1, true);
- };
-
- // If the controls are shown at once a webkit bug will mess up font smoothing
- // when the video starts playing.
- // The only way I was able to prevent this is to show controls on loadedmetadata
- this.playlistControls.style.opacity = "0";
- this.containerElement.appendChild(this.playlistControls);
+ trackInput.innerHTML = "/" + normalize(this.playlist.length, this.playlistLength) + "";
+
+ var _this = this;
+ this.mediaElement.onmouseover = function(event) {
+ this.focus = true;
+ if(!this.paused && this.readyState > 1) _this.fadeIn(.05);
+ };
+ this.playlistControls.onmouseover = function(event) {
+ _this.mediaElement.focus = true;
+ if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeIn(0);
+ };
+ this.mediaElement.onmouseout = function(event) {
+ // prevents the default controls from disappearing
+ if(event.relatedTarget && (event.relatedTarget == prevButton || event.relatedTarget == nextButton || event.relatedTarget == trackInput.firstChild || event.relatedTarget == trackTitleTextP.lastChild || event.relatedTarget.hasAttribute("precision"))) {
+ event.preventDefault();
+ } else {
+ this.focus = false;
+ if(!this.paused && this.readyState > 1) _this.fadeOut(0);
+ }
+ };
+ this.playlistControls.onmouseout = function(event) {
+ _this.mediaElement.focus = false;
+ if(!_this.mediaElement.paused && _this.mediaElement.readyState > 1) _this.fadeOut(.1);
+ };
+ this.mediaElement.focus = false;
+ this.mediaElement.addEventListener("pause", function(){_this.fadeIn(0);}, false);
+ this.mediaElement.addEventListener("play", function(){if(!_this.mediaElement.focus) _this.fadeOut(0);}, false);
+
+ trackInput.onsubmit = function(event) {
+ event.preventDefault();
+ var track = this.getElementsByTagName("input")[0].value;
+ if(!(/^\d+$/.test(track))) return;
+ track = parseInt(track);
+ if(track < 1 || track > _this.playlistLength) return;
+ track = (track - _this.startTrack - 1 + _this.playlistLength) % _this.playlistLength;
+ if(track == _this.currentTrack) return;
+ if(track < _this.playlist.length) {
+ _this.loadTrack(track, true);
+ }
+ };
+ prevButton.onclick = function() {
+ if(_this.playlist.length == 1) return;
+ _this.loadTrack(_this.currentTrack - 1, true);
+ };
+ nextButton.onclick = function() {
+ if(_this.playlist.length == 1) return;
+ _this.loadTrack(_this.currentTrack + 1, true);
+ };
+
+ this.playlistControls.style.opacity = "1";
+ this.containerElement.appendChild(this.playlistControls);
};
mediaPlayer.prototype.initializeDownloadControls = function() {
- this.playlistControls = document.createElement("div");
- this.playlistControls.className = "CTFplaylistControls";
-
- var hoverElement = document.createElement("div");
- hoverElement.className = "CTFhoverElement";
- this.playlistControls.innerHTML = "";
-
- this.playlistControls.appendChild(hoverElement);
-
- var _this = this;
-
- this.playlistControls.firstChild.onmouseout = function(event) {
- this.nextSibling.style.display = "block";
- _this.fadeOut(0)
- };
-
- this.playlistControls.firstChild.onmouseover = function(event) {
- if(event.relatedTarget && event.relatedTarget.className == "CTFhoverElement") {
- this.nextSibling.style.display = "none";
- _this.fadeIn(0)
- }
- };
- hoverElement.onmouseover = function(event) {
- this.previousSibling.style.display ="block";
- }
-
- hoverElement.onmouseout = function(event) {
- if(!event.relatedTarget || event.relatedTarget.className != "CTFtitleText") {
- this.previousSibling.style.display ="none";
- }
- };
-
- this.mediaElement.onmouseout = function(event) {
- if(event.relatedTarget && (event.relatedTarget == hoverElement || event.relatedTarget.className == "CTFtitleText")) {
- event.preventDefault();
- }
- }
-
- this.playlistControls.addEventListener("webkitTransitionEnd", function() {if(this.style.opacity == "0") this.firstChild.style.display = "none";}, false);
-
- this.playlistControls.style.opacity = "0";
- this.playlistControls.firstChild.style.display = "none";
- //this.playlistControls.firstChild.style.pointerEvents = "auto";
-
- this.containerElement.appendChild(this.playlistControls);
+ this.playlistControls = document.createElement("div");
+ this.playlistControls.className = "CTFplaylistControls";
+
+ var hoverElement = document.createElement("div");
+ hoverElement.className = "CTFhoverElement";
+ this.playlistControls.innerHTML = "";
+
+ this.playlistControls.appendChild(hoverElement);
+
+ var _this = this;
+
+ this.playlistControls.firstChild.onmouseout = function(event) {
+ this.nextSibling.style.display = "block";
+ _this.fadeOut(0)
+ };
+
+ this.playlistControls.firstChild.onmouseover = function(event) {
+ if(event.relatedTarget && event.relatedTarget.className == "CTFhoverElement") {
+ this.nextSibling.style.display = "none";
+ _this.fadeIn(0)
+ }
+ };
+ hoverElement.onmouseover = function(event) {
+ this.previousSibling.style.display ="block";
+ }
+
+ hoverElement.onmouseout = function(event) {
+ if(!event.relatedTarget || event.relatedTarget.className != "CTFtitleText") {
+ this.previousSibling.style.display ="none";
+ }
+ };
+
+ this.mediaElement.onmouseout = function(event) {
+ if(event.relatedTarget && (event.relatedTarget == hoverElement || event.relatedTarget.className == "CTFtitleText")) {
+ event.preventDefault();
+ }
+ }
+
+ this.playlistControls.addEventListener("webkitTransitionEnd", function() {if(this.style.opacity == "0") this.firstChild.style.display = "none";}, false);
+
+ this.playlistControls.style.opacity = "0";
+ this.playlistControls.firstChild.style.display = "none";
+
+ this.containerElement.appendChild(this.playlistControls);
};
mediaPlayer.prototype.fadeOut = function(delay) {
- this.playlistControls.style.WebkitTransition = "opacity .4s linear " + delay + "s";
- this.playlistControls.style.opacity = "0";
+ this.playlistControls.style.WebkitTransition = "opacity .4s linear " + delay + "s";
+ this.playlistControls.style.opacity = "0";
};
mediaPlayer.prototype.fadeIn = function(delay) {
- this.playlistControls.style.WebkitTransition = "opacity .05s linear " + delay + "s";
- this.playlistControls.style.opacity = "0.93";
+ this.playlistControls.style.WebkitTransition = "opacity .05s linear " + delay + "s";
+ this.playlistControls.style.opacity = "0.93";
};
mediaPlayer.prototype.fixAspectRatio = function() {
- var w = this.mediaElement.videoWidth;
- var h = this.mediaElement.videoHeight;
- if(w == 0 || h == 0) { // audio source
+ var w = this.mediaElement.videoWidth;
+ var h = this.mediaElement.videoHeight;
+ if(w == 0 || h == 0) { // audio source
//this.mediaElement.style.height = "24px"; // the height of the controls
this.mediaElement.style.width = this.width + "px"; this.mediaElement.style.height = this.height + "px";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
} else if (w/h > this.width/this.height) {
this.mediaElement.style.width = this.width + "px"; this.mediaElement.style.height = "";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
} else {
this.mediaElement.style.height = this.height + "px"; this.mediaElement.style.width = "";
- // Apparently webkit uses floor, not round
- if(this.playlistControls) this.playlistControls.style.width = Math.floor(w/h*this.height) + "px";
+ if(this.playlistControls) {
+ // Apparently QuickTime uses floor, not round
+ var width = Math.floor(w/h*this.height);
+ this.playlistControls.style.width = width + "px";
+ if(this.usePlaylistControls) this.playlistControls.getElementsByTagName("p")[0].style.width = (width - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth - 12) + "px";
+ }
+ }
+ if(this.usePlaylistControls) {
+ // need this otherwise a webkit bug messes up font smoothing
+ this.fadeIn(.05);
}
- if(this.usePlaylistControls) {
- this.fadeIn(.05);
- }
-
+
};
mediaPlayer.prototype.resetAspectRatio = function() {
- this.mediaElement.style.width = this.width + "px";
- this.mediaElement.style.height = this.height + "px";
- if(this.playlistControls) this.playlistControls.style.width = this.width + "px";
+ this.mediaElement.style.width = this.width + "px";
+ this.mediaElement.style.height = this.height + "px";
+ if(this.playlistControls) {
+ this.playlistControls.style.width = this.width + "px";
+ if(this.usePlaylistControls) this.playlistControls.getElementsByTagName("p")[0].style.width = (this.width - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth - 12) + "px";
+ }
};
mediaPlayer.prototype.switchLoop = function() {
- if(this.mediaElement.hasAttribute("loop")) this.mediaElement.removeAttribute("loop");
- else this.mediaElement.setAttribute("loop", "true");
+ if(this.mediaElement.hasAttribute("loop")) this.mediaElement.removeAttribute("loop");
+ else this.mediaElement.setAttribute("loop", "true");
}
mediaPlayer.prototype.nextTrack = function() {
- if(!this.mediaElement.hasAttribute("loop")) {
- if(this.currentTrack + this.startTrack + 1 == this.playlistLength) return;
- this.loadTrack(this.currentTrack + 1, true);
- }
+ if(!this.mediaElement.hasAttribute("loop")) {
+ if(this.currentTrack + this.startTrack + 1 == this.playlistLength) return;
+ this.loadTrack(this.currentTrack + 1, true);
+ }
};
mediaPlayer.prototype.loadTrack = function(track, autoplay) {
- track = track % this.playlist.length;
+ track = track % this.playlist.length;
if(track < 0) track += this.playlist.length; // weird JS behavior
- this.resetAspectRatio();
+ this.resetAspectRatio();
this.mediaElement.src = this.playlist[track].mediaURL;
- // If src is not set before poster, poster is not shown. Webkit bug?
- if(this.playlist[track].posterURL) {
- if(this.playlist[track].mediaType == "video") {
- this.mediaElement.poster = this.playlist[track].posterURL;
- this.mediaElement.style.background = "";
- // this.mediaElement.style.backgroundSize = "";
- } else {
- if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
- this.mediaElement.style.backgroundImage = "url('" + this.playlist[track].posterURL + "')";
- this.mediaElement.style.backgroundRepeat = "no-repeat";
- this.mediaElement.style.backgroundPosition = "center center";
- // this.mediaElement.style.backgroundSize = "100 %";
- }
- } else {
- if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
- this.mediaElement.style.background = "";
- }
- this.currentTrack = track;
- if(autoplay) {
+ // If src is not set before poster, poster is not shown. Webkit bug?
+ if(this.playlist[track].posterURL) {
+ if(this.playlist[track].mediaType == "video") {
+ this.mediaElement.poster = this.playlist[track].posterURL;
+ this.mediaElement.style.background = "";
+ // this.mediaElement.style.backgroundSize = "";
+ } else {
+ if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
+ this.mediaElement.style.backgroundImage = "url('" + this.playlist[track].posterURL + "')";
+ this.mediaElement.style.backgroundRepeat = "no-repeat";
+ this.mediaElement.style.backgroundPosition = "center center";
+ // this.mediaElement.style.backgroundSize = "100 %";
+ }
+ } else {
+ if(this.mediaElement.hasAttribute("poster")) this.mediaElement.removeAttribute("poster");
+ this.mediaElement.style.background = "";
+ }
+ this.currentTrack = track;
+ if(autoplay) {
this.mediaElement.setAttribute("preload", "auto");
this.mediaElement.setAttribute("autoplay", "autoplay");
}
- if(this.usePlaylistControls) {
- var title = this.playlist[track].title;
- if(!title) title = "(no title)";
- title = "" + title + "";
- this.playlistControls.getElementsByTagName("p")[0].innerHTML = ((track + this.startTrack) % this.playlistLength + 1) + ". " + title;
- var inputField = this.playlistControls.getElementsByTagName("input")[0];
- var newInputField = document.createElement("input");
- newInputField.setAttribute("type", "text");
- newInputField.setAttribute("value", (track + this.startTrack) % this.playlistLength + 1);
- newInputField.style.width = (8 * this.playlistLength.toString().length) + "px";
- // simply changing the value does not update if user has used the field
- this.playlistControls.getElementsByTagName("form")[0].replaceChild(newInputField, inputField);
- //this.playlistControls.getElementsByTagName("input")[0].setAttribute("value", track + this.startTrack + 1);
- } else {
- var title = "Download " + (this.playlist[track].mediaType == "audio" ? "Audio" : "Video");
- title = "" + title + "";
- this.playlistControls.getElementsByTagName("p")[0].innerHTML = title;
- }
+ if(this.usePlaylistControls) {
+ var title = this.playlist[track].title;
+ if(!title) title = "(no title)";
+ title = "" + title + "";
+ this.playlistControls.getElementsByTagName("p")[0].innerHTML = ((track + this.startTrack) % this.playlistLength + 1) + ". " + title;
+ var inputField = this.playlistControls.getElementsByTagName("input")[0];
+ var newInputField = document.createElement("input");
+ newInputField.setAttribute("type", "text");
+ newInputField.setAttribute("value", (track + this.startTrack) % this.playlistLength + 1);
+ newInputField.style.width = (8 * this.playlistLength.toString().length) + "px";
+ // simply changing the value does not update if user has used the field
+ this.playlistControls.getElementsByTagName("form")[0].replaceChild(newInputField, inputField);
+ // this.playlistControls.getElementsByTagName("input")[0].setAttribute("value", track + this.startTrack + 1);
+ } else {
+ var title = "Download " + (this.playlist[track].mediaType == "audio" ? "Audio" : "Video");
+ title = "" + title + "";
+ this.playlistControls.getElementsByTagName("p")[0].innerHTML = title;
+ }
};
mediaPlayer.prototype.setContextInfo = function(event, contextInfo) {
- var track = this.currentTrack;
- if(track == null) track = 0;
- contextInfo.mediaType = this.playlist[track].mediaType;
- contextInfo.siteInfo = this.playlist[track].siteInfo;
- //if(this.mediaElement) contextInfo.loop = this.mediaElement.hasAttribute("loop");
- // contextInfo.isPlaylist = (this.playlist.length > 1); // not used
- safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
- event.stopPropagation();
+ var track = this.currentTrack;
+ if(track == null) track = 0;
+ contextInfo.mediaType = this.playlist[track].mediaType;
+ contextInfo.siteInfo = this.playlist[track].siteInfo;
+ // if(this.mediaElement) contextInfo.loop = this.mediaElement.hasAttribute("loop");
+ // contextInfo.isPlaylist = (this.playlist.length > 1); // not used
+ safari.self.tab.setContextMenuEventUserInfo(event, contextInfo);
+ event.stopPropagation();
};
mediaPlayer.prototype.addToPlaylist = function(playlist, init) {
- if(init) this.playlist = playlist.concat(this.playlist);
- else this.playlist = this.playlist.concat(playlist);
- if(this.usePlaylistControls && this.playlistControls) {
- this.playlistControls.getElementsByTagName("span")[0].innerHTML = "/" + normalize(this.playlist.length + this.startTrack, this.playlistLength);
- var width = this.playlistControls.offsetWidth - this.playlistControls.getElementsByClassName("CTFtrackSelect")[0].offsetWidth;
- this.playlistControls.getElementsByTagName("p")[0].style.width = (width - 7) + "px";
- }
+ if(init) this.playlist = playlist.concat(this.playlist);
+ else this.playlist = this.playlist.concat(playlist);
+ if(this.usePlaylistControls && this.playlistControls) {
+ this.playlistControls.getElementsByTagName("span")[0].innerHTML = "/" + normalize(this.playlist.length + this.startTrack, this.playlistLength);
+ }
};
function normalize(n,m) {
- if(n > m) return m.toString();
- var string = n.toString();
- while(string.length < m.toString().length) {
- string = "0" + string;
- }
- return string;
+ if(n > m) return m.toString();
+ var string = n.toString();
+ while(string.length < m.toString().length) {
+ string = "0" + string;
+ }
+ return string;
}
diff --git a/ClickToPlugin.safariextension/next.png b/ClickToPlugin.safariextension/next.png
index 0cea8b02..72e161b6 100644
Binary files a/ClickToPlugin.safariextension/next.png and b/ClickToPlugin.safariextension/next.png differ
diff --git a/ClickToPlugin.safariextension/next_active.png b/ClickToPlugin.safariextension/next_active.png
index 3ec0a0ca..4c0fd79d 100644
Binary files a/ClickToPlugin.safariextension/next_active.png and b/ClickToPlugin.safariextension/next_active.png differ
diff --git a/ClickToPlugin.safariextension/prev.png b/ClickToPlugin.safariextension/prev.png
index a8f8888b..b79a46b6 100644
Binary files a/ClickToPlugin.safariextension/prev.png and b/ClickToPlugin.safariextension/prev.png differ
diff --git a/ClickToPlugin.safariextension/prev_active.png b/ClickToPlugin.safariextension/prev_active.png
index fcbd8c5b..1b41e105 100644
Binary files a/ClickToPlugin.safariextension/prev_active.png and b/ClickToPlugin.safariextension/prev_active.png differ
diff --git a/ClickToPlugin.safariextension/styles.css b/ClickToPlugin.safariextension/styles.css
index 63aa3f6b..1a17ac7d 100644
--- a/ClickToPlugin.safariextension/styles.css
+++ b/ClickToPlugin.safariextension/styles.css
@@ -1,11 +1,11 @@
/* Reset random stuff that might be set by the parent page */
.clickToFlashPlaceholder * {
- margin: 0 !important;
- padding: 0 !important;
- border: 0 !important;
- border-radius: 0 !important;
- text-align: left !important;
- background: none !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ border: 0 !important;
+ border-radius: 0 !important;
+ text-align: left !important;
+ background: none !important;
}
/*********************
@@ -13,11 +13,11 @@
*********************/
.clickToFlashPlaceholder {
- background: -webkit-gradient(linear, left top, left bottom, from(rgba(235, 235, 235, 1)), to(rgba(190, 190, 190, 1))) !important;
- border: 1px solid rgba(0, 0, 0, 0.5) !important;
- -webkit-user-select: none !important;
- display: inline-block !important;
- -webkit-box-sizing: border-box !important;
+ background: -webkit-gradient(linear, left top, left bottom, from(rgba(235, 235, 235, 1)), to(rgba(190, 190, 190, 1))) !important;
+ border: 1px solid rgba(0, 0, 0, 0.5) !important;
+ -webkit-user-select: none !important;
+ display: inline-block !important;
+ -webkit-box-sizing: border-box !important;
}
.clickToFlashPlaceholder.notable {
@@ -29,39 +29,39 @@
}
.clickToFlashPlaceholder:active {
- background: -webkit-gradient(linear, left bottom, left top, from(rgba(225, 225, 225, 1)), to(rgba(200, 200, 200, 1))) !important;
+ background: -webkit-gradient(linear, left bottom, left top, from(rgba(225, 225, 225, 1)), to(rgba(200, 200, 200, 1))) !important;
}
.clickToFlashPlaceholderContainer {
- position: relative !important;
- width: inherit !important;
- height: inherit !important;
- margin: -1px !important;
+ position: relative !important;
+ width: inherit !important;
+ height: inherit !important;
+ margin: -1px !important;
overflow: visible !important;
}
div.logoVerticalPosition {
- display: table-cell !important;
- vertical-align: middle !important;
- width: inherit !important;
- height: inherit !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ width: inherit !important;
+ height: inherit !important;
}
.logoHorizontalPosition {
- float: left !important;
- position: relative !important;
- left: 50% !important;
- height: auto !important;
- width: auto !important;
+ float: left !important;
+ position: relative !important;
+ left: 50% !important;
+ height: auto !important;
+ width: auto !important;
overflow: visible !important;
}
.clickToFlashPlaceholder .logoContainer {
- float: left !important;
- position: relative !important;
- left: -50% !important;
- width: auto !important;
- height: auto !important;
+ float: left !important;
+ position: relative !important;
+ left: -50% !important;
+ width: auto !important;
+ height: auto !important;
overflow: visible !important;
}
@@ -75,40 +75,41 @@ div.logoVerticalPosition {
}
.clickToFlashPlaceholder .logo {
- border-radius: 8px !important;
- border: 4px solid rgba(0, 0, 0, 0.3) !important;
- font-size: 20px !important;
+ border-radius: 8px !important;
+ border: 4px solid rgba(0, 0, 0, 0.3) !important;
+ font-size: 20px !important;
font-style: normal !important;
- width: auto !important;
+ width: auto !important;
margin: 0 !important;
- color: rgba(0, 0, 0, 0.5) !important;
- font-weight: bold !important;
- padding: 14px 5px 7px 5px !important;
- -webkit-user-select: none !important;
- cursor: default !important;
- background: none !important;
- position: relative !important;
- height: auto !important;
- line-height: 0 !important;
+ color: rgba(0, 0, 0, 0.5) !important;
+ font-weight: bold !important;
+ padding: 14px 5px 7px 5px !important;
+ -webkit-user-select: none !important;
+ white-space: nowrap !important;
+ cursor: default !important;
+ background: none !important;
+ position: relative !important;
+ height: auto !important;
+ line-height: 0 !important;
font-family: "Helvetica Neue", Helvetica, sans-serif !important;
}
.clickToFlashPlaceholder .logo.inset {
- color: rgba(255, 255, 255, 0.45) !important;
- border-color: rgba(255, 255, 255, 0.45) !important;
- position: absolute !important;
- top: 1px !important;
+ color: rgba(255, 255, 255, 0.45) !important;
+ border-color: rgba(255, 255, 255, 0.45) !important;
+ position: absolute !important;
+ top: 1px !important;
font-family: "Helvetica Neue", Helvetica, sans-serif !important;
}
.clickToFlashPlaceholder .logoContainer.mini .logo,
.clickToFlashPlaceholder .logoContainer.hidden .logo.tmp {
color: rgba(50, 50, 50, 0.4) !important;
- font-size: 10px !important;
+ font-size: 10px !important;
font-style: normal !important;
- border: 2px solid rgba(50, 50, 50, 0.2) !important;
- padding: 7px 2px 4px 2px !important;
- border-radius: 4px !important;
+ border: 2px solid rgba(50, 50, 50, 0.2) !important;
+ padding: 7px 2px 4px 2px !important;
+ border-radius: 4px !important;
}
.clickToFlashPlaceholder .logoContainer.hidden .logo.tmp {
@@ -116,182 +117,182 @@ div.logoVerticalPosition {
}
.clickToFlashPlaceholder .logoContainer.mini .logo.inset {
- color: rgba(255, 255, 255, 0.25) !important;
- border-color: rgba(255, 255, 255, 0.25) !important;
+ color: rgba(255, 255, 255, 0.25) !important;
+ border-color: rgba(255, 255, 255, 0.25) !important;
}
.CTFvideoContainer {
- position: relative !important;
- display: inline-block !important;
- margin: 0 !important;
- padding: 0 !important;
+ position: relative !important;
+ display: inline-block !important;
+ margin: 0 !important;
+ padding: 0 !important;
}
.CTFvideoElement {
- display: block !important;
- position: relative !important;
- margin: 0px auto 0px auto !important;
+ display: block !important;
+ position: relative !important;
+ margin: 0px auto 0px auto !important;
}
.CTFQTObject {
- position: absolute !important;
- width: 0px !important;
- height: 0px !important;
+ position: absolute !important;
+ width: 0px !important;
+ height: 0px !important;
}
/* PLAYLIST CONTROLS */
.CTFplaylistControls {
- z-index: 1 !important;
- -webkit-user-select: none !important;
- display: block !important;
- position: relative !important;
- bottom: 48px !important;
- margin: 0px auto 0px auto !important;
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- padding: 0px !important;
- height: 24px !important;
- background-image: url('controls_background.png') !important;
- background-repeat: repeat-x !important;
- /*opacity: 0 !important;*/
- /*-webkit-transition: opacity .5s linear !important;*/
- pointer-events: none !important;
- text-rendering: auto !important;
+ z-index: 1 !important;
+ -webkit-user-select: none !important;
+ display: block !important;
+ position: relative !important;
+ bottom: 48px !important;
+ margin: 0px auto 0px auto !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ padding: 0px !important;
+ height: 24px !important;
+ background-image: url('controls_background.png') !important;
+ background-repeat: repeat-x !important;
+ /*opacity: 0 !important;*/
+ /*-webkit-transition: opacity .5s linear !important;*/
+ pointer-events: none !important;
+ text-rendering: auto !important;
}
.CTFtitleText {
- color: white !important;
- pointer-events: auto !important;
- text-decoration: none !important;
- border: 0 !important;
+ color: white !important;
+ pointer-events: auto !important;
+ text-decoration: none !important;
+ border: 0 !important;
}
.CTFtitleText:hover {
- text-decoration: underline !important;
+ text-decoration: underline !important;
}
/*:hover.CTFplaylistControls {
- opacity: 1 !important;
+ opacity: 1 !important;
}*/
.CTFplaylistControls div {
- height: inherit !important;
+ height: inherit !important;
}
.CTFtrackSelect div.CTFprevButton {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- margin: 0 !important;
- padding: 0 !important;
- width: 35px !important;
- background-image: url('prev.png') !important;
- background-repeat: no-repeat !important;
- background-position: center center !important;
- pointer-events: auto !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ width: 37px !important;
+ background-image: url('prev.png') !important;
+ background-repeat: no-repeat !important;
+ background-position: center center !important;
+ pointer-events: auto !important;
}
.CTFtrackSelect div.CTFprevButton:active {
- background-image: url('prev_active.png') !important;
+ background-image: url('prev_active.png') !important;
}
.CTFtrackSelect form.CTFtrackInput {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- padding: 0 !important;
- margin: 0 !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ padding: 0 !important;
+ margin: 0 !important;
}
.CTFtrackSelect div.CTFnextButton {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- margin: 0 0 0 0 !important;
- padding: 0 0 0 0 !important;
- width: 35px !important;
- background-image: url('next.png') !important;
- background-repeat: no-repeat !important;
- background-position: center center !important;
- pointer-events: auto !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ margin: 0 0 0 0 !important;
+ padding: 0 0 0 0 !important;
+ width: 37px !important;
+ background-image: url('next.png') !important;
+ background-repeat: no-repeat !important;
+ background-position: center center !important;
+ pointer-events: auto !important;
}
.CTFtrackSelect div.CTFnextButton:active {
- background-image: url('next_active.png') !important;
+ background-image: url('next_active.png') !important;
}
.CTFtrackTitle {
- position: absolute !important;
- top: 0px !important;
- left: 0px !important;
- height: 24px !important;
+ position: absolute !important;
+ top: 0px !important;
+ left: 0px !important;
+ height: 24px !important;
}
.CTFtrackSelect {
- position: absolute !important;
- top: 0px !important;
- right: 6px !important;
- /*margin: 0 2px 0 0 !important;*/
+ position: absolute !important;
+ top: 0px !important;
+ right: 4px !important;
+ /*margin: 0 2px 0 0 !important;*/
}
.CTFtrackTitle div.CTFtrackTitleText {
- display: table-cell !important;
- vertical-align: middle !important;
- height: inherit !important;
- padding: 0 5px 0 7px !important;
+ display: table-cell !important;
+ vertical-align: middle !important;
+ height: inherit !important;
+ padding: 0 5px 0 7px !important;
}
.CTFtrackTitle div.CTFtrackTitleText p {
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- margin: 0 !important;
- padding: 0 !important;
- white-space: nowrap !important;
- overflow: hidden !important;
- text-overflow: ellipsis !important;
- text-align: left !important;
- line-height: normal !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ white-space: nowrap !important;
+ overflow: hidden !important;
+ text-overflow: ellipsis !important;
+ text-align: left !important;
+ line-height: normal !important;
}
.CTFtrackSelect input {
- background-color: rgba(255, 255, 255, 0.1) !important;
- border: 1px solid rgba(0, 0, 0, 1) !important;
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- margin: 0 !important;
- padding: 0 !important;
- text-align: right !important;
- pointer-events: auto !important;
- height: 12px !important;
- line-height: 1 !important;
+ background-color: rgba(255, 255, 255, 0.1) !important;
+ border: 1px solid rgba(0, 0, 0, 1) !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ text-align: right !important;
+ pointer-events: auto !important;
+ height: 12px !important;
+ line-height: 1 !important;
}
.CTFtrackSelect span {
- color: white !important;
- font-family: "Lucida Grande", Helvetica, sans-serif !important;
- font-style: normal !important;
- font-size: 10px !important;
- font-weight: normal !important;
- line-height: 1 !important;
+ color: white !important;
+ font-family: "Lucida Grande", Helvetica, sans-serif !important;
+ font-style: normal !important;
+ font-size: 10px !important;
+ font-weight: normal !important;
+ line-height: 1 !important;
}
/*need the specificity*/
div.CTFplaylistControls div.CTFhoverElement {
- position: absolute !important;
- left: 28px !important;
- top: 18px !important;
- width: 24px !important;
- height: 6px !important;
- pointer-events: auto !important;
+ position: absolute !important;
+ left: 28px !important;
+ top: 18px !important;
+ width: 24px !important;
+ height: 6px !important;
+ pointer-events: auto !important;
}