Created
May 17, 2013 12:54
-
-
Save Coconuthack/5598837 to your computer and use it in GitHub Desktop.
Eloquent JS CH12 & 13 DOm and Browser Events
This file contains hidden or 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
//Eloquent javascript - CH12 | |
//Functions relating to the DOM | |
//Helper functions form other chapters | |
function escapeHTML(text) { | |
var replacements = [["&", "&"], ["\"", """], | |
["<", "<"], [">", ">"]]; | |
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