diff --git a/src/main/webapp/scripts/lib/spawn/spawn.js b/src/main/webapp/scripts/lib/spawn/spawn.js index e15024775c74933586e077a8ccdfeef36f9dcde0..6c8f176f182f4fb014a7f643fa0a521022cd17af 100644 --- a/src/main/webapp/scripts/lib/spawn/spawn.js +++ b/src/main/webapp/scripts/lib/spawn/spawn.js @@ -106,16 +106,16 @@ }); } + function hasClassName(el, className){ - var elClasses = el.className.split(/\s+/); + var elClasses = (el.className||'').split(/\s+/); // existing classes return elClasses.indexOf(className.trim()) > -1; } // add new element class without destroying existing class function addClassName(el, newClass){ - el.className = el.className || ''; - var classes = el.className.split(/\s+/); // existing classes + var classes = (el.className||'').split(/\s+/); // existing classes var newClasses = [].concat(newClass||[]).join(' ').split(/\s+/); // don't add duplicate classes newClasses.forEach(function(cls){ @@ -124,8 +124,12 @@ classes.push(cls); } }); + classes = classes.join(' ').trim(); // set the className and return the string - return el.className = classes.join(' ').trim(); + if (classes) { + el.className = classes; + } + return classes; } @@ -185,7 +189,7 @@ var el, $el, parts, id, classes, tagParts, attrs, isVoid, // property names to skip later skip = [ - 'innerHTML', 'html', 'attr', 'config', + 'innerHTML', 'html', 'attr', 'config', 'kind', 'tag', 'tagName', 'prepend', 'append', 'appendTo', 'classes', 'className', 'addClass', @@ -199,13 +203,13 @@ opts = tag[1]; tag = tag[0]; } - + // handle passing a config object as the only argument if (!children && !opts && typeof tag !== 'string') { opts = tag; tag = null; } - + tag = tag || opts.tag || opts.tagName || 'span'; if (tag === '!'){ @@ -434,7 +438,7 @@ } if (opts.after){ - // don't append element twice if + // don't append element twice if // there's 'before' AND 'after' if (!opts.before) { appendChildren(frag, opts.after, spawn); @@ -442,7 +446,7 @@ } el = frag; } - + if (errors.length){ if (hasConsole) console.log(errors); } @@ -460,7 +464,7 @@ }; if (typeof opts.done == 'function') { - opts.done.call(el); + opts.done.call(el); } return el; diff --git a/src/main/webapp/scripts/utils.js b/src/main/webapp/scripts/utils.js index f65aa438aa768897051fa560598d8d4c209d67a9..f394ccea730194c039987d910122b71a88386840 100755 --- a/src/main/webapp/scripts/utils.js +++ b/src/main/webapp/scripts/utils.js @@ -102,6 +102,43 @@ function replaceEach(str, replacements, regex_params){ } +function hasClassName(el, className){ + var elClasses = (el.className||'').split(/\s+/); // existing classes + return elClasses.indexOf(className.trim()) > -1; +} + + +// add new element class without destroying existing class +function addClassName(el, newClass){ + var classes = (el.className||'').split(/\s+/); // existing classes + var newClasses = [].concat(newClass||[]).join(' ').split(/\s+/); + // don't add duplicate classes + newClasses.forEach(function(cls){ + if (!cls) return; + if (!hasClassName(el, cls)) { + classes.push(cls); + } + }); + classes = classes.join(' ').trim(); + // set the className and return the string + if (classes) { + el.className = classes; + } + return classes; +} + + +// add new data object item to be used for [data-] attribute(s) +function addDataObjects(el, attrs){ + el.data = el.data || {}; + forOwn(attrs, function(name, prop){ + el.data[name] = prop; + }); + // set the data attributes and return the new data object + return el.data; +} + + // make sure the ajax calls are NOT cached //$.ajaxSetup({cache:false}); @@ -678,7 +715,7 @@ function compareByText( obj1, obj2 ){ // simplest accordion of all $.fn.superSimpleAccordion = function(){ - + var container = $(this).show(); var h3s = container.find('h3'); var divs = h3s.next('div'); @@ -704,5 +741,5 @@ $.fn.superSimpleAccordion = function(){ '#accordion h3.active { background: #1A75BB; color: #fff; } ' + '#accordion .content { padding: 1em; border: 1px solid #d0d0d0; }' + '</style>'); - + }; diff --git a/src/main/webapp/scripts/xnat/admin/dicomScpManager.js b/src/main/webapp/scripts/xnat/admin/dicomScpManager.js index 10885b22a6c53e560f0ee0eee9e1c517188ab1c5..006b9ccd913b3cfb6d8aef4a8402bbd18140c06c 100644 --- a/src/main/webapp/scripts/xnat/admin/dicomScpManager.js +++ b/src/main/webapp/scripts/xnat/admin/dicomScpManager.js @@ -21,7 +21,7 @@ var XNAT = getObject(XNAT || {}); var dicomScpManager, undefined, rootUrl = XNAT.url.rootUrl; - XNAT.admin = + XNAT.admin = getObject(XNAT.admin || {}); XNAT.admin.dicomScpManager = dicomScpManager = @@ -209,24 +209,29 @@ var XNAT = getObject(XNAT || {}); // TODO: move event listeners to parent elements - events will bubble up // ^-- this will reduce the number of event listeners function enabledCheckbox(item){ - var ckbox = spawn('input.enabled', { + var enabled = !!item.enabled; + var ckbox = spawn('input.dicom-scp-enabled', { type: 'checkbox', - checked: !!item.enabled, + checked: enabled, + value: enabled, + data: { id: item.id, name: item.aeTitle }, onchange: function(){ // save the status when clicked - var enabled = this.checked; + var checkbox = this; + enabled = checkbox.checked; XNAT.xhr.put({ url: scpUrl(item.id + '/enabled/' + enabled), success: function(){ var status = (enabled ? ' enabled' : ' disabled'); + checkbox.value = enabled; XNAT.ui.banner.top(1000, '<b>' + item.aeTitle + '</b> ' + status, 'success'); - console.log(item.id + (enabled ? ' enabled' : ' disabled')) + console.log(item.aeTitle + status) } }); } }); return spawn('div.center', [ - spawn('label.switchbox', [ + spawn('label.switchbox|title=' + item.aeTitle, [ ckbox, ['span.switchbox-outer', [['span.switchbox-inner']]] ]) @@ -275,13 +280,13 @@ var XNAT = getObject(XNAT || {}); } }, 'Delete'); } - + dicomScpManager.getAll().done(function(data){ data.forEach(function(item){ scpTable.tr({ title: item.aeTitle, data: { id: item.id, port: item.port }}) - .td([editLink(item, item.aeTitle)]) - .td([['div.mono.center', item.port]]) - .td([enabledCheckbox(item)]) + .td([editLink(item, item.aeTitle)]).addClass('aeTitle') + .td([['div.mono.center', item.port]]).addClass('port') + .td([enabledCheckbox(item)]).addClass('status') .td([['div.center', [editButton(item), spacer(10), deleteButton(item)]]]); }); @@ -296,19 +301,19 @@ var XNAT = getObject(XNAT || {}); }); dicomScpManager.$table = $(scpTable.table); - + return scpTable.table; }; dicomScpManager.init = function(container){ - + var $manager = $$(container||'div#dicom-scp-manager'); dicomScpManager.$container = $manager; $manager.append(dicomScpManager.table()); // dicomScpManager.table($manager); - + var newReceiver = spawn('button.new-dicomscp-receiver.btn.btn-sm.submit', { html: 'New DICOM SCP Receiver', onclick: function(){ @@ -348,7 +353,7 @@ var XNAT = getObject(XNAT || {}); newReceiver, ['div.clear.clearfix'] ])); - + return { element: $manager[0], spawned: $manager[0], diff --git a/src/main/webapp/scripts/xnat/ui/panel.js b/src/main/webapp/scripts/xnat/ui/panel.js index a81f17bba63d28369aac354ef4f9fa7f31d32216..bcc141ad457941df46514cab57712cb5471f120c 100644 --- a/src/main/webapp/scripts/xnat/ui/panel.js +++ b/src/main/webapp/scripts/xnat/ui/panel.js @@ -21,36 +21,6 @@ var XNAT = getObject(XNAT || {}); XNAT.ui.panel = panel = getObject(XNAT.ui.panel || {}); - function hasClassName(el, className){ - var elClasses = el.className.split(/\s+/); - return elClasses.indexOf(className.trim()) > -1; - } - - // add new element class without destroying existing class - function addClassName(el, newClass){ - el.className = el.className || ''; - var classes = el.className.split(/\s+/); // existing classes - var newClasses = newClass.split(/\s+/); - // don't add duplicate classes - newClasses.forEach(function(cls){ - if (!hasClassName(el, cls)) { - classes.push(cls); - } - }); - // set the className and return the string - return el.className = classes.join(' ').trim(); - } - - // add new data object item to be used for [data-] attribute(s) - function addDataObjects(el, attrs){ - el.data = el.data || {}; - forOwn(attrs, function(name, prop){ - el.data[name] = prop; - }); - // set the data attributes and return the new data object - return el.data; - } - function setDisabled(elements, disabled){ $$(elements).each(function(idx){ var _disabled = !!disabled; @@ -116,7 +86,7 @@ var XNAT = getObject(XNAT || {}); opts.title = opts.title || opts.label || opts.header; var _target = spawn('div.panel-body', opts.element), - + hideHeader = (isDefined(opts.header) && (opts.header === false || /^-/.test(opts.title))), hideFooter = (isDefined(opts.footer) && (opts.footer === false || /^-/.test(opts.footer))), @@ -358,7 +328,7 @@ var XNAT = getObject(XNAT || {}); addClassName(_formPanel, 'validate'); addDataObjects() } - + // cache a jQuery-wrapped element var $formPanel = $(_formPanel); @@ -709,10 +679,10 @@ var XNAT = getObject(XNAT || {}); } } }; - + // setup a dialog box that contains stuff panel.dialogForm = panel.formDialog = function(opts){ - var dialog = new xmodal.Modal + var dialog = new xmodal.Modal }; panel.info = function(opts){}; @@ -843,7 +813,7 @@ var XNAT = getObject(XNAT || {}); } }; - + panel.display = function(opts){ return XNAT.ui.template.panelDisplay(opts).spawned; }; @@ -907,12 +877,11 @@ var XNAT = getObject(XNAT || {}); opts = cloneObject(opts); opts.element = extend(true, { type: 'hidden', - className: opts.className || opts.classes || '', name: opts.name, id: opts.id || toDashed(opts.name), value: firstDefined(opts.value+'', '') }, opts.element); - addClassName(opts.element, 'hidden'); + addClassName(opts.element, [opts.className, opts.classes, opts.addClass, 'hidden']); if (opts.validation || opts.validate) { addDataObjects(opts.element, { validate: opts.validation || opts.validate @@ -987,7 +956,7 @@ var XNAT = getObject(XNAT || {}); opts.text+'', opts.html+'', ''); - + opts.element.html = lookupValue(opts.element.html); opts.element.title = 'Double-click to open in code editor.'; @@ -1005,7 +974,7 @@ var XNAT = getObject(XNAT || {}); } opts.element.rows = opts.rows || opts.element.rows || 10; - + var textarea = spawn('textarea', opts.element); return XNAT.ui.template.panelDisplay(opts, textarea).spawned; @@ -1023,7 +992,7 @@ var XNAT = getObject(XNAT || {}); ////////////////////////////////////////////////// // SELECT MENU PANEL ELEMENTS ////////////////////////////////////////////////// - + panel.select = {}; panel.select.menu = function panelSelectMenu(opts, multi){ @@ -1037,11 +1006,12 @@ var XNAT = getObject(XNAT || {}); opts.element = extend({ id: opts.id, name: opts.name, - className: opts.className||'', title: opts.title||opts.name||opts.id||'', value: firstDefined(opts.value+'', '') }, opts.element); - + + addClassName(opts.element, [opts.className, opts.classes, opts.addClass]); + if (multi) { opts.element.multiple = true; } @@ -1069,7 +1039,7 @@ var XNAT = getObject(XNAT || {}); ////////////////////////////////////////////////// // DATA PANELS - RETRIEVE/DISPLAY DATA ////////////////////////////////////////////////// - + panel.dataTable = function(opts){ opts = cloneObject(opts); @@ -1085,7 +1055,7 @@ var XNAT = getObject(XNAT || {}); panelTable.target.appendChild(dataTable.table); return panelTable; - + }; panel.dataList = function(opts){ @@ -1108,7 +1078,7 @@ var XNAT = getObject(XNAT || {}); return XNAT.ui.panel = panel; - + // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // STOP EVERYTHING!!!!! // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/main/webapp/scripts/xnat/ui/table.js b/src/main/webapp/scripts/xnat/ui/table.js index 711a971af9f87f40971849b65fe3700280b76ba8..97aa14c640f6d4455fc142dfa0b4cbdee6033e62 100755 --- a/src/main/webapp/scripts/xnat/ui/table.js +++ b/src/main/webapp/scripts/xnat/ui/table.js @@ -28,20 +28,6 @@ var XNAT = getObject(XNAT); element = window.spawn, undefined; - // add new element class without destroying existing class - function addClassName(el, newClass){ - el.className = [].concat(el.className||[], newClass).join(' ').trim(); - return el.className; - } - - // add new data object item to be used for [data-] attribute(s) - function addDataObjects(obj, attrs){ - obj.data = obj.data || {}; - forOwn(attrs, function(name, prop){ - obj.data[name] = prop; - }); - return obj.data; - } /** * Constructor function for XNAT.table() @@ -70,11 +56,15 @@ var XNAT = getObject(XNAT); }; this.setLast = function(el){ - this.last.parent = + this.last.parent = this.last.child = this.last[el.tagName.toLowerCase()] = el; }; + this.getLast = function(){ + return this.last.child; + }; + this._rows = []; this._cols = 0; // how many columns? @@ -84,10 +74,27 @@ var XNAT = getObject(XNAT); } - // alias prototype for less typing Table.p = Table.prototype; + // return last item to use with jQuery methods + // XNAT.table().tr().$('attr', ['title', 'foo']).td('Bar').$({ addClass: 'bar' }).getHTML(); + // <table><tr title="foo"><td class="bar">Bar</td></tr></table> + // yes, the HTML is shorter and simpler, but also harder to generate programmatically + Table.p.$ = function(method, args){ + var $el = $(this.getLast()); + var methods = isPlainObject(method) ? method : null; + args = args || []; + if (!methods) { + methods = {}; + // force an object if not already + methods[method] = args; + } + forOwn(methods, function(name, arg){ + $el[name].apply($el, [].concat(arg)); + }); + return this; + }; // jQuery methods we'd like to use: var $methods = [ @@ -98,9 +105,8 @@ var XNAT = getObject(XNAT); ]; $methods.forEach(function(method){ - Table.p[method] = function(){ - var $el = this.last$(); - $el[method].apply($el, arguments); + Table.p[method] = function(args){ + this.$(method, args); return this; } }); @@ -115,6 +121,7 @@ var XNAT = getObject(XNAT); Table.p.td = function(opts, content){ var td = element('td', opts, content); this.last.td = td; + this.last.child = td; this.last.tr.appendChild(td); return this; }; @@ -122,6 +129,7 @@ var XNAT = getObject(XNAT); Table.p.th = function(opts, content){ var th = element('th', opts, content); this.last.th = th; + this.last.child = th; this.last.tr.appendChild(th); this._cols++; // do this here? return this; @@ -143,7 +151,8 @@ var XNAT = getObject(XNAT); this.last.parent.appendChild(tr); } this.last.tr = tr; - //this.setLast(tr); + this.last.child = tr; + // this.setLast(tr); // nullify last <th> and <td> elements since this is a new row this.last.th = this.last.td = null; return this; @@ -197,13 +206,23 @@ var XNAT = getObject(XNAT); Table.p.thead = function(opts, data){ var head = element('thead', opts); this.table.appendChild(head); + // this.last.child = head; this.setLast(head); return this; }; + Table.p.tfoot = function(opts, data){ + var foot = element('tfoot', opts); + this.table.appendChild(foot); + // this.last.child = foot; + this.setLast(foot); + return this; + }; + Table.p.tbody = function(opts, data){ var body = element('tbody', opts); this.table.appendChild(body); + // this.last.child = body; this.setLast(body); return this; }; @@ -318,18 +337,18 @@ var XNAT = getObject(XNAT); }; - Table.p.render = function(element, empty){ - var $element; - if (element) { - $element = $$(element); + Table.p.render = function(container, empty){ + var $container; + if (container) { + $container = $$(container); if (empty){ - $element.empty(); + $container.empty(); } - $element.append(this.table); + $container.append(this.table); } return this.table; }; - + // 'opts' are options for the <table> element // 'config' is for other configurable stuff table = function(opts, config){ diff --git a/src/main/webapp/scripts/xnat/ui/templates.js b/src/main/webapp/scripts/xnat/ui/templates.js index 3d61b218d68bda21380655cdba18120bc7c8d06d..904219c1882be5f1e9a5f9ef8b945d94c49273b9 100644 --- a/src/main/webapp/scripts/xnat/ui/templates.js +++ b/src/main/webapp/scripts/xnat/ui/templates.js @@ -21,24 +21,9 @@ var XNAT = getObject(XNAT); XNAT.ui = getObject(XNAT.ui || {}); - XNAT.ui.template = template = + XNAT.ui.template = template = XNAT.ui.template || {}; - // add new element class without destroying existing class - function addClassName(el, newClass){ - el.className = [].concat(el.className||[], newClass).join(' ').trim(); - return el.className; - } - - // add new data object item to be used for [data-] attribute(s) - function addDataObjects(obj, attrs){ - obj.data = obj.data || {}; - forOwn(attrs, function(name, prop){ - obj.data[name] = prop; - }); - return obj.data; - } - function lookupValue(el, lookup){ if (!lookup) { lookup = el; @@ -92,7 +77,7 @@ var XNAT = getObject(XNAT); }; // ======================================== - + // ======================================== // generic panel element template.panelElement = function(opts, content){ @@ -126,27 +111,30 @@ var XNAT = getObject(XNAT); // ======================================== // display only element for form panels template.panelDisplay = function(opts, element){ - + opts = cloneObject(opts); opts.id = opts.id||toDashed(opts.name||''); opts.label = opts.label||''; - + // pass in an element or create a new 'div' element - element = + element = element || spawn('div', extend(true, { id: opts.id, - className: opts.className||'', title: opts.title||opts.name||opts.id, html: opts.value||opts.html||opts.text||opts.body||'' }, opts.element)); - + + if (opts.className || opts.classes || opts.addClass) { + addClassName(element, [opts.className, opts.classes, opts.addClass]); + } + return template.panelElement(opts, [ // only add a label if specified (opts.label ? ['label.element-label|for='+element.id||opts.id, opts.label] : ''), ['div.element-wrapper', [].concat( - + (opts.beforeElement ? opts.beforeElement : []), element , @@ -158,7 +146,7 @@ var XNAT = getObject(XNAT); )] ]); }; - // ======================================== + // ======================================== // ======================================== @@ -172,14 +160,17 @@ var XNAT = getObject(XNAT); type: opts.type||'text', id: opts.id, name: opts.name, - className: opts.className||'', size: opts.size || 25, title: opts.title||opts.label||opts.name||opts.id, value: opts.value||'' }, opts.element); + if (opts.className || opts.classes || opts.addClass) { + addClassName(opts.element, [opts.className, opts.classes, opts.addClass]); + } + opts.data = opts.data || {}; - + if (opts.element.type !== 'password'){ opts.data.value = opts.data.value || opts.value; } @@ -190,7 +181,7 @@ var XNAT = getObject(XNAT); } addDataObjects(opts.element, opts.data); - + if (opts.placeholder) { opts.element.placeholder = opts.placeholder; } @@ -204,7 +195,7 @@ var XNAT = getObject(XNAT); // set the value of individual form elements var hasValue = isDefined(opts.value); - + // look up a namespaced object value if the value starts with '??' var doLookup = '??'; if (hasValue && opts.value.toString().indexOf(doLookup) === 0) { @@ -303,13 +294,13 @@ var XNAT = getObject(XNAT); hiddenInput.value = this.checked ? (this.value || this.checked || 'true') : 'false'; $hiddenInput.toggleClass('dirty'); }; - + // copy name to title element.title = element.name; - + // remove name of checkbox/radio to avoid conflicts element.name = ''; - + // add a class for easy selection addClassName(element, 'controller'); addClassName(opts, 'controller'); @@ -337,8 +328,8 @@ var XNAT = getObject(XNAT); ['div.element-wrapper', elements] ]); }; - - + + template.codeEditor = function(opts, contents){ // options for the 'div.editor-content' element opts = extend(true, opts, {