I know about Adobe's Flash Detection kit - but is there any way to find out simply if Flash is installed/supported by the visitor? If the browser supports Flash, that's great, but I don't care what version. I'm struggling to find a simple bit of JavaScript that would do the trick. Has anyone seen something like this?
Cheers!
http://code.google.com/p/swfobject/
JavaScript Flash Detection Library (Flash Detect)
"A (pure) JavaScript library designed to simplify the process of detecting if
the Adobe Flash Player is installed in a Web Browser."
<script language="JavaScript">
function detectPlugin() {
// allow for multiple checks in a single pass
var daPlugins = detectPlugin.arguments;
// consider pluginFound to be false until proven true
var pluginFound = false;
// if plugins array is there and not fake
if (navigator.plugins && navigator.plugins.length > 0) {
var pluginsArrayLength = navigator.plugins.length;
// for each plugin...
for (pluginsArrayCounter=0; pluginsArrayCounter < pluginsArrayLength; pluginsArrayCounter++ ) {
// loop through all desired names and check each against the current plugin name
var numFound = 0;
for(namesCounter=0; namesCounter < daPlugins.length; namesCounter++) {
// if desired plugin name is found in either plugin name or description
if( (navigator.plugins[pluginsArrayCounter].name.indexOf(daPlugins[namesCounter]) >= 0) ||
(navigator.plugins[pluginsArrayCounter].description.indexOf(daPlugins[namesCounter]) >= 0) ) {
// this name was found
numFound++;
}
}
// now that we have checked all the required names against this one plugin,
// if the number we found matches the total number provided then we were successful
if(numFound == daPlugins.length) {
pluginFound = true;
// if we've found the plugin, we can stop looking through at the rest of the plugins
break;
}
}
}
return pluginFound;
} // detectPlugin
function detectFlash() {
pluginFound = detectPlugin('Shockwave','Flash');
// if not found, try to detect with VisualBasic
if(!pluginFound && detectableWithVB) {
pluginFound = detectActiveXControl('ShockwaveFlash.ShockwaveFlash.1');
}
// check for redirection
if (pluginFound) {
alert ("You has teh flash");
}
}
detectFlash();
</script>
Adapted from:
http://developer.apple.com/internet/webcontent/detectplugins.html
Related
I am writing a chrome extension that needs to get an html5 video element on a page, but some video elements were in iframes. I added onto my function to search through iframes, but I started getting errors because of the Same-Origin-Policy related to iframes with different src domains.
In my function, is there an easy way to exclude iframes that violate the Same-Origin-Policy? Or better yet (even though likely not possible), is there a way to still search iframes with different src domains from the main page?
The function in question:
function getVideo() {
var videos = document.getElementsByTagName("video");
if (videos.length >= 1) {
return videos[0];
}
var iframes = document.getElementsByTagName("iframe");
if (iframes.length >= 1) {
for (const frame of iframes) {
videos = frame.contentWindow.document.getElementsByTagName("video");
if (videos.length >= 1) {
return videos[0];
}
}
}
return null; // if a video doesn't exist
}
Edit:
See bottom of answer for current solution.
Original Answer:
Just when you think you have searched long enough on here to warrant a question, you find something that is actually useful.
Based off the answer to this question, I updated my code to this:
function getVideo() {
var videos = document.getElementsByTagName("video");
if (videos.length >= 1) {
return [videos[0], "main"];
}
// Code that will run only inside iframe
if (parent === top) {
var videos = document.getElementsByTagName("video");
if (videos.length >= 1) {
return [videos[0], "iframe"];
}
}
return [null, null]; // if a video doesn't exist
}
And included this in my manifest, so that the script would be injected into the iframes as well:
"content_scripts": [{
"all_frames": true,
...
...
}],
This works, but it does make my other functions pretty ugly. Example:
// if a video exists, set it to the speed and give a notification
function setSpeed(newSpeed) {
var returnVal = getVideo();
var video = returnVal[0], type = returnVal[1];
if (video != null && type === "main") {
video.playbackRate = newSpeed;
inWindowAlert("Speed: " + newSpeed, 1000);
setIcon(newSpeed);
}
if (parent === top) {
if (video != null && type === "iframe") {
video.playbackRate = newSpeed;
inWindowAlert("Speed: " + newSpeed, 1000);
setIcon(newSpeed);
}
}
}
I will try to come up with a cleaner solution, but for now it works. Hope this helps anyone.
New Solution:
Just wanted to update this to say that I completely rewrote the extension's logic to handle this more easily.
The new solution lets each instance of the content script running in each frame run independently and simply collect all videos in its context. I also collect them in a Set to avoid accidental duplication.
I still want to go through again to eliminate the usage of global variables, but the extension works well enough now, so it will likely remain as it is for awhile.
New code:
function getVideos() {
let new_videos = document.getElementsByTagName("video");
if (new_videos.length >= 1) {
VIDEOS = new Set(new_videos);
return VIDEOS;
}
return new Set();
}
and
// set video to the speed and give a notification, restricts available speeds
function setSpeed(newSpeed, video) {
//* BUG-FIX: playback rates below 0.07 rather than 0 were causing errors
newSpeed = newSpeed > 16 ? 16 : newSpeed < 0.07 ? 0 : newSpeed;
// limit decimal values to 2 digits, + in front truncates 2.00 -> 2
SPEED = +newSpeed.toFixed(2);
video.playbackRate = SPEED;
tempAlert("Speed: " + SPEED, 2000, video);
setIcon(SPEED);
}
Where VIDEOS and SPEED are global variables.
How can I set the badge number on a specific tab only? So far I have a code that sets the badge number on all the tabs.. I've been reading around A LOT, but there doesn't seem to be a whole lot of information about this, so perhaps I will find a solution for this here.
I would like something like Adblock Plus, which sets the badge number for a specific tab. This is pretty easy in Chrome etc, but doesn't seem to be the case in Safari.
Does anyone know how extensions like Adblock plus shows the badge number on a specific tab?
So far I only have this code, but as mentioned, it sets the badge on all the tabs, which is not the result I want.
safari.extension.toolbarItems[0].badge = 2;
Edit:
I have been looking at the source code of Adblock plus, and a few other extensions that had this function. And it seems it is using some prototype.
Adblock plus background snippet:
BrowserAction.prototype = {
_set: function(name, value)
{
var toolbarItem = getToolbarItemForWindow(this._page._tab.browserWindow);
if (!toolbarItem)
{
return;
}
var property = toolbarItemProperties[name];
if (!property)
{
property = toolbarItemProperties[name] = {
pages: new ext.PageMap(),
global: toolbarItem[name]
};
}
property.pages.set(this._page, value);
if (isPageActive(this._page))
{
toolbarItem[name] = value;
}
},
setIcon: function(path)
{
this._set("image", safari.extension.baseURI + path.replace("$size", "16"));
},
setBadge: function(badge)
{
if (!badge)
{
this._set("badge", 0);
}
else if ("number" in badge)
{
this._set("badge", badge.number);
}
}
};
Content script (adblockplus.js)
FilterNotifier.on("filter.hitCount", function(filter, newValue, oldValue, page)
{
if (!(filter instanceof BlockingFilter) || !page)
{
return;
}
Prefs.blocked_total++;
var blocked = blockedPerPage.get(page) || 0;
blockedPerPage.set(page, ++blocked);
if (Prefs.show_statsinicon)
{
page.browserAction.setBadge(
{
color: badgeColor,
number: blocked
});
}
});
It seems this is how Adblock plus does it, but so far I haven't been able to replicate it. Still trying though..
Okay, so I finally found a solution for this, and thought I would share what I did, in case somebody else is in the same situation.
This morning I got the idea of storing the data in an array, when the user visits one of the websites I want to display the badge number on (doesn't store all websites the user visits), only if it matched one of the websites I wanted to target. I stored the following data in the array: root domain (example.com) and the badgeNumber.
For this to work, you need to make an array of the root domain of the websites you want to target, and then only execute the following when it matches, otherwise the array would fill up very quickly, and we don't want too much data in it.
In the global page, start by making an empty array to store the data
var badgeUpdateArray = [];
You then need to set up message handling in your global page as well.
safari.application.addEventListener('message', handleMessage, false);
function handleMessage(event) {
if(event.name === "setBadgeText"){
var id = badgeUpdateArray.length + 1;
var isFound = 0;
var found = badgeUpdateArray.some(function (el) {
if(el.identifier === event.message.identifier){
// Was found
isFound = 1;
}
});
if (isFound == 0) {
// Not found, add to the array
badgeUpdateArray.push({identifier:event.message.identifier,badgeNumber:event.message.badgeNumber});
}
// Set the badge number
safari.extension.toolbarItems[0].badge = event.message.badgeNumber;
}
}
Now we need to send the message from the content script to the global page. You need to get the root domain (example.com), I'm not getting into that here, as it's pretty easy. You will also need the badgeNumber value, this can be gathered from wherever (GET request, or elsewhere..)
Remember, only execute this code if the website matches your target domains.
var message = {
identifier: domain,
badgeNumber: rows.length
}
safari.self.tab.dispatchMessage("setBadgeText", message);
This will send the message, and store the data in the array, it will also set the badge number.
Now, for this to be working on different tabs, you will need to make an event handler for "activate" on the global page, this will run whenever a tab is active.
safari.application.addEventListener("activate", updateBadge, true);
function updateBadge(){
var cDomain = safari.application.activeBrowserWindow.activeTab.url;
cDomain = cDomain.replace("www3.","");
cDomain = cDomain.replace("www2.","");
cDomain = cDomain.replace("www1.","");
cDomain = cDomain.replace("www.","");
cDomain = new URL(cDomain);
cDomain = cDomain.hostname;
var id = badgeUpdateArray.length + 1;
var isFound = 0;
var badgeNumber = 0;
var found = badgeUpdateArray.some(function (el) {
badgeNumber = el.badgeNumber;
if(el.identifier === cDomain){
// Was found, set the badge number
isFound = 1;
safari.extension.toolbarItems[0].badge = el.badgeNumber;
}
});
if (isFound == 0) {
// Was not found
safari.extension.toolbarItems[0].badge = 0;
}
}
Hopefully I've got it all in here, and at least something that works, though I have to say that I would prefer an easier way of storing it.. like Chrome etc does it, with the tab API.
So, I have a variable I am creating that is passed along with POST data from a form. Due to some sort of code quirk, any modern browser will create the variable twice, and trigger two different unique id's for the same event, if setting the value of the variable to a cookie. If a modern browser sets the value to localstorage instead, only one unique id is generated and everything works fine.
However, Mobile Safari doesn't treat localstorage as it should be(because Apple moved the directory for localstorage to one that gets emptied randomly), and IE8 fails to set the value to localstorage. In order to bypass these issues, those two browsers should set a cookie instead, which works as intended and generates a single unique identifier for the event.
I cannot just use feature detection, because IE8 technically supports localstorage, but not when the document type of the page is anything other than HTML5. Mobile Safari also supports localstorage, but treats it differently than other modern browsers.
I can tell that the two checks are working to identify Chrome as "anything else", however the unique identifier is showing up as undefined.
What is going wrong with the code below that is preventing the variable from being set and stored in localstorage?
$(document).ready(function() {
if ($.browser.msie && parseInt($.browser.version, 10) === 8) {
var uuid = $.cookie("uuid");
if(typeof uuid === 'undefined'){
var uuid = guid();
document.cookie='uuid='+uuid;
var iam = "ie8";
alert(iam);
}
} else {
if (navigator.userAgent.match(/(iPad|iPhone|iPod touch);.*CPU.*OS 7_\d/i)){
var uuid = $.cookie("uuid");
if(typeof uuid === 'undefined'){
var uuid = guid();
document.cookie='uuid='+uuid;
var iam = "safari mobile";
alert(iam);
} else {
if (localStorage.getItem("uuid") === null) {
var uuid = guid();
localStorage.setItem("uuid", uuid);
var iam = "anything else";
alert(iam);
}
}
}
}
});
Things to note:
There is a function that is called in 3 second intervals that posts this data over to a PHP processing file using Ajax.
There is a function called guid that generates a 20 character unique code.
Browsers we specifically need to check for: IE8(and possibly below) and Mobile Safari(ie, on iPad, iPhone, or iPod).
In Google Chrome and Firefox, uuid is undefined with the current script structure, when instead it should be locally stored and feature a string generated by the guid function.
Above this code are links to jQuery 1.8.2(to gain access to $.browser) and jQuery.cookie.js
You have an else { if () where you likely meant to have else if (){
http://jsfiddle.net/FE2AQ/1/
//$(document).ready(function () { // this isn't really needed
if ($.browser.msie && parseInt($.browser.version, 10) === 8) {
var uuid = $.cookie("uuid");
if (typeof uuid === 'undefined') {
var uuid = guid();
document.cookie = 'uuid=' + uuid;
var iam = "ie8";
alert(iam);
}
} else if (navigator.userAgent.match(/(iPad|iPhone|iPod touch);.*CPU.*OS 7_\d/i)) {
var uuid = $.cookie("uuid");
if (typeof uuid === 'undefined') {
var uuid = guid();
document.cookie = 'uuid=' + uuid;
var iam = "safari mobile";
alert(iam);
}
} else {
if (localStorage.getItem("uuid") === null) {
var uuid = guid();
localStorage.setItem("uuid", uuid);
var iam = "anything else";
alert(iam);
}
}
//});
Is there a way to detect if NaCl is available on the current browser?
It seems that checking for chrome.app.isInstalled turns into false positive on some non-Chrome browsers
You can check if the browser handles the NaCl mime type. E.g.:
navigator.mimeTypes['application/x-nacl'] !== undefined.
Similarly, for PNaCl, you can check for 'application/x-pnacl'.
You can check for Chrome and a particular version of Chrome like this:
var have_nacl = false;
var have_pnacl = false;
var index = navigator.userAgent.indexOf('Chrome');
if (index != -1) {
var version = parseFloat(navigator.userAgent.substring(index + 7));
if (31 <= version) have_pnacl = true;
if (14 <= version) have_nacl = true;
}
However, this does not tell the full story. Versions 31+ have PNaCl and it's enabled by default. NaCl is only enabled by default for apps in the Chrome store so you would still need to test if NaCl is enabled. One way to do this is to set a watchdog timer then try to load an NaCl module and capture the load event. In the load event clear the watchdog timer. For example:
var watchdog;
var watchdog_time;
function watchdog_timeout() {
alert('NaCl module failed to load');
}
function watchdog_clear() {
clearTimeout(watchdog);
}
function watchdog_set(time) {
watchdog_time = time;
watchdog = setTimeout(watchdog_timeout, time);
}
watchdog_set(5000); // Timeout in 5 sec
var module = document.getElementById('module'); // Use your module's ID
module.addEventListener('load', function () {
watchdog_clear();
alert('NaCl module loaded');
}, true);
// Inject the module, where module.nmf is your NMF file.
module.innerHTML = '<embed src="module.nmf" type="application/x-nacl"/>';
This requires that you have something like the following somewhere in your HTML:
<div id="module"></div>
If your module takes awhile to download you might also want to capture the loadstart and progress events and extend the watchdog time.
function watchdog_extend() {
watchdog_clear();
watchdog_set(watchdog_time);
}
module.addEventListener('loadstart', watchdog_extend, true);
module.addEventListener('progress', watchdog_extend, true);
I've been tasked with rewriting the Javascript engine currently powering my customer's internal website. While reviewing the code I've come across this function flvFPW1 which I do not recognize, nor can I decipher the code(my Javascript knowledge is modest at best). A Google search gives me a few hits, but most if not all page hits are from the Javascript used on that particular page. In other words, I cannot find a description for this function, even though it is obviously used by others.
Can someone here enlighten me?
Thanks / Fredrik
My own research agrees that it's a dreamweaver extension: I found code for version 1.44 (scroll down some on this page) rather than 1.3:
function flvFPW1(){//v1.44
var v1=arguments,v2=v1[2].split(","),v3=(v1.length>3)?v1[3]:false,v4=(v1.length>4)?parseInt(v1[4]):0,
v5=(v1.length>5)?parseInt(v1[5]):0,v6,v7=0,v8,v9,v10,v11,v12,v13,v14,v15,v16;v11=
new Array("width,left,"+v4,"height,top,"+v5);for (i=0;i<v11.length;i++){v12=v11[i].split(",");l_iTarget=parseInt(v12[2]);
if (l_iTarget>1||v1[2].indexOf("%")>-1){v13=eval("screen."+v12[0]);
for (v6=0;v6<v2.length;v6++){v10=v2[v6].split("=");
if (v10[0]==v12[0]){v14=parseInt(v10[1]);if (v10[1].indexOf("%")>-1){v14=(v14/100)*v13;v2[v6]=v12[0]+"="+v14;}}
if (v10[0]==v12[1]){v16=parseInt(v10[1]);v15=v6;}}
if (l_iTarget==2){v7=(v13-v14)/2;v15=v2.length;}
else if (l_iTarget==3){v7=v13-v14-v16;}v2[v15]=v12[1]+"="+v7;}}v8=v2.join(",");v9=window.open(v1[0],v1[1],v8);
if (v3){v9.focus();}document.MM_returnValue=false;return v9;}
Which was, of course, passed through a compressor to save bandwidth making it very hard to read. I spent a little bit of time un-obfuscating it before I realized that I could get better results by adding "dreamweaver" to my search string. Doing that I was able to find some more interesting documentation:
http://www.flevooware.nl/dreamweaver/extdetails.asp?extID=8 (short description)
http://satsuki.altervista.org/basibloggers/source40.txt (full script code, in italian)
In short: it's basically just a wrapper for window.open. Here's the progress I made translating the code:
function flvFPW1()
{//v1.44
var v1=arguments; // pass v1[0] and v1[1] directly to window.open
var arg3=v1[2].split(",");
var focusNewWindow=(v1.length>3)?v1[3]:false;
var newWindowWidth=(v1.length>4)?parseInt(v1[4]):0;
var newWindowHeight=(v1.length>5)?parseInt(v1[5]):0;
var adjustedWindowPosition=0,result,keyValuePair,AxisProperty;
var windowSize,sizeValue,arg3Index,anchorValue;
var hwArray= new Array("width,left,"+newWindowWidth,"height,top,"+newWindowHeight);
for (i=0;i<hwArray.length;i++) // x-axis, then y-axis
{
AxisProperty=hwArray[i].split(","); // {"width", "left", 0} or {"height", "top", 0}
l_iTarget=parseInt(AxisProperty[2]); // l_iTarget defined where?
if (l_iTarget>1||v1[2].indexOf("%")>-1)
{
screenSize=eval("screen."+AxisProperty[0]); // x or y size of the window
for (var i=0;i<arg3.length;i++)
{
keyValuePair=arg3[i].split("=");
if (keyValuePair[0]==AxisProperty[0]) // if the key is (width|height)
{
sizeValue=parseInt(keyValuePair[1]);
if (keyValuePair[1].indexOf("%")>-1)
{
sizeValue=(sizeValue/100)* screenSize;
arg3[i]=AxisProperty[0]+"="+sizeValue;
}
}
if (keyValuePair[0]==AxisProperty[1]) // if the key is (left|top)
{
anchorValue=parseInt(keyValuePair[1]);
arg3Index=i;
}
}
if (l_iTarget==2)
{
adjustedWindowPosition=(screenSize-sizeValue)/2; // will center the window on this axix
arg3Index=arg3.length;
}
else if (l_iTarget==3)
{
adjustedWindowPosition= screenSize-sizeValue-anchorValue;
}
arg3[arg3Index]=AxisProperty[1]+"="+adjustedWindowPosition; // (left|top) = value
}
}
var newArg3=arg3.join(",");
result=window.open(v1[0],v1[1],newArg3);
if (focusNewWindow)
{
result.focus();
}
document.MM_returnValue=false;
return result;
}
on your site, type in this in the location bar:
javascript:alert(flvFPW1);
it will report the function code
I don't think it is a built in function, so it is just some function one of your team wrote.
It might be a function that Dreamweaver adds to a page to do something though...
Install Firefox (http://www.mozilla.com/en-US/firefox/) and the FireBug extension(https://addons.mozilla.org/en-US/firefox/addon/1843). Use FireBug's DOM tab to find the function and click on it in the right column. It will take you to the file/line that the function is defined on.
Or open the HTML page in your favorite powerful text editor (like TextPad or TextMate) and do a Search/Find for the function name.
If you're saying that you've found the function but can't actually understand it, then you should probably paste the code in your question.
Google yields:
function flvFPW1() { // v1.3
// Copyright 2002, Marja Ribbers-de Vroed, FlevOOware (www.flevooware.nl/dreamweaver/)
var v1 = arguments, v2 = v1[2].split(","), v3 = (v1.length > 3) ? v1[3] : false, v4 = (v1.length > 4) ? parseInt(v1[4]) : 0, v5 = (v1.length > 5) ? parseInt(v1[5]) : 0, v6, v7 = 0, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18;
if (v4 > 1) {
v10 = screen.width;
for (v6 = 0; v6 < v2.length; v6++) {
v18 = v2[v6].split("=");
if (v18[0] == "width") {
v8 = parseInt(v18[1]);
}
if (v18[0] == "left") {
v9 = parseInt(v18[1]);
v11 = v6;
}
}
if (v4 == 2) {
v7 = (v10 - v8) / 2;
v11 = v2.length;
} else if (v4 == 3) {
v7 = v10 - v8 - v9;
}
v2[v11] = "left=" + v7;
}
if (v5 > 1) {
v14 = screen.height;
for (v6 = 0; v6 < v2.length; v6++) {
v18 = v2[v6].split("=");
if (v18[0] == "height") {
v12 = parseInt(v18[1]);
}
if (v18[0] == "top") {
v13 = parseInt(v18[1]);
v15 = v6;
}
}
if (v5 == 2) {
v7 = (v14 - v12) / 2;
v15 = v2.length;
} else if (v5 == 3) {
v7 = v14 - v12 - v13;
}
v2[v15] = "top=" + v7;
}
v16 = v2.join(",");
v17 = window.open(v1[0], v1[1], v16);
if (v3) {
v17.focus();
}
document.MM_returnValue = false;
}
The URL in the comment leads to:
FlevOOware - Dreamweaver Extensions - Popup Link
Thanks for helping out guys! spilth: Yes I found the function in the js-file but couldn't comprehend the code. Since I found the same function on several other pages that were not related to my customer's page I assumed its purpose would already be known by other people.. so I didn't bother with posting the code. I will next time though.
Best Regards