Skip to content

Instantly share code, notes, and snippets.

@Sakurina
Created October 27, 2010 15:13
Show Gist options
  • Save Sakurina/649219 to your computer and use it in GitHub Desktop.
Save Sakurina/649219 to your computer and use it in GitHub Desktop.
jsss - party like it's 1996, stylesheets in JavaScript, Netscape Communicator 4 style.
/*
* jsss - party like it's 1996
* by Yanik Magnan - http://r-ch.net
*
* A toy implementation of sorts for Netscape's long-gone CSS
* competitor, JavaScript Stylesheets. Please don't use this
* in production code. Really.
*
* Bits of the spec[1] this more or less conforms to:
* 1 - Basic Concepts
* Tags' style attributes can be changed through document.tags
* or simply 'tags'. Currently, tag names are case-sensitive.
* 1.1 - Containment in HTML
* Currently, only using <style type="text/javascript"> will
* cause your stylesheet to get loaded. Style attributes will
* likely never be supported, as that would conflict with CSS.
* <link rel=stylesheet> support may be added later.
* 1.3 - Class as Selector
* Classes can be operated on the same way tags currently can,
* so a declaration like "classes.punk.color = '#00FF00'" is valid
* but "classes.punk.all.color = '#00FF00'" is not, despite being
* lifted directly from the spec.
* 1.7 - Comments, 3.2 - Evaluating Expressions for Property Values
* No comment needed; this is handled by JS itself.
* 3.3 - Simplifying Assignment Using Methods
* .margins and .paddings are available on tags and classes.
* 5.* - Formatting model
* Handled by the browsers already.
* 6.* - Properties
* All properties supported by JSSS are present, and tend to be
* the same name as members of CSSStyleDeclaration objects.
* 7.1 - Length Units
*
* [1]: http://www.w3.org/Submission/1996/1/WD-jsss-960822
*
* TO DO:
* 1.4 - ID as Selector
* 1.5 - Combining Classes and ID as Selectors
* 1.6 - Contextual Selectors
* 2.* - Typographical Elements
* 3.1 - Assigning Style-Evaluating Functions
* 4.* - Precedence Rules
* 7.2 - Color Units
* 7.4 - URL
* Testing.
* Find a use for this other than lulz.
*/
/*
* onDOMReady
* Copyright (c) 2009 Ryan Morr (ryanmorr.com)
* Licensed under the MIT license.
*/
function onDOMReady(fn,ctx){var ready,timer;var onStateChange=function(e){if(e&&e.type=="DOMContentLoaded"){fireDOMReady()}else if(e&&e.type=="load"){fireDOMReady()}else if(document.readyState){if((/loaded|complete/).test(document.readyState)){fireDOMReady()}else if(!!document.documentElement.doScroll){try{ready||document.documentElement.doScroll('left')}catch(e){return}fireDOMReady()}}};var fireDOMReady=function(){if(!ready){ready=true;fn.call(ctx||window);if(document.removeEventListener)document.removeEventListener("DOMContentLoaded",onStateChange,false);document.onreadystatechange=null;window.onload=null;clearInterval(timer);timer=null}};if(document.addEventListener)document.addEventListener("DOMContentLoaded",onStateChange,false);document.onreadystatechange=onStateChange;timer=setInterval(onStateChange,5);window.onload=onStateChange};
/* Back to regularly-scheduled programming... */
var tags = undefined;
var classes = undefined;
var _jsssTagList = [];
var _jsssClassList = [];
function createTagHierarchy() {
document.tags = {}; tags = document.tags;
document.classes = {}; classes = document.classes;
var allTags = document.getElementsByTagName("*");
for (var i=0; i<allTags.length; i++) {
var tag = allTags[i].nodeName;
if (eval("document.tags."+tag) == undefined) {
eval("document.tags."+tag+" = new JSSSStyleObject();");
_jsssTagList.push(tag); }
var klass = allTags[i].className;
if (!klass == "" && !/ /.test(klass) && !/-/.test(klass))
if (eval("document.classes."+klass) == undefined) {
eval("document.classes."+klass+" = new JSSSStyleObject();");
_jsssClassList.push(klass); }
}
}
/* Style Object */
function JSSSStyleObject() {
// This object represents a style class or an HTML tag.
var attrList = ["fontSize", "fontStyle", "lineHeight", // fonts
"color", "background", "bgColor", // colors
"wordSpacing", "letterSpacing", "textDecoration", "verticalAlign",
"textTransform", "textAlign", "textIndent", // text
"leftMargin", "rightMargin", "topMargin", "bottomMargin",
"topPadding", "bottomPadding", "leftPadding", "rightPadding",
"borderStyle", "borderWidth", "width", "height", "float", "clear", // box
"display", "listStyle", "whiteSpace" // classification
];
for (var i=0; i<attrList.length; i++)
eval("this."+attrList[0]+" = undefined;");
this.margins = function(t,r,b,l) {
this.topMargin = t;
this.rightMargin = r;
this.bottomMargin = b;
this.leftMargin = l;
}
this.paddings = function(t,r,b,l) {
this.topPadding = t;
this.rightPadding = r;
this.bottomPadding = b;
this.leftPadding = l;
}
this.applyStyles = function(sd) {
for (var i=0; i<attrList.length; i++)
eval("sd."+attrList[i]+" = this."+attrList[i]+";");
}
}
/* Find and Eval Stylesheets */
function findAndEvalLinkStylesheets() {
console.log("To be implemented");
}
function findAndEvalStyleStylesheets() {
var styles = document.getElementsByTagName("style");
for (var i=0; i<styles.length; i++) {
var style = styles[i];
if (style.hasAttribute("type"))
if (style.getAttribute("type") == "text/javascript")
eval(style.childNodes[0].nodeValue);
}
}
function applyStyles() {
// Classes
for (var i=0; i<_jsssClassList.length; i++) {
var klassEls = document.getElementsByClassName(_jsssClassList[i]);
for (var j=0; j<klassEls.length; j++) {
var styleObject = eval("document.classes."+_jsssClassList[i]);
var styleDeclaration = klassEls[j].style;
styleObject.applyStyles(styleDeclaration);
}
}
// Tags
for (var i=0; i<_jsssTagList.length; i++) {
var tagEls = document.getElementsByTagName(_jsssTagList[i]);
for (var j=0; j<tagEls.length; j++) {
var styleObject = eval("document.tags."+_jsssTagList[i]);
var styleDeclaration = tagEls[j].style;
styleObject.applyStyles(styleDeclaration);
}
}
}
function loadJSSS() {
createTagHierarchy();
findAndEvalStyleStylesheets();
applyStyles();
}
onDOMReady(loadJSSS);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment