From 29ec9a330fffa9cf5ed2e35109661dee2ef8c9ab Mon Sep 17 00:00:00 2001 From: "Mark M. Florida" <mflorida@gmail.com> Date: Mon, 2 May 2016 20:59:24 -0500 Subject: [PATCH] Many fixes and tweaks: tabs are now grouped, added special methods for panel-specific form elements, CSS still needs tweaking. --- src/main/webapp/page/admin/content.jsp | 1 + .../data/config/site-admin-sample-new.yaml | 25 ++- src/main/webapp/scripts/xnat/ui/input.js | 2 +- src/main/webapp/scripts/xnat/ui/panel.js | 16 +- src/main/webapp/scripts/xnat/ui/tabs.js | 164 ++++++++++++++---- src/main/webapp/scripts/xnat/ui/templates.js | 117 +++++++++++++ 6 files changed, 275 insertions(+), 50 deletions(-) create mode 100644 src/main/webapp/scripts/xnat/ui/templates.js diff --git a/src/main/webapp/page/admin/content.jsp b/src/main/webapp/page/admin/content.jsp index fd16510e..ea2c52b7 100755 --- a/src/main/webapp/page/admin/content.jsp +++ b/src/main/webapp/page/admin/content.jsp @@ -30,6 +30,7 @@ </div> + <script src="${sessionScope.siteRoot}/scripts/xnat/ui/templates.js"></script> <script src="${sessionScope.siteRoot}/page/admin/tabs.js"></script> </div> diff --git a/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml b/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml index 14018dc2..20fd7829 100644 --- a/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml +++ b/src/main/webapp/page/admin/data/config/site-admin-sample-new.yaml @@ -17,6 +17,10 @@ root: name: siteSetup label: Site Setup group: xnatSetup + active: true + config: + data: + foo: bar contains: panels # the value for 'contains' can be a custom name for 'contents' panels: siteInfo: @@ -25,7 +29,7 @@ root: label: Site Information contents: siteId: - kind: input.text + kind: panel.input.text name: siteId label: Site ID validation: required id onblur @@ -43,8 +47,7 @@ root: config: html: Hello people. style: - padding: 20px - color: red + fontWeight: bold security: kind: tab name: security @@ -56,24 +59,18 @@ root: label: General Site Security Settings contents: securityChannel: - kind: element - tag: select + kind: template.panelSelect name: securityChannel label: Security Channel - contains: options + value: https +# contains: options options: http: - tag: option - name: http + label: http value: http https: - tag: option - name: https + label: https value: https config: id: security-channel title: Security Channel - - - - diff --git a/src/main/webapp/scripts/xnat/ui/input.js b/src/main/webapp/scripts/xnat/ui/input.js index 09aaca32..0120e088 100644 --- a/src/main/webapp/scripts/xnat/ui/input.js +++ b/src/main/webapp/scripts/xnat/ui/input.js @@ -1,5 +1,5 @@ /*! - * Spawn UI elements using the Spawner service + * Spawn form input elements */ var XNAT = getObject(XNAT); diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index c7383f78..e311ad9b 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -45,11 +45,13 @@ var XNAT = getObject(XNAT || {}); ['button.btn.btn-sm.btn-link.defaults.pull-left', 'Default Settings'], ['div.clear'] ], - _panel = spawn('form.xnat-form-panel.panel.panel-default', [ + _panel = spawn('form.xnat-form-panel.panel.panel-default', [ ['div.panel-heading', [ ['h3.panel-title', config.title || config.label] ]], + _target, + ['div.panel-footer', config.footer || _footer] ]); return { @@ -62,6 +64,18 @@ var XNAT = getObject(XNAT || {}); } }; + panel.input = {}; + + panel.input.text = function(opts){ + return XNAT.ui.templates.panelInput(opts).spawned; + }; + + panel.input.email = function(opts){ + opts.type = 'text'; + opts.className = [].concat(opts.className||[], 'email').join(' ').trim(); + return XNAT.ui.templates.panelInput(opts).spawned; + }; + function footerButton(text, type, disabled, classes){ var button = { type: type || 'button', diff --git a/src/main/webapp/scripts/xnat/ui/tabs.js b/src/main/webapp/scripts/xnat/ui/tabs.js index d1114853..86e0d70b 100755 --- a/src/main/webapp/scripts/xnat/ui/tabs.js +++ b/src/main/webapp/scripts/xnat/ui/tabs.js @@ -33,22 +33,148 @@ var XNAT = getObject(XNAT || {}); getObject(XNAT.page || {}); + // ================================================== + // SET UP ONE TAB GROUP + // add a single tab group to the groups + tab.group = function(obj, container){ + var id = toDashed(obj.id || obj.name); + if (!id) return; // a tab group MUST have an id + var group = spawn('ul.nav.tab-group', { + id: id, + html: + '<li class="label">' + + (obj.label || obj.title || obj.text || 'Tab Group') + + '</li>' + }); + if (container) { + $$(container).append(group); + } + return group; + }; + // ================================================== + + + // ================================================== + // SET UP TAB GROUPS + tab.groups = function(obj, container, empty){ + var groups = [], + $container = $$(container); + $.each(obj, function(name, label){ + groups.push(tab.group({ + id: toDashed(name), + label: label + })); + }); + if (empty){ + $container.empty(); + } + $container.append(groups); + return groups; + }; + // ================================================== + + + // save the id of the active tab + XNAT.ui.tab.active = ''; + + function activateTab(tab, id){ + + var $tab = $(tab), + $tabs = $(tab).closest('div.xnat-tab-container'); + + // first deactivate ALL tabs and panes + $tabs + .find('div.tab-pane') + .hide() + .removeClass('active'); + + $tabs + .find('li.tab') + .removeClass('active'); + + // then activate THIS tab and pane + + $tab.addClass('active'); + + $('#'+id) + .show() + .addClass('active'); + + XNAT.ui.tab.active = id; + + } + + // ================================================== + // CREATE A SINGLE TAB + tab.init = function _tab(obj){ + + var _flipper, _pane; + + obj = getObject(obj); + obj.config = getObject(obj.config); + obj.config.id = obj.config.id || obj.id || (toDashed(obj.name) + '-content'); + obj.config.data = extend({ name: obj.name }, obj.config.data); + + _flipper = spawn('li.tab', { + onclick: function(){ + activateTab(this, obj.config.id) + } + }, [ + ['a', { + title: obj.label, + //href: '#'+obj.config.id, + href: '#!', + html: obj.label + }] + ]); + _pane = spawn('div.tab-pane', obj.config); + + if (obj.active) { + $(_flipper).addClass('active'); + $(_pane).addClass('active'); + tab.active = _pane.id; + } + + // add all the flippers + $('#'+(toDashed(obj.group))+'.tab-group').append(_flipper); + + function render(element){ + $$(element).append(_pane); + return _pane; + } + + function get(){ + return _pane; + } + + return { + // contents: obj.tabs||obj.contents||obj.content||'', + flipper: _flipper, + pane: _pane, + element: _pane, + spawned: _pane, + render: render, + get: get + } + }; + // ================================================== + + // ================================================== // MAIN FUNCTION tabs.init = function _tabs(obj){ - console.log('XNAT.ui.tabs.init()'); - console.log(obj); - var spawned = spawn('div.tabs'); + // set up the group elements + tab.groups(obj.groups, '#admin-config-tabs > .xnat-nav-tabs'); + function render(element){ $$(element).append(spawned); return spawned; } function get(){ - console.log('XNAT.ui.tab.init().get()'); return spawned; } @@ -91,36 +217,6 @@ var XNAT = getObject(XNAT || {}); // ================================================== - // ================================================== - // CREATE A SINGLE TAB - tab.init = function _tab(obj){ - - console.log('XNAT.ui.tab.init()'); - console.log(obj); - - var spawned = spawn('div.tab'); - - function render(element){ - $$(element).append(spawned); - return spawned; - } - - function get(){ - console.log('XNAT.ui.tab.init().get()'); - return spawned; - } - - return { - // contents: obj.tabs||obj.contents||obj.content||'', - element: spawned, - spawned: spawned, - render: render, - get: get - } - }; - -// ================================================== - tabs.tab = tab; diff --git a/src/main/webapp/scripts/xnat/ui/templates.js b/src/main/webapp/scripts/xnat/ui/templates.js new file mode 100644 index 00000000..db56fa39 --- /dev/null +++ b/src/main/webapp/scripts/xnat/ui/templates.js @@ -0,0 +1,117 @@ +/*! + * Templates for creating UI elements with spawn.js + */ + +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, template, + $ = jQuery || null; // check and localize + + XNAT.ui = getObject(XNAT.ui || {}); + + XNAT.ui.template = template = + XNAT.ui.template || {}; + + + // ======================================== + // generic panel element + template.panelElement = function(opts, content){ + var _templ, _spawn, _html; + opts.className = [].concat(opts.className||[], 'panel-element').join(' ').trim(); + _templ = [ + 'div|data-name='+(opts.name||''), + { className: opts.className }, + content + ]; + _spawn = function(){ + return spawn.apply(null, _templ); + }; + _html = _spawn().outerHTML; + return { + template: _templ, // the raw template (Spawn array) + spawned: _spawn(), // pre-spawned + spawn: _spawn, // call to make a fresh spawn + html: _html, // pre-spawned HTML + get: _spawn, + getHTML: function(){ // call to get fresh HTML + return spawn(_templ).outerHTML; + } + } + }; + // ======================================== + + + // ======================================== + // input element for form panels + template.panelInput = function(opts){ + return template.panelElement(opts, [ + ['label.element-label|for='+opts.id, opts.label||opts.title||opts.name], + ['div.element-wrapper', [ + ['input', { + type: opts.type||'text', + id: opts.id, + name: opts.name, + className: opts.className||'', + size: 25, + title: opts.title||opts.name||opts.id + }], + ['div.description', opts.description||opts.body||opts.html] + ]] + ]); + }; + // ======================================== + + + // ======================================== + // select element for form panels + template.panelSelect = function(opts){ + opts = getObject(opts); + opts.name = opts.name || opts.id; + opts.id = opts.id || toDashed(opts.name); + + var _select = spawn('select', { + id: opts.id, + name: opts.name, + className: opts.className||'', + //size: 25, + title: opts.title||opts.name||opts.id||'', + value: opts.value||'' + }); + // add the options + $.each(opts.options||{}, function(name, prop){ + var _option = spawn('option', { + html: prop.label || prop.text, + value: prop.value + }); + // select the option if it's the select element's value + if (prop.value === opts.value){ + _option.selected = true; + } + _select.appendChild(_option) + }); + return template.panelElement(opts, [ + ['label.element-label|for='+opts.id, opts.label||opts.title||opts.name], + ['div.element-wrapper', [ + _select, + ['div.description', opts.description||opts.body||opts.html] + ]] + ]); + }; + // ======================================== + + + return XNAT.ui.templates = XNAT.ui.template = template; + +})); -- GitLab