Created
July 5, 2020 19:12
-
-
Save mmastrac/6d148c42fe4db832025aa05ef8dbaed1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var Stylus = { | |
inject: function(what, loadCallback) { | |
return createInjector(what, loadCallback); | |
}, | |
}; | |
var STYLUS_STATUS_ID = '__STYLUS_style_el'; | |
var Injector = function() {}; | |
Injector.prototype = { | |
remove: function() { | |
throw "remove() is not yet implemented"; | |
}, | |
_trackLoad: function(elem, cb) { | |
var self = this; | |
elem.addEventListener('load', function() { | |
self._inject(cb()); | |
}); | |
elem.addEventListener('DOMContentLoaded', function() { | |
self._inject(cb()); | |
}); | |
self._inject(cb()); | |
}, | |
_inject: function(doc) { | |
if (!doc || doc === this._currentDoc) { | |
return; | |
} | |
this._currentDoc = doc; | |
if (this._loadCallback) { | |
try { | |
this._loadCallback(doc); | |
} catch (e) { | |
console.log("Load callback failure", e); | |
} | |
} | |
this._refreshCss(doc); | |
}, | |
_refreshCss: function(doc) { | |
var self = this; | |
if (!doc || doc !== this._currentDoc) { | |
console.log("Document is no longer valid, stopping updates."); | |
return; | |
} | |
var wnd = doc.defaultView; | |
// Figure out if we've already injected a style | |
var old = doc.getElementById(STYLUS_STATUS_ID); | |
// Create our new, pending style (use the XHTML namespace for SVG + HTML) | |
var css = doc.createElementNS('http://www.w3.org/1999/xhtml', 'link'); | |
css.rel = "stylesheet"; | |
css.href = "/style.css?t=" + new Date().valueOf(); | |
css.onload = function() { | |
if (old) { | |
old.remove(); | |
} | |
css.id = STYLUS_STATUS_ID; | |
wnd.setTimeout(function() { | |
self._refreshCss(doc); | |
}, 1000); | |
} | |
css.onerror = function() { | |
css.remove(); | |
wnd.setTimeout(function() { | |
self._refreshCss(doc); | |
}, 1000); | |
} | |
if (old) { | |
// Place the new style next to the old one if it exists | |
old.insertAdjacentElement("afterend", css); | |
} else { | |
// Otherwise insert a new element | |
var parent = (doc.head || doc.body || doc.documentElement); | |
if (parent) { | |
console.log("Inserting new CSS link, parent = " + parent.tagName + " namespace = " + parent.namespaceURI); | |
parent.appendChild(css); | |
} else { | |
throw "Invalid parent element"; | |
} | |
} | |
} | |
}; | |
function createInjector(what, loadCallback) { | |
var injector = new Injector(); | |
injector._loadCallback = loadCallback; | |
if (!what) { | |
throw "Invalid null argument to createInjector"; | |
} | |
if (what instanceof HTMLElement) { | |
if (what.tagName === "OBJECT" || what.tagName === "IFRAME") { | |
injector._trackLoad(what, function() { return what.contentDocument; }); | |
return injector; | |
} | |
} | |
if (what instanceof HTMLDocument) { | |
injector._inject(what); | |
return injector; | |
} | |
if (what instanceof Window && what.document) { | |
injector._inject(what.document); | |
return injector; | |
} | |
throw "Invalid argument to createInjector: must be a document/window or an <OBJECT>/<IFRAME> element"; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment