I am creating an HTML emailer for my client and they want one link for two buttons. when their users do not have their apps installed on their phones, they must be redirected to the default URL. I am not too bright in Javascript / jQuery because I am not able to find answers.
If users have installed their applications on their mobile devices so in this scenario we need the HREF attribute to be changed as per the Android / iOS devices and the application installed on their device if the application is not installed the user will be sent to the default URL.
I tried this method for the execution
<script language=javascript>
<!-- for button 1 -->
var windowsize = $(window).width();
$(document).resize(function () {
$(window).resize(function () {
var windowsize = $(window).width();
});
})
const getHref = () => {
const element = document.getElementById("link-change");
const IS_IPAD = navigator.userAgent.match(/iPad/i) != null;
const IS_IPHONE = (navigator.userAgent.match(/iPhone/i) != null) || (navigator.userAgent.match(/iPod/i) != null);
if (IS_IPAD || IS_IPHONE) {
element.href = "ios.com"; //
}
else {
element.href = "default.com"; // default
if (windowsize < 768) {
element.href = "android.com"; // default
}
else {
element.href = "default.com"; // default
}
};
};
getHref();
const getHref2 = () => {
const element = document.getElementById("link-change-first");
const IS_IPAD = navigator.userAgent.match(/iPad/i) != null;
const IS_IPHONE = (navigator.userAgent.match(/iPhone/i) != null) || (navigator.userAgent.match(/iPod/i) != null);
if (IS_IPAD || IS_IPHONE) {
element.href = "ios.com"; //
}
else {
element.href = "default.com"; // default
if (windowsize < 768) {
element.href = "android.com"; // default
}
else {
element.href = "default.com"; // default
}
};
};
getHref2();
</script>
this worked if the application was installed on the user's android device only and if the app is not installed on their devices it doesn't work at all.
for iOS somehow this method is not working at all please let me know how I can achieve the desired outcome
Related
I built a barcode scanning system using Chrome's built-in BarcodeDetector. I based the work on Paul Kinlan's QR code scanner which works fine on my phone, but when I run my own code on my phone, it often causes Chrome or the whole System UI to freeze. Sometimes it gets so bad that I need to restart the phone by holding down the power button.
I have tried debugging in the Chrome developer console, but when the phone freezes, so does the developer console.
When I comment out the actual QR code detection, I can leave the page open in Chrome for 10 minutes and it just keeps running. With QR code detection running, the phone will freeze anywhere from immediately to 3 minutes later.
I put the support files (js and HTML) in a Gist - I don't think they are the issue because everything works when the barcode scanning is commented out.
My first attempt:
// Inspired by/based on on https://github.com/PaulKinlan/qrcode/blob/production/app/scripts/main.mjs
import WebCamManager from './scan/WebCamManager.js';
(function () {
'use strict';
var QRCodeCamera = function (element) {
var root = document.getElementById(element);
var cameraRoot = root.querySelector('.CameraRealtime');
var cameraManager = new WebCamManager(cameraRoot);
var cameraVideo = root.querySelector('.Camera-video');
// Offscreen canvas is supposed to help with processing speed
var cameraCanvas = new OffscreenCanvas(1,1);
var context = cameraCanvas.getContext('2d');
const detector = new BarcodeDetector({
formats: ['qr_code'],
});
cameraManager.onframeready = async function (frameData) {
cameraCanvas.width = cameraVideo.videoWidth;
cameraCanvas.height = cameraVideo.videoHeight;
context.drawImage(frameData, 0, 0, cameraVideo.videoWidth, cameraVideo.videoHeight);
if (self.onframe) {
// Comment out the line below to stop processing QR codes
await self.onframe(cameraCanvas);
}
};
var processingFrame = false;
self.onframe = async function (cameraCanvas) {
// There is a frame in the camera, what should we do with it?
if (processingFrame == false) {
processingFrame = true;
let result = await detector.detect(cameraCanvas);
processingFrame = false;
if (result === undefined || result === null || result.length === 0) {
return
};
if ('vibrate' in navigator) {
navigator.vibrate([200]);
}
cameraManager.stop();
var currentURL = new URL(window.location.href);
var newURL;
if (result[0].rawValue
&& (newURL = new URL(result[0].rawValue))
&& newURL.hostname == currentURL.hostname
&& newURL.pathname.startsWith('/pickup/qr/')
) {
window.location.href = newURL;
} else {
alert('Unsupported QR Code: ' + result[0].rawValue);
}
cameraManager.start();
}
};
};
window.addEventListener('load', function () {
var camera = new QRCodeCamera('camera');
});
})();
I also tried splitting the QR detection to a worker (worker code in Gist), but I have the same issue:
const worker = new Worker('/js/scan-worker.js');
worker.addEventListener('message', async (e) => {
if (Array.isArray(e.data)) {
var result = e.data;
if (result === undefined || result === null || result.length === 0) {
processingFrame = false;
return
};
if ('vibrate' in navigator) {
navigator.vibrate([200]);
}
var currentURL = new URL(window.location.href);
var newURL;
if (result[0].rawValue
&& (newURL = new URL(result[0].rawValue))
&& newURL.hostname == currentURL.hostname
&& newURL.pathname.startsWith('/pickup/qr/')
) {
worker.terminate();
window.location.href = newURL;
} else {
alert('Unsupported QR Code: ' + result[0].rawValue);
}
} else {
var newError = document.createElement('div');
newError.classList.add('alert', 'alert-danger');
newError.innerHTML = e.data;
errorContainer.prepend(newError);
worker.terminate();
}
processingFrame = false;
});
cameraManager.onframeready = async function (frameData) {
if (processingFrame == false) {
cameraCanvas.width = cameraVideo.videoWidth;
cameraCanvas.height = cameraVideo.videoHeight;
context.drawImage(frameData, 0, 0, cameraVideo.videoWidth, cameraVideo.videoHeight);
if (self.onframe) {
await self.onframe(cameraCanvas, context);
}
}
};
self.onframe = async function (cameraCanvas, context) {
// There is a frame in the camera, what should we do with it?
if (processingFrame == false) {
processingFrame = true;
worker.postMessage(context.getImageData(0, 0, cameraCanvas.width, cameraCanvas.height));
}
};
Not sure if this would make a difference - all the JS code is run through Laravel Mix.
I hope this is simple. This is a react app where the user can click a button to download a file. When the button is clicked I make a server call to get a secure S3 bucket URL. I'm returning the URL and using window.open() to open the file. This works.
Instead of opening the file I would like to just download it. How do I do this?
handleDownloadResumeFile(event) {
event.preventDefault();
const url = event.target.value;
Meteor.call('getResumeUrl', url, function(error, result) {
if (error) {
console.log(error);
}
if (result && result.url) {
window.open(result.url);
}
});
}
Use saveAs(url, fileName') function from this, it works for me
https://github.com/eligrey/FileSaver.js
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 1.3.8
* 2018-03-22 14:03:47
*
* By Eli Grey, https://eligrey.com
* License: MIT
* See https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md
*/
/*global self */
/*jslint bitwise: true, indent: 4, laxbreak: true, laxcomma: true, smarttabs: true, plusplus: true */
/*! #source http://purl.eligrey.com/github/FileSaver.js/blob/master/src/FileSaver.js */
var saveAs = saveAs || (function(view) {
"use strict";
// IE <10 is explicitly unsupported
if (typeof view === "undefined" || typeof navigator !== "undefined" && /MSIE [1-9]\./.test(navigator.userAgent)) {
return;
}
var
doc = view.document
// only get URL when necessary in case Blob.js hasn't overridden it yet
, get_URL = function() {
return view.URL || view.webkitURL || view;
}
, save_link = doc.createElementNS("http://www.w3.org/1999/xhtml", "a")
, can_use_save_link = "download" in save_link
, click = function(node) {
var event = new MouseEvent("click");
node.dispatchEvent(event);
}
, is_safari = /constructor/i.test(view.HTMLElement) || view.safari
, is_chrome_ios =/CriOS\/[\d]+/.test(navigator.userAgent)
, setImmediate = view.setImmediate || view.setTimeout
, throw_outside = function(ex) {
setImmediate(function() {
throw ex;
}, 0);
}
, force_saveable_type = "application/octet-stream"
// the Blob API is fundamentally broken as there is no "downloadfinished" event to subscribe to
, arbitrary_revoke_timeout = 1000 * 40 // in ms
, revoke = function(file) {
var revoker = function() {
if (typeof file === "string") { // file is an object URL
get_URL().revokeObjectURL(file);
} else { // file is a File
file.remove();
}
};
setTimeout(revoker, arbitrary_revoke_timeout);
}
, dispatch = function(filesaver, event_types, event) {
event_types = [].concat(event_types);
var i = event_types.length;
while (i--) {
var listener = filesaver["on" + event_types[i]];
if (typeof listener === "function") {
try {
listener.call(filesaver, event || filesaver);
} catch (ex) {
throw_outside(ex);
}
}
}
}
, auto_bom = function(blob) {
// prepend BOM for UTF-8 XML and text/* types (including HTML)
// note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF
if (/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) {
return new Blob([String.fromCharCode(0xFEFF), blob], {type: blob.type});
}
return blob;
}
, FileSaver = function(blob, name, no_auto_bom) {
if (!no_auto_bom) {
blob = auto_bom(blob);
}
// First try a.download, then web filesystem, then object URLs
var
filesaver = this
, type = blob.type
, force = type === force_saveable_type
, object_url
, dispatch_all = function() {
dispatch(filesaver, "writestart progress write writeend".split(" "));
}
// on any filesys errors revert to saving with object URLs
, fs_error = function() {
if ((is_chrome_ios || (force && is_safari)) && view.FileReader) {
// Safari doesn't allow downloading of blob urls
var reader = new FileReader();
reader.onloadend = function() {
var url = is_chrome_ios ? reader.result : reader.result.replace(/^data:[^;]*;/, 'data:attachment/file;');
var popup = view.open(url, '_blank');
if(!popup) view.location.href = url;
url=undefined; // release reference before dispatching
filesaver.readyState = filesaver.DONE;
dispatch_all();
};
reader.readAsDataURL(blob);
filesaver.readyState = filesaver.INIT;
return;
}
// don't create more object URLs than needed
if (!object_url) {
object_url = get_URL().createObjectURL(blob);
}
if (force) {
view.location.href = object_url;
} else {
var opened = view.open(object_url, "_blank");
if (!opened) {
// Apple does not allow window.open, see https://developer.apple.com/library/safari/documentation/Tools/Conceptual/SafariExtensionGuide/WorkingwithWindowsandTabs/WorkingwithWindowsandTabs.html
view.location.href = object_url;
}
}
filesaver.readyState = filesaver.DONE;
dispatch_all();
revoke(object_url);
}
;
filesaver.readyState = filesaver.INIT;
if (can_use_save_link) {
object_url = get_URL().createObjectURL(blob);
setImmediate(function() {
save_link.href = object_url;
save_link.download = name;
click(save_link);
dispatch_all();
revoke(object_url);
filesaver.readyState = filesaver.DONE;
}, 0);
return;
}
fs_error();
}
, FS_proto = FileSaver.prototype
, saveAs = function(blob, name, no_auto_bom) {
return new FileSaver(blob, name || blob.name || "download", no_auto_bom);
}
;
// IE 10+ (native saveAs)
if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob) {
return function(blob, name, no_auto_bom) {
name = name || blob.name || "download";
if (!no_auto_bom) {
blob = auto_bom(blob);
}
return navigator.msSaveOrOpenBlob(blob, name);
};
}
// todo: detect chrome extensions & packaged apps
//save_link.target = "_blank";
FS_proto.abort = function(){};
FS_proto.readyState = FS_proto.INIT = 0;
FS_proto.WRITING = 1;
FS_proto.DONE = 2;
FS_proto.error =
FS_proto.onwritestart =
FS_proto.onprogress =
FS_proto.onwrite =
FS_proto.onabort =
FS_proto.onerror =
FS_proto.onwriteend =
null;
return saveAs;
}(
typeof self !== "undefined" && self
|| typeof window !== "undefined" && window
|| this
));
My javascript websocket client crashes when it is receiving messages at a high rate. I've tried 3 browsers and they all crash. Chrome as first, IE second and Edge can keep up a little longer.
The messagerate is about 30 messages in less then a second. All about 10-20 chars long (data-part).
Are the onmessage calls async? And can they run parallel (next onmessage already starts before the previous is done) or are the requests placed in some sort of queue?
I've tried to "block" the onMessage to no avail.
var blockWS = false;
function pageLoad() {
if ('WebSocket' in window) {
var ws = new WebSocket(((window.location.protocol === 'https:') ? 'wss://' : 'ws://') + window.location.host + '/ws');
ws.onmessage = function(message) {
while (blockWS) {
// wait
}
blockWS = true;
var el = document.getElementById('printer');
el.innerHTML += message.data;
el.scrollTop = el.scrollHeight;
blockWS = false;
};
} else {
// The browser doesn't support WebSocket
document.getElementById('body').innerHTML = '<h1>Your browser does not support WebSocket.</h1>';
}
}
<html>
<body onload="pageLoad()">
<div id="body">
<div id="printer"></div>
</div>
</body>
</html>
The easy (not sure about performance here) way to do what you're wanting to do is to use the setInterval() method outside of the loop and simply store the array of messages as they come in from the websockets. Here is some test code that you could do:
EDIT: I added an updated part of the code so that the insert into the DOM will only happen if there are new messages that need to be shown.
// Your code that is crashing the browser:
/*var blockWS = false;
function pageLoad() {
if ('WebSocket' in window) {
var ws = new WebSocket(((window.location.protocol === 'https:') ? 'wss://' : 'ws://') + window.location.host + '/ws');
ws.onmessage = function(message) {
while (blockWS) {
// wait
}
blockWS = true;
var el = document.getElementById('printer');
el.innerHTML += message.data;
el.scrollTop = el.scrollHeight;
blockWS = false;
};
} else {
// The browser doesn't support WebSocket
document.getElementById('body').innerHTML = '<h1>Your browser does not support WebSocket.</h1>';
}
}*/
// Using the setInterval method (I used 1s, but you can change that to your preferences):
function pageLoad() {
const MESSAGE_INSERT_TIME_MS = 1000;
let messages = [];
let intervalId = null;
if ('WebSocket' in window) {
const protocol = window.location.protocol === 'https:' ? 'wss://' : 'ws://';
const ws = new WebSocket(`${protocol}${window.location.host}/ws`);
ws.onmessage = (message) => {
messages.push(message);
};
// At any point inside the "pageLoad()" function, you can use "intervalId.clearInterval()" to stop doing this function.
intervalId = setInterval(() => {
const el = document.getElementById('printer');
if (!el.innerHTML === messages.join('')) {
el.innerHTML = messages;
el.scrollTop = el.scrollHeight;
}
}, MESSAGE_INSERT_TIME_MS);
}
}
Hi i am creating an web chat application in that i want user can copy paste the image from desktop or can paste directly the screen shot but i am unable to achieve it.
I used following code:
$("#dummy").on("paste",function(event){
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // will give you the mime types
for (index in items) {
var item = items[index];
if (item.kind === 'file') {
var blob = item.getAsFile();
var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)}; // data url!
reader.readAsDataURL(blob);
}
}
})
using the above code in Chrome and Firefox i am getting Clipboarddata undefined in case of image.
I tried lots of links on google but not able to reach the target.
I also tried below link from stackoverflow:
Paste an image from clipboard using JavaScript
also the below link:
http://strd6.com/2011/09/html5-javascript-pasting-image-data-in-chrome/
http://codepen.io/netsi1964/pen/IoJbg
can any one help me with complete example how to achieve It?
Demo
Works on latest chrome/firefox. Chrome implementation is simple. Firefox has restrictions that user must give command to do paste like keyboard event and editable input must be focused, so we do tricks here - on ctrl down we focusthat input field, on release unfocus.
HTML:
<canvas style="border:1px solid grey;" id="my_canvas" width="300" height="300"></canvas>
JS:
var CLIPBOARD = new CLIPBOARD_CLASS("my_canvas", true);
/**
* image pasting into canvas
*
* #param string canvas_id canvas id
* #param boolean autoresize if canvas will be resized
*/
function CLIPBOARD_CLASS(canvas_id, autoresize) {
var _self = this;
var canvas = document.getElementById(canvas_id);
var ctx = document.getElementById(canvas_id).getContext("2d");
var ctrl_pressed = false;
var reading_dom = false;
var text_top = 15;
var pasteCatcher;
var paste_mode;
//handlers
document.addEventListener('keydown', function (e) {
_self.on_keyboard_action(e);
}, false); //firefox fix
document.addEventListener('keyup', function (e) {
_self.on_keyboardup_action(e);
}, false); //firefox fix
document.addEventListener('paste', function (e) {
_self.paste_auto(e);
}, false); //official paste handler
//constructor - prepare
this.init = function () {
//if using auto
if (window.Clipboard)
return true;
pasteCatcher = document.createElement("div");
pasteCatcher.setAttribute("id", "paste_ff");
pasteCatcher.setAttribute("contenteditable", "");
pasteCatcher.style.cssText = 'opacity:0;position:fixed;top:0px;left:0px;';
pasteCatcher.style.marginLeft = "-20px";
pasteCatcher.style.width = "10px";
document.body.appendChild(pasteCatcher);
document.getElementById('paste_ff').addEventListener('DOMSubtreeModified', function () {
if (paste_mode == 'auto' || ctrl_pressed == false)
return true;
//if paste handle failed - capture pasted object manually
if (pasteCatcher.children.length == 1) {
if (pasteCatcher.firstElementChild.src != undefined) {
//image
_self.paste_createImage(pasteCatcher.firstElementChild.src);
}
}
//register cleanup after some time.
setTimeout(function () {
pasteCatcher.innerHTML = '';
}, 20);
}, false);
}();
//default paste action
this.paste_auto = function (e) {
paste_mode = '';
pasteCatcher.innerHTML = '';
var plain_text_used = false;
if (e.clipboardData) {
var items = e.clipboardData.items;
if (items) {
paste_mode = 'auto';
//access data directly
for (var i = 0; i < items.length; i++) {
if (items[i].type.indexOf("image") !== -1) {
//image
var blob = items[i].getAsFile();
var URLObj = window.URL || window.webkitURL;
var source = URLObj.createObjectURL(blob);
this.paste_createImage(source);
}
}
e.preventDefault();
}
else {
//wait for DOMSubtreeModified event
//https://bugzilla.mozilla.org/show_bug.cgi?id=891247
}
}
};
//on keyboard press -
this.on_keyboard_action = function (event) {
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey) {
if (ctrl_pressed == false)
ctrl_pressed = true;
}
//c
if (k == 86) {
if (document.activeElement != undefined && document.activeElement.type == 'text') {
//let user paste into some input
return false;
}
if (ctrl_pressed == true && !window.Clipboard)
pasteCatcher.focus();
}
};
//on kaybord release
this.on_keyboardup_action = function (event) {
k = event.keyCode;
//ctrl
if (k == 17 || event.metaKey || event.ctrlKey || event.key == 'Meta')
ctrl_pressed = false;
};
//draw image
this.paste_createImage = function (source) {
var pastedImage = new Image();
pastedImage.onload = function () {
if(autoresize == true){
//resize canvas
canvas.width = pastedImage.width;
canvas.height = pastedImage.height;
}
else{
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
ctx.drawImage(pastedImage, 0, 0);
};
pastedImage.src = source;
};
}
Safari doesn't implement DataTransfer.items, so there's no way to
extract image data (i.e. a screenshot copied to the clipboard) in
Javascript. You can get copied files, but not data.
[From stakeoverflow post]
Chrome
Add your code to he code from codepen and give an id to the div (line 50)
Include your script as posted above with the divs id
$("#one").on("paste", function (event) {
var items = (event.clipboardData || event.originalEvent.clipboardData).items;
console.log(JSON.stringify(items)); // will give you the mime types
for (index in items) {
var item = items[index];
if (item.kind === 'file') {
var blob = item.getAsFile();
var reader = new FileReader();
reader.onload = function (event) {
console.log(event.target.result)
}; // data url!
reader.readAsDataURL(blob);
}
}
})
Make a screenshot, select the first div (that one with the id one), hit ctrl+v, the screenshot appears in the div and the imagedata is loged to console.
Firefox
Use the code I prepeared you within this fiddle
<html>
<head>
<meta charset="utf-8">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<style>
#one {
border: 1px solid black;
min-height: 100px;
min-width: 100px;
}
</style>
</head>
<body>
Copy image from clipboard in Firefox.
<br /> Select the box below and paste a image from clipboard via ctrl+v
<br /> Data printed at console
<br />
<div id="one" contenteditable="true"></div>
<script>
$(function () {
$("#one").bind("input paste", function (ev) {
window.setTimeout(function (ev) {
var input = $("#one").children()[0].src;
var s = input.split(',');
var mime = s[0];
var data = s[1];
console.log(mime);
console.log(data);
}, 300);
});
});
</script>
</body>
</html>
Chrome & Firefox combined
A combined version, using the code from #pareshm for Chrome and my code for Firefox may be found in this updated fiddle (Tested with clipboard content created via system screendump by ctrl+print and copy image part from gimp)
Using HTML5 I am trying to get the attribute (ie rotation), located in the header of a mp4 (I play it using a video tag), to do this I am trying to get the bytes that make up the header, and knowing the structure, find this atom.
Does anyone know how to do this in javascript?
You can use mediainfo.js,
It's a porting of mediainfo (cpp) in javascript compiled with emsciptem.
Here is a working example: https://mediainfo.js.org/
You will need to include the js/mediainfo.js file and put mediainfo.js.mem file in the same folder.
You need to check the sources on this file to see how it works:
https://mediainfo.js.org/js/mediainfopage.js
[...]
function parseFile(file) {
if (processing) {
return;
}
processing = true;
[...]
var fileSize = file.size, offset = 0, state = 0, seekTo = -1, seek = null;
mi.open_buffer_init(fileSize, offset);
var processChunk = function(e) {
var l;
if (e.target.error === null) {
var chunk = new Uint8Array(e.target.result);
l = chunk.length;
state = mi.open_buffer_continue(chunk, l);
var seekTo = -1;
var seekToLow = mi.open_buffer_continue_goto_get_lower();
var seekToHigh = mi.open_buffer_continue_goto_get_upper();
if (seekToLow == -1 && seekToHigh == -1) {
seekTo = -1;
} else if (seekToLow < 0) {
seekTo = seekToLow + 4294967296 + (seekToHigh * 4294967296);
} else {
seekTo = seekToLow + (seekToHigh * 4294967296);
}
if(seekTo === -1){
offset += l;
}else{
offset = seekTo;
mi.open_buffer_init(fileSize, seekTo);
}
chunk = null;
} else {
var msg = 'An error happened reading your file!';
console.err(msg, e.target.error);
processingDone();
alert(msg);
return;
}
// bit 4 set means finalized
if (state&0x08) {
var result = mi.inform();
mi.close();
addResult(file.name, result);
processingDone();
return;
}
seek(l);
};
function processingDone() {
processing = false;
$status.hide();
$cancel.hide();
$dropcontrols.fadeIn();
$fileinput.val('');
}
seek = function(length) {
if (processing) {
var r = new FileReader();
var blob = file.slice(offset, length + offset);
r.onload = processChunk;
r.readAsArrayBuffer(blob);
}
else {
mi.close();
processingDone();
}
};
// start
seek(CHUNK_SIZE);
}
[...]
// init mediainfo
miLib = MediaInfo(function() {
console.debug('MediaInfo ready');
$loader.fadeOut(function() {
$dropcontrols.fadeIn();
window['miLib'] = miLib; // debug
mi = new miLib.MediaInfo();
$fileinput.on('change', function(e) {
var el = $fileinput.get(0);
if (el.files.length > 0) {
parseFile(el.files[0]);
}
});
});
Here is the Github address with the sources of the project: https://github.com/buzz/mediainfo.js
I do not think you can extract such detailed metadata from a video, using HTML5 and its video-tag. The only things you can extract (video length, video tracks, etc.) are listed here:
http://www.w3schools.com/tags/ref_av_dom.asp
Of course, there might be special additional methods available in some browsers, but there is no "general" approach - you would need more than the existing methods of HTML5.