From b93181e28a895b29962e4dbfa3d506524bcb1dbd Mon Sep 17 00:00:00 2001 From: "Mark M. Florida" <markflorida@wustl.edu> Date: Mon, 29 Aug 2016 11:34:14 -0500 Subject: [PATCH] XNAT-4486, XNAT-4487: data used to fill in values on Site Admin page is cached to prevent multiple requests; info icon moved to left of element's label. --- src/main/webapp/page/admin/content.jsp | 51 +- src/main/webapp/scripts/xnat/spawner.js | 6 +- src/main/webapp/scripts/xnat/ui/panel.js | 876 +++++++++++------------ src/main/webapp/scripts/xnat/xhr.js | 47 +- 4 files changed, 486 insertions(+), 494 deletions(-) diff --git a/src/main/webapp/page/admin/content.jsp b/src/main/webapp/page/admin/content.jsp index 0fc50101..61bb2cc0 100755 --- a/src/main/webapp/page/admin/content.jsp +++ b/src/main/webapp/page/admin/content.jsp @@ -52,55 +52,42 @@ XNAT.data = extend(true, { siteConfig: {}, notifications: {} - }, XNAT.data); + }, 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; + XNAT.data['/xapi/siteConfig'] = XNAT.data.siteConfig; </c:if> <%-- can't use empty/undefined object --%> <c:if test="${not empty notifications}"> XNAT.data.notifications = ${notifications}; + XNAT.data['/xapi/notifications'] = XNAT.data.notifications; </c:if> - var jsonUrl = XNAT.url.rootUrl('/xapi/spawner/resolve/siteAdmin/adminPage'); + // these properties MUST be set before spawning 'tabs' widgets + XNAT.tabs.container = $('#admin-config-tabs').find('div.content-tabs'); + XNAT.tabs.layout = 'left'; - $.get({ - url: jsonUrl, - success: function(data){ - - // these properties MUST 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(XNAT.tabs.container, 500, function(){ - initInfoLinks(); - //if (window.location.hash) { - // XNAT.ui.tab.select(getUrlHashValue()); - //} - }); - - // SAVE THE UI JSON - XNAT.app.adminTabs = adminTabs; - - } + var adminTabs = XNAT.spawner.resolve('siteAdmin/adminPage'); + adminTabs.render(XNAT.tabs.container, 200, function(){ + //initInfoLinks(); + // SAVE THE UI JSON + XNAT.app.adminTabs = adminTabs; }); })(); - - function initInfoLinks(){ - $('.infolink').click(function(e){ - var idx = this.id.substr(9); - var help = infoContent[idx]; - xmodal.message(help.title, help.content); - }); - }; + +// function initInfoLinks(){ +// $('.infolink').click(function(e){ +// var idx = this.id.substr(9); +// var help = infoContent[idx]; +// xmodal.message(help.title, help.content); +// }); +// } </script> </div> diff --git a/src/main/webapp/scripts/xnat/spawner.js b/src/main/webapp/scripts/xnat/spawner.js index e1661b05..ed0a1cbb 100644 --- a/src/main/webapp/scripts/xnat/spawner.js +++ b/src/main/webapp/scripts/xnat/spawner.js @@ -316,9 +316,11 @@ var XNAT = getObject(XNAT); url: url }, opts)); - function spawnRender(container){ + function spawnRender(){ + var renderArgs = arguments; return request.done(function(obj){ - spawner.spawn(obj).render($$(container)) + spawner.spawn(obj).render.apply(request, renderArgs); + return request; }); } diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index bcb57930..c602a2f0 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -50,7 +50,15 @@ var XNAT = getObject(XNAT || {}); // set the data attributes and return the new data object return el.data; } - + + function setDisabled(elements, disabled){ + $$(elements).each(function(idx){ + var _disabled = !!disabled; + var modifyClass = _disabled ? 'addClass' : 'removeClass'; + $(this).prop('disabled', _disabled)[modifyClass]('disabled'); + }); + } + // string that indicates to look for a namespaced object value var lookupPrefix = '??'; @@ -153,13 +161,140 @@ var XNAT = getObject(XNAT || {}); else if (/submit|primary/.test(type)) { button.classes.push('submit') } - if (disabled) { + if (disabled === true) { button.classes.push('disabled'); - button.disabled = 'disabled' + button.disabled = true } return spawn('button', button); } + // populate the data fields if this panel is in the 'active' tab + // (only getting values for the active tab should cut down on requests) + function loadData(form, obj){ + + obj = cloneObject(obj); + + obj.load = obj.load || obj.url; + + + // need a form to put the data into! + // and a 'load' property too + if (!form || !obj.load) { + loadingDialog().close(); + return; + } + + var $form = $(form); + + obj.load = (obj.load+'').trim(); + + // if 'load' starts with '$?', '~/', or just '/' + // then values need to load via REST + var ajaxPrefix = /^(\$\?|~\/|\/)/; + var doAjax = ajaxPrefix.test(obj.load); + + // if 'load' starts with '!?' do an eval() + var evalPrefix = '!?'; + + // if 'load' starts with ?? (or NOT evalPrefix or ajaxPrefix), do lookup + var lookupPrefix = '??'; + + // ...BUT... + // if there's an existing property name: + // XNAT.data['/rest/url'] + // that matches the URL, then use that + if (doAjax && XNAT.data && XNAT.data[obj.load]) { + doAjax = false; + obj.prop = obj.load; + obj.load = '??:XNAT:data' + } + + if (!doAjax) { + + var doLookup = obj.load.indexOf(lookupPrefix) === 0; + if (doLookup) { + obj.load = (obj.load.split(lookupPrefix)[1]||'').trim().split('|')[0]; + obj.prop = obj.prop || obj.load.split('|')[1] || ''; + $(form).setValues(lookupObjectValue(window, obj.load, obj.prop)); + loadingDialog().close(); + return form; + } + + var doEval = obj.load.indexOf(evalPrefix) === 0; + if (doEval) { + obj.load = (obj.load.split(evalPrefix)[1]||'').trim(); + } + + // lastly try to eval the 'load' value + try { + $form.setValues(eval(obj.load)); + } + catch (e) { + console.log(e); + } + + loadingDialog().close(); + + return $form[0]; + + } + + ////////// + // REST + ////////// + + var ajaxUrl = obj.refresh || ''; + + // if 'load' starts with $?, do ajax request + //var ajaxPrefix = '$?'; + var ajaxProp = ''; + + // value: $? /path/to/data | obj:prop:name + // value: ~/path/to/data|obj.prop.name + if (doAjax) { + ajaxUrl = (obj.load.split(ajaxPrefix)[2]||'').trim().split('|')[0]; + ajaxProp = ajaxUrl.split('|')[1] || ''; + } + + // need a url to get the data + if (!ajaxUrl || !stringable(ajaxUrl)) { + loadingDialog().close(); + return form; + } + + // force GET method + obj.method = 'GET'; + + // setup the ajax request + // override values with an + // 'ajax' or 'xhr' property + obj.ajax = extend(true, { + method: obj.method, + url: XNAT.url.rootUrl(ajaxUrl) + }, obj.ajax || obj.xhr); + + obj.ajax.success = function(data){ + if (ajaxProp){ + data = data[ajaxProp]; + } + $(form).dataAttr('status', 'clean'); + $(form).setValues(data); + }; + + obj.ajax.error = function(){ + $(form).dataAttr('status', 'error'); + }; + + + obj.ajax.complete = function(){ + loadingDialog().close(); + }; + + // return the ajax thing for method chaining + return XNAT.xhr.request(obj.ajax); + + } + // creates a panel that's a form that can be submitted // TODO: REFACTOR THIS BEAST panel.form = function panelForm(opts, callback){ @@ -223,180 +358,63 @@ var XNAT = getObject(XNAT || {}); // cache a jQuery-wrapped element var $formPanel = $(_formPanel); - // set form element values from an object map - function setValues(form, dataObj){ - // find all form inputs with a name attribute - $$(form).find(':input').each(function(){ - - var $this = $(this); - var val = lookupObjectValue(dataObj, this.name||this.title); - - if (Array.isArray(val)) { - val = val.join(', '); - $this.addClass('array-list') - } - else { - val = stringable(val) ? val : JSON.stringify(val); - } - - // used on hidden inputs to reset values - if ($this.hasClasses('proxy && dirty')) { - this.value = $this.dataAttr('value'); - } - - //if (val === "") return; - - // $this.not(':checkbox, :radio').changeVal(val); - $this.not(':radio').changeVal(val); - - if (/checkbox/i.test(this.type)) { - this.checked = realValue(val); - } - - if (/radio/i.test(this.type)) { - this.checked = isEqual(this.value, val); - if (this.checked) { - $this.trigger('change'); - } - } - - $this.removeClass('dirty').dataAttr('value', val); - - }); - - loadingDialog().closeAll(); - - } - - - // populate the data fields if this panel is in the 'active' tab - // (only getting values for the active tab should cut down on requests) - function loadData(form, obj){ - - obj = cloneObject(obj); - - obj.load = obj.load || obj.url; - - // need a form to put the data into! - // and a 'load' property too - if (!form || !obj.load) { - loadingDialog().close(); - return; - } - - obj.load = (obj.load+'').trim(); - - // if 'load' starts with '$?', '~/', or just '/' - // then values need to load via REST - var ajaxPrefix = /^(\$\?|~\/|\/)/; - var doAjax = ajaxPrefix.test(obj.load); - - // if 'load' starts with '!?' do an eval() - var evalPrefix = '!?'; - - // if 'load' starts with ?? (or NOT evalPrefix or ajaxPrefix), do lookup - var lookupPrefix = '??'; - - if (!doAjax) { - - var doLookup = obj.load.indexOf(lookupPrefix) === 0; - if (doLookup) { - obj.load = (obj.load.split(lookupPrefix)[1]||'').trim().split('|')[0]; - obj.prop = obj.prop || obj.load.split('|')[1] || ''; - setValues(form, lookupObjectValue(window, obj.load, obj.prop)); - loadingDialog().close(); - return form; - } - - var doEval = obj.load.indexOf(evalPrefix) === 0; - if (doEval) { - obj.load = (obj.load.split(evalPrefix)[1]||'').trim(); - } - - // lastly try to eval the 'load' value - try { - setValues(form, eval(obj.load)); - } - catch (e) { - console.log(e); - } - - loadingDialog().close(); - return form; - - } - - ////////// - // REST - ////////// - - var ajaxUrl = obj.refresh || ''; - - // if 'load' starts with $?, do ajax request - //var ajaxPrefix = '$?'; - var ajaxProp = ''; - - // value: $? /path/to/data | obj:prop:name - // value: ~/path/to/data|obj.prop.name - if (doAjax) { - ajaxUrl = (obj.load.split(ajaxPrefix)[2]||'').trim().split('|')[0]; - ajaxProp = ajaxUrl.split('|')[1] || ''; - } - - // need a url to get the data - if (!ajaxUrl || !stringable(ajaxUrl)) { - loadingDialog().close(); - return form; - } - - // force GET method - obj.method = 'GET'; - - // setup the ajax request - // override values with an - // 'ajax' or 'xhr' property - obj.ajax = extend(true, { - method: obj.method, - url: XNAT.url.rootUrl(ajaxUrl) - }, obj.ajax || obj.xhr); - - obj.ajax.success = function(data){ - if (ajaxProp){ - data = data[ajaxProp]; - } - $(form).dataAttr('status', 'clean'); - setValues(form, data); - }; - - obj.ajax.error = function(){ - $(form).dataAttr('status', 'error'); - }; - - - obj.ajax.complete = function(){ - loadingDialog().close(); - }; - - // return the ajax thing for method chaining - return XNAT.xhr.request(obj.ajax); - - } + // // set form element values from an object map + // // HANDLED BY $('form').setValues({name:'value'}) now + // function dontSetValues(form, dataObj){ + // // find all form inputs with a name attribute + // $$(form).find(':input').each(function(){ + // + // var $this = $(this); + // var val = lookupObjectValue(dataObj, this.name||this.title); + // + // if (Array.isArray(val)) { + // val = val.join(', '); + // $this.addClass('array-list') + // } + // else { + // val = stringable(val) ? val : JSON.stringify(val); + // } + // + // // used on hidden inputs to reset values + // if ($this.hasClasses('proxy && dirty')) { + // this.value = $this.dataAttr('value'); + // } + // + // //if (val === "") return; + // + // // $this.not(':checkbox, :radio').changeVal(val); + // $this.not(':radio').changeVal(val); + // + // if (/checkbox/i.test(this.type)) { + // this.checked = realValue(val); + // } + // + // if (/radio/i.test(this.type)) { + // this.checked = isEqual(this.value, val); + // if (this.checked) { + // $this.trigger('change'); + // } + // } + // + // $this.removeClass('dirty').dataAttr('value', val); + // + // }); + // + // loadingDialog().closeAll(); + // + // } // if (opts.load) { // loadData(_formPanel, opts) // } - // keep an eye on the inputs - $formPanel.find(':input').on('change', function(){ - $formPanel.dataAttr('status', 'dirty'); - }); - opts.onload = opts.onload || callback; // custom event for reloading data (refresh) $formPanel.on('reload-data', function(){ + var _load = opts.refresh || opts.load || opts.url; loadData(this, { - load: opts.refresh || opts.load || opts.url + load: _load ? ('$?' + _load.replace(/^\$\?/, '')) : '' }); }); @@ -418,6 +436,11 @@ var XNAT = getObject(XNAT || {}); multiform.errors = 0; + // keep an eye on the inputs + // $formPanel.on('change', 'input, select, textarea', function(){ + // setDisabled($formPanel.find('.panel-footer button'), false); + // }); + // intercept the form submit to do it via REST instead $formPanel.on('submit', function(e){ @@ -500,10 +523,12 @@ var XNAT = getObject(XNAT || {}); method: $form.data('method') || opts.method || 'POST', url: this.action, success: function(){ - var obj = {}; + var obj = {}, + _load = opts.refresh || opts.reload || opts.url || opts.load; // actually, NEVER use returned data... // ALWAYS reload from the server - obj.load = opts.refresh || opts.reload || opts.url || opts.load; + // (prepending '$?' assures that) + obj.load = _load ? ('$?' + _load.replace(/^\$\?/, '')) : ''; if (!silent){ XNAT.ui.banner.top(2000, 'Data saved successfully.', 'success'); loadData($form, obj); @@ -672,10 +697,13 @@ var XNAT = getObject(XNAT || {}); var dialog = new xmodal.Modal }; + panel.info = function(opts){}; + panel.info.dialog = {}; + // create a single generic panel element panel.element = function(opts){ - var _element, _inner = [], _target; + var _element, _inner = [], _target, infoId = '', _info = ''; opts = cloneObject(opts); opts.element = opts.element || opts.config || {}; if (opts.id || opts.element.id) { @@ -685,17 +713,43 @@ var XNAT = getObject(XNAT || {}); addDataObjects(opts.element, { name: opts.name||'' }); opts.label = opts.label||opts.title||opts.name||''; - _inner.push(['div.element-label', opts.label]); - - // 'contents' will be inserted into the 'target' element - _target = spawn('div.element-wrapper'); - // add a help info icon if one is specified if (opts.info){ - _inner.push(['span#infolink-'+infoId+'.infolink.icon.icon-sm.icon-status.icon-qm','']); - infoContent[infoId++] = {label:opts.label, content:opts.info}; + infoId = randomID('i', false); + _info = spawn('a.infolink|href=#!', { + id: infoId, + style: { + position: 'relative', + top: '3px', + right: '8px' + } + }, [ + ['img', { + src: XNAT.url.rootUrl('/style/icons/icon-qm-48.png'), + width: 16, + height: 16 + }] + ]); + + panel.info.dialog[infoId] = function(){ + console.log('info for ' + opts.label); + xmodal.message({ + title: opts.label, + content: opts.info, + height: 240, + footer: false + }); + }; + + //_inner.push(_info); + // infoContent[infoId++] = {label:opts.label, content:opts.info}; } + _inner.push(['div.element-label', [_info, opts.label]]); + + // 'contents' will be inserted into the 'target' element + _target = spawn('div.element-wrapper'); + // add the target to the content array _inner.push(_target); @@ -720,7 +774,16 @@ var XNAT = getObject(XNAT || {}); }; panel.element.init = panel.element; - + + + $(function(){ + // delegate 'infolink' click handlers to 'body' element + $('body').on('click', 'a.infolink', function(){ + panel.info.dialog[this.id].apply(this, arguments); + }); + }); + + panel.subhead = function(opts){ opts = cloneObject(opts); opts.html = opts.html || opts.text || opts.label; @@ -1029,119 +1092,120 @@ var XNAT = getObject(XNAT || {}); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - /** - * Panel widget with default 'Submit' and 'Revert' buttons - * @param opts - * @param container - * @returns {*} - */ - panel.form = function panelForm(opts, container){ - - var _panel, $panel, - saveBtn, revertBtn, - $saveBtn, $revertBtn; - - opts.tag = 'form.xnat-form-panel'; - - opts.title = opts.label; - - opts.body = []; - - if (opts.description) { - opts.body.push(element.p(opts.description || '')) - } - - if (opts.elements) { - opts.body = opts.body.concat(setupElements(opts.elements)) - } - - saveBtn = footerButton('Save', 'submit', true, 'save pull-right'); - revertBtn = footerButton('Discard Changes', 'button', true, 'revert pull-right'); - - opts.footer = [ - saveBtn, - spawn('span.pull-right', ' '), - revertBtn, - footerButton('Default Settings', 'link', false, 'defaults pull-left'), - spawn('div.clear') - ]; - - // CREATE THE PANEL - _panel = panel(opts); - - $panel = $(_panel.element); - $saveBtn = $(saveBtn); - $revertBtn = $(revertBtn); - - // what's the submission method? - var method = opts.method || 'GET'; - - method = method.toUpperCase(); - - var url = '#'; - - if (method === 'GET') { - url = XNAT.url.restUrl(opts.url) - } - else if (/PUT|POST|DELETE/.test(method)) { - // add CSRF token for PUT, POST, or DELETE - url = XNAT.url.csrfUrl(opts.url) - } - else { - // any other 'method' value is ignored - } - - // set panel as 'dirty' when stuff changes - $panel.on('change', ':input', function(){ - $(this).addClass('dirty'); - setDisabled($panel.find('.panel-footer button'), false); - }); - - $panel.on('submit', function(e){ - e.preventDefault(); - // submit the data and disable 'Save' and 'Revert' buttons - if (opts.url) { - try { - XNAT.xhr.request({ - method: method, - url: url, - data: $panel, - success: function(){ - console.log('success!'); - setDisabled([$saveBtn, $revertBtn], true); - }, - error: function(){ - console.log('error.') - } - }) - } - catch (e) { - setDisabled([$saveBtn, $revertBtn], true); - console.log(e) - } - } - }); - - _panel.revert = function(){ - discardChanges($panel); - setDisabled([$saveBtn, $revertBtn], true); - }; - - $revertBtn.on('click', _panel.revert); - - _panel.panel = _panel.element; - - return { - element: _panel, - spawned: _panel, - get: function(){ - return _panel; - } - } - - }; + // /** + // * Panel widget with default 'Submit' and 'Revert' buttons + // * @param opts + // * @param container + // * @returns {*} + // */ + // panel.form = function panelForm(opts, container){ + // + // var _panel, $panel, + // saveBtn, revertBtn, + // $saveBtn, $revertBtn; + // + // opts.tag = 'form.xnat-form-panel'; + // + // opts.title = opts.label; + // + // opts.body = []; + // + // if (opts.description) { + // opts.body.push(element.p(opts.description || '')) + // } + // + // if (opts.elements) { + // opts.body = opts.body.concat(setupElements(opts.elements)) + // } + // + // saveBtn = footerButton('Save', 'submit', true, 'save pull-right'); + // revertBtn = footerButton('Discard Changes', 'button', true, 'revert pull-right'); + // + // opts.footer = [ + // saveBtn, + // spawn('span.pull-right', ' '), + // revertBtn, + // footerButton('Default Settings', 'link', false, 'defaults pull-left'), + // spawn('div.clear') + // ]; + // + // // CREATE THE PANEL + // _panel = panel(opts); + // + // $panel = $(_panel.element); + // $saveBtn = $(saveBtn); + // $revertBtn = $(revertBtn); + // + // // what's the submission method? + // var method = opts.method || 'GET'; + // + // method = method.toUpperCase(); + // + // var url = '#'; + // + // if (method === 'GET') { + // url = XNAT.url.restUrl(opts.url) + // } + // else if (/PUT|POST|DELETE/.test(method)) { + // // add CSRF token for PUT, POST, or DELETE + // url = XNAT.url.csrfUrl(opts.url) + // } + // else { + // // any other 'method' value is ignored + // } + // + // // set panel as 'dirty' when stuff changes + // $panel.on('change', ':input', function(){ + // $(this).addClass('dirty'); + // setDisabled($panel.find('.panel-footer button'), false); + // }); + // + // $panel.on('submit', function(e){ + // e.preventDefault(); + // // submit the data and disable 'Save' and 'Revert' buttons + // if (opts.url) { + // try { + // XNAT.xhr.request({ + // method: method, + // url: url, + // data: $panel, + // success: function(){ + // console.log('success!'); + // setDisabled([$saveBtn, $revertBtn], true); + // }, + // error: function(){ + // console.log('error.') + // } + // }) + // } + // catch (e) { + // setDisabled([$saveBtn, $revertBtn], true); + // console.log(e) + // } + // } + // }); + // + // _panel.revert = function(){ + // discardChanges($panel); + // setDisabled([$saveBtn, $revertBtn], true); + // }; + // + // $revertBtn.on('click', _panel.revert); + // + // _panel.panel = _panel.element; + // + // return { + // element: _panel, + // spawned: _panel, + // get: function(){ + // return _panel; + // } + // } + // + // }; // return a single 'toggle' element + // TODO: create toggler widget function radioToggle(item){ var element = extend(true, {}, item), @@ -1198,54 +1262,6 @@ var XNAT = getObject(XNAT || {}); } - // create elements that are part of an 'element-group' - // returns Spawn arguments array - function groupElements(items){ - return items.map(function(item){ - var label = ''; - var tag = item.kind === 'hidden' ? 'div.hidden' : 'div.group-item'; - if (item.label) { - label = elementLabel(item.label, item.id) - } - tag += '|data-name=' + item.name; - return [tag, [].concat(label, panelElement(item))]; - }); - } - - function discardChanges(form){ - - var $form = $$(form); - - // reset all checkboxes and radio buttons - $form.find(':checkbox, :radio').each(function(){ - var $this = $(this); - if ($this.hasClass('dirty')) { - if ($this.data('state') !== 'checked') { - if ($this.is(':checked')) { - $this.trigger('click') - } - else { - // nevermind. - } - } - $this.removeClass('dirty'); - } - }); - - // reset text inputs based on [data-value] attribute - $form.find(':input').not(':checkbox, :radio').val(function(){ - return $(this).data('value'); - }).trigger('change').removeClass('dirty'); - - // simulate click on items that were initially checked - //$form.find(':input[data-state="checked"]').trigger('click'); - - } - - function setValue(target, source){ - $$(target).val($$(source).val()); - } - function toggleValue(target, source, modifier){ var $source = $$(source); @@ -1265,15 +1281,6 @@ var XNAT = getObject(XNAT || {}); } - function setDisabled(elements, disabled){ - [].concat(elements).forEach(function(element){ - var _disabled = !!disabled; - var modifyClass = _disabled ? 'addClass' : 'removeClass'; - $$(element).prop('disabled', _disabled)[modifyClass]('disabled'); - }); - } - - function setHidden(elements, hidden){ [].concat(elements).forEach(function(element){ var showOrHide, modifyClass; @@ -1290,97 +1297,90 @@ var XNAT = getObject(XNAT || {}); } - XNAT.ui = getObject(XNAT.ui || {}); - XNAT.ui.panel = panel; // temporarily use the 'form' panel kind - XNAT.ui.panelForm = XNAT.ui.formPanel = panel.form; - - - $(function(){ - - var $body = $('body'); - - // bind the XNAT.event.toggle() function to elements with 'data-' attributes - $body.on('change.modify', '[data-modify]', function(){ - - var $this = $(this); - var checked = $this.is(':checked'); - - // allow multiple states to be passed - separated by semicolons - var states = $this.data('modify').split(';'); - - states.forEach(function(set){ - - var parts = set.split(':'); - - var state = parts[0].trim(); - - // allow multiple arguments as a comma-separated list - var args = parts[1].split(','); - - var _target = args[0].trim(); - var _source = (args[1] || '').trim() || _target; - - if (args[1]) { - _source = args[1].trim(); - } - - switch (state) { - - case 'toggle.disabled' || 'toggle.disable': - setDisabled(_target, checked); - break; - - case 'toggle.enabled' || 'toggle.enable': - setDisabled(_target, !checked); - break; - - case 'disable' || 'disabled': - setDisabled(_target, true); - break; - - case 'enable' || 'enabled': - setDisabled(_target, false); - break; - - case 'toggle.hidden' || 'toggle.hide': - setHidden(_target, checked); - break; - - case 'toggle.visible' || 'toggle.show': - setHidden(_target, !checked); - break; - - case 'hide': - setHidden(_target, true); - break; - - case 'show': - setHidden(_target, false); - break; - - case 'toggle.value': - toggleValue(_target, _source, $this[0]); - break; - - case 'apply.value' || 'set.value': - setValue(_target, $this); - break; - - case 'get.value': - setValue($this, _target); - break; - - } - - }) - - }); - - // trigger a change on load? - //$('[data-modify]').trigger('change.modify'); - - }); + // $(function(){ + // + // var $body = $('body'); + // + // // bind the XNAT.event.toggle() function to elements with 'data-' attributes + // $body.on('change.modify', '[data-modify]', function(){ + // + // var $this = $(this); + // var checked = $this.is(':checked'); + // + // // allow multiple states to be passed - separated by semicolons + // var states = $this.data('modify').split(';'); + // + // states.forEach(function(set){ + // + // var parts = set.split(':'); + // + // var state = parts[0].trim(); + // + // // allow multiple arguments as a comma-separated list + // var args = parts[1].split(','); + // + // var _target = args[0].trim(); + // var _source = (args[1] || '').trim() || _target; + // + // if (args[1]) { + // _source = args[1].trim(); + // } + // + // switch (state) { + // + // case 'toggle.disabled' || 'toggle.disable': + // setDisabled(_target, checked); + // break; + // + // case 'toggle.enabled' || 'toggle.enable': + // setDisabled(_target, !checked); + // break; + // + // case 'disable' || 'disabled': + // setDisabled(_target, true); + // break; + // + // case 'enable' || 'enabled': + // setDisabled(_target, false); + // break; + // + // case 'toggle.hidden' || 'toggle.hide': + // setHidden(_target, checked); + // break; + // + // case 'toggle.visible' || 'toggle.show': + // setHidden(_target, !checked); + // break; + // + // case 'hide': + // setHidden(_target, true); + // break; + // + // case 'show': + // setHidden(_target, false); + // break; + // + // case 'toggle.value': + // toggleValue(_target, _source, $this[0]); + // break; + // + // case 'apply.value' || 'set.value': + // setValue(_target, $this); + // break; + // + // case 'get.value': + // setValue($this, _target); + // break; + // + // } + // + // }) + // + // }); + // + // // trigger a change on load? + // //$('[data-modify]').trigger('change.modify'); + // + // }); })(XNAT, jQuery, window); - -var infoId = 0, infoContent = []; diff --git a/src/main/webapp/scripts/xnat/xhr.js b/src/main/webapp/scripts/xnat/xhr.js index 7418977d..7a70b78e 100755 --- a/src/main/webapp/scripts/xnat/xhr.js +++ b/src/main/webapp/scripts/xnat/xhr.js @@ -439,14 +439,19 @@ var XNAT = getObject(XNAT||{}), } // set form element values from an object map - function setValues(form, dataObj){ + // 'form' can be a form element, selector, or array of inputs + function setValues(inputs, dataObj){ // cache and check if form exists - var $form = $$(form); + var $inputs = $$(inputs); - if (!$form.length) return; + if (!$inputs.length) return; - // find all input and select elements with a name attribute - $form.find(':input').each(function(){ + if ($inputs.length === 1 && /form/i.test($inputs[0].tagName)) { + $inputs = $inputs.find(':input'); + } + + // apply values to each input + $inputs.each(function(){ var $this = $(this); var val = lookupObjectValue(dataObj, this.name||this.title); @@ -459,33 +464,31 @@ var XNAT = getObject(XNAT||{}), val = stringable(val) ? val : JSON.stringify(val); } - changeValue(this, val); + //if (val === "") return; - // special handling for checkboxes - if (this.type === 'checkbox') { - this.checked = realValue(val) + if (/checkbox/i.test(this.type)) { + this.checked = realValue(val); } - // special handling for radio buttons - if (this.type === 'radio') { + else if (/radio/i.test(this.type)) { this.checked = isEqual(this.value, val); if (this.checked) { $this.trigger('change'); } } + else { + changeValue($this, val); + } + + $this.removeClass('dirty').dataAttr('value', val); + }); - // // set textarea innerText from a 'value' property - // $form.find('textarea[name]').each(function(){ - // var $textarea = $(this); - // var textValue = (function(){ - // var val = dataObj[this.name]; - // return stringable(val) ? val+'' : safeStringify(val); - // })(); - // changeValue($textarea, textValue); - // // $textarea.val(textValue).change(); - // }); - return $form; + + return $inputs; } + // make globally accessible through $ + $.setValues = setValues; + // this could be a handy jQuery method $.fn.setValues = function(dataObj){ setValues(this, dataObj); -- GitLab