beta
This commit is contained in:
552
nodejs/public/js/ICanHaz.js
Executable file
552
nodejs/public/js/ICanHaz.js
Executable file
@ -0,0 +1,552 @@
|
||||
/*!
|
||||
ICanHaz.js version 0.10.2 -- by @HenrikJoreteg
|
||||
More info at: http://icanhazjs.com
|
||||
*/
|
||||
(function () {
|
||||
/*
|
||||
mustache.js — Logic-less templates in JavaScript
|
||||
|
||||
See http://mustache.github.com/ for more info.
|
||||
*/
|
||||
|
||||
var Mustache = function () {
|
||||
var _toString = Object.prototype.toString;
|
||||
|
||||
Array.isArray = Array.isArray || function (obj) {
|
||||
return _toString.call(obj) == "[object Array]";
|
||||
}
|
||||
|
||||
var _trim = String.prototype.trim, trim;
|
||||
|
||||
if (_trim) {
|
||||
trim = function (text) {
|
||||
return text == null ? "" : _trim.call(text);
|
||||
}
|
||||
} else {
|
||||
var trimLeft, trimRight;
|
||||
|
||||
// IE doesn't match non-breaking spaces with \s.
|
||||
if ((/\S/).test("\xA0")) {
|
||||
trimLeft = /^[\s\xA0]+/;
|
||||
trimRight = /[\s\xA0]+$/;
|
||||
} else {
|
||||
trimLeft = /^\s+/;
|
||||
trimRight = /\s+$/;
|
||||
}
|
||||
|
||||
trim = function (text) {
|
||||
return text == null ? "" :
|
||||
text.toString().replace(trimLeft, "").replace(trimRight, "");
|
||||
}
|
||||
}
|
||||
|
||||
var escapeMap = {
|
||||
"&": "&",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
'"': '"',
|
||||
"'": '''
|
||||
};
|
||||
|
||||
function escapeHTML(string) {
|
||||
return String(string).replace(/&(?!\w+;)|[<>"']/g, function (s) {
|
||||
return escapeMap[s] || s;
|
||||
});
|
||||
}
|
||||
|
||||
var regexCache = {};
|
||||
var Renderer = function () {};
|
||||
|
||||
Renderer.prototype = {
|
||||
otag: "<<",
|
||||
ctag: ">>",
|
||||
pragmas: {},
|
||||
buffer: [],
|
||||
pragmas_implemented: {
|
||||
"IMPLICIT-ITERATOR": true
|
||||
},
|
||||
context: {},
|
||||
|
||||
render: function (template, context, partials, in_recursion) {
|
||||
// reset buffer & set context
|
||||
if (!in_recursion) {
|
||||
this.context = context;
|
||||
this.buffer = []; // TODO: make this non-lazy
|
||||
}
|
||||
|
||||
// fail fast
|
||||
if (!this.includes("", template)) {
|
||||
if (in_recursion) {
|
||||
return template;
|
||||
} else {
|
||||
this.send(template);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// get the pragmas together
|
||||
template = this.render_pragmas(template);
|
||||
|
||||
// render the template
|
||||
var html = this.render_section(template, context, partials);
|
||||
|
||||
// render_section did not find any sections, we still need to render the tags
|
||||
if (html === false) {
|
||||
html = this.render_tags(template, context, partials, in_recursion);
|
||||
}
|
||||
|
||||
if (in_recursion) {
|
||||
return html;
|
||||
} else {
|
||||
this.sendLines(html);
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Sends parsed lines
|
||||
*/
|
||||
send: function (line) {
|
||||
if (line !== "") {
|
||||
this.buffer.push(line);
|
||||
}
|
||||
},
|
||||
|
||||
sendLines: function (text) {
|
||||
if (text) {
|
||||
var lines = text.split("\n");
|
||||
for (var i = 0; i < lines.length; i++) {
|
||||
this.send(lines[i]);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/*
|
||||
Looks for %PRAGMAS
|
||||
*/
|
||||
render_pragmas: function (template) {
|
||||
// no pragmas
|
||||
if (!this.includes("%", template)) {
|
||||
return template;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
var regex = this.getCachedRegex("render_pragmas", function (otag, ctag) {
|
||||
return new RegExp(otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" + ctag, "g");
|
||||
});
|
||||
|
||||
return template.replace(regex, function (match, pragma, options) {
|
||||
if (!that.pragmas_implemented[pragma]) {
|
||||
throw({message:
|
||||
"This implementation of mustache doesn't understand the '" +
|
||||
pragma + "' pragma"});
|
||||
}
|
||||
that.pragmas[pragma] = {};
|
||||
if (options) {
|
||||
var opts = options.split("=");
|
||||
that.pragmas[pragma][opts[0]] = opts[1];
|
||||
}
|
||||
return "";
|
||||
// ignore unknown pragmas silently
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
Tries to find a partial in the curent scope and render it
|
||||
*/
|
||||
render_partial: function (name, context, partials) {
|
||||
name = trim(name);
|
||||
if (!partials || partials[name] === undefined) {
|
||||
throw({message: "unknown_partial '" + name + "'"});
|
||||
}
|
||||
if (!context || typeof context[name] != "object") {
|
||||
return this.render(partials[name], context, partials, true);
|
||||
}
|
||||
return this.render(partials[name], context[name], partials, true);
|
||||
},
|
||||
|
||||
/*
|
||||
Renders inverted (^) and normal (#) sections
|
||||
*/
|
||||
render_section: function (template, context, partials) {
|
||||
if (!this.includes("#", template) && !this.includes("^", template)) {
|
||||
// did not render anything, there were no sections
|
||||
return false;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
|
||||
var regex = this.getCachedRegex("render_section", function (otag, ctag) {
|
||||
// This regex matches _the first_ section ({{#foo}}{{/foo}}), and captures the remainder
|
||||
return new RegExp(
|
||||
"^([\\s\\S]*?)" + // all the crap at the beginning that is not {{*}} ($1)
|
||||
|
||||
otag + // {{
|
||||
"(\\^|\\#)\\s*(.+)\\s*" + // #foo (# == $2, foo == $3)
|
||||
ctag + // }}
|
||||
|
||||
"\n*([\\s\\S]*?)" + // between the tag ($2). leading newlines are dropped
|
||||
|
||||
otag + // {{
|
||||
"\\/\\s*\\3\\s*" + // /foo (backreference to the opening tag).
|
||||
ctag + // }}
|
||||
|
||||
"\\s*([\\s\\S]*)$", // everything else in the string ($4). leading whitespace is dropped.
|
||||
|
||||
"g");
|
||||
});
|
||||
|
||||
|
||||
// for each {{#foo}}{{/foo}} section do...
|
||||
return template.replace(regex, function (match, before, type, name, content, after) {
|
||||
// before contains only tags, no sections
|
||||
var renderedBefore = before ? that.render_tags(before, context, partials, true) : "",
|
||||
|
||||
// after may contain both sections and tags, so use full rendering function
|
||||
renderedAfter = after ? that.render(after, context, partials, true) : "",
|
||||
|
||||
// will be computed below
|
||||
renderedContent,
|
||||
|
||||
value = that.find(name, context);
|
||||
|
||||
if (type === "^") { // inverted section
|
||||
if (!value || Array.isArray(value) && value.length === 0) {
|
||||
// false or empty list, render it
|
||||
renderedContent = that.render(content, context, partials, true);
|
||||
} else {
|
||||
renderedContent = "";
|
||||
}
|
||||
} else if (type === "#") { // normal section
|
||||
if (Array.isArray(value)) { // Enumerable, Let's loop!
|
||||
renderedContent = that.map(value, function (row) {
|
||||
return that.render(content, that.create_context(row), partials, true);
|
||||
}).join("");
|
||||
} else if (that.is_object(value)) { // Object, Use it as subcontext!
|
||||
renderedContent = that.render(content, that.create_context(value),
|
||||
partials, true);
|
||||
} else if (typeof value == "function") {
|
||||
// higher order section
|
||||
renderedContent = value.call(context, content, function (text) {
|
||||
return that.render(text, context, partials, true);
|
||||
});
|
||||
} else if (value) { // boolean section
|
||||
renderedContent = that.render(content, context, partials, true);
|
||||
} else {
|
||||
renderedContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
return renderedBefore + renderedContent + renderedAfter;
|
||||
});
|
||||
},
|
||||
|
||||
/*
|
||||
Replace {{foo}} and friends with values from our view
|
||||
*/
|
||||
render_tags: function (template, context, partials, in_recursion) {
|
||||
// tit for tat
|
||||
var that = this;
|
||||
|
||||
var new_regex = function () {
|
||||
return that.getCachedRegex("render_tags", function (otag, ctag) {
|
||||
return new RegExp(otag + "(=|!|>|&|\\{|%)?([^#\\^]+?)\\1?" + ctag + "+", "g");
|
||||
});
|
||||
};
|
||||
|
||||
var regex = new_regex();
|
||||
var tag_replace_callback = function (match, operator, name) {
|
||||
switch(operator) {
|
||||
case "!": // ignore comments
|
||||
return "";
|
||||
case "=": // set new delimiters, rebuild the replace regexp
|
||||
that.set_delimiters(name);
|
||||
regex = new_regex();
|
||||
return "";
|
||||
case ">": // render partial
|
||||
return that.render_partial(name, context, partials);
|
||||
case "{": // the triple mustache is unescaped
|
||||
case "&": // & operator is an alternative unescape method
|
||||
return that.find(name, context);
|
||||
default: // escape the value
|
||||
return escapeHTML(that.find(name, context));
|
||||
}
|
||||
};
|
||||
var lines = template.split("\n");
|
||||
for(var i = 0; i < lines.length; i++) {
|
||||
lines[i] = lines[i].replace(regex, tag_replace_callback, this);
|
||||
if (!in_recursion) {
|
||||
this.send(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_recursion) {
|
||||
return lines.join("\n");
|
||||
}
|
||||
},
|
||||
|
||||
set_delimiters: function (delimiters) {
|
||||
var dels = delimiters.split(" ");
|
||||
this.otag = this.escape_regex(dels[0]);
|
||||
this.ctag = this.escape_regex(dels[1]);
|
||||
},
|
||||
|
||||
escape_regex: function (text) {
|
||||
// thank you Simon Willison
|
||||
if (!arguments.callee.sRE) {
|
||||
var specials = [
|
||||
'/', '.', '*', '+', '?', '|',
|
||||
'(', ')', '[', ']', '{', '}', '\\'
|
||||
];
|
||||
arguments.callee.sRE = new RegExp(
|
||||
'(\\' + specials.join('|\\') + ')', 'g'
|
||||
);
|
||||
}
|
||||
return text.replace(arguments.callee.sRE, '\\$1');
|
||||
},
|
||||
|
||||
/*
|
||||
find `name` in current `context`. That is find me a value
|
||||
from the view object
|
||||
*/
|
||||
find: function (name, context) {
|
||||
name = trim(name);
|
||||
|
||||
// Checks whether a value is thruthy or false or 0
|
||||
function is_kinda_truthy(bool) {
|
||||
return bool === false || bool === 0 || bool;
|
||||
}
|
||||
|
||||
var value;
|
||||
|
||||
// check for dot notation eg. foo.bar
|
||||
if (name.match(/([a-z_]+)\./ig)) {
|
||||
var childValue = this.walk_context(name, context);
|
||||
if (is_kinda_truthy(childValue)) {
|
||||
value = childValue;
|
||||
}
|
||||
} else {
|
||||
if (is_kinda_truthy(context[name])) {
|
||||
value = context[name];
|
||||
} else if (is_kinda_truthy(this.context[name])) {
|
||||
value = this.context[name];
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value == "function") {
|
||||
return value.apply(context);
|
||||
}
|
||||
if (value !== undefined) {
|
||||
return value;
|
||||
}
|
||||
// silently ignore unkown variables
|
||||
return "";
|
||||
},
|
||||
|
||||
walk_context: function (name, context) {
|
||||
var path = name.split('.');
|
||||
// if the var doesn't exist in current context, check the top level context
|
||||
var value_context = (context[path[0]] != undefined) ? context : this.context;
|
||||
var value = value_context[path.shift()];
|
||||
while (value != undefined && path.length > 0) {
|
||||
value_context = value;
|
||||
value = value[path.shift()];
|
||||
}
|
||||
// if the value is a function, call it, binding the correct context
|
||||
if (typeof value == "function") {
|
||||
return value.apply(value_context);
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
// Utility methods
|
||||
|
||||
/* includes tag */
|
||||
includes: function (needle, haystack) {
|
||||
return haystack.indexOf(this.otag + needle) != -1;
|
||||
},
|
||||
|
||||
// by @langalex, support for arrays of strings
|
||||
create_context: function (_context) {
|
||||
if (this.is_object(_context)) {
|
||||
return _context;
|
||||
} else {
|
||||
var iterator = ".";
|
||||
if (this.pragmas["IMPLICIT-ITERATOR"]) {
|
||||
iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
|
||||
}
|
||||
var ctx = {};
|
||||
ctx[iterator] = _context;
|
||||
return ctx;
|
||||
}
|
||||
},
|
||||
|
||||
is_object: function (a) {
|
||||
return a && typeof a == "object";
|
||||
},
|
||||
|
||||
/*
|
||||
Why, why, why? Because IE. Cry, cry cry.
|
||||
*/
|
||||
map: function (array, fn) {
|
||||
if (typeof array.map == "function") {
|
||||
return array.map(fn);
|
||||
} else {
|
||||
var r = [];
|
||||
var l = array.length;
|
||||
for(var i = 0; i < l; i++) {
|
||||
r.push(fn(array[i]));
|
||||
}
|
||||
return r;
|
||||
}
|
||||
},
|
||||
|
||||
getCachedRegex: function (name, generator) {
|
||||
var byOtag = regexCache[this.otag];
|
||||
if (!byOtag) {
|
||||
byOtag = regexCache[this.otag] = {};
|
||||
}
|
||||
|
||||
var byCtag = byOtag[this.ctag];
|
||||
if (!byCtag) {
|
||||
byCtag = byOtag[this.ctag] = {};
|
||||
}
|
||||
|
||||
var regex = byCtag[name];
|
||||
if (!regex) {
|
||||
regex = byCtag[name] = generator(this.otag, this.ctag);
|
||||
}
|
||||
|
||||
return regex;
|
||||
}
|
||||
};
|
||||
|
||||
return({
|
||||
name: "mustache.js",
|
||||
version: "0.4.0",
|
||||
|
||||
/*
|
||||
Turns a template and view into HTML
|
||||
*/
|
||||
to_html: function (template, view, partials, send_fun) {
|
||||
var renderer = new Renderer();
|
||||
if (send_fun) {
|
||||
renderer.send = send_fun;
|
||||
}
|
||||
renderer.render(template, view || {}, partials);
|
||||
if (!send_fun) {
|
||||
return renderer.buffer.join("\n");
|
||||
}
|
||||
}
|
||||
});
|
||||
}();
|
||||
/*!
|
||||
ICanHaz.js -- by @HenrikJoreteg
|
||||
*/
|
||||
/*global */
|
||||
(function () {
|
||||
function trim(stuff) {
|
||||
if (''.trim) return stuff.trim();
|
||||
else return stuff.replace(/^\s+/, '').replace(/\s+$/, '');
|
||||
}
|
||||
|
||||
// Establish the root object, `window` in the browser, or `global` on the server.
|
||||
var root = this;
|
||||
|
||||
var ich = {
|
||||
VERSION: "0.10.2",
|
||||
templates: {},
|
||||
|
||||
// grab jquery or zepto if it's there
|
||||
$: (typeof window !== 'undefined') ? window.jQuery || window.Zepto || null : null,
|
||||
|
||||
// public function for adding templates
|
||||
// can take a name and template string arguments
|
||||
// or can take an object with name/template pairs
|
||||
// We're enforcing uniqueness to avoid accidental template overwrites.
|
||||
// If you want a different template, it should have a different name.
|
||||
addTemplate: function (name, templateString) {
|
||||
if (typeof name === 'object') {
|
||||
for (var template in name) {
|
||||
this.addTemplate(template, name[template]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ich[name]) {
|
||||
console.error("Invalid name: " + name + ".");
|
||||
} else if (ich.templates[name]) {
|
||||
console.error("Template \"" + name + " \" exists");
|
||||
} else {
|
||||
ich.templates[name] = templateString;
|
||||
ich[name] = function (data, raw) {
|
||||
data = data || {};
|
||||
var result = Mustache.to_html(ich.templates[name], data, ich.templates);
|
||||
return (ich.$ && !raw) ? ich.$(trim(result)) : result;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
// clears all retrieval functions and empties cache
|
||||
clearAll: function () {
|
||||
for (var key in ich.templates) {
|
||||
delete ich[key];
|
||||
}
|
||||
ich.templates = {};
|
||||
},
|
||||
|
||||
// clears/grabs
|
||||
refresh: function () {
|
||||
ich.clearAll();
|
||||
ich.grabTemplates();
|
||||
},
|
||||
|
||||
// grabs templates from the DOM and caches them.
|
||||
// Loop through and add templates.
|
||||
// Whitespace at beginning and end of all templates inside <script> tags will
|
||||
// be trimmed. If you want whitespace around a partial, add it in the parent,
|
||||
// not the partial. Or do it explicitly using <br/> or
|
||||
grabTemplates: function () {
|
||||
var i,
|
||||
l,
|
||||
scripts = document.getElementsByTagName('script'),
|
||||
script,
|
||||
trash = [];
|
||||
for (i = 0, l = scripts.length; i < l; i++) {
|
||||
script = scripts[i];
|
||||
if (script && script.innerHTML && script.id && (script.type === "text/html" || script.type === "text/x-icanhaz")) {
|
||||
ich.addTemplate(script.id, trim(script.innerHTML));
|
||||
trash.unshift(script);
|
||||
}
|
||||
}
|
||||
for (i = 0, l = trash.length; i < l; i++) {
|
||||
trash[i].parentNode.removeChild(trash[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Export the ICanHaz object for **Node.js**, with
|
||||
// backwards-compatibility for the old `require()` API. If we're in
|
||||
// the browser, add `ich` as a global object via a string identifier,
|
||||
// for Closure Compiler "advanced" mode.
|
||||
if (typeof exports !== 'undefined') {
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
exports = module.exports = ich;
|
||||
}
|
||||
exports.ich = ich;
|
||||
} else {
|
||||
root['ich'] = ich;
|
||||
}
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
if (ich.$) {
|
||||
ich.$(function () {
|
||||
ich.grabTemplates();
|
||||
});
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
ich.grabTemplates();
|
||||
}, true);
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
})();
|
335
nodejs/public/js/app.js
Executable file
335
nodejs/public/js/app.js
Executable file
@ -0,0 +1,335 @@
|
||||
var app = {};
|
||||
|
||||
app.api = (function(app){
|
||||
var baseURL = '/api/'
|
||||
|
||||
function post(url, data, callack){
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: baseURL+url,
|
||||
headers:{
|
||||
'auth-token': app.auth.getToken()
|
||||
},
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
complete: function(res, text){
|
||||
callack(
|
||||
text !== 'success' ? res.statusText : null,
|
||||
JSON.parse(res.responseText),
|
||||
res.status
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function put(url, data, callack){
|
||||
$.ajax({
|
||||
type: 'PUT',
|
||||
url: baseURL+url,
|
||||
headers:{
|
||||
'auth-token': app.auth.getToken()
|
||||
},
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
complete: function(res, text){
|
||||
callack(
|
||||
text !== 'success' ? res.statusText : null,
|
||||
JSON.parse(res.responseText),
|
||||
res.status
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function remove(url, callack){
|
||||
$.ajax({
|
||||
type: 'delete',
|
||||
url: baseURL+url,
|
||||
headers:{
|
||||
'auth-token': app.auth.getToken()
|
||||
},
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
complete: function(res, text){
|
||||
callack(
|
||||
text !== 'success' ? res.statusText : null,
|
||||
JSON.parse(res.responseText),
|
||||
res.status
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get(url, callack){
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: baseURL+url,
|
||||
headers:{
|
||||
'auth-token': app.auth.getToken()
|
||||
},
|
||||
contentType: "application/json; charset=utf-8",
|
||||
dataType: "json",
|
||||
complete: function(res, text){
|
||||
callack(
|
||||
text !== 'success' ? res.statusText : null,
|
||||
JSON.parse(res.responseText),
|
||||
res.status
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {post: post, get: get, put: put, delete: remove}
|
||||
})(app)
|
||||
|
||||
app.auth = (function(app) {
|
||||
function setToken(token){
|
||||
localStorage.setItem('APIToken', token);
|
||||
}
|
||||
|
||||
function getToken(){
|
||||
return localStorage.getItem('APIToken');
|
||||
}
|
||||
|
||||
function isLoggedIn(callack){
|
||||
if(getToken()){
|
||||
return app.api.get('user/me', function(error, data){
|
||||
return callack(error, data);
|
||||
});
|
||||
}else{
|
||||
callack(null, false);
|
||||
}
|
||||
}
|
||||
|
||||
function logIn(args, callack){
|
||||
app.api.post('auth/login', args, function(error, data){
|
||||
if(data.login){
|
||||
setToken(data.token);
|
||||
}
|
||||
callack(error, !!data.token);
|
||||
});
|
||||
}
|
||||
|
||||
function logOut(){
|
||||
localStorage.removeItem('APIToken');
|
||||
}
|
||||
|
||||
function makeUserFromInvite(args, callack){
|
||||
app.api.post('auth/invite/'+ args.token, args, function(error, data){
|
||||
if(data.login){
|
||||
callack(null, data);
|
||||
setToken(data.token);
|
||||
}
|
||||
callack(error, !!data.token);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getToken: getToken,
|
||||
isLoggedIn: isLoggedIn,
|
||||
logIn: logIn,
|
||||
logOut: logOut,
|
||||
makeUserFromInvite: makeUserFromInvite,
|
||||
}
|
||||
|
||||
})(app);
|
||||
|
||||
app.user = (function(app){
|
||||
function list(callack){
|
||||
app.api.get('user/?detail=true', function(error, data){
|
||||
callack(error, data);
|
||||
})
|
||||
}
|
||||
|
||||
function add(args, callack){
|
||||
app.api.post('user/', args, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function remove(args, callack){
|
||||
app.api.delete('user/'+ args.username, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function changePassword(args, callack){
|
||||
app.api.put('users/'+ arg.username || '', args, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function createInvite(callack){
|
||||
app.api.post('user/invite', {}, function(error, data, status){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function consumeInvite(args){
|
||||
app.api.post('/auth/invite/'+args.token, args, function(error, data){
|
||||
if(data.token){
|
||||
app.auth.setToken(data.token)
|
||||
return callack(null, true)
|
||||
}
|
||||
callack(error)
|
||||
});
|
||||
}
|
||||
|
||||
return {list, remove, createInvite};
|
||||
|
||||
})(app);
|
||||
|
||||
app.host = (function(app){
|
||||
function list(callack){
|
||||
app.api.get('host/?detail=true', function(error, data){
|
||||
callack(error, data.hosts)
|
||||
});
|
||||
}
|
||||
|
||||
function get(host, callack){
|
||||
app.api.get('host/' + host, function(error, data){
|
||||
callack(error, data)
|
||||
});
|
||||
}
|
||||
|
||||
function add(args, callack){
|
||||
app.api.post('host/', args, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function edit(args, callack){
|
||||
app.api.put('host/' + args.edit_host, args, function(error, data){
|
||||
callack(error, data);
|
||||
});
|
||||
}
|
||||
|
||||
function remove(args, callack){
|
||||
app.api.delete('host/'+ args.host, function(error, data){
|
||||
callack(error, data);
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
list: list,
|
||||
get: get,
|
||||
add: add,
|
||||
edit: edit,
|
||||
remove: remove,
|
||||
}
|
||||
})(app);
|
||||
|
||||
app.util = (function(app){
|
||||
|
||||
function getUrlParameter(name) {
|
||||
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
|
||||
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)');
|
||||
var results = regex.exec(location.search);
|
||||
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
|
||||
};
|
||||
|
||||
function actionMessage(message, options){
|
||||
options = options || {};
|
||||
$target = options.$target || $('div.actionMessage');
|
||||
message = message || '';
|
||||
|
||||
if($target.html() === message) return;
|
||||
|
||||
if($target.html()){
|
||||
$target.slideUp('fast', function(){
|
||||
$target.html('')
|
||||
if(message) actionMessage(message, options);
|
||||
})
|
||||
return;
|
||||
}else{
|
||||
if(options.type) $target.addClass('alert-' + options.type);
|
||||
$target.html(message).slideDown('fast');
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.serializeObject = function() {
|
||||
var
|
||||
arr = $(this).serializeArray(),
|
||||
obj = {};
|
||||
|
||||
for(var i = 0; i < arr.length; i++) {
|
||||
if(obj[arr[i].name] === undefined) {
|
||||
obj[arr[i].name] = arr[i].value;
|
||||
} else {
|
||||
if(!(obj[arr[i].name] instanceof Array)) {
|
||||
obj[arr[i].name] = [obj[arr[i].name]];
|
||||
}
|
||||
obj[arr[i].name].push(arr[i].value);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
return {
|
||||
getUrlParameter: getUrlParameter,
|
||||
actionMessage: actionMessage
|
||||
}
|
||||
})(app);
|
||||
|
||||
$.holdReady( true );
|
||||
if(!location.pathname.includes('/login')){
|
||||
app.auth.isLoggedIn(function(error, isLoggedIn){
|
||||
if(error || !isLoggedIn){
|
||||
location.replace('/login/?redirect='+location.pathname);
|
||||
}else{
|
||||
$.holdReady( false );
|
||||
}
|
||||
})
|
||||
}else{
|
||||
$.holdReady( false );
|
||||
}
|
||||
|
||||
$( document ).ready( function () {
|
||||
|
||||
$( 'div.row' ).fadeIn( 'slow' ); //show the page
|
||||
|
||||
//panel button's
|
||||
$( '.fa-arrows-v' ).click( function () {
|
||||
$( this ).closest( '.card' ).find( '.card-body' ).slideToggle( 'fast' );
|
||||
});
|
||||
|
||||
$( '.glyphicon-remove-circle' ).click( function () {
|
||||
$( this ).closest( 'div.panel' ).slideUp( 'fast' );
|
||||
});
|
||||
|
||||
$( '.glyphicon-refresh' ).each( function () {
|
||||
$(this).click( function () {
|
||||
tableAJAX();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
//ajax form submit
|
||||
function formAJAX( btn, del ) {
|
||||
event.preventDefault(); // avoid to execute the actual submit of the form.
|
||||
var $form = $(btn).closest( '[action]' ); // gets the 'form' parent
|
||||
var formData = $form.find( '[name]' ).serializeObject(); // builds query formDataing
|
||||
var method = $form.attr('method') || 'post';
|
||||
|
||||
console.log('formAJAX method', method)
|
||||
|
||||
if( !$form.validate(
|
||||
{
|
||||
form: {
|
||||
alertCount: true,
|
||||
alertCountMessage: " errors found on this form!"
|
||||
}
|
||||
}) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
app.api[method]($form.attr( 'action' ), formData, function(error, data){
|
||||
tableAJAX( data.message ); //re-populate table
|
||||
if(!error){
|
||||
eval( $form.attr( 'evalAJAX' ) ); //gets JS to run after completion
|
||||
}
|
||||
});
|
||||
|
||||
}
|
1999
nodejs/public/js/bootstrap.js
vendored
Executable file
1999
nodejs/public/js/bootstrap.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
6
nodejs/public/js/bootstrap.min.js
vendored
Executable file
6
nodejs/public/js/bootstrap.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
nodejs/public/js/jquery-validate.js
vendored
Executable file
1
nodejs/public/js/jquery-validate.js
vendored
Executable file
@ -0,0 +1 @@
|
||||
(function(e){function r(e,t){var n=t.attr("validate").split(":"),r=n[1],i=t.val(),s=n[0];t.siblings("label").children("b").remove();t.parent().removeClass("has-error");if(isNaN(r)===false&&r&&i.length<r){return e.processValidation("Must be "+r+" characters",t)}if(isNaN(r)===false&&i.length===0){return}if(s in e.rule){return e.processValidation(e.rule[s].apply(this,[i,r]),t)}}var t={rule:{eq:function(t,n){var r=e("[name="+n.nameOpt+"]").val();if(t!=r){return"Miss-match"}}},form:{alertCount:false,alertCountMessage:" errors!"},processValidation:function(t,r){if(typeof t=="undefined"||t==true){return}e("<b>").html(" - "+t).appendTo(r.siblings("label"));r.parent().addClass("has-error");n++;return false}};var n=0;e.fn.validate=function(i){n=0;var s=false,o=e.extend({},t,i);if(this.is("[validate]")){r(o,this)}else{s=true;this.find("[validate]").each(function(){r(o,e(this))})}if(n===0){return true}else{if(o.form.alertCount&&s)alert(n+o.form.alertCountMessage);event.preventDefault();return false}};jQuery.extend({validateSettings:function(n){return t=e.extend({},t,n)}})})(jQuery);$.validateSettings({rule:{ip:function(e){e=e.split(".");if(e.length!=4){return"Malformed IP"}$.each(e,function(e,t){if(t>255||t<0){return"Malformed IP"}})},host:function(e){var t=/^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/;if(t.test(e)===false){return"Invalid"}},user:function(e){var t=/^[a-z0-9\_\-\@\.]{1,32}$/;if(t.test(e)===false){return"Invalid"}},password:function(e){var t=/^(?=[^\d_].*?\d)\w(\w|[!@#$%]){1,48}/;if(t.test(e)===false){return"Try again"}}}})
|
2
nodejs/public/js/jquery.min.js
vendored
Executable file
2
nodejs/public/js/jquery.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
23
nodejs/public/js/jquery.syntaxhighlighter.min.js
vendored
Executable file
23
nodejs/public/js/jquery.syntaxhighlighter.min.js
vendored
Executable file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
MIT License {@link http://creativecommons.org/licenses/MIT/}
|
||||
*/
|
||||
"undefined"===typeof window.console&&(window.console={});
|
||||
"undefined"===typeof window.console.emulated&&("function"===typeof window.console.log?window.console.hasLog=!0:("undefined"===typeof window.console.log&&(window.console.log=function(){}),window.console.hasLog=!1),"function"===typeof window.console.debug?window.console.hasDebug=!0:("undefined"===typeof window.console.debug&&(window.console.debug=!window.console.hasLog?function(){}:function(){for(var a=["console.debug:"],b=0;b<arguments.length;b++)a.push(arguments[b]);window.console.log.apply(window.console,
|
||||
a)}),window.console.hasDebug=!1),"function"===typeof window.console.warn?window.console.hasWarn=!0:("undefined"===typeof window.console.warn&&(window.console.warn=!window.console.hasLog?function(){}:function(){for(var a=["console.warn:"],b=0;b<arguments.length;b++)a.push(arguments[b]);window.console.log.apply(window.console,a)}),window.console.hasWarn=!1),"function"===typeof window.console.error?window.console.hasError=!0:("undefined"===typeof window.console.error&&(window.console.error=function(){var a=
|
||||
"An error has occured.";if(window.console.hasLog){for(var a=["console.error:"],b=0;b<arguments.length;b++)a.push(arguments[b]);window.console.log.apply(window.console,a);a="An error has occured. More information is available in your browser's javascript console."}for(b=0;b<arguments.length;++b){if(typeof arguments[b]!=="string")break;a=a+("\n"+arguments[b])}if(typeof Error!=="undefined")throw Error(a);throw a;}),window.console.hasError=!1),"function"===typeof window.console.trace?window.console.hasTrace=
|
||||
!0:("undefined"===typeof window.console.trace&&(window.console.trace=function(){window.console.error("console.trace does not exist")}),window.console.hasTrace=!1),window.console.emulated=!0);
|
||||
(function(a){a.appendStylesheet=a.appendStylesheet||function(b,c){if(!document.body){setTimeout(function(){a.appendStylesheet.apply(a,[b,c])},500);return a}var d="stylesheet-"+b.replace(/[^a-zA-Z0-9]/g,""),e=a("#"+d);typeof c==="undefined"&&(c=false);if(e.length===1)if(c)e.remove();else return a;var e=document.getElementsByTagName(a.browser.safari?"head":"body")[0],f=document.createElement("link");f.type="text/css";f.rel="stylesheet";f.media="screen";f.href=b;f.id=d;e.appendChild(f);return a};a.appendScript=
|
||||
a.appendScript||function(b,c){if(!document.body){setTimeout(function(){a.appendScript.apply(a,[b,c])},500);return a}var d="script-"+b.replace(/[^a-zA-Z0-9]/g,""),e=a("#"+d);typeof c==="undefined"&&(c=false);if(e.length===1)if(c)e.remove();else return a;var e=document.getElementsByTagName(a.browser.safari?"head":"body")[0],f=document.createElement("script");f.type="text/javascript";f.src=b;f.id=d;e.appendChild(f);return a}})(jQuery);
|
||||
(function(a){a.fn.findAndSelf=a.fn.findAndSelf||function(b){return a(this).find(b).andSelf().filter(b)};Number.prototype.replace=Number.prototype.replace||function(){return(""+this).replace.apply(this,arguments)};a.SyntaxHighlighter?window.console.warn("SyntaxHighlighter has already been defined..."):a.SyntaxHighlighter={config:{load:true,highlight:true,debug:false,wrapLines:true,lineNumbers:true,stripEmptyStartFinishLines:true,stripInitialWhitespace:true,alternateLines:false,defaultClassname:"highlight",
|
||||
theme:"balupton",themes:["balupton"],addSparkleExtension:true,prettifyBaseUrl:"http://balupton.github.com/jquery-syntaxhighlighter/prettify",baseUrl:"http://balupton.github.com/jquery-syntaxhighlighter"},init:function(b){var c=this.config,d=c.baseUrl;if(d[d.length-1]==="/")c.baseUrl=d.substr(0,d.length-2);delete d;a.extend(true,this.config,b||{});a.Sparkle&&a.Sparkle.addExtension("syntaxhighlighter",function(){a(this).syntaxHighlight()});a.fn.syntaxHighlight=a.fn.SyntaxHighlight=this.fn;c.load&&this.load();
|
||||
c.highlight&&this.highlight();return this},load:function(){var b=this.config,c=b.prettifyBaseUrl,d=b.baseUrl,b=b.themes;if(!this.loaded()){a.appendScript(c+"/prettify.min.js");a.appendStylesheet(c+"/prettify.min.css");a.appendStylesheet(d+"/styles/style.min.css");a.each(b,function(b,c){a.appendStylesheet(d+"/styles/theme-"+c+".min.css")});a.browser.msie&&a.appendStylesheet(d+"/styles/ie.min.css");this.loadedExtras=true}return this},loadedExtras:false,loaded:function(){return typeof prettyPrint!==
|
||||
"undefined"&&this.loadedExtras},determineLanguage:function(a){for(var c=null,d=/lang(uage)?-([a-z0-9]+)/g,e=d.exec(a);e!==null;){c=e[2];e=d.exec(a)}return c},fn:function(){var b=a(this);a.SyntaxHighlighter.highlight({el:b});return this},highlight:function(b){typeof b!=="object"&&(b={});var c=this,d=c.config,e=b.el||false;e instanceof jQuery||(e=a("body"));if(c.loaded()){var f=d.defaultClassname,g="";if(typeof f==="array"){g="."+f.join(",.");f=f.join(" ")}else{f=""+f;g="."+f.replace(" ",",.")}if(g===
|
||||
"."||!f){window.console.error("SyntaxHighlighter.highlight: Invalid defaultClassname.",[this,arguments],[d.defaultClassname]);window.console.trace()}e=e.findAndSelf("code,pre").filter("[class*=lang],"+g).filter(":not(.prettyprint)");e.css({"overflow-y":"visible","overflow-x":"visible","white-space":"pre"}).addClass("prettyprint "+f).each(function(){var b=a(this),d=b.attr("class"),d=c.determineLanguage(d);b.addClass("lang-"+d)});d.lineNumbers&&e.addClass("linenums");d.theme&&e.addClass("theme-"+d.theme);
|
||||
d.alternateLines&&e.addClass("alternate");prettyPrint();d.stripEmptyStartFinishLines&&e.find("li:first-child > :first-child, li:last-child > :first-child").each(function(){var b=a(this),d=/^([\r\n\s\t]|\ )*$/.test(b.html()),c=b.parent(),c=b.siblings();if(d&&(c.length===0||c.length===1&&c.filter(":last").is("br"))){c=b.parent();b=c.val();c.next().val(b);c.remove()}});d.stripInitialWhitespace&&e.find("li:first-child > :first-child").each(function(){var b=a(this),c=(b.html().match(/^(([\r\n\s\t]|\ )+)/)||
|
||||
[])[1]||"";c.length&&b.parent().siblings().children(":first-child").add(b).each(function(){var b=a(this),d=b.html(),d=d.replace(RegExp("^"+c,"gm"),"");b.html(d)})});d.wrapLines?e.css({"overflow-x":"hidden","overflow-y":"hidden","white-space":"pre-wrap","max-height":"none"}):e.css({"overflow-x":"auto","overflow-y":"auto","white-space":"normal","max-height":"500px"});return this}d.debug&&window.console.debug("SyntaxHighlighter.highlight: Chosen SyntaxHighlighter is not yet defined. Waiting 1200 ms then trying again.");
|
||||
setTimeout(function(){c.highlight.apply(c,[b])},1200)}}})(jQuery);
|
4602
nodejs/public/js/moment.js
Normal file
4602
nodejs/public/js/moment.js
Normal file
File diff suppressed because it is too large
Load Diff
1
nodejs/public/js/mustache.min.js
vendored
Normal file
1
nodejs/public/js/mustache.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
147
nodejs/public/js/val.js
Executable file
147
nodejs/public/js/val.js
Executable file
@ -0,0 +1,147 @@
|
||||
( function( $ ) {
|
||||
var settings = {
|
||||
rule: {
|
||||
eq: function( value, options ) {
|
||||
var compare = $( '[name=' + options + ']' ).val();
|
||||
|
||||
if ( value != compare ) {
|
||||
return "Miss-match";
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
form: {
|
||||
alertCount: false, //pop-up with error count
|
||||
alertCountMessage: " errors!"
|
||||
},
|
||||
|
||||
processValidation: function ( error_message, $input ) {
|
||||
if ( typeof error_message == 'undefined' || error_message == true ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$( '<b>' ).html( ' - ' + error_message ).appendTo( $input.siblings( 'label' ) );
|
||||
$input.parent().addClass("has-error");
|
||||
failedCount++;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var failedCount = 0;
|
||||
|
||||
function processRule( thisSettings, $input ) {
|
||||
var attr = $input.attr( 'validate' ).split( ':' ), //array of params
|
||||
requirement = attr[1],
|
||||
value = $input.val(), //link to input value
|
||||
rule = attr[0];
|
||||
|
||||
$input.siblings( 'label' ).children( 'b' ).remove(); //removes old error
|
||||
$input.parent().removeClass( "has-error" ); //removes has-error class
|
||||
|
||||
//checks if field is required, and length
|
||||
if (isNaN(requirement) === false && requirement && value.length < requirement) {
|
||||
return thisSettings.processValidation( 'Must be ' + requirement + ' characters', $input );
|
||||
}
|
||||
|
||||
//checks if empty to stop processing
|
||||
if ( isNaN( requirement ) === false && value.length === 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( rule in thisSettings.rule ) {
|
||||
return thisSettings.processValidation( thisSettings.rule[rule].apply( this, [value, requirement] ), $input );
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.validate = function( settingsObj, event ) {
|
||||
event = event || window.event;
|
||||
|
||||
failedCount = 0;
|
||||
var thisForm = false,
|
||||
thisSettings = $.extend( true, settings, settingsObj );
|
||||
|
||||
if ( this.is( '[validate]' ) ) {
|
||||
processRule( thisSettings, this );
|
||||
} else {
|
||||
thisForm = true;
|
||||
this.find( '[validate]' ).each( function () {
|
||||
if(!processRule( thisSettings, $( this ) )){
|
||||
// failedCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.attr('isValid', !failedCount);
|
||||
if ( failedCount === 0 ) { //no errors
|
||||
return true;
|
||||
} else { //errors
|
||||
if ( thisForm ){
|
||||
if(thisSettings.form.alertCount){
|
||||
alert( failedCount + thisSettings.form.alertCountMessage );
|
||||
}
|
||||
/* if(event) event.returnValue = false;
|
||||
if(event) event.preventDefault();
|
||||
return false;
|
||||
|
||||
if(event.preventDefault) if(event)*/
|
||||
//event.returnValue = false;
|
||||
event.preventDefault();
|
||||
event.defaultPrevented;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
jQuery.extend({
|
||||
validateSettings: function( settingsObj ) {
|
||||
$.extend( true, settings, settingsObj );
|
||||
},
|
||||
|
||||
validateInit: function( ettingsObj ) {
|
||||
$( '[action]' ).on( 'submit', function ( event, settingsObj ){
|
||||
$( this ).validate( settingsObj, event );
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}( jQuery ));
|
||||
|
||||
$.validateSettings({
|
||||
rule:{
|
||||
ip: function( value ) {
|
||||
value = value.split( '.' );
|
||||
|
||||
if ( value.length != 4 ) {
|
||||
return "Malformed IP";
|
||||
}
|
||||
|
||||
$.each( value, function( key, value ) {
|
||||
if( value > 255 || value < 0 ) {
|
||||
return "Malformed IP";
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
host: function( value ) {
|
||||
var reg = /^(?=.{1,255}$)[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?(?:\.[0-9A-Za-z](?:(?:[0-9A-Za-z]|-){0,61}[0-9A-Za-z])?)*\.?$/;
|
||||
if ( reg.test( value ) === false ) {
|
||||
return "Invalid";
|
||||
}
|
||||
},
|
||||
|
||||
user: function( value ) {
|
||||
var reg = /^[a-z0-9\_\-\@\.]{1,32}$/;
|
||||
if ( reg.test( value ) === false ) {
|
||||
return "Invalid";
|
||||
}
|
||||
},
|
||||
|
||||
password: function( value ) {
|
||||
var reg = /^(?=[^\d_].*?\d)\w(\w|[!@#$%]){1,48}/;
|
||||
if ( reg.test( value ) === false ) {
|
||||
return "Weak password, Try again";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
8
nodejs/public/js/waypoints-sticky.min.js
vendored
Executable file
8
nodejs/public/js/waypoints-sticky.min.js
vendored
Executable file
@ -0,0 +1,8 @@
|
||||
// Generated by CoffeeScript 1.6.2
|
||||
/*
|
||||
Sticky Elements Shortcut for jQuery Waypoints - v2.0.3
|
||||
Copyright (c) 2011-2013 Caleb Troughton
|
||||
Dual licensed under the MIT license and GPL license.
|
||||
https://github.com/imakewebthings/jquery-waypoints/blob/master/licenses.txt
|
||||
*/
|
||||
(function(){(function(t,n){if(typeof define==="function"&&define.amd){return define(["jquery","waypoints"],n)}else{return n(t.jQuery)}})(this,function(t){var n,s;n={wrapper:'<div class="sticky-wrapper" />',stuckClass:"stuck"};s=function(t,n){t.wrap(n.wrapper);return t.parent()};t.waypoints("extendFn","sticky",function(e){var i,r,a;r=t.extend({},t.fn.waypoint.defaults,n,e);i=s(this,r);a=r.handler;r.handler=function(n){var s,e;s=t(this).children(":first");e=n==="down"||n==="right";s.toggleClass(r.stuckClass,e);i.height(e?s.outerHeight():"");if(a!=null){return a.call(this,n)}};i.waypoint(r);return this.data("stuckClass",r.stuckClass)});return t.waypoints("extendFn","unsticky",function(){this.parent().waypoint("destroy");this.unwrap();return this.removeClass(this.data("stuckClass"))})})}).call(this);
|
8
nodejs/public/js/waypoints.min.js
vendored
Executable file
8
nodejs/public/js/waypoints.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user