Skip to content

Instantly share code, notes, and snippets.

@swedishkid
Last active July 12, 2016 08:26
Show Gist options
  • Save swedishkid/deddb8d1a4d4249d74ac4e58e495d1c2 to your computer and use it in GitHub Desktop.
Save swedishkid/deddb8d1a4d4249d74ac4e58e495d1c2 to your computer and use it in GitHub Desktop.
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));
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