form-cheatsheet/src/old/init.js

202 lines
5.3 KiB
JavaScript

(function ($) {
"use strict";
// Make sure regex patterns are only parsed once
var $newLinePattern = /\{n}/g,
$spacePattern = /\{s}/g,
$tabPattern = /\{t}/g,
$whiteSpacePattern = /^(?:\s+)?$/g,
$inputTagPattern = /<input(.*?)>/g,
$optionClosingTagPattern = />(?:\s+)?<\/option>/g,
$htmlAttributeSpacingPattern = /(\s+)([^id][a-z_\-]+="(?:.*?)")/ig;
// Just kill form submission
$.qs('form').onsubmit = function(e) {
e.preventDefault();
e.stopPropagation();
console.log("Form 'submit' event fired.");
return false;
};
var format = {
/**
* Format the display of an input element, and align the attributes
* on separate lines
*
* @param {HTMLInputElement} formElement
* @return {string}
*/
input: function (formElement) {
// Let's do some ugly DOM manipulation to make the output of the
// highlighted have lined up attributes.
// For the spacing, we replace normal whitespace characters with
// {x} placeholders so the highlighter doesn't mangle them
var formElementSpaces = '{s}'.repeat(formElement.tagName.length + 2);
var formElementReplace = '{n}' + formElementSpaces;
var formElementHTML = formElement.outerHTML
.trim()
.replace($inputTagPattern, '<input$1 />')
.replace($htmlAttributeSpacingPattern, formElementReplace + '$2');
return formElementHTML;
},
/**
* Format the display of an option element
*
* @param {HTMLOptionElement} formElement
* @return {string}
*/
option: function (formElement) {
var raw = format.generic(formElement);
if (hasHtmlChildren(formElement) && formElement.childNodes.length > 0) {
return raw;
}
raw = raw.replace($whiteSpacePattern, '');
return raw.replace($optionClosingTagPattern, ' />');
},
/**
* Format the display of elements without specific formatting methods
*
* @param {HTMLElement} formElement
* @return {string}
*/
generic: function (formElement) {
return formElement.outerHTML.trim();
}
};
/**
* Format the current element
*
* @param {HTMLElement} formElement
* @param {number} i
* @return string
*/
function formatElement (formElement, i) {
var elementPrefix = (i > 0)
? '{n}' + '{t}'.repeat(i)
: '';
if (formElement.nodeType === 3) {
return elementPrefix + formElement.nodeValue;
}
var tagName = formElement.tagName.toLowerCase();
var formattingMethod = (Object.keys(format).indexOf(tagName) !== -1)
? format[tagName]
: format.generic;
return elementPrefix + formattingMethod(formElement);
}
/**
* Check whether an element has an other elements as children
*
* @param {HTMLElement} element
* @return {boolean}
*/
function hasHtmlChildren (element) {
var x = 0;
var node;
var numChildren = element.childNodes.length;
if (numChildren === 0) {
return false;
}
for (; x < numChildren; x++) {
node = element.childNodes.item(x);
// Only count as a child if the node is an element
if (node.nodeType === 1) {
return true;
}
}
return false;
}
/**
* Recursively format the form elements for better alignment
*
* @param {HTMLElement} formElement
* @param {number} level
* @return {string}
*/
function formatHtml(formElement, level) {
level = level || 0;
var children = $.toArray(formElement.childNodes);
var hasChildren = hasHtmlChildren(formElement);
var rawChildren = formElement.innerHTML;
var formattedHTML = formatElement(formElement, level);
// If there are no children, just return the formatted element
if (!hasChildren) {
return formattedHTML;
}
children = children.filter(function (node) {
// Discard text nodes if they only contain whitespace
if (node.nodeType === 3 && node.nodeValue.match($whiteSpacePattern)) {
return false;
}
// Keep other nodes
return true;
});
level++;
var newChildrenHTML = children.reduce(function (prevHTML, node) {
return prevHTML + formatHtml(node, level);
}, '');
// Format those closing tags
if (level > 0 && hasChildren) {
newChildrenHTML += '{n}' + '{t}'.repeat(level - 1);
}
formattedHTML = formattedHTML.replace(rawChildren, newChildrenHTML);
return formattedHTML;
}
// Get each form field's html and syntax highlight it
$.getByClass('form-field').forEach(function(parent) {
// Setup up the highligher
var hl = new DlHighlight({lang: 'html'});
var labelHTML = formatHtml($.qs('label', parent), 0);
var formElements = $.qsa('button, input, datalist, keygen, meter, output, progress, select, textarea', parent);
var formElementHTML = '';
formElements.forEach(function (formElement) {
formElementHTML += '{n}{n}' + formatHtml(formElement, 0);
});
// Join the label markup with the form element markup
var formCode = labelHTML + formElementHTML.trim();
// Now replace the placeholders with proper whitespace equvalent markup
var highLighted = hl.doItNow(formCode);
highLighted = $.replaceMultiple(highLighted, [
[$newLinePattern, '<br />'],
[$spacePattern, '&nbsp;'],
[$tabPattern, '&nbsp;'.repeat(4)]
]);
// Piece together the HTML for the prettier HTML examples
var codeElement = document.createElement('code');
codeElement.className = 'DlHighlight html';
codeElement.innerHTML = highLighted;
// Append the prettified HTML to the parent element
parent.appendChild(codeElement);
});
}(doc));