diff --git a/res/app/device-list/column/device-column-service.js b/res/app/device-list/column/device-column-service.js index 7c4908c1..29f25a7d 100644 --- a/res/app/device-list/column/device-column-service.js +++ b/res/app/device-list/column/device-column-service.js @@ -18,7 +18,7 @@ var filterOps = { } } -module.exports = function DeviceColumnService($filter, $compile, gettext) { +module.exports = function DeviceColumnService($filter, gettext) { // Definitions for all possible values. return { state: DeviceStatusCell({ @@ -252,14 +252,8 @@ module.exports = function DeviceColumnService($filter, $compile, gettext) { return device.provider ? device.provider.name : '' } }) - , notes: XEditableCell({ + , notes: DeviceNoteCell({ title: gettext('Notes') - , compile: $compile - , scopeRequired: true - , attrs: { - model: 'device.notes' - , onbeforesave: 'updateNote(device.serial, $data)' - } , value: function(device) { return device.notes || '' } @@ -620,30 +614,31 @@ function DeviceStatusCell(options) { }) } -function XEditableCell(options) { +function DeviceNoteCell(options) { return _.defaults(options, { title: options.title , defaultOrder: 'asc' - , build: function (scope) { - var td = document.createElement('td') - , a = document.createElement('a') + , build: function () { + var td = document.createElement('td') + , span = document.createElement('span') + , i = document.createElement('i') - // Ref: http://vitalets.github.io/angular-xeditable/#text-simple - a.setAttribute('href', '#') - a.setAttribute('editable-text', options.attrs.model) - a.setAttribute('onbeforesave', options.attrs.onbeforesave) + td.className = 'device-note' + span.className = 'xeditable-wrapper' + span.appendChild(document.createTextNode('')) - a.appendChild(document.createTextNode(options.attrs.model)) - td.appendChild(a) + i.className = 'device-note-edit fa fa-pencil pointer' + + td.appendChild(span) + td.appendChild(i) - // compile with new scope - options.compile(td)(scope) return td } , update: function(td, item) { - var a = td.firstChild - , t = a.firstChild - t.nodeValue = options.value(item) || 'click to add' + var span = td.firstChild + , t = span.firstChild + + t.nodeValue = options.value(item) return td } , compare: function(a, b) { diff --git a/res/app/device-list/details/device-list-details-directive.js b/res/app/device-list/details/device-list-details-directive.js index 52e0ca5f..420afa0d 100644 --- a/res/app/device-list/details/device-list-details-directive.js +++ b/res/app/device-list/details/device-list-details-directive.js @@ -30,6 +30,7 @@ module.exports = function DeviceListDetailsDirective( , rows = tbody.rows , prefix = 'd' + Math.floor(Math.random() * 1000000) + '-' , mapping = Object.create(null) + , childScopes = Object.create(null) function kickDevice(device, force) { @@ -84,9 +85,72 @@ module.exports = function DeviceListDetailsDirective( } } + // On clicking device-note-edit icon + // This function will create a new angular-xeditable span + // inside xeditableWrapper and compile it with + // new child scope. + // Childscope will be destroyed when the editing will be over + function checkDeviceNote(e) { + if (e.target.classList.contains('device-note-edit')) { + + var i = e.target + , id = i.parentNode.parentNode.id + , device = mapping[id] + , xeditableWrapper = i.parentNode.firstChild + , xeditableSpan = document.createElement('span') + , childScope = scope.$new() + + // Ref: http://vitalets.github.io/angular-xeditable/#text-btn + xeditableSpan.setAttribute('editable-text', 'device.notes') + xeditableSpan.setAttribute('onbeforesave', 'updateNote(id, device.serial, $data)') + xeditableSpan.setAttribute('onCancel', 'onDeviceNoteCancel(id)') + + childScope.id = id + childScope.device = device + childScopes[id] = childScope + + $compile(xeditableSpan)(childScope) + xeditableWrapper.appendChild(xeditableSpan) + + // Trigger click to open the form. + angular.element(xeditableSpan).triggerHandler('click') + } + } + + function destroyXeditableNote(id) { + var tr = tbody.children[id] + for (var i = 0; i < tr.cells.length; i++) { + var col = tr.cells[i] + + if (col.firstChild && + col.firstChild.nodeName.toLowerCase() == 'span' && + col.firstChild.classList.contains('xeditable-wrapper')) { + + var xeditableWrapper = col.firstChild + , children = xeditableWrapper.children + + // Remove all childs under xeditablerWrapper + for (var j = 0; j < children.length; j++) { + xeditableWrapper.removeChild(children[j]) + } + } + } + childScopes[id].$destroy() + } + + scope.updateNote = function(id, serial, note) { + DeviceService.updateNote(serial, note) + destroyXeditableNote(id) + } + + scope.onDeviceNoteCancel = function(id) { + destroyXeditableNote(id) + } + element.on('click', function (e) { checkDeviceStatus(e) checkDeviceSmallImage(e) + checkDeviceNote(e) }) // Import column definitions @@ -279,20 +343,6 @@ module.exports = function DeviceListDetailsDirective( } })() - // check if new column needs a new scope or not - // and build accordingly - function buildColumn(col, device) { - var td - - if (col.scopeRequired) { - var childScope = scope.$new() - childScope.device = device - td = col.build(childScope) - } else { - td = col.build() - } - return td - } // Creates a completely new row for the device. Means that this is // the first time we see the device. function createRow(device) { @@ -307,10 +357,8 @@ module.exports = function DeviceListDetailsDirective( } for (var i = 0, l = activeColumns.length; i < l; ++i) { - var col = scope.columnDefinitions[activeColumns[i]] - - td = buildColumn(col, device) - col.update(td, device) + td = scope.columnDefinitions[activeColumns[i]].build() + scope.columnDefinitions[activeColumns[i]].update(td, device) tr.appendChild(td) } @@ -319,10 +367,6 @@ module.exports = function DeviceListDetailsDirective( return tr } - scope.updateNote = function(serial, note) { - DeviceService.updateNote(serial, note) - } - // Patches all rows. function patchAll(patch) { for (var i = 0, l = rows.length; i < l; ++i) { @@ -339,7 +383,7 @@ module.exports = function DeviceListDetailsDirective( switch (op[0]) { case 'insert': var col = scope.columnDefinitions[op[2]] - tr.insertBefore(col.update(buildColumn(col, device), device), tr.cells[op[1]]) + tr.insertBefore(col.update(col.build(), device), tr.cells[op[1]]) break case 'remove': tr.deleteCell(op[1]) diff --git a/res/app/device-list/device-list.css b/res/app/device-list/device-list.css index d378b2f8..9645afe4 100644 --- a/res/app/device-list/device-list.css +++ b/res/app/device-list/device-list.css @@ -71,3 +71,15 @@ img.device-icon-smallest { .stf-device-list .device-product-name-using { border-bottom: 1px solid; /* leaving out the color inherits text color */ } + +.stf-device-list .device-note { +} + +.stf-device-list .device-note-edit { + margin-left: 15px; + visibility: hidden; +} + +.stf-device-list .device-note:hover .device-note-edit { + visibility: visible; +} diff --git a/res/web_modules/angular-xeditable/style.css b/res/web_modules/angular-xeditable/style.css index 2f4242fb..39001ba2 100644 --- a/res/web_modules/angular-xeditable/style.css +++ b/res/web_modules/angular-xeditable/style.css @@ -1,17 +1,52 @@ -a.editable-click { - text-decoration: none; - color: #167FFC; - border-bottom: none; +/* + Currently angular-xeditable does not support popover + This is a work around to make angular-xeditable look like + popover +*/ + +.xeditable-wrapper { + position: relative; } -a.editable-click:hover { - color: #808080; +.xeditable-wrapper form { + background: #FFF; + border: 1px solid #AAA; + border-radius: 5px; + display: inline-block; + left: 50%; + margin-left: -190px; + padding: 7px; + position: absolute; + top: -55px; + width: 380px; + z-index: 101; } -a.editable-empty { - color: transparent; +.xeditable-wrapper form:before { + content: ''; + width: 0; + height: 0; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-top: 10px solid #AAA; + position: absolute; + bottom: -10px; + left: 190px; } -a.editable-empty:focus { - color: #808080; +.xeditable-wrapper form:after { + content: ''; + width: 0; + height: 0; + border-left: 9px solid transparent; + border-right: 9px solid transparent; + border-top: 9px solid #FFF; + position: absolute; + bottom: -9px; + left: 191px; +} + +.xeditable-wrapper .editable-buttons .btn { + margin-left: 6px !important; + cursor: pointer; }