778 lines
26 KiB
JavaScript
778 lines
26 KiB
JavaScript
/**
|
|
* @license Hyphenopoly_Loader 3.1.1 - client side hyphenation
|
|
* ©2019 Mathias Nater, Zürich (mathiasnater at gmail dot com)
|
|
* https://github.com/mnater/Hyphenopoly
|
|
*
|
|
* Released under the MIT license
|
|
* http://mnater.github.io/Hyphenopoly/LICENSE
|
|
*/
|
|
|
|
/**
|
|
* Wrap all code in an iife to keep a scope. Important objects are parameters
|
|
* of this iife to keep codesize low.
|
|
* @param {Object} w shorthand for window
|
|
* @param {Object} d shorthand for document
|
|
* @param {Object} H shorthand for Hyphenopoly
|
|
* @param {Object} o shorthand for object
|
|
*/
|
|
(function H9YL(w, d, H, o) {
|
|
"use strict";
|
|
|
|
const store = sessionStorage;
|
|
const wa = w.WebAssembly;
|
|
const lcFallbacks = new Map();
|
|
const lcRequire = new Map();
|
|
|
|
/**
|
|
* Create Object without standard Object-prototype
|
|
* @returns {Object} empty object
|
|
*/
|
|
function empty() {
|
|
return o.create(null);
|
|
}
|
|
|
|
|
|
/**
|
|
* Shorthand for Object.keys(obj).forEach(function () {})
|
|
* @param {Object} obj the object to iterate
|
|
* @param {function} fn the function to execute
|
|
* @returns {undefined}
|
|
*/
|
|
function eachKey(obj, fn) {
|
|
o.keys(obj).forEach(fn);
|
|
}
|
|
|
|
/**
|
|
* Set H.cf (Hyphenopoly.clientFeatures) either by reading out previously
|
|
* computed settings from sessionStorage or creating an template object.
|
|
* This is in an iife to keep complexity low.
|
|
*/
|
|
(function configFeat() {
|
|
if (H.cacheFeatureTests && store.getItem("Hyphenopoly_Loader")) {
|
|
H.cf = JSON.parse(store.getItem("Hyphenopoly_Loader"));
|
|
} else {
|
|
H.cf = {
|
|
"langs": empty(),
|
|
"polyfill": false,
|
|
"wasm": null
|
|
};
|
|
}
|
|
}());
|
|
|
|
/**
|
|
* Set H.paths defaults or overwrite with user settings.
|
|
* This is in an iife to keep complexity low.
|
|
*/
|
|
(function configPaths() {
|
|
const maindir = (d.currentScript)
|
|
? d.currentScript.src.replace(/Hyphenopoly_Loader.js/i, "")
|
|
: "../";
|
|
const patterndir = maindir + "patterns/";
|
|
if (H.paths) {
|
|
H.paths.maindir = H.paths.maindir || maindir;
|
|
H.paths.patterndir = H.paths.patterndir || patterndir;
|
|
} else {
|
|
H.paths = o.create({
|
|
"maindir": maindir,
|
|
"patterndir": patterndir
|
|
});
|
|
}
|
|
}());
|
|
|
|
/**
|
|
* Set some H.setup fields to defaults or overwrite with user settings.
|
|
* This is in an iife to keep complexity low.
|
|
*/
|
|
(function configSetup() {
|
|
if (H.setup) {
|
|
H.setup.selectors = H.setup.selectors || {".hyphenate": {}};
|
|
H.setup.timeout = H.setup.timeout || 1000;
|
|
H.setup.hide = H.setup.hide || "all";
|
|
} else {
|
|
H.setup = {
|
|
"hide": "all",
|
|
"selectors": {".hyphenate": {}},
|
|
"timeout": 1000
|
|
};
|
|
}
|
|
}());
|
|
|
|
/**
|
|
* Copy required languages to local lcRequire and
|
|
* eventually fallbacks to local lcFallbacks.
|
|
* This is in an iife to keep complexity low.
|
|
*/
|
|
(function configRequire() {
|
|
eachKey(H.require, function copyRequire(k) {
|
|
// eslint-disable-next-line security/detect-object-injection
|
|
lcRequire.set(k.toLowerCase(), H.require[k]);
|
|
});
|
|
if (H.fallbacks) {
|
|
eachKey(H.fallbacks, function copyFallbacks(k) {
|
|
lcFallbacks.set(
|
|
k.toLowerCase(),
|
|
// eslint-disable-next-line security/detect-object-injection
|
|
H.fallbacks[k].toLowerCase()
|
|
);
|
|
});
|
|
}
|
|
}());
|
|
|
|
/**
|
|
* Define function H.toggle.
|
|
* This function hides or unhides (depending of the parameter state)
|
|
* the whole document (H.setup.hide == "all") or
|
|
* each selected element (H.setup.hide == "element") or
|
|
* text of each selected element (H.setup.hide == "text")
|
|
* @param {string} state State: either on (visible) or off (hidden)
|
|
*/
|
|
H.toggle = function toggle(state) {
|
|
if (state === "on") {
|
|
const stylesNode = d.getElementById("H9Y_Styles");
|
|
if (stylesNode) {
|
|
stylesNode.parentNode.removeChild(stylesNode);
|
|
}
|
|
} else {
|
|
const vis = " {visibility: hidden !important}\n";
|
|
const sc = d.createElement("style");
|
|
let myStyle = "";
|
|
sc.id = "H9Y_Styles";
|
|
switch (H.setup.hide) {
|
|
case "all":
|
|
myStyle = "html" + vis;
|
|
break;
|
|
case "element":
|
|
eachKey(H.setup.selectors, function eachSelector(sel) {
|
|
myStyle += sel + vis;
|
|
});
|
|
break;
|
|
case "text":
|
|
eachKey(H.setup.selectors, function eachSelector(sel) {
|
|
myStyle += sel + " {color: transparent !important}\n";
|
|
});
|
|
break;
|
|
default:
|
|
myStyle = "";
|
|
}
|
|
sc.appendChild(d.createTextNode(myStyle));
|
|
d.head.appendChild(sc);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Setup basic event system. Some events are defined but the definition of
|
|
* what happens when they are triggered is deferred to Hyphenopoly.js
|
|
* This is in an iife to keep complexity low.
|
|
*/
|
|
(function setupEvents() {
|
|
// Events known to the system
|
|
const definedEvents = new Map();
|
|
// Default events, execution deferred to Hyphenopoly.js
|
|
const deferred = [];
|
|
|
|
/*
|
|
* Eegister for custom event handlers, where event is not yet defined
|
|
* these events will be correctly registered in Hyphenopoly.js
|
|
*/
|
|
const tempRegister = [];
|
|
|
|
/**
|
|
* Create Event Object
|
|
* @param {string} name The Name of the event
|
|
* @param {function} defFunc The default method of the event
|
|
* @param {boolean} cancellable Is the default cancellable
|
|
* @returns {undefined}
|
|
*/
|
|
function define(name, defFunc, cancellable) {
|
|
definedEvents.set(name, {
|
|
"cancellable": cancellable,
|
|
"default": defFunc,
|
|
"register": []
|
|
});
|
|
}
|
|
|
|
define(
|
|
"timeout",
|
|
function def(e) {
|
|
H.toggle("on");
|
|
w.console.info(
|
|
"Hyphenopolys 'FOUHC'-prevention timed out after %dms",
|
|
e.delay
|
|
);
|
|
},
|
|
false
|
|
);
|
|
|
|
define(
|
|
"error",
|
|
function def(e) {
|
|
switch (e.lvl) {
|
|
case "info":
|
|
w.console.info(e.msg);
|
|
break;
|
|
case "warn":
|
|
w.console.warn(e.msg);
|
|
break;
|
|
default:
|
|
w.console.error(e.msg);
|
|
}
|
|
},
|
|
true
|
|
);
|
|
|
|
define(
|
|
"contentLoaded",
|
|
function def(e) {
|
|
deferred.push({
|
|
"data": e,
|
|
"name": "contentLoaded"
|
|
});
|
|
},
|
|
false
|
|
);
|
|
|
|
define(
|
|
"engineLoaded",
|
|
function def(e) {
|
|
deferred.push({
|
|
"data": e,
|
|
"name": "engineLoaded"
|
|
});
|
|
},
|
|
false
|
|
);
|
|
|
|
define(
|
|
"hpbLoaded",
|
|
function def(e) {
|
|
deferred.push({
|
|
"data": e,
|
|
"name": "hpbLoaded"
|
|
});
|
|
},
|
|
false
|
|
);
|
|
|
|
define(
|
|
"loadError",
|
|
function def(e) {
|
|
deferred.push({
|
|
"data": e,
|
|
"name": "loadError"
|
|
});
|
|
},
|
|
false
|
|
);
|
|
|
|
define(
|
|
"tearDown",
|
|
null,
|
|
true
|
|
);
|
|
|
|
/**
|
|
* Dispatch event <name> with arguments <data>
|
|
* @param {string} name The name of the event
|
|
* @param {Object|undefined} data Data of the event
|
|
* @returns {undefined}
|
|
*/
|
|
function dispatch(name, data) {
|
|
data = data || empty();
|
|
let defaultPrevented = false;
|
|
definedEvents.get(name).register.forEach(
|
|
function call(currentHandler) {
|
|
data.preventDefault = function preventDefault() {
|
|
if (definedEvents.get(name).cancellable) {
|
|
defaultPrevented = true;
|
|
}
|
|
};
|
|
currentHandler(data);
|
|
}
|
|
);
|
|
if (
|
|
!defaultPrevented &&
|
|
definedEvents.get(name).default
|
|
) {
|
|
definedEvents.get(name).default(data);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Add EventListender <handler> to event <name>
|
|
* @param {string} name The name of the event
|
|
* @param {function} handler Function to register
|
|
* @param {boolean} defer If the registration is deferred
|
|
* @returns {undefined}
|
|
*/
|
|
function addListener(name, handler, defer) {
|
|
if (definedEvents.has(name)) {
|
|
definedEvents.get(name).register.push(handler);
|
|
} else if (defer) {
|
|
tempRegister.push({
|
|
"handler": handler,
|
|
"name": name
|
|
});
|
|
} else {
|
|
H.events.dispatch(
|
|
"error",
|
|
{
|
|
"lvl": "warn",
|
|
"msg": "unknown Event \"" + name + "\" discarded"
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
if (H.handleEvent) {
|
|
eachKey(H.handleEvent, function add(name) {
|
|
/* eslint-disable security/detect-object-injection */
|
|
addListener(name, H.handleEvent[name], true);
|
|
/* eslint-enable security/detect-object-injection */
|
|
});
|
|
}
|
|
|
|
H.events = empty();
|
|
H.events.deferred = deferred;
|
|
H.events.tempRegister = tempRegister;
|
|
H.events.dispatch = dispatch;
|
|
H.events.define = define;
|
|
H.events.addListener = addListener;
|
|
}());
|
|
|
|
/**
|
|
* Feature test for wasm.
|
|
* @returns {boolean} support
|
|
*/
|
|
function runWasmTest() {
|
|
/*
|
|
* Wasm feature test with iOS bug detection
|
|
* (https://bugs.webkit.org/show_bug.cgi?id=181781)
|
|
*/
|
|
if (
|
|
typeof wa === "object" &&
|
|
typeof wa.Instance === "function"
|
|
) {
|
|
/* eslint-disable array-element-newline */
|
|
const module = new wa.Module(Uint8Array.from([
|
|
0, 97, 115, 109, 1, 0, 0, 0, 1, 6, 1, 96, 1, 127, 1, 127,
|
|
3, 2, 1, 0, 5, 3, 1, 0, 1, 7, 8, 1, 4, 116, 101, 115,
|
|
116, 0, 0, 10, 16, 1, 14, 0, 32, 0, 65, 1, 54, 2, 0, 32,
|
|
0, 40, 2, 0, 11
|
|
]));
|
|
/* eslint-enable array-element-newline */
|
|
return (new wa.Instance(module).exports.test(4) !== 0);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Load script by adding <script>-tag
|
|
* @param {string} path Where the script is stored
|
|
* @param {string} filename Filename of the script
|
|
* @returns {undefined}
|
|
*/
|
|
function loadScript(path, filename) {
|
|
const script = d.createElement("script");
|
|
script.src = path + filename;
|
|
if (filename === "hyphenEngine.asm.js") {
|
|
script.addEventListener("load", function listener() {
|
|
H.events.dispatch("engineLoaded", {"msg": "asm"});
|
|
});
|
|
}
|
|
d.head.appendChild(script);
|
|
}
|
|
|
|
const loadedBins = new Map();
|
|
|
|
/**
|
|
* Load binary files either with fetch (on new browsers that support wasm)
|
|
* or with xmlHttpRequest
|
|
* @param {string} path Where the script is stored
|
|
* @param {string} fne Filename of the script with extension
|
|
* @param {string} name Name of the ressource
|
|
* @param {Object} msg Message
|
|
* @returns {undefined}
|
|
*/
|
|
function loadBinary(path, fne, name, msg) {
|
|
/**
|
|
* Get bin file using fetch
|
|
* @param {string} p Where the script is stored
|
|
* @param {string} f Filename of the script with extension
|
|
* @param {string} n Name of the ressource
|
|
* @param {Object} m Message
|
|
* @returns {undefined}
|
|
*/
|
|
function fetchBinary(p, f, n, m) {
|
|
w.fetch(p + f).then(
|
|
function resolve(response) {
|
|
if (response.ok) {
|
|
if (n === "hyphenEngine") {
|
|
H.bins.set(n, response.arrayBuffer().then(
|
|
function getModule(buf) {
|
|
return new wa.Module(buf);
|
|
}
|
|
));
|
|
H.events.dispatch("engineLoaded", {"msg": m});
|
|
} else {
|
|
const files = loadedBins.get(f);
|
|
files.forEach(function eachHpb(rn) {
|
|
H.bins.set(
|
|
rn,
|
|
(files.length > 1)
|
|
? response.clone().arrayBuffer()
|
|
: response.arrayBuffer()
|
|
);
|
|
H.events.dispatch(
|
|
"hpbLoaded",
|
|
{"msg": rn}
|
|
);
|
|
});
|
|
}
|
|
} else {
|
|
H.events.dispatch("loadError", {
|
|
"file": f,
|
|
"msg": m,
|
|
"name": n,
|
|
"path": p
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get bin file using XHR
|
|
* @param {string} p Where the script is stored
|
|
* @param {string} f Filename of the script with extension
|
|
* @param {string} n Name of the ressource
|
|
* @param {Object} m Message
|
|
* @returns {undefined}
|
|
*/
|
|
function requestBinary(p, f, n, m) {
|
|
/* eslint-disable-next-line no-negated-condition */
|
|
const xhr = new XMLHttpRequest();
|
|
xhr.onload = function onload() {
|
|
if (xhr.status === 200) {
|
|
loadedBins.get(f).
|
|
forEach(function eachHpb(rn) {
|
|
H.bins.set(
|
|
rn,
|
|
xhr.response
|
|
);
|
|
H.events.dispatch(
|
|
"hpbLoaded",
|
|
{"msg": rn}
|
|
);
|
|
});
|
|
} else {
|
|
H.events.dispatch("loadError", {
|
|
"file": f,
|
|
"msg": m,
|
|
"name": n,
|
|
"path": p
|
|
});
|
|
}
|
|
};
|
|
xhr.open("GET", p + f);
|
|
xhr.responseType = "arraybuffer";
|
|
xhr.send();
|
|
}
|
|
if (!loadedBins.has(fne)) {
|
|
loadedBins.set(fne, [msg]);
|
|
if (H.cf.wasm) {
|
|
fetchBinary(path, fne, name, msg);
|
|
} else {
|
|
requestBinary(path, fne, name, msg);
|
|
}
|
|
} else if (name !== "hyphenEngine") {
|
|
loadedBins.get(fne).push(msg);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pre-Allocate memory for (w)asm
|
|
* Default is 32 wasm Pages (). For languages with larger .hpb
|
|
* files a higher value is needed.
|
|
* Get the value from baseData.heapSize in Hyphenopoly.js
|
|
* @param {string} lang Language
|
|
* @returns {undefined}
|
|
*/
|
|
function allocateMemory(lang) {
|
|
const specVal = new Map(
|
|
[["de", 54], ["hu", 205], ["nb-no", 91], ["nl", 41]]
|
|
);
|
|
const wasmPages = specVal.get(lang) || 32;
|
|
H.specMems = H.specMems || new Map();
|
|
if (H.cf.wasm) {
|
|
H.specMems.set(lang, new wa.Memory({
|
|
"initial": wasmPages,
|
|
"maximum": 256
|
|
}));
|
|
} else {
|
|
/* eslint-disable no-bitwise */
|
|
const asmPages = (2 << Math.floor(
|
|
Math.log(wasmPages) * Math.LOG2E
|
|
)) << 16;
|
|
/* eslint-enable no-bitwise */
|
|
H.specMems.set(lang, new ArrayBuffer(asmPages));
|
|
}
|
|
}
|
|
|
|
(function testClientFeatures() {
|
|
const tester = (function tester() {
|
|
let fakeBody = null;
|
|
/* eslint-disable array-element-newline */
|
|
const css = [
|
|
"visibility:hidden;",
|
|
"-moz-hyphens:auto;",
|
|
"-webkit-hyphens:auto;",
|
|
"-ms-hyphens:auto;",
|
|
"hyphens:auto;",
|
|
"width:48px;",
|
|
"font-size:12px;",
|
|
"line-height:12px;",
|
|
"border:none;",
|
|
"padding:0;",
|
|
"word-wrap:normal"
|
|
].join("");
|
|
/* eslint-enable array-element-newline */
|
|
|
|
/**
|
|
* Create and append div with CSS-hyphenated word
|
|
* @param {string} lang Language
|
|
* @returns {undefined}
|
|
*/
|
|
function create(lang) {
|
|
/* eslint-disable security/detect-object-injection */
|
|
if (H.cf.langs[lang]) {
|
|
return;
|
|
}
|
|
/* eslint-enable security/detect-object-injection */
|
|
fakeBody = fakeBody || d.createElement("body");
|
|
const testDiv = d.createElement("div");
|
|
testDiv.lang = lang;
|
|
testDiv.style.cssText = css;
|
|
testDiv.appendChild(d.createTextNode(lcRequire.get(lang)));
|
|
fakeBody.appendChild(testDiv);
|
|
}
|
|
|
|
/**
|
|
* Append fakeBody with tests to target (document)
|
|
* @param {Object} target Where to append fakeBody
|
|
* @returns {Object|null} The body element or null, if no tests
|
|
*/
|
|
function append(target) {
|
|
if (fakeBody) {
|
|
target.appendChild(fakeBody);
|
|
return fakeBody;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Remove fakeBody
|
|
* @returns {undefined}
|
|
*/
|
|
function clear() {
|
|
if (fakeBody) {
|
|
fakeBody.parentNode.removeChild(fakeBody);
|
|
}
|
|
}
|
|
return {
|
|
"append": append,
|
|
"clear": clear,
|
|
"create": create
|
|
};
|
|
}());
|
|
|
|
/**
|
|
* Checks if hyphens (ev.prefixed) is set to auto for the element.
|
|
* @param {Object} elm - the element
|
|
* @returns {Boolean} result of the check
|
|
*/
|
|
function checkCSSHyphensSupport(elm) {
|
|
return (
|
|
elm.style.hyphens === "auto" ||
|
|
elm.style.webkitHyphens === "auto" ||
|
|
elm.style.msHyphens === "auto" ||
|
|
elm.style["-moz-hyphens"] === "auto"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Expose the hyphenate-function of a specific language to
|
|
* Hyphenopoly.hyphenators.<language>
|
|
*
|
|
* Hyphenopoly.hyphenators.<language> is a Promise that fullfills
|
|
* to hyphenate(entity, sel) as soon as the ressources are loaded
|
|
* and the engine is ready.
|
|
* If Promises aren't supported (e.g. IE11) a error message is produced.
|
|
*
|
|
* @param {string} lang - the language
|
|
* @returns {undefined}
|
|
*/
|
|
function exposeHyphenateFunction(lang) {
|
|
/* eslint-disable security/detect-object-injection */
|
|
H.hyphenators = H.hyphenators || empty();
|
|
if (!H.hyphenators[lang]) {
|
|
if (w.Promise) {
|
|
H.hyphenators[lang] = new Promise(function pro(rs, rj) {
|
|
H.events.addListener("engineReady", function handler(e) {
|
|
if (e.msg === lang) {
|
|
rs(H.createHyphenator(e.msg));
|
|
}
|
|
}, true);
|
|
H.events.addListener("loadError", function handler(e) {
|
|
if (e.name === lang || e.name === "hyphenEngine") {
|
|
rj(new Error("File " + e.file + " can't be loaded from " + e.path));
|
|
}
|
|
}, false);
|
|
});
|
|
H.hyphenators[lang].catch(function catchPromiseError(e) {
|
|
H.events.dispatch(
|
|
"error",
|
|
{
|
|
"lvl": "error",
|
|
"msg": e.message
|
|
}
|
|
);
|
|
});
|
|
} else {
|
|
H.hyphenators[lang] = {
|
|
|
|
/**
|
|
* Fires an error message, if then is called
|
|
* @returns {undefined}
|
|
*/
|
|
"then": function () {
|
|
H.events.dispatch(
|
|
"error",
|
|
{"msg": "Promises not supported in this engine. Use a polyfill."}
|
|
);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
/* eslint-enable security/detect-object-injection */
|
|
}
|
|
|
|
/**
|
|
* Load .hpb files
|
|
* @param {string} lang The language
|
|
* @returns {undefined}
|
|
*/
|
|
function loadPattern(lang) {
|
|
let filename = lang + ".hpb";
|
|
let langFallback = lang;
|
|
H.cf.polyfill = true;
|
|
// eslint-disable-next-line security/detect-object-injection
|
|
H.cf.langs[lang] = "H9Y";
|
|
if (lcFallbacks && lcFallbacks.has(lang)) {
|
|
langFallback = lcFallbacks.get(lang);
|
|
filename = langFallback + ".hpb";
|
|
}
|
|
H.bins = H.bins || new Map();
|
|
loadBinary(H.paths.patterndir, filename, langFallback, lang);
|
|
}
|
|
|
|
if (H.cf.wasm === null) {
|
|
H.cf.wasm = runWasmTest();
|
|
}
|
|
lcRequire.forEach(function eachReq(value, lang) {
|
|
if (value === "FORCEHYPHENOPOLY" ||
|
|
// eslint-disable-next-line security/detect-object-injection
|
|
(H.cf.langs[lang] && H.cf.langs[lang] === "H9Y")
|
|
) {
|
|
loadPattern(lang);
|
|
} else {
|
|
tester.create(lang);
|
|
}
|
|
});
|
|
|
|
const testContainer = tester.append(d.documentElement);
|
|
if (testContainer !== null) {
|
|
const nl = testContainer.getElementsByTagName("div");
|
|
eachKey(nl, function eachNode(n) {
|
|
/* eslint-disable security/detect-object-injection */
|
|
if (checkCSSHyphensSupport(nl[n]) && nl[n].offsetHeight > 12) {
|
|
H.cf.langs[nl[n].lang] = "CSS";
|
|
} else {
|
|
loadPattern(nl[n].lang);
|
|
}
|
|
/* eslint-enable security/detect-object-injection */
|
|
});
|
|
tester.clear();
|
|
}
|
|
if (H.cf.polyfill) {
|
|
loadScript(H.paths.maindir, "Hyphenopoly.js");
|
|
if (H.cf.wasm) {
|
|
loadBinary(
|
|
H.paths.maindir,
|
|
"hyphenEngine.wasm",
|
|
"hyphenEngine",
|
|
"wasm"
|
|
);
|
|
} else {
|
|
loadScript(H.paths.maindir, "hyphenEngine.asm.js");
|
|
}
|
|
eachKey(H.cf.langs, function prepareEach(lang) {
|
|
/* eslint-disable security/detect-object-injection */
|
|
if (H.cf.langs[lang] === "H9Y") {
|
|
allocateMemory(lang);
|
|
exposeHyphenateFunction(lang);
|
|
}
|
|
/* eslint-enable security/detect-object-injection */
|
|
});
|
|
}
|
|
}());
|
|
|
|
/**
|
|
* Hides the specified elements and starts the process by
|
|
* dispatching a "contentLoaded"-event in Hyphenopoly
|
|
* @returns {undefined}
|
|
*/
|
|
function handleDCL() {
|
|
if (H.setup.hide.match(/^(?:element|text)$/)) {
|
|
H.toggle("off");
|
|
}
|
|
H.events.dispatch(
|
|
"contentLoaded",
|
|
{"msg": ["contentLoaded"]}
|
|
);
|
|
}
|
|
|
|
if (H.cf.polyfill) {
|
|
if (H.setup.hide === "all") {
|
|
H.toggle("off");
|
|
}
|
|
if (H.setup.hide !== "none") {
|
|
H.setup.timeOutHandler = w.setTimeout(function timedOut() {
|
|
H.toggle("on");
|
|
H.events.dispatch("timeout", {"delay": H.setup.timeout});
|
|
}, H.setup.timeout);
|
|
}
|
|
if (d.readyState === "loading") {
|
|
d.addEventListener(
|
|
"DOMContentLoaded",
|
|
handleDCL,
|
|
{
|
|
"once": true,
|
|
"passive": true
|
|
}
|
|
);
|
|
} else {
|
|
handleDCL();
|
|
}
|
|
} else {
|
|
H.events.dispatch("tearDown", {});
|
|
w.Hyphenopoly = null;
|
|
}
|
|
|
|
if (H.cacheFeatureTests) {
|
|
store.setItem(
|
|
"Hyphenopoly_Loader",
|
|
JSON.stringify(H.cf)
|
|
);
|
|
}
|
|
}(window, document, Hyphenopoly, Object));
|