Last active
July 12, 2016 08:26
-
-
Save swedishkid/deddb8d1a4d4249d74ac4e58e495d1c2 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
String.prototype.toDOM = function () { | |
var d = document | |
, i | |
, a = d.createElement("div") | |
, b = d.createDocumentFragment(); | |
a.innerHTML = this; | |
while (i = a.firstChild) b.appendChild(i); | |
return b; | |
}; | |
var Primer = (function (document) { | |
var core = {}; | |
function hookupEvents() { | |
var doc = document; | |
var htm = doc.documentElement; | |
var lct = null; // last click target | |
var nearest = function (elm, tag) { | |
while (elm && elm.nodeName != tag) { | |
elm = elm.parentNode; | |
} | |
return elm; | |
}; | |
var nearestElementWithRel = function(elm) { | |
while (elm && elm.attributes && !elm.attributes.rel) { | |
elm = elm.parentNode; | |
} | |
return elm; | |
} | |
function handler(e) { | |
e = e || window.event; | |
lct = e.target || e.srcElement; | |
var elem = nearestElementWithRel(lct); | |
if (!elem) { | |
return; | |
} | |
if (!elem.getAttribute('rel')) { | |
return; | |
} | |
var href = elem.getAttribute('data-ajax') || elem.href; | |
var parts = elem.getAttribute('rel').split(':'); | |
var eventType = parts[0]; | |
var component = parts[1]; | |
if (parts.length === 3) { | |
console.log(parts[2]); | |
} | |
if (e.type !== eventType) { | |
return; | |
} | |
switch (component) { | |
case 'recipe': | |
console.log('Should call ' + href); | |
var formData = new FormData(); | |
console.log(elem.attributes); | |
for (var j = 0; j < elem.attributes.length; j++) { | |
var attr = elem.attributes[j]; | |
if(attr.name.startsWith('data-')){ | |
formData.append(attr.name.replace('data-', ''), attr.value); | |
} | |
} | |
var r = new XMLHttpRequest(); | |
r.open("POST", href, true); | |
r.onreadystatechange = function () { | |
if (r.readyState != 4 || r.status != 200) return; | |
var model = JSON.parse(r.responseText); | |
if (model.recipes) { | |
for (var i = 0; i < model.recipes.length; i++) { | |
var recipe = model.recipes[i]; | |
switch (recipe.type) { | |
case 'prepend': | |
console.log('Attempting to select ' + recipe.selector); | |
var element = document.querySelector(recipe.selector); | |
if (element) { | |
if (element.parentElement) { | |
element.parentElement.insertBefore(recipe.content.toDOM(), element.parentElement.firstChild); | |
} else { | |
console.log('Element with selector ' + selector + ' does not have parentnode'); | |
} | |
} else { | |
console.log('Element with selector ' + selector + ' was not found'); | |
} | |
break; | |
case 'append': | |
var element = document.querySelector(recipe.selector); | |
element.appendChild(recipe.content.toDOM()); | |
break; | |
case 'replace': | |
var element = document.querySelector(recipe.selector); | |
element.outerHTML = recipe.content; | |
break; | |
case 'focus': | |
var element = document.querySelector(recipe.selector); | |
element.focus(); | |
break; | |
case 'moveCaretToEnd': | |
var element = document.querySelector(recipe.selector); | |
element.setSelectionRange(element.value.length, element.value.length); | |
break; | |
case 'autoResize': | |
var element = document.querySelector(recipe.selector); | |
var resize = function() { | |
element.style.height = 'auto'; | |
element.style.height = element.scrollHeight + 'px'; | |
}; | |
var delayedResize = function () { | |
window.setTimeout(resize, 0); | |
}; | |
if (window.attachEvent) { | |
element.attachEvent('onchange', delayedResize); | |
element.attachEvent('oncut', delayedResize); | |
element.attachEvent('onpaste', delayedResize); | |
element.attachEvent('ondrop', delayedResize); | |
element.attachEvent('onkeydown', delayedResize); | |
} else { | |
element.addEventListener('change', delayedResize, false); | |
element.addEventListener('cut', delayedResize, false); | |
element.addEventListener('paste', delayedResize, false); | |
element.addEventListener('drop', delayedResize, false); | |
element.addEventListener('keydown', delayedResize, false); | |
} | |
resize(); | |
default: | |
console.log('Cannot handle recipe type: ' + recipe.type); | |
} | |
} | |
} | |
}; | |
r.send(formData); | |
return false; | |
default: | |
return; | |
} | |
}; | |
htm.onclick = handler; | |
htm.ondblclick = handler; | |
//htm.onchange = handler; | |
//htm.onmouseover = handler; | |
//htm.onmouseout = handler; | |
//htm.onkeyup = handler; | |
htm.onsubmit = function (e) { | |
e = e || window.event; | |
var elem = e.target || e.srcElement; | |
if (!elem || elem.nodeName != 'FORM' || !elem.getAttribute('rel')) { | |
return; | |
} | |
if (elem.getAttribute('rel') === 'recipe') { | |
console.log("Should submit"); | |
var data = new FormData(elem); | |
var href = elem.getAttribute('action'); | |
console.log('Should call ' + href); | |
var r = new XMLHttpRequest(); | |
r.open("POST", href, true); | |
r.onreadystatechange = function() { | |
if (r.readyState != 4 || r.status != 200) return; | |
var model = JSON.parse(r.responseText); | |
if (model.recipes) { | |
for (var i = 0; i < model.recipes.length; i++) { | |
var recipe = model.recipes[i]; | |
switch (recipe.type) { | |
case 'prepend': | |
console.log('Attempting to select ' + recipe.selector); | |
var element = document.querySelector(recipe.selector); | |
if (element) { | |
if (element.parentElement) { | |
element.parentElement.insertBefore(recipe.content.toDOM(), element.parentElement.firstChild); | |
} else { | |
console.log('Element with selector ' + selector + ' does not have parentnode'); | |
} | |
} else { | |
console.log('Element with selector ' + selector + ' was not found'); | |
} | |
break; | |
case 'append': | |
var element = document.querySelector(recipe.selector); | |
element.appendChild(recipe.content.toDOM()); | |
break; | |
case 'replace': | |
var element = document.querySelector(recipe.selector); | |
element.outerHTML = recipe.content; | |
break; | |
default: | |
console.log('Cannot handle recipe type: ' + recipe.type); | |
} | |
} | |
} | |
}; | |
r.send(data); | |
return false; | |
} | |
return; | |
} | |
} | |
hookupEvents(); | |
return core; | |
}(document)); |
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
using Nancy; | |
using Nancy.Responses; | |
using Newtonsoft.Json; | |
using Newtonsoft.Json.Linq; | |
namespace DotNetBook.Primer | |
{ | |
public class Recipe | |
{ | |
private readonly JArray recipes = new JArray(); | |
public static Recipe Create() | |
{ | |
return new Recipe(); | |
} | |
public Recipe Append(string selector, string content) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "append", | |
["selector"] = selector, | |
["content"] = content | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Prepend(string selector, string content) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "prepend", | |
["selector"] = selector, | |
["content"] = content | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Replace(string selector, string content) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "replace", | |
["selector"] = selector, | |
["content"] = content | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Remove(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "remove", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe InsertAfter(string selector, string content) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "insertAfter", | |
["selector"] = selector, | |
["content"] = content | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe InsertBefore(string selector, string content) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "insertBefore", | |
["selector"] = selector, | |
["content"] = content | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Hide(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "hide", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Show(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "show", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Toggle(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "toggle", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe Focus(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "focus", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
// User-defined conversion from Digit to double | |
public static implicit operator Response(Recipe d) | |
{ | |
var root = new JObject(); | |
root["recipes"] = d.recipes; | |
return new TextResponse(root.ToString(Formatting.Indented), "application/json"); | |
} | |
public Recipe MoveCaretToEnd(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "moveCaretToEnd", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
public Recipe AutoResize(string selector) | |
{ | |
var recipe = new JObject | |
{ | |
["type"] = "autoResize", | |
["selector"] = selector | |
}; | |
recipes.Add(recipe); | |
return this; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment