Skip to content

Instantly share code, notes, and snippets.

@Coconuthack
Created May 17, 2013 12:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Coconuthack/5598837 to your computer and use it in GitHub Desktop.
Save Coconuthack/5598837 to your computer and use it in GitHub Desktop.
Eloquent JS CH12 & 13 DOm and Browser Events
//Eloquent javascript - CH12
//Functions relating to the DOM
//Helper functions form other chapters
function escapeHTML(text) {
var replacements = [["&", "&"], ["\"", """],
["<", "&lt;"], [">", "&gt;"]];
forEach(replacements, function(replace) {
text = text.replace(replace[0], replace[1]);
});
return text;
}
function forEach(array, action) {
for (var i = 0; i < array.length; i++)
action(array[i]);
}
function map(func, array) {
//returns an array
//each element is the result of func applied
//to each element in the input array
var result = [];
forEach(array, function (element) {
result.push(func(element));
});
return result;
}
function isTextNode(node) {
return node.nodeType == 3;
}
function isImage(node) {
return !isTextNode(node) && node.nodeName == "IMG";
}
function asHTML(node) {
//given dome node produces string
//representing HTML text for that node and its children
if (isTextNode(node)){
return escapeHTML(node.nodeValue);
}
else if (node.firstChild) { // node.chidNodes.length == 0
return "<" + node.nodeName + "/>";
}
else {
return "<" + node.nodeName + ">"
map(asHTML, node.childNodes).join("") +
"</" + node.nodeName + ">";
}
}
function $(id) {
return document.getElementById(id);
}
//Example creating new nodes
var secondHeader = document.createElement("H1");
var secondTitle = document.createTextNode("Chapter 2: Deep magic");
//Next, we'll want to put the title name into the h1 element, and then add the element to the document.
secondHeader.appendChild(secondTitle);
document.body.appendChild(secondHeader);
//Ex 2
var newImage = document.createElement("IMG");
newImage.setAttribute("src", "img/Hiva Oa.png");
document.body.appendChild(newImage);
//Workaround IE broswer compatibility
function setNodeAttribute(node, attribute, value) {
if (attribute == "class")
node.className = value;
else if (attribute == "checked")
node.defaultChecked = value;
else if (attribute == "for")
node.htmlFor = value;
else if (attribute == "style")
node.style.cssText = value;
else
node.setAttribute(attribute, value);
}
//simple function for building DOM elements
function dom(name, attributes) {
//arg 1 : tag name, arg 2 : object containing attributes of node, or null when no attr needd
//arg 2+ : added to the node as child nodes, if string made into text node
var node = document.createElement(name);
if (attributes) {
forEachIn(attributes, function(name, value) {
setNodeAttribute(node, name, value);
});
}
for (var i = 2; i < arguments.length; i++) {
var child = arguments[i];
if (typeof child == "string")
child = document.createTextNode(child);
node.appendChild(child);
}
return node;
}
var newParagraph =
dom("P", null, "A paragraph with a ",
dom("A", {href: "http://en.wikipedia.org/wiki/Alchemy"},
"link"),
" inside of it.");
document.body.appendChild(newParagraph);
//other way creatin a new node
var link = newParagraph.childNodes[1];
newParagraph.insertBefore(dom("STRONG", null, "great "), link); // inserts the STRONG taag before the 2nd child
newParagraph.replaceChild(document.createTextNode("lousy "), newParagraph.childNodes[1]);
function removeElement(node) {
if (node.parentNode)
node.parentNode.removeChild(node);
}
//makeTable function
//takes two array as args
//1 : js object it should summarise
//2 : strings column names
function makeTable(data, columns) {
var headRow = dom("TR"); // creates the head row
forEach(columns, function(name) {
headRow.appendChild(dom("TH", null, name));
}); //ads t
var body = dom("TBODY", null, headRow);
forEach(data, function(object) {
var row = dom("TR");
forEach(columns, function(name) {
row.appendChild(dom("TD", null, String(object[name])));
});
body.appendChild(row);
});
return dom("TABLE", null, body);
}
var table = makeTable(document.body.childNodes,
["nodeType", "tagName"]);
document.body.appendChild(table);
//playing with the position of a node , spinning it around
$("picture").style.position = "absolute";
var angle = 0;
var spin = setInterval(function() {
angle += 0.1;
$("picture").style.left = (100 + 100 * Math.cos(angle)) + "px";
$("picture").style.top = (100 + 100 * Math.sin(angle)) + "px";
}, 100);
//Registering Event handler function abstraction
if (typeof document.addEventListener == "function")
var registerEventHandler = function(node, event, handler) {
node.addEventListener(event, handler, false);
};
else
var registerEventHandler = function(node, event, handler) {
node.attachEvent("on" + event, handler);
};
function unregisterEventHandler(node, event, handler) {
if (typeof node.removeEventListener == "function")
node.removeEventListener(event, handler, false);
else
node.detachEvent("on" + event, handler);
}
function showEvent(event) {
show(event || window.event);
}
registerEventHandler($("textfield"), "keypress", showEvent);
//this handler attached to the whole document intercepts all mouse clicks
// and prints some info
function reportClick(event) {
event = event || window.event;
var target = event.target || event.srcElement;
var pageX = event.pageX, pageY = event.pageY;
if (pageX == undefined) {
pageX = event.clientX + document.body.scrollLeft;
pageY = event.clientY + document.body.scrollTop;
}
print("Mouse clicked at ", pageX, ", ", pageY,
". Inside element:");
show(target);
}
// write a function to 'normalise' event objects to work the same across browsers
function printCharacter(event) {
event = event || window.event;
var charCode = event.charCode;
if (charCode == undefined || charCode === 0)
charCode = event.keyCode;
print("Character '", String.fromCharCode(charCode), "'");
}
registerEventHandler($("textfield"), "keypress", printCharacter);
//Broswer Incompatibilites
//Solution : Event normaliser function
function normaliseEvent(event) {
if (!event.stopPropagation) {
event.stopPropagation = function() {this.cancelBubble = true;};
event.preventDefault = function() {this.returnValue = false;};
}
if (!event.stop) { //counter the bubbling
event.stop = function() {
this.stopPropagation();
this.preventDefault();
};
}
if (event.srcElement && !event.target)
event.target = event.srcElement;
if ((event.toElement || event.fromElement) && !event.relatedTarget)
event.relatedTarget = event.toElement || event.fromElement;
if (event.clientX != undefined && event.pageX == undefined) {
event.pageX = event.clientX + document.body.scrollLeft;
event.pageY = event.clientY + document.body.scrollTop;
}
if (event.type == "keypress") {
if (event.charCode === 0 || event.charCode == undefined)
event.character = String.fromCharCode(event.keyCode);
else
event.character = String.fromCharCode(event.charCode);
}
return event;
}
function addHandler(node, type, handler) {
function wrapHandler(event) {
handler(normaliseEvent(event || window.event));
}
registerEventHandler(node, type, wrapHandler);
return {node: node, type: type, handler: wrapHandler};
}
function removeHandler(object) {
unregisterEventHandler(object.node, object.type, object.handler);
}
var blockQ = addHandler($("textfield"), "keypress", function(event) {
if (event.character.toLowerCase() == "q")
event.stop();
});
//The new addHandler function wraps the handler function it is given in
// a new function, so it can take care of normalising the event objects.
// It returns an object that can be given to removeHandler when we want to
// remove this specific handler.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment