-
-
Save gbakernet/1205005 to your computer and use it in GitHub Desktop.
Example of ES6 Proxy
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
<!DOCTYPE html> | |
<!-- | |
This is a simple experiment relying on ECMAScript 6 Proxies. To try this out, | |
use Aurora (http://www.mozilla.org/en-US/firefox/channel/). | |
The goal was to create a HTML writer where the method names were really just | |
the HTML tags names, but without manually creating each method. This uses | |
a Proxy to create a shell to an underlying writer object that checks each | |
method name to see if it's in a list of known tags. | |
--> | |
<html> | |
<body> | |
<script> | |
/* | |
* The constructor name I want is HTMLWriter. | |
*/ | |
var HTMLWriter = (function(){ | |
/* | |
* Lazily-incomplete list of HTML tags. | |
*/ | |
var tags = [ | |
"a", "abbr", "acronym", "address", "applet", "area", | |
"b", "base", "basefont", "bdo", "big", "blockquote", | |
"body", "br", "button", | |
"caption", "center", "cite", "code", "col", "colgroup", | |
"dd", "del", "dir", "div", "dfn", "dl", "dt", | |
"em", | |
"fieldset", "font", "form", "frame", "frameset", | |
"h1", "h2", "h3", "h4", "h5", "h6", "head", "hr", "html", | |
"i", "iframe", "img", "input", "ins", "isindex", | |
"kbd", | |
"label", "legend", "li", "link", | |
"map", "menu", "meta", | |
"noframes", "noscript", | |
"object", "ol", "optgroup", "option", | |
"p", "param", "pre", | |
"q", | |
"s", "samp", "script", "select", "small", "span", "strike", | |
"strong", "style", "sub", "sup", | |
"table", "tbody", "td", "textarea", "tfoot", "th", "thead", | |
"title", "tr", "tt", | |
"u", "ul", | |
"var" | |
]; | |
/* | |
* Define an internal-only type. Code taken from: | |
* http://www.nczonline.net/blog/2009/02/17/mozilla-javascript-extension-nosuchmethod/ | |
*/ | |
function InternalHTMLWriter(){ | |
this._work = []; | |
} | |
InternalHTMLWriter.prototype = { | |
escape: function (text){ | |
return text.replace(/[><"&]/g, function(c){ | |
switch(c){ | |
case ">": return ">"; | |
case "<": return "<"; | |
case "\"": return """; | |
case "&": return "&"; | |
} | |
}); | |
}, | |
startTag: function(tagName, attributes){ | |
this._work.push("<" + tagName); | |
if (attributes){ | |
var name, value; | |
for (name in attributes){ | |
if (attributes.hasOwnProperty(name)){ | |
value = this.escape(attributes[name]); | |
this._work.push(" " + name + "=\"" + value + "\""); | |
} | |
} | |
} | |
this._work.push(">"); | |
return this; | |
}, | |
text: function(text){ | |
this._work.push(this.escape(text)); | |
return this; | |
}, | |
endTag: function(tagName){ | |
this._work.push("</" + tagName + ">"); | |
return this; | |
}, | |
toString: function(){ | |
return this._work.join(""); | |
} | |
}; | |
/* | |
* Output a pseudo-constructor. It's not a real constructor, | |
* since it just returns the proxy object, but I like the | |
* "new" pattern vs. factory functions. | |
*/ | |
return function(){ | |
var writer = new InternalHTMLWriter(), | |
proxy = Proxy.create({ | |
/* | |
* Only really need getter, don't want anything else going on. | |
*/ | |
get: function(receiver, name){ | |
var tagName, | |
closeTag = false; | |
if (name in writer){ | |
return writer[name]; | |
} else { | |
if (tags.indexOf(name) > -1){ | |
tagName = name; | |
} else if (name.charAt(0) == "x" && tags.indexOf(name.substring(1)) > -1){ | |
tagName = name.substring(1); | |
closeTag = true; | |
} | |
if (tagName){ | |
return function(){ | |
if (!closeTag){ | |
writer.startTag(tagName, arguments[0]); | |
} else { | |
writer.endTag(tagName); | |
} | |
return receiver; | |
}; | |
} | |
} | |
}, | |
/* | |
* Don't allow fixing. | |
*/ | |
fix: function(){ | |
return undefined; | |
} | |
}); | |
return proxy; | |
}; | |
})(); | |
//hmmm...doesn't look like magic way down here | |
var w = new HTMLWriter(); | |
w.html() | |
.head().title().text("Example & Test").xtitle().xhead() | |
.body().text("Hello world!").xbody() | |
.xhtml(); | |
console.log(w); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment