From b0ac5733228740fc5eb65883e1d74fa8211a3fa6 Mon Sep 17 00:00:00 2001 From: "Mark M. Florida" <mflorida@gmail.com> Date: Fri, 29 Apr 2016 18:17:38 -0500 Subject: [PATCH] Basically re-wrote XNAT.spawner; added input.js and tab.js; updated xnat.tag with new scripts. --- .gitignore | 1 + src/main/webapp/WEB-INF/tags/page/xnat.tag | 2 + src/main/webapp/page/admin/index.jsp | 8 +- .../webapp/page/admin/spawner/content.jsp | 4 +- src/main/webapp/page/content.jsp | 6 +- src/main/webapp/scripts/lib/spawn/spawn.js | 6 +- src/main/webapp/scripts/xnat/spawner.js | 137 ++++++++++++++++-- src/main/webapp/scripts/xnat/ui/input.js | 105 ++++++++++++++ src/main/webapp/scripts/xnat/ui/tab.js | 27 ++++ src/main/webapp/scripts/xnat/ui/tabs.js | 30 ++-- 10 files changed, 293 insertions(+), 33 deletions(-) create mode 100644 src/main/webapp/scripts/xnat/ui/input.js create mode 100644 src/main/webapp/scripts/xnat/ui/tab.js diff --git a/.gitignore b/.gitignore index 7bcf3a84..1e0769a5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ .idea *.iml *.log +*--xx* src/generated gradle.properties /out diff --git a/src/main/webapp/WEB-INF/tags/page/xnat.tag b/src/main/webapp/WEB-INF/tags/page/xnat.tag index ff50a8a2..3172fa51 100755 --- a/src/main/webapp/WEB-INF/tags/page/xnat.tag +++ b/src/main/webapp/WEB-INF/tags/page/xnat.tag @@ -196,11 +196,13 @@ <script src="${_siteRoot}/scripts/xnat/xhr.js"></script> <script src="${_siteRoot}/scripts/xnat/event.js"></script> <script src="${_siteRoot}/scripts/xnat/element.js"></script> + <script src="${_siteRoot}/scripts/xnat/ui/input.js"></script> <script src="${_siteRoot}/scripts/xnat/ui/table.js"></script> <script src="${_siteRoot}/scripts/xnat/ui/panel.js"></script> <script src="${_siteRoot}/scripts/xnat/ui/tabs.js"></script> <script src="${_siteRoot}/scripts/xnat/ui/popup.js"></script> <script src="${_siteRoot}/scripts/xnat/ui/dialog.js"></script> + <script src="${_siteRoot}/scripts/xnat/spawner.js"></script> <%--<script src="${_siteRoot}/scripts/timeLeft.js"></script>--%> diff --git a/src/main/webapp/page/admin/index.jsp b/src/main/webapp/page/admin/index.jsp index 98fb2ccd..fcef2c3a 100644 --- a/src/main/webapp/page/admin/index.jsp +++ b/src/main/webapp/page/admin/index.jsp @@ -7,7 +7,13 @@ <pg:wrapper> <pg:xnat> - <jsp:include page="content.jsp"/> + <c:set var="view" value="${param.view}"/> + + <c:if test="${empty view}"> + <c:set var="view" value="content"/> + </c:if> + + <jsp:include page="${view}.jsp"/> </pg:xnat> </pg:wrapper> diff --git a/src/main/webapp/page/admin/spawner/content.jsp b/src/main/webapp/page/admin/spawner/content.jsp index 125460e2..f8897050 100644 --- a/src/main/webapp/page/admin/spawner/content.jsp +++ b/src/main/webapp/page/admin/spawner/content.jsp @@ -19,10 +19,10 @@ <c:set var="_siteRoot" value="${sessionScope.siteRoot}"/> - <c:import url="/xapi/spawner/resolve/siteAdmin/siteAdmin" var="siteAdmin"/> + <%--<c:import url="/xapi/spawner/resolve/siteAdmin/siteAdmin" var="siteAdmin"/>--%> <%--<button type="button" id="view-json">View JSON</button>--%> - <div class="hidden">${siteAdmin}</div> + <%--<div class="hidden">${siteAdmin}</div>--%> <!-- button element will be rendered in this span --> <span id="view-json"></span> diff --git a/src/main/webapp/page/content.jsp b/src/main/webapp/page/content.jsp index ac529c21..e7deaccf 100755 --- a/src/main/webapp/page/content.jsp +++ b/src/main/webapp/page/content.jsp @@ -24,9 +24,9 @@ customPage.getPage('', $pageContent); - window.onhashchange = function(){ - customPage.getPage('', $pageContent); - } +// window.onhashchange = function(){ +// customPage.getPage('', $pageContent); +// } })(); </script> diff --git a/src/main/webapp/scripts/lib/spawn/spawn.js b/src/main/webapp/scripts/lib/spawn/spawn.js index 683d9f32..602acd0d 100644 --- a/src/main/webapp/scripts/lib/spawn/spawn.js +++ b/src/main/webapp/scripts/lib/spawn/spawn.js @@ -120,7 +120,7 @@ var el, $el, parts, id, classes, tagParts, attrs, isVoid, // property names to skip later skip = ['innerHTML', 'html', 'append', 'appendTo', - 'classes', 'attr', 'data', 'fn'], + 'classes', 'className', 'attr', 'data', 'fn'], errors = []; // collect errors // deal with passing an array as the only argument @@ -217,8 +217,8 @@ } // allow use of 'classes' property for classNames - if (opts.className || opts.classes){ - el.className = [].concat(opts.className||[], opts.classes||[]).join(' ').trim(); + if (opts.className || opts.classes || opts.addClass){ + el.className = [].concat(opts.className||[], opts.classes||[], opts.addClass||[]).join(' ').trim(); } // add attributes and properties to element diff --git a/src/main/webapp/scripts/xnat/spawner.js b/src/main/webapp/scripts/xnat/spawner.js index 49249c0f..07c77098 100644 --- a/src/main/webapp/scripts/xnat/spawner.js +++ b/src/main/webapp/scripts/xnat/spawner.js @@ -17,29 +17,138 @@ var XNAT = getObject(XNAT); }(function(){ var undefined, - spawner = getObject(XNAT.spawner||{}); + ui, spawner, + NAMESPACE = 'XNAT.ui', + $ = jQuery || null, // check and localize + hasConsole = console && console.log; - function Spawner(obj){ - extend(true, this, obj); - this.spawned = null; - this.children = {}; - } + XNAT.ui = + getObject(XNAT.ui||{}); + XNAT.spawner = spawner = + getObject(XNAT.spawner||{}); - Spawner.p = Spawner.prototype; + // keep track of items that spawned + spawner.spawnedElements = []; + + // keep track of items that didn't spawn + spawner.notSpawned = []; - Spawner.p.init = function(obj){ - }; + // ================================================== + // MAIN FUNCTION + spawner.spawn = function SPAWN(obj){ + + var frag = document.createDocumentFragment(), + $frag = $(frag); + + forOwn(obj, function(item, o){ + + var kind, method, spawned, + // save the config properties in a new object + config = o.config || o.element || {}; + + // use 'name' property in element or config + // then look for 'name' at object root + // lastly use the object name + config.name = config.name || o.name || item; + + // accept 'kind' or 'type' property name + // but 'kind' will take priority + // with a fallback to a generic div + kind = o.kind || o.type || 'div.spawned'; + + // do a raw spawn() if 'kind' is 'element' + // or if there's a tag property + if (kind === 'element' || o.tag){ + try { + spawned = window.spawn(o.tag||config.tag||'div', config); + // jQuery's .append() method is + // MUCH more robust and forgiving + // than element.appendChild() + $frag.append(spawned); + spawner.spawnedElements.push(spawned); + } + catch (e) { + if (hasConsole) console.log(e); + spawner.notSpawned.push(config); + } + } + else { + // check for a matching XNAT.ui method to call: + // XNAT.ui.kind() + method = eval(NAMESPACE+'.'+kind); + + // only spawn elements with defined methods + if (isFunction(method)) { + + // 'spawned' item will be an HTML element + spawned = method(config); + + // add the spawned element to the master frag + $frag.append(spawned); + + // save a reference to the spawned element + spawner.spawnedElements.push(spawned); + + } + else { + spawner.notSpawned.push(item); + } + } + + // spawn child elements from 'contents' + if (o.contents || o.content || o.children) { + o.contents = o.contents || o.content || o.children; + $frag.append(SPAWN(o.contents).spawned); + } + + }); + + SPAWN.spawned = frag; + + SPAWN.children = $frag.contents(); + + SPAWN.get = function(){ + return frag; + }; + + SPAWN.render = function(element, empty){ + var $el = $$(element); + // empty the container element before spawning? + if (empty){ + $el.empty(); + } + $el.append(frag); + return spawn; + }; + + SPAWN.foo = '(spawn.foo)'; + + return SPAWN; - Spawner.p.render = function($container){ - $$($container).append(this.spawned); - return this; }; + // ================================================== - spawner.spawn = function(obj){ - return new Spawner(obj); + + spawner.testSpawn = function(){ + var jsonUrl = + XNAT.url.rootUrl('/page/admin/data/config/site-admin-sample-new.json'); + return $.getJSON({ + url: jsonUrl, + success: function(data){ + spawner.spawn(data); + console.log('spawnedElements:'); + console.log(spawner.spawnedElements); + console.log('notSpawned:'); + console.log(spawner.notSpawned); + } + }); }; + + // this script has loaded + spawner.loaded = true; + return XNAT.spawner = spawner; })); diff --git a/src/main/webapp/scripts/xnat/ui/input.js b/src/main/webapp/scripts/xnat/ui/input.js new file mode 100644 index 00000000..476768e3 --- /dev/null +++ b/src/main/webapp/scripts/xnat/ui/input.js @@ -0,0 +1,105 @@ +/*! + * Spawn UI elements using the Spawner service + */ + +var XNAT = getObject(XNAT); + +(function(factory){ + if (typeof define === 'function' && define.amd) { + define(factory); + } + else if (typeof exports === 'object') { + module.exports = factory(); + } + else { + return factory(); + } +}(function(){ + + var undefined, uiInput, textTypes, + numberTypes, otherTypes, + $ = jQuery || null, // check and localize + ui, input; + + XNAT.ui = getObject(XNAT.ui||{}); + + XNAT.ui.input = + input = XNAT.ui.input || {}; + + + // if XNAT.ui.input is already defined, + // save it and its properties to add later + // as methods and properties to the function + uiInput = input || null; + + + // ======================================== + // MAIN FUNCTION + input = function(type, config){ + // only one argument? + // could be a config object + if (!config && typeof type != 'string') { + config = type; + type = null; // it MUST contain a 'type' property + } + config = getObject(config); + config.type = type || config.type || 'text'; + return spawn('input', config) + }; + // ======================================== + + + function setupType(type, className, config){ + config = getObject(config); + config.addClass = className; + config.data = extend({ validate: type }, config.data); + if (!config.data.validate) delete config.data.validate; + return input(type, config); + } + + // methods for direct creation of specific input types + // some are 'real' element types, others are XNAT-specific + textTypes = [ + 'text', 'email', 'url', 'strict', + 'id', 'alpha', 'alphanum' + ]; + textTypes.forEach(function(type){ + input[type] = function(config){ + return setupType('text', type, config); + } + }); + + numberTypes = ['number', 'int', 'integer', 'float']; + numberTypes.forEach(function(type){ + input[type] = function(config){ + return setupType('number', type, config); + } + }); + + otherTypes = [ + 'password', 'date', 'checkbox', + 'radio', 'button', 'hidden' + ]; + otherTypes.forEach(function(type){ + input[type] = function(config){ + return setupType(type, type, config); + } + }); + + // save a list of all available input types + input.types = [].concat(textTypes, numberTypes, otherTypes); + + // add back items that may have been on + // a global XNAT.ui.input object + if (uiInput && isPlainObject(uiInput)) { + forOwn(uiInput, function(item, value){ + input[item] = value; + }) + } + + // this script has loaded + input.loaded = true; + + return XNAT.ui.input = input; + +})); diff --git a/src/main/webapp/scripts/xnat/ui/tab.js b/src/main/webapp/scripts/xnat/ui/tab.js new file mode 100644 index 00000000..444eb93e --- /dev/null +++ b/src/main/webapp/scripts/xnat/ui/tab.js @@ -0,0 +1,27 @@ +/*! + * Functions for creating XNAT tab UI elements + */ + +var XNAT = getObject(XNAT||{}); + +(function(factory){ + if (typeof define === 'function' && define.amd) { + define(factory); + } + else if (typeof exports === 'object') { + module.exports = factory(); + } + else { + return factory(); + } +}(function(){ + + var tab; + + // just one tab + XNAT.ui.tab = tab = + getObject(XNAT.ui.tab || {}); + + + +})); diff --git a/src/main/webapp/scripts/xnat/ui/tabs.js b/src/main/webapp/scripts/xnat/ui/tabs.js index f5c365b6..8b5c40e7 100755 --- a/src/main/webapp/scripts/xnat/ui/tabs.js +++ b/src/main/webapp/scripts/xnat/ui/tabs.js @@ -6,23 +6,33 @@ var XNAT = getObject(XNAT||{}); (function(XNAT, $, window, undefined){ - var ui, tabs, page, + var ui, tab, tabs, page, element = XNAT.element; var $body = $(document.body); - XNAT.ui = ui = getObject(XNAT.ui || {}); - XNAT.ui.tabs = XNAT.tabs = tabs = getObject(XNAT.ui.tabs || {}); - XNAT.page = page = getObject(XNAT.page || {}); + XNAT.ui = ui = + getObject(XNAT.ui || {}); + + // just one tab + XNAT.ui.tab = tab = + getObject(XNAT.ui.tab || {}); + + // a whole bunch of tabs + XNAT.ui.tabs = XNAT.tabs = tabs = + getObject(XNAT.ui.tabs || {}); + + XNAT.page = page = + getObject(XNAT.page || {}); /** * Initialize the tabs - * @param [tabsArray] {Array} array of tab config objects + * @param [tabItems] {Array} array of tab config objects * @param [container] {Element} parent element for tabs * @returns {{}} */ - function init(tabsArray, container){ + function init(tabItems, container){ // a place to store things locally var __ = {}; @@ -244,7 +254,7 @@ var XNAT = getObject(XNAT||{}); __.tabs.$panes.addClass('side pull-'+other); } - [].concat(config).forEach(function(item){ + $.each(config, function(name, item){ if (item.kind !== 'tab') { if (item.kind === 'meta'){ @@ -296,9 +306,9 @@ var XNAT = getObject(XNAT||{}); // expose globally __.setup = setupTabs; - // run setup on init() if 'tabsArray' is present - if (tabsArray && tabsArray.length){ - setupTabs(tabsArray); + // run setup on init() if 'tabItems' is present + if (tabItems){ + setupTabs(tabItems); } __.render = function(container){ -- GitLab