mirror of
https://github.com/seigler/dash-docs
synced 2025-07-27 01:36:13 +00:00
Start supporting touch events for non-buggy iOS support and faster menus Display and hide wallets on click instead of on mouseout to prevent accidental clicks or mouseout events Add a wrapper function to detect ghost and accidental clicks Reorganize wallet javascript functions for better readability Fix bug in which a wallet would display on mouse over after user clicked inside it's bubble Fix accidental use of global variables
185 lines
7.2 KiB
JavaScript
185 lines
7.2 KiB
JavaScript
// This file is licensed under the MIT License (MIT) available on
|
|
// http://opensource.org/licenses/MIT.
|
|
|
|
// This file should be used only for javascript code
|
|
// necessary for all pages to work properly.
|
|
|
|
function addEvent(a, b, c) {
|
|
// Attach event to a DOM node.
|
|
// Ex. addEvent(node,'click',function);
|
|
return (a.addEventListener) ? a.addEventListener(b, c, false) : (a.attachEvent) ? a.attachEvent('on' + b, c) : false;
|
|
}
|
|
|
|
function removeEvent(a, b, c) {
|
|
// Detach event from a DOM node.
|
|
// Ex. removeEvent(node,'click',function);
|
|
return (a.removeEventListener) ? a.removeEventListener(b, c, false) : (a.detachEvent) ? a.detachEvent('on' + b, c) : false;
|
|
}
|
|
|
|
function cancelEvent(e) {
|
|
// Cancel current event.
|
|
// Ex. cancelEvent(event);
|
|
if (!e) var e = window.event;
|
|
(e.preventDefault) ? e.preventDefault() : e.returnValue = false;
|
|
}
|
|
|
|
function getEventTarget(e) {
|
|
// Return target DOM node on which the event is triggered.
|
|
// Ex. getEventTarget(event);
|
|
if (!e) var e = window.event;
|
|
return (e.target && e.target.nodeType == 3) ? e.target.parentNode : (e.target) ? e.target : e.srcElement;
|
|
}
|
|
|
|
function getStyle(a, b) {
|
|
// Return the value of the computed style on a DOM node.
|
|
// Ex. getStyle(node,'padding-bottom');
|
|
if (window.getComputedStyle) return document.defaultView.getComputedStyle(a, null).getPropertyValue(b);
|
|
var n = b.indexOf('-');
|
|
if (n !== -1) b = b.substr(0, n) + b.substr(n + 1, 1).toUpperCase() + b.substr(n + 2);
|
|
return a.currentStyle[b];
|
|
}
|
|
|
|
function addClass(node, data) {
|
|
// Add class to node.
|
|
var cl = node.className.split(' ');
|
|
for (var i = 0, n = cl.length; i < n; i++) {
|
|
if (cl[i] == data) return;
|
|
}
|
|
cl.push(data);
|
|
node.className = cl.join(' ');
|
|
}
|
|
|
|
function removeClass(node, data) {
|
|
// Remove class from node.
|
|
var ocl = node.className.split(' ');
|
|
var ncl = [];
|
|
for (var i = 0, n = ocl.length; i < n; i++) {
|
|
if (ocl[i] != data) ncl.push(ocl[i]);
|
|
}
|
|
node.className = ncl.join(' ');
|
|
}
|
|
|
|
function supportsSVG() {
|
|
// Return true if the browser supports SVG.
|
|
// Ex. if(!supportsSVG()){..apply png fallback..}
|
|
// Old FF 3.5 and Safari 3 versions have svg support, but a very poor one
|
|
// http://www.w3.org/TR/SVG11/feature#Image Defeat FF 3.5 only
|
|
// http://www.w3.org/TR/SVG11/feature#Animation Defeat Saf 3 but also returns false in IE9
|
|
// http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute Defeat Saf 3 but also returns false in Chrome and safari4
|
|
// http://www.w3.org/TR/SVG11/feature#Text Defeat Saf 3 but also returns false in FF and safari4
|
|
if (!document.createElementNS || !document.createElementNS('http://www.w3.org/2000/svg', 'svg').createSVGRect) return false;
|
|
if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1")) return false;
|
|
if (!document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicGraphicsAttribute", "1.1") && !document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Animation", "1.1") && !document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Text", "1.1")) return false;
|
|
return true;
|
|
}
|
|
|
|
function fallbackSVG() {
|
|
// Replace all images extensions from .svg to .png if browser doesn't support SVG files.
|
|
if (supportsSVG()) return;
|
|
for (var i = 0, nd = document.getElementsByTagName('*'), n = nd.length; i < n; i++) {
|
|
if (nd[i].nodeName == 'IMG' && /.*\.svg$/.test(nd[i].src)) nd[i].src = nd[i].src.slice(0, -3) + 'png';
|
|
if (/\.svg/.test(getStyle(nd[i], 'background-image'))) nd[i].style.backgroundImage = getStyle(nd[i], 'background-image').replace('.svg', '.png');
|
|
if (/\.svg/.test(getStyle(nd[i], 'background'))) nd[i].style.background = getStyle(nd[i], 'background').replace('.svg', '.png');
|
|
}
|
|
}
|
|
|
|
function onTouchClick(e, callback) {
|
|
// Detect and handle clicks using click and touch events while preventing accidental or ghost clicks.
|
|
var timeout = 1000,
|
|
touchEndListener = function(e) {
|
|
// Call callback if touch events match the patterns of a click.
|
|
removeEvent(t, 'touchend', touchEndListener);
|
|
setClickTimeout();
|
|
if (Math.abs(e.changedTouches[0].pageX - x) > 20 || Math.abs(e.changedTouches[0].pageY - y) > 20) return;
|
|
callback(e);
|
|
},
|
|
wrongClickListener = function(e) {
|
|
// Cancel click events on different targets within timeframe.
|
|
// This avoids accidental clicks when the page is scrolled or updated due to the 300ms click event delay on mobiles.
|
|
removeEvent(document.body, 'click', wrongClickListener);
|
|
if (!clickReady() && getEventTarget(e) != t) cancelEvent(e);
|
|
}
|
|
setClickTimeout = function() {
|
|
// Update timeout during which click events will be blocked.
|
|
document.body.setAttribute('data-touchtimeout', new Date().getTime() + timeout);
|
|
},
|
|
clickReady = function() {
|
|
// Check if timeout during click events are blocked has expired.
|
|
var ti = document.body.getAttribute('data-touchtimeout');
|
|
return (ti === null || ti === '' || parseInt(ti, 10) < new Date().getTime());
|
|
};
|
|
// Apply appropriate actions according to each event type.
|
|
switch (e.type) {
|
|
case 'touchstart':
|
|
// Save initial touchstart coordinates and listen for touchend events and accidental click events.
|
|
var x = e.changedTouches[0].pageX,
|
|
y = e.changedTouches[0].pageY,
|
|
t = e.changedTouches[0].target;
|
|
setClickTimeout();
|
|
addEvent(t, 'touchend', touchEndListener);
|
|
addEvent(document.body, 'click', wrongClickListener);
|
|
setTimeout(function() {
|
|
removeEvent(document.body, 'click', wrongClickListener);
|
|
}, timeout);
|
|
break;
|
|
case 'click':
|
|
// Call callback on click in the absence of a recent touchstart event to prevent ghost clicks.
|
|
if (!clickReady()) return;
|
|
callback();
|
|
break;
|
|
}
|
|
}
|
|
|
|
function mobileMenuShow(e) {
|
|
// Show the mobile menu when the visitors touch the menu icon.
|
|
var show = function() {
|
|
var mm = document.getElementById('menusimple');
|
|
var ml = document.getElementById('langselect');
|
|
mm.style.display = ml.style.display = (mm.style.display == 'block') ? '' : 'block';
|
|
cancelEvent(e);
|
|
};
|
|
onTouchClick(e, show);
|
|
}
|
|
|
|
function mobileMenuHover(e) {
|
|
// Prevent mobile menu to shrink on hover to prevent accidental clicks on other entries.
|
|
var t = getEventTarget(e),
|
|
fn = (t.parentNode.className.indexOf('hover') === -1) ? addClass : removeClass,
|
|
initHover = function() {
|
|
if (t.nodeName != 'A') return;
|
|
var p = t;
|
|
while (p.parentNode.nodeName == 'UL' || p.parentNode.nodeName == 'LI') p = p.parentNode;
|
|
addClass(p, 'menutap');
|
|
for (var i = 0, nds = p.getElementsByTagName('LI'), n = nds.length; i < n; i++) {
|
|
if (nds[i] == t.parentNode) continue;
|
|
removeClass(nds[i], 'active');
|
|
if (nds[i].getElementsByTagName('UL').length > 0) continue;
|
|
removeClass(nds[i], 'hover');
|
|
}
|
|
while (t != p) {
|
|
if (t.nodeName == 'LI') {
|
|
fn(t, 'hover');
|
|
fn(t, 'active');
|
|
}
|
|
t = t.parentNode;
|
|
}
|
|
};
|
|
onTouchClick(e, initHover);
|
|
}
|
|
|
|
function addAnchorLinks() {
|
|
// Apply anchor links icon on each title displayed on CSS hover.
|
|
var nodes = [];
|
|
var tags = ['H2', 'H3', 'H4', 'H5', 'H6'];
|
|
for (var i = 0, n = tags.length; i < n; i++) {
|
|
for (var ii = 0, t = document.getElementsByTagName(tags[i]), nn = t.length; ii < nn; ii++) nodes.push(t[ii]);
|
|
}
|
|
for (var i = 0, n = nodes.length; i < n; i++) {
|
|
if (!nodes[i].id) continue;
|
|
if (nodes[i].getElementsByTagName('A').length > 0 && nodes[i].getElementsByTagName('A')[0].innerHTML == '') return;
|
|
addClass(nodes[i], 'anchorAf');
|
|
var anc = document.createElement('A');
|
|
anc.href = '#' + nodes[i].id;
|
|
nodes[i].insertBefore(anc, nodes[i].firstChild);
|
|
}
|
|
}
|