var util = function() { $.fn.serializeObject = function() { var o = {}; var a = this.serializeArray(); $.each(a, function() { if (o[this.name]) { if (!o[this.name].push) { o[this.name] = [o[this.name]]; } o[this.name].push(this.value || ''); } else { o[this.name] = this.value || ''; } }); return o; }; function inURL(url, str) { var exists = false; if ( url.indexOf( str ) > -1 ) { exists = true; } return exists; } function registerEmitter() { var Emitter = function(obj) { this.emit = function(obj, channel) { if (!channel) var channel = 'data'; this.trigger(channel, obj); }; }; MicroEvent.mixin(Emitter); return new Emitter(); } function listenFor(keys) { var shortcuts = { // from jquery.hotkeys.js 8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause", 20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home", 37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7", 104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta" } window.addEventListener("keyup", function(e) { var pressed = shortcuts[e.keyCode]; if(_.include(keys, pressed)) app.emitter.emit("keyup", pressed); }, false); } function observeExit(elem, callback) { var cancelButton = elem.find('.cancelButton'); app.emitter.on('esc', function() { cancelButton.click(); app.emitter.clear('esc'); }); cancelButton.click(callback); } function show( thing ) { $('.' + thing ).show(); $('.' + thing + '-overlay').show(); } function hide( thing ) { $('.' + thing ).hide(); $('.' + thing + '-overlay').hide(); if (thing === "dialog") app.emitter.clear('esc'); // todo more elegant solution } function position( thing, elem, offset ) { var position = $(elem.target).offset(); if (offset) { if (offset.top) position.top += offset.top; if (offset.left) position.left += offset.left; } $('.' + thing + '-overlay').show().click(function(e) { $(e.target).hide(); $('.' + thing).hide(); }); $('.' + thing).show().css({top: position.top + $(elem.target).height(), left: position.left}); } function render( template, target, options ) { if ( !options ) options = {data: {}}; if ( !options.data ) options = {data: options}; var html = $.mustache( $( "." + template + "Template:first" ).html(), options.data ); if (target instanceof jQuery) { var targetDom = target; } else { var targetDom = $( "." + target + ":first" ); } if( options.append ) { targetDom.append( html ); } else { targetDom.html( html ); } if (template in app.after) app.after[template](); } function notify( message, options ) { if (!options) var options = {}; $('#notification-container').show(); $('#notification-message').text(message); if (!options.loader) $('.notification-loader').hide(); if (options.loader) $('.notification-loader').show(); if (!options.persist) setTimeout(function() { $('#notification-container').hide() }, 3000); } function formatMetadata(data) { out = '
'; $.each(data, function(key, val) { if (typeof(val) == 'string' && key[0] != '_') { out = out + '
' + key + '
' + val; } else if (typeof(val) == 'object' && key != "geometry" && val != null) { if (key == 'properties') { $.each(val, function(attr, value){ out = out + '
' + attr + '
' + value; }) } else { out = out + '
' + key + '
' + val.join(', '); } } }); out = out + '
'; return out; } function getBaseURL(url) { var baseURL = ""; if ( inURL(url, '_design') ) { if (inURL(url, '_rewrite')) { var path = url.split("#")[0]; if (path[path.length - 1] === "/") { baseURL = ""; } else { baseURL = '_rewrite/'; } } else { baseURL = '_rewrite/'; } } return baseURL; } var persist = { restore: function() { $('.persist').each(function(i, el) { var inputId = $(el).attr('id'); if(localStorage.getItem(inputId)) $('#' + inputId).val(localStorage.getItem(inputId)); }) }, save: function(id) { localStorage.setItem(id, $('#' + id).val()); }, clear: function() { $('.persist').each(function(i, el) { localStorage.removeItem($(el).attr('id')); }) } } // simple debounce adapted from underscore.js function delay(func, wait) { return function() { var context = this, args = arguments; var throttler = function() { delete app.timeout; func.apply(context, args); }; if (!app.timeout) app.timeout = setTimeout(throttler, wait); }; }; function resetForm(form) { $(':input', form) .not(':button, :submit, :reset, :hidden') .val('') .removeAttr('checked') .removeAttr('selected'); } function largestWidth(selector, min) { var min_width = min || 0; $(selector).each(function(i, n){ var this_width = $(n).width(); if (this_width > min_width) { min_width = this_width; } }); return min_width; } function getType(obj) { if (obj === null) { return 'null'; } if (typeof obj === 'object') { if (obj.constructor.toString().indexOf("Array") !== -1) { return 'array'; } else { return 'object'; } } else { return typeof obj; } } function lookupPath(path) { var docs = app.apiDocs; try { _.each(path, function(node) { docs = docs[node]; }) } catch(e) { util.notify("Error selecting documents" + e); docs = []; } return docs; } function nodePath(docField) { if (docField.children('.object-key').length > 0) return docField.children('.object-key').text(); if (docField.children('.array-key').length > 0) return docField.children('.array-key').text(); if (docField.children('.doc-key').length > 0) return docField.children('.doc-key').text(); return ""; } function selectedTreePath() { var nodes = [] , parent = $('.chosen'); while (parent.length > 0) { nodes.push(nodePath(parent)); parent = parent.parents('.doc-field:first'); } return _.compact(nodes).reverse(); } // TODO refactor handlers so that they dont stack up as the tree gets bigger function handleTreeClick(e) { var clicked = $(e.target); if(clicked.hasClass('expand')) return; if (clicked.children('.array').length > 0) { var field = clicked; } else if (clicked.siblings('.array').length > 0) { var field = clicked.parents('.doc-field:first'); } else { var field = clicked.parents('.array').parents('.doc-field:first'); } $('.chosen').removeClass('chosen'); field.addClass('chosen'); return false; } var createTreeNode = { "string": function (obj, key) { var val = $('
'); if (obj[key].length > 45) { val.append($('') .text(obj[key].slice(0, 45))) .append( $('...') .click(function () { val.html('') .append($('') .text(obj[key].length ? obj[key] : " ") ) }) ) } else { var val = $('
'); val.append( $('') .text(obj[key].length ? obj[key] : " ") ) } return val; } , "number": function (obj, key) { var val = $('
') val.append($('' + obj[key] + '')) return val; } , "null": function (obj, key) { var val = $('
') val.append($('' + obj[key] + '')) return val; } , "boolean": function (obj, key) { var val = $('
') val.append($('' + obj[key] + '')) return val; } , "array": function (obj, key, indent) { if (!indent) indent = 1; var val = $('
') $('[...]') .click(function (e) { var n = $(this).parent(); var cls = 'sub-'+key+'-'+indent n.html('') n.append('[') for (i in obj[key]) { var field = $('
').click(handleTreeClick); n.append( field .append('
'+i+'
') .append(createTreeNode[getType(obj[key][i])](obj[key], i, indent + 1)) ) } n.append(']') $('div.'+cls).width(largestWidth('div.'+cls)) }) .appendTo($('
').appendTo(val)) return val; } , "object": function (obj, key, indent) { if (!indent) indent = 1; var val = $('
') $('{...}') .click(function (e) { var n = $(this).parent(); n.html('') n.append('{') for (i in obj[key]) { var field = $('
').click(handleTreeClick); var p = $('
'); var di = $('
'+i+'
') field.append(p) .append(di) .append(createTreeNode[getType(obj[key][i])](obj[key], i, indent + 1)) n.append(field) } n.append('}') di.width(largestWidth('div.object-key')) }) .appendTo($('
').appendTo(val)) return val; } } function renderTree(doc) { var d = $('div#document-editor'); for (i in doc) { var field = $('
').click(handleTreeClick); $('
').appendTo(field); field.append('
'+i+'
') field.append(createTreeNode[getType(doc[i])](doc, i)); d.append(field); } $('div.doc-key-base').width(largestWidth('div.doc-key-base')) } return { inURL: inURL, registerEmitter: registerEmitter, listenFor: listenFor, show: show, hide: hide, position: position, render: render, notify: notify, observeExit: observeExit, formatMetadata:formatMetadata, getBaseURL:getBaseURL, resetForm: resetForm, delay: delay, persist: persist, lookupPath: lookupPath, selectedTreePath: selectedTreePath, renderTree: renderTree }; }();