How can I detect support for WebP via Javascript? I'd like to use feature detection rather than browser detection if possible, but I can't find a way to do so. Modernizr (www.modernizr.com) doesn't check for it.
This is my solution - is taking around 6ms and I'm considering WebP is only a feature for a modern browser. Uses a different approach using canvas.toDataUrl() function instead of image as the way to detect the feature:
function support_format_webp()
{
var elem = document.createElement('canvas');
if (!!(elem.getContext && elem.getContext('2d')))
{
// was able or not to get WebP representation
return elem.toDataURL('image/webp').indexOf('data:image/webp') == 0;
}
else
{
// very old browser like IE 8, canvas not supported
return false;
}
}
I think something like this might work:
var hasWebP = false;
(function() {
var img = new Image();
img.onload = function() {
hasWebP = !!(img.height > 0 && img.width > 0);
};
img.onerror = function() {
hasWebP = false;
};
img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
})();
In Firefox and IE, the "onload" handler just won't be called at all if the image can't be understood, and the "onerror" is called instead.
You didn't mention jQuery, but as an example of how to deal with the asynchronous nature of that check you could return a jQuery "Deferred" object:
function hasWebP() {
var rv = $.Deferred();
var img = new Image();
img.onload = function() { rv.resolve(); };
img.onerror = function() { rv.reject(); };
img.src = 'http://www.gstatic.com/webp/gallery/1.webp';
return rv.promise();
}
Then you could write:
hasWebP().then(function() {
// ... code to take advantage of WebP ...
}, function() {
// ... code to deal with the lack of WebP ...
});
Here is a jsfiddle example.
A more advanced checker: http://jsfiddle.net/JMzj2/29/. This one loads images from a data URL and checks whether it loads successfully. Since WebP now also supports lossless images, you could check whether the current browser supports just lossy WebP or also lossless WebP. (Note: This implicitly also checks for data URL support.)
var hasWebP = (function() {
// some small (2x1 px) test images for each feature
var images = {
basic: "data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==",
lossless: "data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="
};
return function(feature) {
var deferred = $.Deferred();
$("<img>").on("load", function() {
// the images should have these dimensions
if(this.width === 2 && this.height === 1) {
deferred.resolve();
} else {
deferred.reject();
}
}).on("error", function() {
deferred.reject();
}).attr("src", images[feature || "basic"]);
return deferred.promise();
}
})();
var add = function(msg) {
$("<p>").text(msg).appendTo("#x");
};
hasWebP().then(function() {
add("Basic WebP available");
}, function() {
add("Basic WebP *not* available");
});
hasWebP("lossless").then(function() {
add("Lossless WebP available");
}, function() {
add("Lossless WebP *not* available");
});
Official way by Google:
Since some old browsers have partial support for webp, so it is better to be more specific which webp feature you are trying to use & detect this specific feature, and here is Google's official recommendation for how to detect a specific webp feature:
// check_webp_feature:
// 'feature' can be one of 'lossy', 'lossless', 'alpha' or 'animation'.
// 'callback(feature, isSupported)' will be passed back the detection result (in an asynchronous way!)
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
Example Usage:
check_webp_feature('lossy', function (feature, isSupported) {
if (isSupported) {
// webp is supported,
// you can cache the result here if you want
}
});
Note that image-loading is non-blocking and asynchronous. This means that any code that depends on WebP support should preferably be put in the callback function.
Also note that other synchronous solutions won't work well with Firefox 65
Preferred solution in HTML5
<picture>
<source srcset="/path/to/image.webp" type="image/webp">
<img src="/path/to/image.jpg" alt="insert alt text here">
</picture>
Wiki on W3C
This is an old question, but Modernizr now supports Webp detection.
http://modernizr.com/download/
Look for img-webp under Non-core detects.
Here's a version of James Westgate's answer in ES6.
function testWebP() {
return new Promise(res => {
const webP = new Image();
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
webP.onload = webP.onerror = () => {
res(webP.height === 2);
};
})
};
testWebP().then(hasWebP => console.log(hasWebP));
FF64: false
FF65: true
Chrome: true
I love the synchronous answer from Rui Marques, but unfortunately FF65 still returns false despite having the ability to display WebP.
Here is code without having to request an image. Updated with qwerty's new fiddle.
http://jsfiddle.net/z6kH9/
function testWebP(callback) {
var webP = new Image();
webP.onload = webP.onerror = function () {
callback(webP.height == 2);
};
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};
testWebP(function(support) {
document.body.innerHTML = support ? 'Yeah man!' : 'Nope';
});
WebPJS uses smarter WebP support detection with no external images required:
http://webpjs.appspot.com/
I've found webp support feature detect requires 300+ms when the page is JavaScript heavy. So I wrote a script with caching features:
script cache
localstorage cache
It will only detect once when user first accessing the page.
/**
* #fileOverview WebP Support Detect.
* #author ChenCheng<sorrycc#gmail.com>
*/
(function() {
if (this.WebP) return;
this.WebP = {};
WebP._cb = function(isSupport, _cb) {
this.isSupport = function(cb) {
cb(isSupport);
};
_cb(isSupport);
if (window.chrome || window.opera && window.localStorage) {
window.localStorage.setItem("webpsupport", isSupport);
}
};
WebP.isSupport = function(cb) {
if (!cb) return;
if (!window.chrome && !window.opera) return WebP._cb(false, cb);
if (window.localStorage && window.localStorage.getItem("webpsupport") !== null) {
var val = window.localStorage.getItem("webpsupport");
WebP._cb(val === "true", cb);
return;
}
var img = new Image();
img.src = "data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA";
img.onload = img.onerror = function() {
WebP._cb(img.width === 2 && img.height === 2, cb);
};
};
WebP.run = function(cb) {
this.isSupport(function(isSupport) {
if (isSupport) cb();
});
};
})();
/* Here's a one-liner hack that works (without the use/need of any
externals...save bytes)...
Your CSS... */
body.no-webp .logo {
background-image: url('logo.png');
}
body.webp .logo {
background-image: url('logo.webp');
}
...
<body>
<!--
The following img tag is the *webp* support checker. I'd advise you use any
(small-sized) image that would be utilized on the current page eventually
(probably an image common to all your pages, maybe a logo) so that when
it'll be (really) used on the page, it'll be loaded from cache by the
browser instead of making another call to the server (for some other image
that won't be).
Sidebar: Using 'display: none' so it's not detected by screen readers and
so it's also not displayed (obviously). :)
-->
<img
style='display: none'
src='/path/to/low-sized-image.webp'
onload="this.parentNode.classList.add('webp')"
onerror="this.parentNode.classList.add('no-webp')"
/>
...
</body>
<!-- PS. It's my first answer on SO. Thank you. :) -->
WebP images with htaccess
Place the following in your .htaccess file and jpg/png images will be replaced with WebP images if found in the same folder.
<IfModule mod_rewrite.c>
RewriteEngine On
# Check if browser support WebP images
RewriteCond %{HTTP_ACCEPT} image/webp
# Check if WebP replacement image exists
RewriteCond %{DOCUMENT_ROOT}/$1.webp -f
# Serve WebP image instead
RewriteRule (.+)\.(jpe?g|png)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>
<IfModule mod_mime.c>
AddType image/webp .webp
</IfModule>
Read more here
here is a simple function with Promise based on Pointy's response
let webpSupport = undefined // so we won't have to create the image multiple times
const webp1Px = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA'
function isWebpSupported () {
if (webpSupport !== undefined) {
return Promise.resolve(webpSupport)
}
return new Promise((resolve, _reject) => {
const img = new Image()
img.onload = () => {
webpSupport = !!(img.height > 0 && img.width > 0);
resolve(webpSupport)
}
img.onerror = () => {
webpSupport = false
resolve(webpSupport)
}
img.src = webp1Px
})
}
My short version. I'm used it to give browser webP or jpg/png.
Google eat this, and old iphone ( f̶u̶c̶k̶i̶n̶g̶ ̶s̶h̶e̶e̶t̶ -safari) work great too!
function checkWebP(callback) {
var webP = new Image();
webP.onload = webP.onerror = function () {
callback(webP.height == 2);
};
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
};
checkWebP(function(support) {
if(support) {
//Do what you whant =)
console.log('work webp');
}else{
//Do what you whant =)
console.log('not work, use jgp/png')
}
})
This is a hybrid HTML/Javascript method that will let you determine supported image types in order of preference (your preference). In this example it will return the first supported image type in the browser and checks AVIF, WebP, JpegXL and JPG.
<picture style="display:none;">
<source type=image/avif srcset="data:image/avif;base64,AAAAFGZ0eXBhdmlmAAAAAG1pZjEAAACgbWV0YQAAAAAAAAAOcGl0bQAAAAAAAQAAAB5pbG9jAAAAAEQAAAEAAQAAAAEAAAC8AAAAGwAAACNpaW5mAAAAAAABAAAAFWluZmUCAAAAAAEAAGF2MDEAAAAARWlwcnAAAAAoaXBjbwAAABRpc3BlAAAAAAAAAAQAAAAEAAAADGF2MUOBAAAAAAAAFWlwbWEAAAAAAAAAAQABAgECAAAAI21kYXQSAAoIP8R8hAQ0BUAyDWeeUy0JG+QAACANEkA= 1x">
<source type=image/webp srcset="data:image/webp;base64,UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA 1x">
<source type=image/jxl srcset="data:image/jxl;base64,/woAEBAJCAQBACwASxLFgoUJEP3D/wA= 1x">
<img onload=console.log(this.currentSrc.substring(this.currentSrc.indexOf(':')+1,this.currentSrc.indexOf(';'))) src="data:image/jpg;base64,/9j/4AAQSkZJRgABAQIAHAAcAAD/2wBDAAMDAwMDAwMDAwMEBAQEBAYFBQUFBgkGBwYHBgkOCAoICAoIDgwPDAsMDwwWEQ8PERYZFRQVGR4bGx4mJCYyMkP/wgALCAABAAEBAREA/8QAFAABAAAAAAAAAAAAAAAAAAAACf/aAAgBAQAAAABU/wD/xAAUEAEAAAAAAAAAAAAAAAAAAAAA/9oACAEBAAE/AH//2Q==">
</picture>
You can replace the log function with whatever you need.
Benefits of this approach will be:
you don't have to create and query a bunch of objects in Javascript so it is efficient
The browser doesn't have to fetch any images, they are encoded inline, so it is fast and synchronous. You can stick this in anywhere and have the answer in the next line without callbacks.
The browser will only create an image result for the first supported line, so it is efficient.
It's easy to add future image support by adding one line.
You can order the images for whatever priority you will be using in your application.
You can turn this into individual tests by pruning image types you don't care about.
This should work even when the PICTURE element is not supported, but requires currentSrc, so IE11 will fail.. in which case just test for currentSrc in img or else assume JPG support is baked in always.
EDIT: removed the line break that got into the example, thanks.
There is a way to test webP support instantly.
It's sync and accurate, so there is no need to wait for a callback to render images.
function testWebP = () => {
const canvas = typeof document === 'object' ?
document.createElement('canvas') : {};
canvas.width = canvas.height = 1;
return canvas.toDataURL ? canvas.toDataURL('image/webp').indexOf('image/webp') === 5 : false;
}
This method improved my rendering time dramatically
Webp extension Detect And Replacement JavaScript:
async function supportsWebp() {
if (!self.createImageBitmap) return false;
const webpData = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA=';
const blob = await fetch(webpData).then(r => r.blob());
return createImageBitmap(blob).then(() => true, () => false);
}
(async () => {
if(await supportsWebp()) {
console.log('webp does support');
}
else {
$('#banners .item').each(function(){
var src=$(this).find('img').attr('src');
src = src.replace(".webp", ".jpg");
$(this).find('img').attr('src',src);
});
console.log('webp does not support');
}
})();
Improved version to handle Firefox based on Rui Marques. I added the scan for the different strings based on comments to that answer.
If this improvement is accepted by the community, it should be edited in to that answer.
function canUseWebP()
{
var elem = document.createElement('canvas');
if (!!(elem.getContext && elem.getContext('2d')))
{
var testString = (!(window.mozInnerScreenX == null)) ? 'png' : 'webp';
// was able or not to get WebP representation
return elem.toDataURL('image/webp').indexOf('data:image/' + testString) == 0;
}
// very old browser like IE 8, canvas not supported
return false;
}
Great news. It works in Safari.
document.addEventListener('DOMContentLoaded', function() {
testWebP(document.body)
})
function testWebP(elem) {
const webP = new Image();
webP.src = 'data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
webP.onload = webP.onerror = function () {
webP.height === 2 ? elem.classList.add('webp-true') : elem.classList.add('webp-false')
}
console.log(webP)
}
A source: https://gist.github.com/Protoff/d6643387f03d47b44b2d7c3cf7b3e0a0
Using #Pointy's answer this is for Angular 2+:
import { Injectable } from '#angular/core';
import { Subject } from 'rxjs/Subject';
#Injectable()
export class ImageService {
private isWebpEnabledSource = new Subject<boolean>();
isWebpEnabledAnnounced$ = this.isWebpEnabledSource.asObservable();
isWebpEnabled() {
let webpImage = new Image();
webpImage.src = 'data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==';
webpImage.onload = () => {
if (webpImage.width === 2 && webpImage.height === 1) {
this.isWebpEnabledSource.next(true);
} else {
this.isWebpEnabledSource.next(false);
}
}
}
}
The above solutions may not work in safari and firefox. So I started looking for a more robust solution and stumbled upon a great library about webp support: webp-hero We can take only detectWebpSupport function from this library:
var __awaiter = (this && this.__awaiter) || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new(P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function(thisArg, body) {
var _ = {
label: 0,
sent: function() {
if (t[0] & 1) throw t[1];
return t[1];
},
trys: [],
ops: []
},
f, y, t, g;
return g = {
next: verb(0),
"throw": verb(1),
"return": verb(2)
}, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
return this;
}), g;
function verb(n) {
return function(v) {
return step([n, v]);
};
}
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return {
value: op[1],
done: false
};
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2]) _.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5) throw op[1];
return {
value: op[0] ? op[1] : void 0,
done: true
};
}
};
function detectWebpSupport() {
return __awaiter(this, void 0, void 0, function() {
var testImageSources, testImage, results;
return __generator(this, function(_a) {
switch (_a.label) {
case 0:
testImageSources = [
"data:image/webp;base64,UklGRjIAAABXRUJQVlA4ICYAAACyAgCdASoCAAEALmk0mk0iIiIiIgBoSygABc6zbAAA/v56QAAAAA==",
"data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAQAAAAfQ//73v/+BiOh/AAA="
];
testImage = function(src) {
return new Promise(function(resolve, reject) {
var img = document.createElement("img");
img.onerror = function(error) {
return resolve(false);
};
img.onload = function() {
return resolve(true);
};
img.src = src;
});
};
return [4 /*yield*/ , Promise.all(testImageSources.map(testImage))];
case 1:
results = _a.sent();
return [2 /*return*/ , results.every(function(result) {
return !!result;
})];
}
});
});
}
detectWebpSupport().then(d => console.log('does it support?', d))
//* WebP support checking
import { useState, useEffect } from "react";
const WebpSupportCheck = (feature, callback) => {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
const IsWebpSupported = () => {
const [state, setState] = useState()
useEffect(() => {
WebpSupportCheck('lossy', function (feature, isSupported) {
if (isSupported) {
setState(true)
} else {
setState(false)
}
})
}, [state])
return state
}
export default IsWebpSupported
Related
I have been trying to bypass the captcha but all efforts in vain.
I don't know which function triger and thus it move forward as there is no submit button on the website.
So it only moves forward to show Challenge completed screen when someone do solve it manually.
I am stuck on injecting token. Please Guide me what to do next because i am noob in javascript
here is few javascript functions which i thnk are cause of all this.
Please tell me how to trigger a callback function so it moves to next page. or Complete the Funcaptcha.
Thanks
var loadedCheck = 0;
function getAllUrlParams(e) {
var t = e ? e.split("?")[1] : window.location.search.slice(1),
a = {};
if (t)
for (var n = (t = t.split("#")[0]).split("&"), i = 0; i < n.length; i++) {
var o = n[i].split("="),
s = o[0],
r = void 0 === o[1] || o[1];
if (((s = s.toLowerCase()), "string" == typeof r && (r = r.toLowerCase()), s.match(/\[(\d+)?\]$/))) {
var l = s.replace(/\[(\d+)?\]/, "");
if ((a[l] || (a[l] = []), s.match(/\[\d+\]$/))) {
var c = /\[(\d+)\]/.exec(s)[1];
a[l][c] = r;
} else a[l].push(r);
} else a[s] ? (a[s] && "string" == typeof a[s] ? ((a[s] = [a[s]]), a[s].push(r)) : a[s].push(r)) : (a[s] = r);
}
return a;
}
function loadArkose() {
var e = getAllUrlParams(window.location.href);
"xbox_1" === e.uitheme
? navigator.__defineGetter__("userAgent", function () {
return "Xbox_Dark";
})
: "xbox_2" === e.uitheme
? navigator.__defineGetter__("userAgent", function () {
return "Xbox_Light";
})
: "win8wiz" === e.uitheme &&
navigator.__defineGetter__("userAgent", function () {
return "Win8Wiz";
});
var t = window.location.pathname.split("/"),
a = new ArkoseEnforcement({
public_key: t[1],
language: e.mkt,
target_html: "arkose",
callback: function () {
parent.postMessage(JSON.stringify({ eventId: "challenge-complete", payload: { sessionToken: a.getSessionToken() } }), "*");
},
loaded_callback: function () {
(frameHeight = document.getElementById("fc-iframe-wrap").offsetHeight),
(frameWidth = document.getElementById("fc-iframe-wrap").offsetWidth),
"xbox_1" === e.uitheme || "xbox_2" === e.uitheme ? a.enableDirectionalInput() : e.uitheme,
parent.postMessage(JSON.stringify({ eventId: "challenge-loaded", payload: { sessionToken: a.getSessionToken(), frameHeight: frameHeight, frameWidth: frameWidth } }), "*"),
(loadedCheck = 1);
},
onsuppress: function () {
parent.postMessage(JSON.stringify({ eventId: "challenge-suppressed", payload: { sessionToken: a.getSessionToken() } }), "*");
},
onshown: function () {
parent.postMessage(JSON.stringify({ eventId: "challenge-shown", payload: { sessionToken: a.getSessionToken() } }), "*");
},
});
}
window.addEventListener("message", function (e) {
try {
JSON.parse(e.data);
} catch (e) {
return;
}
var t = JSON.parse(e.data);
switch (t.eventId) {
case "challenge-left":
case "challenge-right":
case "challenge-down":
case "challenge-up":
case "challenge-proceed":
window.dispatchEvent(new CustomEvent("FunCaptcha-action", { detail: { action: t.payload.action } }));
}
});
var interval = setInterval(function () {
(frameHeight = document.getElementById("fc-iframe-wrap").offsetHeight),
(frameWidth = document.getElementById("fc-iframe-wrap").offsetWidth),
1 == loadedCheck && parent.postMessage(JSON.stringify({ eventId: "challenge-iframeSize", payload: { frameHeight: frameHeight, frameWidth: frameWidth } }), "*");
}, 3e3);
Well After trying alot i was unable to find solution but then suddenly anti-captcha api Services updated there extension.
So this method worked for me.
Get Registered on anti-captcha.com and get api
Download Extension from this page Download and set name anticaptcha
add extension to your selenium code through this code snippet.
co = Options()
co.add_extension(os.path.abspath('anticaptcha.crx'))
driver = webdriver.Chrome(options=co)
Now define function which will in inject api key into the extension.
def acp_api_send_request(driver, message_type, data={}):
message = {
'receiver': 'antiCaptchaPlugin',
# request type, for example setOptions
'type': message_type,
# merge with additional data
**data
}
return driver.execute_script("""
return window.postMessage({});
""".format(json.dumps(message)))
Now Before Going to load a website where you want to solve captcha first load any website just so api can be injected properly. call this above function like this. replace your api key with Your_API_KEY_HERE text.
acp_api_send_request(
driver,
'setOptions',
{'options': {'antiCaptchaApiKey':
'Your_API_KEY_HERE'}}
)
Everthing is perfect now just when captcha will load the script will automatically detect it and solve it and submit the form.
happy coding..
I have been searching for all available solutions
This is the best so far i could find but it doesn't work as it should be
It works for first few images then stops. Then i refresh page, works for few more images and then stops again.
So basically what i want to achieve is, give like a 100 images to a function, it starts downloading them 1 by 1
So browser caches those images and those images are not downloaded on other pages and instantly displayed
I want this images to be cached on mobile as well
Here my javascript code that i call. Actually i have more than 100 images but didn't put all here
I accept both jquery and raw javascript solutions doesn't matter
(function() {
'use strict';
var preLoader = function(images, options) {
this.options = {
pipeline: true,
auto: true,
/* onProgress: function(){}, */
/* onError: function(){}, */
onComplete: function() {}
};
options && typeof options == 'object' && this.setOptions(options);
this.addQueue(images);
this.queue.length && this.options.auto && this.processQueue();
};
preLoader.prototype.setOptions = function(options) {
// shallow copy
var o = this.options,
key;
for (key in options) options.hasOwnProperty(key) && (o[key] = options[key]);
return this;
};
preLoader.prototype.addQueue = function(images) {
// stores a local array, dereferenced from original
this.queue = images.slice();
return this;
};
preLoader.prototype.reset = function() {
// reset the arrays
this.completed = [];
this.errors = [];
return this;
};
preLoader.prototype.load = function(src, index) {
console.log("downloading image " + src);
var image = new Image(),
self = this,
o = this.options;
// set some event handlers
image.onerror = image.onabort = function() {
this.onerror = this.onabort = this.onload = null;
self.errors.push(src);
o.onError && o.onError.call(self, src);
checkProgress.call(self, src);
o.pipeline && self.loadNext(index);
};
image.onload = function() {
this.onerror = this.onabort = this.onload = null;
// store progress. this === image
self.completed.push(src); // this.src may differ
checkProgress.call(self, src, this);
o.pipeline && self.loadNext(index);
};
// actually load
image.src = src;
return this;
};
preLoader.prototype.loadNext = function(index) {
// when pipeline loading is enabled, calls next item
index++;
this.queue[index] && this.load(this.queue[index], index);
return this;
};
preLoader.prototype.processQueue = function() {
// runs through all queued items.
var i = 0,
queue = this.queue,
len = queue.length;
// process all queue items
this.reset();
if (!this.options.pipeline)
for (; i < len; ++i) this.load(queue[i], i);
else this.load(queue[0], 0);
return this;
};
function checkProgress(src, image) {
// intermediate checker for queue remaining. not exported.
// called on preLoader instance as scope
var args = [],
o = this.options;
// call onProgress
o.onProgress && src && o.onProgress.call(this, src, image, this.completed.length);
if (this.completed.length + this.errors.length === this.queue.length) {
args.push(this.completed);
this.errors.length && args.push(this.errors);
o.onComplete.apply(this, args);
}
return this;
}
if (typeof define === 'function' && define.amd) {
// we have an AMD loader.
define(function() {
return preLoader;
});
} else {
this.preLoader = preLoader;
}
}).call(this);
// Usage:
$(window).load(function() {
new preLoader([
'//static.pokemonpets.com/images/attack_animations/absorb1.png',
'//static.pokemonpets.com/images/attack_animations/bleeding1.png',
'//static.pokemonpets.com/images/attack_animations/bug_attack1.png',
'//static.pokemonpets.com/images/attack_animations/bug_attack2.png',
'//static.pokemonpets.com/images/attack_animations/bug_boost1.png',
'//static.pokemonpets.com/images/attack_animations/burned1.png',
'//static.pokemonpets.com/images/attack_animations/change_weather_cloud.png',
'//static.pokemonpets.com/images/attack_animations/confused1.png',
'//static.pokemonpets.com/images/attack_animations/copy_all_enemy_moves.png',
'//static.pokemonpets.com/images/attack_animations/copy_last_move_enemy.png',
'//static.pokemonpets.com/images/attack_animations/cringed1.png',
'//static.pokemonpets.com/images/attack_animations/critical1.png',
'//static.pokemonpets.com/images/attack_animations/cure_all_status_problems.png',
'//static.pokemonpets.com/images/attack_animations/dark_attack1.png',
'//static.pokemonpets.com/images/attack_animations/dark_attack2.png',
'//static.pokemonpets.com/images/attack_animations/dark_attack3.png',
'//static.pokemonpets.com/images/attack_animations/dark_boost1.png',
'//static.pokemonpets.com/images/attack_animations/double_effect.png',
'//static.pokemonpets.com/images/attack_animations/dragon_attack1.png',
'//static.pokemonpets.com/images/attack_animations/dragon_attack2.png',
'//static.pokemonpets.com/images/attack_animations/dragon_attack3.png',
'//static.pokemonpets.com/images/attack_animations/dragon_attack4.png'
]);
});
Something like this?
I do not have time to make it pretty.
const pref = "https://static.pokemonpets.com/images/attack_animations/";
const defa = "https://imgplaceholder.com/20x20/000/fff/fa-image";
const images=['absorb1','bleeding1','bug_attack1','bug_attack2','bug_boost1','burned1','change_weather_cloud','confused1','copy_all_enemy_moves','copy_last_move_enemy','cringed1','critical1','cure_all_status_problems','dark_attack1','dark_attack2','dark_attack3','dark_boost1','double_effect','dragon_attack1','dragon_attack2','dragon_attack3','dragon_attack4'];
let cnt = 0;
function loadIt() {
if (cnt >= images.length) return;
$("#imagecontainer > img").eq(cnt).attr("src",pref+images[cnt]+".png"); // preload next
cnt++;
}
const $cont = $("#container");
const $icont = $("#imagecontainer");
// setting up test images
$.each(images,function(_,im) {
$cont.append('<img src="'+defa+'" id="'+im+'"/>'); // actual images
$icont.append('<img src="'+defa+'" data-id="'+im+'"/>'); // preload images
});
$("#imagecontainer > img").on("load",function() {
if (this.src.indexOf("imgplaceholder") ==-1) { // not for the default image
$("#"+$(this).attr("data-id")).attr("src",this.src); // copy preloaded
loadIt(); // run for next entry
}
})
loadIt(); // run
#imagecontainer img { height:20px }
#container img { height:100px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"></div>
<hr/>
<div id="imagecontainer"></div>
I want to create a video player that can play multiple resolution, so I have to load chunks of different codecs.
I tried to append chunk of the same codec and it work. So I tried to use changeType() but when I append the new codec chunk in the video element I found this error "CHUNK_DEMUXER_ERROR_APPEND_FAILED: Append: stream parsing failed.".
const myMediaSource = new MediaSource();
var videoSourceBuffer;
var quality=480,qlast=480;
var currentSegment = 0;
var loading = false;
function videos() {
myMediaSource.addEventListener('sourceopen', sourceOpen, { once: true});
}
function sourceOpen() {
setInterval(feedVideo, 500);
}
function feedVideo() {
if (!loading) {
try {
if (myMediaSource.sourceBuffers.length == 0) {
videoSourceBuffer = myMediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001E,mp4a.40.2"');
appendSegment("cinit.mp4", 0);
first = true;
} else {
if (qlast != quality) {
videoSourceBuffer = myMediaSource.sourceBuffers[0];
if (quality == 1080) {
type = 'video/mp4; codecs="avc1.640028,mp4a.40.2"';
}
else if (quality == 720) {
type = 'video/mp4; codecs="avc1.64001F,mp4a.40.2"';
}
else if (quality == 480) {
type = 'video/mp4; codecs="avc1.64001E,mp4a.40.2"';
}
else if (quality == 360) {
type = 'video/mp4; codecs="avc1.64001E,mp4a.40.2"';
}
videoSourceBuffer.changeType(type);
videoSourceBuffer.mode = "segments";
qlast = quality;
}
}
if (!first) {
appendSegment("c" + currentSegment + ".m4s", currentSegment);
}
else {
first = false;
}
} catch (error) {
console.log('Error! ' + error);
}
}
}
function appendSegment(file, resourcesIndex) {
loading = true;
fetch("http://mysite/video/" + quality + "p/" + file).then(function (response) {
return response.arrayBuffer();
}).then(function (videoData) {
videoSourceBuffer.appendBuffer(videoData);
videoSourceBuffer.addEventListener('updateend', function () {
loading = false;
}, { once: true });
});
}
How can I fix it?
You almost certainly don't need to use changeType here, since that is typically used for changing codec (eg avc -> hevc) or container (eg mp4 -> webm), whereas you are simply switching within the same codec and container.
The problem is almost certainly that you aren't appending an initialisation segment on a quality change - you only do this for the first quality level.
Fix: insert an appropriate initialisation segment before the first media segment of each new quality.
Since the support for arrow functions in JS is still quite low, I'd like to replace them from the following code snippet:
Promise.all([f1(), f2()])
.then(values => { f3(values); })
.catch(values => { f4(values); });
Any idea how can this be achieved?
Should be straight forward, just type "function" instead
Promise.all([f1(), f2()]).then(function(values) {
f3(values);
}).catch(function(values) {
f4(values);
});
Why are you using function expressions at all in there? Do you want to avoid the return values? If not, just go for
Promise.all([f1(), f2()]).then(f3).catch(f4);
This is a solution I wrote to allow existing promise-based code work on promise-less browsers like IE11. Not perfect, but works well.
CanPromise = !!window.Promise;
PromiseResolve = [];
PromiseReject = [];
if (!CanPromise)
{
window.Promise = function (f)
{
var p = {};
p.resolve = function (result)
{
PromiseResolve.push(result);
}
p.reject = function (result)
{
PromiseReject.push(result);
}
return f(p.resolve, p.reject);
};
}
//...........
PromiseResolve.length = 0;
PromiseReject.length = 0;
F1(args);
F2(args);
var AjaxTimeout = 10000;
var period = 100;
var cnt = 0;
var cntMax = parseInt(AjaxTimeout / period);
var t = setInterval(function ()
{
if (PromiseReject.length > 0)
{
clearInterval(t);
Error(PromiseReject[0]);
}
else if (PromiseResolve.length >= 2)
{
clearInterval(t);
Success(PromiseResolve);
}
else if (cnt >= cntMax)
{
clearInterval(t);
}
cnt++;
}, period);
I am trying to embed an swf
Here is my code
<script type="text/javascript">
function initSwf(path)
{
var playerso = new SWFObject(path.concat("/playerHD.swf"), "player01", "600", "450", "9");
playerso.addParam("quality", "high");
playerso.addParam("allowScriptAccess", "always");
playerso.addVariable("xml", path.concat("/xml/details.xml")); // Data xml URL
playerso.addVariable("path", path.concat("/files/")); // URL for assets (swf & jpg)
playerso.write("dviewDiv");
jQuery(document).ready(function()
{
setTimeout( function()
{
jQuery('#mySliders').addClass('hide');
jQuery('#sliderloading').addClass('hide');
jQuery('#dviewDiv').removeClass('hide');
}
, 7000 );
});
}
</script>
The problem with this swfobject is, while it loads, it shows a blank screen or white or whatever background i provide. Which seems bad user experience
I want to modify the library so that while it buffers, i can show some other images and when its buffer is complete it disappears.
As in my code above i have placed a 7 second delay on removing images. It helps but still sometimes the loading takes more than 7 seconds. Is there any possiblity or any modification i can do to find out when it finishes loading so i can remove images then.
example can be viewed on
thevowapp.com/webapp/test.php
Press on 3D BUtton to load the swf file
The library code is as follow
The javascript opensource library i am using has following code
/**
* SWFObject v1.4: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
*
* SWFObject is (c) 2006 Geoff Stearns and is released under the MIT License:
* http://www.opensource.org/licenses/mit-license.php
*
* **SWFObject is the SWF embed script formerly known as FlashObject. The name was changed for
* legal reasons.
*/
if (typeof deconcept == "undefined") {
var deconcept = new Object();
}
if (typeof deconcept.util == "undefined") {
deconcept.util = new Object();
}
if (typeof deconcept.SWFObjectUtil == "undefined") {
deconcept.SWFObjectUtil = new Object();
}
deconcept.SWFObject = function (_1,id,w,h,_5,c,_7,_8,_9,_a,_b) {
if(!document.createElement||!document.getElementById){
return;
}
this.DETECT_KEY = _b?_b:"detectflash";
this.skipDetect = deconcept.util.getRequestParameter(this.DETECT_KEY);
this.params = new Object();
this.variables = new Object();
this.attributes = new Array();
if (_1) {
this.setAttribute("swf",_1);
}
if (id) {
this.setAttribute("id",id);
}
if (w) {
this.setAttribute("width",w);
}
if (h) {
this.setAttribute("height",h);
}
if (_5) {
this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));
}
this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion(this.getAttribute("version"),_7);
if (c) {
this.addParam("bgcolor",c);
}
this.addParam("wMode","transparent");
var q=_8?_8:"high";
this.addParam("quality",q);
this.setAttribute("useExpressInstall",_7);
this.setAttribute("doExpressInstall",false);
var _d=(_9)?_9:window.location;
this.setAttribute("xiRedirectUrl",_d);
this.setAttribute("redirectUrl","");
if (_a) {
this.setAttribute("redirectUrl",_a);
}
};
deconcept.SWFObject.prototype = {
setAttribute:function(_e,_f) {
this.attributes[_e] = _f;
},
getAttribute:function(_10) {
return this.attributes[_10];
},
addParam:function(_11,_12) {
this.params[_11]=_12;
},
getParams:function() {
return this.params;
},
addVariable:function(_13,_14) {
this.variables[_13]=_14;
},
getVariable:function(_15) {
return this.variables[_15];
},
getVariables:function() {
return this.variables;
},
getVariablePairs:function() {
var _16=new Array();
var key;
var _18=this.getVariables();
for(key in _18){
_16.push(key+"="+_18[key]);
}
return _16;
},
getSWFHTML:function() {
var _19="";
if (navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length) {
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType","PlugIn");
}
_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\"";
_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";
var _1a=this.getParams();
for (var key in _1a) {
_19+=[key]+"=\""+_1a[key]+"\" ";
}
var _1c = this.getVariablePairs().join("&");
if (_1c.length>0) {
_19+="flashvars=\""+_1c+"\"";
}
_19+="/>";
} else {
if (this.getAttribute("doExpressInstall")) {
this.addVariable("MMplayerType","ActiveX");
}
_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\">";
_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";
var _1d=this.getParams();
for (var key in _1d) {
_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";
}
var _1f=this.getVariablePairs().join("&");
if (_1f.length>0) {
_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";
}
_19+="</object>";
}
return _19;
},
write:function(_20) {
if (this.getAttribute("useExpressInstall"))
{
var _21=new deconcept.PlayerVersion([6,0,65]);
if (this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version")))
{
this.setAttribute("doExpressInstall",true);
this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));
document.title=document.title.slice(0,47)+" - Flash Player Installation";
this.addVariable("MMdoctitle",document.title);
}
}
if (this.skipDetect || this.getAttribute("doExpressInstall") || this.installedVer.versionIsValid(this.getAttribute("version")))
{
var n=(typeof _20=="string")?document.getElementById(_20):_20;
n.innerHTML=this.getSWFHTML();
return true;
}
else
{
if(this.getAttribute("redirectUrl")!="")
{
document.location.replace(this.getAttribute("redirectUrl"));
}
}
return false;
}
};
deconcept.SWFObjectUtil.getPlayerVersion = function (_23,_24) {
var _25=new deconcept.PlayerVersion([0,0,0]);
if (navigator.plugins&&navigator.mimeTypes.length) {
var x=navigator.plugins["Shockwave Flash"];
if (x&&x.description) {
_25=new deconcept.PlayerVersion(x.description.replace(/([a-z]|[A-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));
}
} else {
try{
var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
for(var i=3;axo!=null;i++) {
axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+i);
_25=new deconcept.PlayerVersion([i,0,0]);
}
} catch(e) {}
if(_23&&_25.major>_23.major) {
return _25;
}
if (!_23||((_23.minor!=0||_23.rev!=0)&&_25.major==_23.major)||_25.major!=6||_24) {
try {
_25=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));
} catch(e) {}
}
}
return _25;
};
deconcept.PlayerVersion = function(_29) {
this.major=parseInt(_29[0])!= null?parseInt(_29[0]):0;
this.minor=parseInt(_29[1])||0;
this.rev=parseInt(_29[2])||0;
};
deconcept.PlayerVersion.prototype.versionIsValid=function(fv) {
if(this.major<fv.major){return false;}
if(this.major>fv.major){return true;}
if(this.minor<fv.minor){return false;}
if(this.minor>fv.minor){return true;}
if(this.rev<fv.rev){return false;}
return true;
};
deconcept.util = {
getRequestParameter:function(_2b) {
var q = document.location.search || document.location.hash;
if (q) {
var _2d = q.indexOf(_2b+"=");
var _2e = (q.indexOf("&",_2d)>-1)?q.indexOf("&",_2d):q.length;
if (q.length>1&&_2d>-1) {
return q.substring(q.indexOf("=",_2d)+1,_2e);
}
}
return "";
}
};
if (Array.prototype.push==null) {
Array.prototype.push=function(_2f) {
this[this.length]=_2f;
return this.length;
};
}
var getQueryParamValue=deconcept.util.getRequestParameter;
var FlashObject=deconcept.SWFObject; // for backwards compatibility
var SWFObject=deconcept.SWFObject;
Similar to this question
Flash Player exposes a PercentLoaded property for the SWF, which you can poll while the SWF loads. Once it reports 100% you can manipulate your DOM (eg hide images) as you describe in your question. Be aware that you can't completely hide your SWF (mask or place off-screen), as this will prevent the SWF from loading in some browsers.
I wrote a tutorial for polling PercentLoaded with SWFObject a few years ago. It uses SWFObject 2.x, which is completely different syntax from 1.4. FWIW, SWFObject 1.4 is really old and is known to have bugs. I suggest using SWFObject 2.3 beta.