diff --git a/src/main/webapp/page/admin/content.jsp b/src/main/webapp/page/admin/content.jsp index 17d49aa4184a80f95f3c0194256be42e55c74522..9c0c9d6fed2afc00111d4be08bba0ac01aba241b 100755 --- a/src/main/webapp/page/admin/content.jsp +++ b/src/main/webapp/page/admin/content.jsp @@ -21,42 +21,65 @@ </header> <!-- Admin tab container --> - <div id="admin-config-tabs" class="content-tabs xnat-tab-container"> + <div id="admin-config-tabs"> + + <div class="content-tabs xnat-tab-container"> + + <%-- + <div class="xnat-nav-tabs side pull-left"> + <!-- ================== --> + <!-- Admin tab flippers --> + <!-- ================== --> + </div> + <div class="xnat-tab-content side pull-right"> + <!-- ================== --> + <!-- Admin tab panes --> + <!-- ================== --> + </div> + --%> - <div class="xnat-nav-tabs side pull-left"> - <!-- ================== --> - <!-- Admin tab flippers --> - <!-- ================== --> - </div> - - <div class="xnat-tab-content side pull-right"> - <!-- ================== --> - <!-- Admin tab panes --> - <!-- ================== --> </div> </div> <c:import url="/xapi/siteConfig" var="siteConfig"/> <c:import url="/xapi/notifications" var="notifications"/> + <script> (function(){ - XNAT.data = extend({}, XNAT.data, { - siteConfig: ${siteConfig}, - notifications: ${notifications} - }); - // get rid of the 'targetSource' property - delete XNAT.data.siteConfig.targetSource; + XNAT.data = getObject(XNAT.data); + + <%-- safety check --%> + <c:if test="${not empty siteConfig}"> + XNAT.data.siteConfig = ${siteConfig}; + // get rid of the 'targetSource' property + delete XNAT.data.siteConfig.targetSource; + </c:if> + + <%-- can't use empty/undefined object --%> + <c:if test="${not empty notifications}"> + XNAT.data.notifications = ${notifications}; + </c:if> var jsonUrl = XNAT.url.rootUrl('/xapi/spawner/resolve/siteAdmin/adminPage'); $.get({ url: jsonUrl, success: function(data){ + + // these properties need to be set before spawning 'tabs' widgets + XNAT.tabs.container = $('#admin-config-tabs').find('div.content-tabs'); + XNAT.tabs.layout = 'left'; + + // SPAWN THE TABS var adminTabs = XNAT.spawner.spawn(data); - adminTabs.render('#admin-config-tabs > .xnat-tab-content'); + + adminTabs.render(XNAT.tabs.container, 500); + + // SAVE THE JSON XNAT.app.adminTabs = adminTabs; + } }); @@ -84,3 +107,4 @@ </div> </pg:restricted> + diff --git a/src/main/webapp/page/admin/spawner/content.jsp b/src/main/webapp/page/admin/spawner/content.jsp index 0736b8bb29bd890052508e32e126a1165d586579..277f3b879092d9b9b36c30430fab6ddddae1e7c8 100644 --- a/src/main/webapp/page/admin/spawner/content.jsp +++ b/src/main/webapp/page/admin/spawner/content.jsp @@ -22,15 +22,19 @@ <div data-name="spawnerElements" class="panel-element" style="overflow:visible;"> + <div class="description" style="margin:20px 5px 0">View and manage XNAT Spawner elements.</div> + <%--<label class="element-label" for="!?"></label>--%> <%--<div class="element-wrapper">--%> - <table id="spawner-element-list" class="xnat-table alt1 clean" style="width:100%;border:none;"> + <style type="text/css"> + #spawner-element-list td { padding: 4px; } + </style> + + <table id="spawner-element-list" class="xnat-table highlight alt1 clean" style="width:100%;border:none;"> <!-- list of available namespaces will show here --> </table> - <div class="description" style="margin:20px 5px 0">View and manage XNAT Spawner elements.</div> - <%--</div>--%> </div> diff --git a/src/main/webapp/page/admin/style.css b/src/main/webapp/page/admin/style.css index b2f6ed2c5a2fd671c8ddd044639a1ef7612e3652..946b2f1f34bd6c48b04502031733291ffde74aea 100644 --- a/src/main/webapp/page/admin/style.css +++ b/src/main/webapp/page/admin/style.css @@ -74,7 +74,7 @@ body.xnat .panel-default { border: 1px solid #c8c8c8; } padding: 12px 16px; color: #222; /background: /* #e9e9e9 */ inherit; } -.panel-default .panel-body { padding: 12px; } +.panel-default .panel-body { padding: 12px 30px; } .panel-default .panel-footer { padding: 12px; background: #f0f0f0; border-top: #c8c8c8; } .panel-title { font-weight: normal; font-size: 20px; line-height: inherit; } @@ -100,7 +100,13 @@ body.xnat .panel-default { border: 1px solid #c8c8c8; } border-bottom: 1px solid #c8c8c8; } -.panel .panel-element textarea { width: 80%; font-family: Courier, monospace; font-weight: normal; } +.panel .panel-element textarea { + width: 80%; padding: 5px 7px; + font-family: Courier, monospace; font-weight: normal; +} + +/* inputs shouldn't be wider than textareas */ +.panel .panel-element input { max-width: 80%; } /* ELEMENT GROUP ITEMS */ .panel .panel-element-group .group-item .element-label { width: auto; } diff --git a/src/main/webapp/scripts/xnat/admin/siteInfo.js b/src/main/webapp/scripts/xnat/admin/siteInfo.js index 070fe46d03d318ae06b89a8bb1d42c68b9ebc837..3f102f37a2d7f3f3a1f8ed495bda5aa941efa303 100644 --- a/src/main/webapp/scripts/xnat/admin/siteInfo.js +++ b/src/main/webapp/scripts/xnat/admin/siteInfo.js @@ -9,7 +9,7 @@ sdtPage.click(changeSiteDescriptionType); sdtText.click(changeSiteDescriptionType); changeSiteDescriptionType(XNAT.data.siteConfig.siteDescriptionType); - }, 100); + }, 1); function changeSiteDescriptionType(eventOrValue){ diff --git a/src/main/webapp/scripts/xnat/spawner.js b/src/main/webapp/scripts/xnat/spawner.js index dc4efb747ccd04985d9735b0d5d363c5e66ffdf3..7faa5a4f7a8a422c473e819dd389a9394156d879 100644 --- a/src/main/webapp/scripts/xnat/spawner.js +++ b/src/main/webapp/scripts/xnat/spawner.js @@ -27,6 +27,8 @@ var XNAT = getObject(XNAT); XNAT.spawner = spawner = getObject(XNAT.spawner || {}); + spawner.counter = 0; + // keep track of items that spawned spawner.spawnedElements = []; @@ -43,8 +45,11 @@ var XNAT = getObject(XNAT); spawner.spawn = function _spawn(obj){ var frag = document.createDocumentFragment(), - $frag = $(frag); + $frag = $(frag), + undefined; + spawner.counter++; + forOwn(obj, function(item, prop){ var kind, methodName, method, spawnedElement, $spawnedElement; @@ -82,7 +87,7 @@ var XNAT = getObject(XNAT); // pass 'content' (not contentS) property to add // stuff directly to spawned element - prop.content = prop.content || prop.children || prop.inner || ''; + prop.content = prop.content || prop.children || ''; try { spawnedElement = @@ -143,6 +148,9 @@ var XNAT = getObject(XNAT); } } + // give up if no spawnedElement + if (!spawnedElement) return; + // spawn child elements from... // 'contents' or 'content' or 'children' or // a property matching the value of either 'contains' or 'kind' @@ -211,18 +219,34 @@ var XNAT = getObject(XNAT); return $frag.contents(); }; - _spawn.render = function(element, empty){ - var $el = $$(element); - // empty the container element before spawning? - if (empty) { - $el.empty(); + _spawn.done = function(callback){ + if (isFunction(callback)) { + callback() } - $el.append(frag); - return spawn; + return _spawn; }; - _spawn.foo = '(spawn.foo)'; + _spawn.render = function(container, wait, callback){ + + var $container = $$(container); + wait = wait !== undefined ? wait : 100; + + $container.hide().append(frag); + $container.fadeIn(wait); + + setTimeout(function(){ + if (isFunction(callback)) { + callback() + } + }, wait); + + return _spawn; + + }; + + _spawn.foo = '(spawn.foo)'; + return _spawn; }; diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index c79640bb6ede7def2e6f8c9e08bc905adb57e0f5..89094323623a6b36c1b07aa4934015f8cd01296d 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -732,26 +732,35 @@ var XNAT = getObject(XNAT || {}); var _menu; opts = cloneObject(opts); - opts.element = opts.element || opts.config || {}; - opts.element.name = opts.element.name || opts.name || ''; - opts.element.id = opts.element.id || opts.id || toDashed(opts.element.name); + + opts.name = opts.name || opts.id || randomID('select-', false); + opts.id = opts.id || toDashed(opts.name||''); + opts.element = extend({ + id: opts.id, + name: opts.name, + className: opts.className||'', + title: opts.title||opts.name||opts.id||'', + value: opts.value||'' + }, opts.element); + if (multi) { opts.element.multiple = true; } - _menu = spawn('select', opts.element, [['option|value=!', 'Select']]); + + _menu = spawn('select', opts.element, [['option', 'Select']]); if (opts.options){ forOwn(opts.options, function(name, prop){ _menu.appendChild(spawn('option', { - value: prop.value, + html: prop.html || prop.text || prop.label || prop.value || prop, + value: prop.value || name, selected: prop.selected || (prop.value === opts.value) - }, prop.label)); + })); }); } - return XNAT.ui.template.panelInput({ - label: opts.label, - name: opts.name - }, _menu).spawned; + + return XNAT.ui.template.panelInput(opts, _menu).spawned; + }; panel.select.init = panel.select.menu; panel.select.single = panel.select.menu; @@ -761,12 +770,6 @@ var XNAT = getObject(XNAT || {}); }; panel.select.multi.init = panel.select.multi; - panel.selectMenu = function panelSelectMenu(opts){ - opts = cloneObject(opts); - return XNAT.ui.template.panelSelect(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 d750f8bbb28674a5ba24a5c7f1c9283cf8d2c178..b819acb6c644d9bf3b78fd0bb2ecf783468276a8 100755 --- a/src/main/webapp/scripts/xnat/ui/tabs.js +++ b/src/main/webapp/scripts/xnat/ui/tabs.js @@ -34,35 +34,27 @@ var XNAT = getObject(XNAT || {}); // ================================================== // SET UP ONE TAB GROUP // add a single tab group to the groups - tab.group = function(obj, container){ + tab.group = function(obj){ 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 }, [ + return spawn('ul.nav.tab-group', { id: id }, [ ['li.label', (obj.label || obj.title || obj.text || 'Tab Group')] ]); - if (container) { - $$(container).append(group); - } - return group; }; // ================================================== // ================================================== // SET UP TAB GROUPS - tab.groups = function(obj, container, empty){ - var groups = [], - $container = $$(container); + tab.groups = function(obj){ + var groups = []; $.each(obj, function(name, label){ groups.push(tab.group({ id: toDashed(name), label: label })); }); - if (empty) { - $container.empty(); - } - $container.append(groups); + // console.log(groups); return groups; }; // ================================================== @@ -70,57 +62,28 @@ var XNAT = getObject(XNAT || {}); // save the id of the active tab XNAT.ui.tab.active = ''; + tab.activate = function(name, container){ - 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 $group, _flipper, _pane; + var $group, groupId, tabId, _flipper, _pane; + + obj = cloneObject(obj); + obj.config = cloneObject(obj.config); - 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); + tabId = toDashed(obj.id || obj.name || ''); _flipper = spawn('li.tab', { - // onclick event handler attached - // directly to tab flipper - onclick: function(){ - activateTab(this, obj.config.id) - } + data: { tab: tabId } }, [ ['a', { title: obj.label, // href: '#'+obj.config.id, - href: '#!', + href: '#' + tabId, html: obj.label }] ]); @@ -137,6 +100,12 @@ var XNAT = getObject(XNAT || {}); } tab.paneFooter = paneFooter; + obj.config.data = + extend(true, {}, obj.config.data, { + name: obj.name||'', + tab: tabId + }); + _pane = spawn('div.tab-pane', obj.config); if (obj.active) { @@ -145,15 +114,19 @@ var XNAT = getObject(XNAT || {}); tab.active = _pane.id; } + groupId = toDashed(obj.group||'other'); + // un-hide the group that this tab is in // (groups are hidden until there is a tab for them) - $group = $('#' + (toDashed(obj.group || 'other')) + '.tab-group'); - + $group = $('#' + groupId + '.tab-group'); + $group.show(); // add all the flippers $group.append(_flipper); + // console.log($group[0]); + function render(element){ $$(element).append(_pane); $$(element).append(paneFooter()); @@ -176,29 +149,58 @@ var XNAT = getObject(XNAT || {}); }; // ================================================== - + // ================================================== // MAIN FUNCTION - tabs.init = function _tabs(obj){ + tabs.init = function tabsInit(obj){ + + var layout, container, $container, + navTabs, tabContent; + + // set container and layout before spawning: + // XNAT.tabs.container = 'div.foo'; + container = tabs.container || 'div.xnat-tab-container'; - var spawned = spawn('div.tabs'); + layout = tabs.layout || 'left'; + + navTabs = spawn('div.xnat-nav-tabs'); + tabContent = spawn('div.xnat-tab-content'); + + if (layout === 'left') { + navTabs.className += ' side pull-left'; + tabContent.className += ' side pull-right'; + } + + $container = $$(container); + + $container.append(navTabs); + $container.append(tabContent); // set up the group elements - tab.groups(obj.meta.tabGroups, '#admin-config-tabs > .xnat-nav-tabs'); + $(navTabs).append(tab.groups(obj.meta.tabGroups)); + + // bind tab click events + $container.on('click', 'li.tab', function(){ + var clicked = $(this).data('tab'); + // de-activate all tabs and panes + $container.find('[data-tab]').removeClass('active'); + // activate the clicked tab and pane + $container.find('[data-tab="' + clicked + '"]').addClass('active'); + }); function render(element){ - $$(element).append(spawned); - return spawned; + $$(element).append(tabContent); + return tabContent; } function get(){ - return spawned; + return tabContent; } return { // contents: obj.tabs||obj.contents||obj.content||'', - element: spawned, - spawned: spawned, + element: tabContent, + spawned: tabContent, render: render, get: get }; @@ -211,3 +213,4 @@ var XNAT = getObject(XNAT || {}); return tabs; })); + diff --git a/src/main/webapp/scripts/xnat/ui/templates.js b/src/main/webapp/scripts/xnat/ui/templates.js index 58609549c982b1fbcb594a4719240ebb79d51b86..635ed9156904b12d80defa9cd6d60a76a2ca1ec8 100644 --- a/src/main/webapp/scripts/xnat/ui/templates.js +++ b/src/main/webapp/scripts/xnat/ui/templates.js @@ -224,30 +224,6 @@ var XNAT = getObject(XNAT); ajaxValue(element, ajaxUrl.trim(), ajaxProp.trim()); } - // if (opts.load) { - // if (opts.load.lookup) { - // lookupValue(element, opts.load.lookup.trim()); - // } - // else if (opts.load.url){ - // $.ajax({ - // method: opts.load.method || 'GET', - // url: XNAT.url.restUrl(opts.load.url), - // success: function(data){ - // // get value from specific object path - // if (isPlainObject(data) && opts.load.prop) { - // data = lookupObjectValue(data, opts.load.prop); - // // opts.load.prop.split('.').forEach(function(part){ - // // data = data[part] || {}; - // // }); - // // data = lookupObjectValue(opts.load.prop); - // } - // $(element).changeVal(data); - // $(element).not('textarea').dataAttr('value', data); - // } - // }) - // } - // } - // trigger an 'onchange' event $element.change(); @@ -302,35 +278,39 @@ var XNAT = getObject(XNAT); // ======================================== // select element for form panels - template.panelSelect = function(opts){ - opts = cloneObject(opts); - opts.name = opts.name || opts.id || randomID('select-', false); - opts.id = opts.id || toDashed(opts.name||''); - opts.element = extend({ - id: opts.id, - name: opts.name, - className: opts.className||'', - //size: 25, - title: opts.title||opts.name||opts.id||'', - value: opts.value||'' - }, opts.element); - - var _select = spawn('select', opts.element, [['option|value=!', 'Select']]); - - // add the options - $.each(opts.options||{}, function(name, prop){ - var _option = spawn('option', extend(true, { - html: prop.html || prop.text || prop.label || prop.value || prop, - value: prop.value || name - }, prop.element)); - // select the option if it's the select element's value - if (prop.value === opts.value){ - _option.selected = true; - } - _select.appendChild(_option) - }); - return template.panelInput(opts, _select); - }; + // template.panelSelect = function(opts){ + // + // opts = cloneObject(opts); + // + // opts.name = opts.name || opts.id || randomID('select-', false); + // opts.id = opts.id || toDashed(opts.name||''); + // opts.element = extend({ + // id: opts.id, + // name: opts.name, + // className: opts.className||'', + // //size: 25, + // title: opts.title||opts.name||opts.id||'', + // value: opts.value||'' + // }, opts.element); + // + // var _select = spawn('select', opts.element, [['option', 'Select']]); + // + // // add the options + // $.each(opts.options||{}, function(name, prop){ + // var _option = spawn('option', extend(true, { + // html: prop.html || prop.text || prop.label || prop.value || prop, + // value: prop.value || name + // }, prop.element)); + // // select the option if it's the select element's value + // if (prop.value === opts.value){ + // _option.selected = true; + // } + // _select.appendChild(_option) + // }); + // + // return template.panelInput(opts, _select); + // + // }; // ======================================== diff --git a/src/main/webapp/style/app.css b/src/main/webapp/style/app.css index 5dc84a0f99fa7620b895d41badee3e6560811af0..7750813028c96b07bb54c12189fc7747cc945495 100644 --- a/src/main/webapp/style/app.css +++ b/src/main/webapp/style/app.css @@ -61,21 +61,28 @@ img { input[type="text"], input[type="password"], input[type="number"] { - padding: 4px 5px 3px 5px; - border: 1px solid #b0b0b0; + padding: 5px 7px; + border: 1px solid #c0c0c0; } textarea { padding: 4px; font-family: Arial, Helvetica, sans-serif; - font-size: 12px; - border: 1px solid #b0b0b0; + font-size: 13px; + border: 1px solid #c0c0c0; } -select { - /* */ +input:focus, +textarea:focus { + border-color: #2fa4e7; + box-shadow: 0 0 2px #2fa4e7; + outline: none; } +select:focus { outline: none; } + +select { } + /* xnat.css */ /***********************************************/ /* XNAT styles */ @@ -961,7 +968,7 @@ hr { /* ////////// FORM ELEMENTS ////////// */ input { font-family: Arial, Helvetica, sans-serif; - font-size: 12px; + font-size: 13px; } /* 'required' items */ @@ -983,9 +990,10 @@ body [type="reset"] { border-radius: 3px; font-family: Arial, Helvetica, sans-serif; font-size: 13px; + white-space: nowrap; letter-spacing: 0.02em; text-decoration: none; - box-shadow: 0px 1px 1px #ccc; + box-shadow: 0 1px 1px #ccc; } /* style for button hover */ @@ -3578,3 +3586,4 @@ textarea.xml-formatted { .pad5h { padding-left: 5px; padding-right: 5px; } .pad10h { padding-left: 10px; padding-right: 10px; } .pad20h { padding-left: 20px; padding-right: 20px; } +