| <!DOCTYPE html> |
| <!-- |
| Copyright 2016 The Chromium Authors. All rights reserved. |
| Use of this source code is governed by a BSD-style license that can be |
| found in the LICENSE file. |
| --> |
| |
| <link rel="import" href="/dashboard/static/simple_xhr.html"> |
| |
| <polymer-element name="editable-list" attributes="xsrfToken"> |
| <template> |
| <style> |
| .item-container { |
| padding-bottom: 4px; |
| } |
| |
| .item-box { |
| border: 1px solid #e5ecf9; |
| background-color: #aec9ff; |
| padding: 4px 5px 4px 5px; |
| position: relative; |
| margin-right: 3px; |
| } |
| |
| .sub-item { |
| background-color: #f6f9ff; |
| } |
| |
| .item-box:hover a.remove-button { |
| display: inline-block; |
| visibility: visible; |
| } |
| |
| a.remove-button { |
| display: inline-block; |
| visibility: hidden; |
| right: 3px; |
| top: -12px; |
| position: relative; |
| margin-top:-25px; |
| margin-right:-15px; |
| padding: 6px 2px; |
| cursor:pointer; |
| color: #fff; |
| border: 1px solid #aeaeae; |
| border-radius: 15px; |
| background: #dd4b39; |
| font-size: 15px; |
| font-weight: bold; |
| line-height: 0px; |
| } |
| |
| .remove-button:before { |
| content: "x"; |
| } |
| |
| .item-box[removing] { |
| opacity: 0.25; |
| } |
| |
| .item-box[removing] a.remove-button { |
| visibility: hidden; |
| opacity: 0; |
| cursor: default; |
| } |
| |
| .add-input-container label { |
| display:block; |
| float:left; |
| margin-right:4px; |
| vertical-align:top; |
| } |
| |
| .kennedy-button-submit { |
| background-color: #4d90fe; |
| background-image: -webkit-linear-gradient(top, #4d90fe, #4787ed); |
| background-image: linear-gradient(to bottom, #4d90fe, #4787ed); |
| border: 1px solid #3079ed; |
| color: #fff; |
| } |
| </style> |
| |
| <div class="add-input-container"> |
| <label> |
| {{itemLabel}}<br /> |
| <input id="item_textfield" |
| type="text" |
| min="1" |
| min="35" |
| size="35"></input> |
| </label> |
| |
| <div hidden?="{{!subItemLabel}}"> |
| <label> |
| {{subItemLabel}}<br /> |
| <input id="sub_item_textfield" |
| type="text" |
| min="1" |
| max="35" |
| size="35"></input> |
| </label> |
| </div> |
| |
| <br /> |
| <button class="kennedy-button-submit" |
| on-click="{{addItemClicked}}">Add</button> |
| </div> |
| |
| <br /> |
| |
| <template repeat="{{item, i in editable_list}}"> |
| <p class="item-container"> |
| <span class="item-box" removing?={{item.removing}}> |
| {{item.name}}<a class="remove-button" |
| on-click="{{removeItemClicked}}" |
| removing?={{item.removing}}></a></span> |
| |
| <span hidden?="{{!item.sub_items}}">: </span> |
| |
| <template repeat="{{sub_item, j in item.sub_items}}"> |
| <span class="item-box sub-item" removing?={{sub_item.removing}}> |
| {{sub_item.name}}<a class="remove-button" on-click="{{removeItemClicked}}"></a> |
| </span> |
| </template> |
| </p> |
| </template> |
| </template> |
| <script> |
| 'use strict'; |
| Polymer('editable-list', { |
| |
| init: function(editable_list, handlerURL, itemLabel, subItemLabel) { |
| this.editable_list = editable_list.sort(this.itemCompare); |
| this.handlerURL = handlerURL; |
| this.itemLabel = itemLabel; |
| this.subItemLabel = subItemLabel; |
| }, |
| |
| /** |
| * Handles remove item button clicked. |
| */ |
| removeItemClicked: function(event, detail, sender) { |
| var model = event.target.templateInstance.model; |
| var index = model.i; |
| var subIndex = model.j; |
| var item = this.editable_list[index]; |
| var subItem = null; |
| |
| if (subIndex != undefined) { |
| subItem = item['sub_items'][subIndex]; |
| subItem.removing = true; |
| } else { |
| item.removing = true; |
| if ('sub_items' in item) { |
| item['sub_items'].forEach(function(i) { |
| i.removing = true; |
| }); |
| } |
| } |
| |
| var params = { |
| item: item['name'], |
| action: 'remove', |
| xsrf_token: this.xsrfToken |
| }; |
| if (subItem) { |
| params['sub_item'] = subItem['name']; |
| } |
| simple_xhr.send(this.handlerURL, params, |
| function(info) { |
| if (subItem) { |
| item['sub_items'].splice(subIndex, 1); |
| if (item['sub_items'].length == 0) { |
| this.editable_list.splice(index, 1); |
| } |
| } else { |
| this.editable_list.splice(index, 1); |
| } |
| }.bind(this), |
| function(msg) { |
| if (subItem) { |
| subItem.removing = false; |
| } else { |
| item.removing = false; |
| for (var i = 0; i < item['sub_items'].length; i++) { |
| item['sub_items'][i].removing = false; |
| } |
| } |
| }.bind(this)); |
| }, |
| |
| /** |
| * Handles add item button clicked. |
| */ |
| addItemClicked: function(event, detail, sender) { |
| var itemValue = this.$.item_textfield.value; |
| var subItemValue = null; |
| if (this.$.sub_item_textfield) { |
| subItemValue = this.$.sub_item_textfield.value; |
| } |
| var params = { |
| item: itemValue, |
| action: 'add', |
| xsrf_token: this.xsrfToken |
| }; |
| if (subItemValue) { |
| params['sub_item'] = subItemValue; |
| } |
| simple_xhr.send(this.handlerURL, params, |
| function(info) { |
| this.addEditableItem(itemValue, subItemValue); |
| }.bind(this), |
| function(msg) { |
| alert(msg); |
| }.bind(this) |
| ); |
| }, |
| |
| /** |
| * Adds editable items. |
| */ |
| addEditableItem: function(itemValue, subItemValue) { |
| var itemMap = {}; |
| var itemMap = this.getItemByValue(itemValue); |
| if (!itemMap) { |
| itemMap = { |
| 'name': itemValue |
| }; |
| this.editable_list.push(itemMap); |
| this.editable_list.sort(this.itemCompare); |
| } |
| |
| if (subItemValue) { |
| if (!('sub_items' in itemMap)) { |
| itemMap['sub_items'] = []; |
| } |
| itemMap['sub_items'].push({ |
| 'name': subItemValue |
| }); |
| itemMap.sort(this.itemCompare); |
| } |
| }, |
| |
| itemCompare: function(itemA, itemB) { |
| return ((itemA['name'] < itemB['name']) ? -1 : |
| ((itemA['name'] > itemB['name']) ? 1 : 0)); |
| }, |
| |
| getItemByValue: function(value) { |
| for (var i = 0; i < this.editable_list.length; i++) { |
| if (this.editable_list[i]['name'] == value) { |
| return this.editable_list[i]; |
| } |
| } |
| return null; |
| } |
| }); |
| </script> |
| </polymer-element> |