Home | History | Annotate | Download | only in options
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 cr.define('options.autofillOptions', function() {
      6   const DeletableItem = options.DeletableItem;
      7   const DeletableItemList = options.DeletableItemList;
      8   const InlineEditableItem = options.InlineEditableItem;
      9   const InlineEditableItemList = options.InlineEditableItemList;
     10 
     11   /**
     12    * Creates a new address list item.
     13    * @param {Array} entry An array of the form [guid, label].
     14    * @constructor
     15    * @extends {options.DeletableItem}
     16    */
     17   function AddressListItem(entry) {
     18     var el = cr.doc.createElement('div');
     19     el.guid = entry[0];
     20     el.label = entry[1];
     21     el.__proto__ = AddressListItem.prototype;
     22     el.decorate();
     23 
     24     return el;
     25   }
     26 
     27   AddressListItem.prototype = {
     28     __proto__: DeletableItem.prototype,
     29 
     30     /** @inheritDoc */
     31     decorate: function() {
     32       DeletableItem.prototype.decorate.call(this);
     33 
     34       // The stored label.
     35       var label = this.ownerDocument.createElement('div');
     36       label.className = 'autofill-list-item';
     37       label.textContent = this.label;
     38       this.contentElement.appendChild(label);
     39     },
     40   };
     41 
     42   /**
     43    * Creates a new credit card list item.
     44    * @param {Array} entry An array of the form [guid, label, icon].
     45    * @constructor
     46    * @extends {options.DeletableItem}
     47    */
     48   function CreditCardListItem(entry) {
     49     var el = cr.doc.createElement('div');
     50     el.guid = entry[0];
     51     el.label = entry[1];
     52     el.icon = entry[2];
     53     el.description = entry[3];
     54     el.__proto__ = CreditCardListItem.prototype;
     55     el.decorate();
     56 
     57     return el;
     58   }
     59 
     60   CreditCardListItem.prototype = {
     61     __proto__: DeletableItem.prototype,
     62 
     63     /** @inheritDoc */
     64     decorate: function() {
     65       DeletableItem.prototype.decorate.call(this);
     66 
     67       // The stored label.
     68       var label = this.ownerDocument.createElement('div');
     69       label.className = 'autofill-list-item';
     70       label.textContent = this.label;
     71       this.contentElement.appendChild(label);
     72 
     73       // The credit card icon.
     74       var icon = this.ownerDocument.createElement('image');
     75       icon.src = this.icon;
     76       icon.alt = this.description;
     77       this.contentElement.appendChild(icon);
     78     },
     79   };
     80 
     81   /**
     82    * Creates a new value list item.
     83    * @param {AutofillValuesList} list The parent list of this item.
     84    * @param {String} entry A string value.
     85    * @constructor
     86    * @extends {options.InlineEditableItem}
     87    */
     88   function ValuesListItem(list, entry) {
     89     var el = cr.doc.createElement('div');
     90     el.list = list;
     91     el.value = entry;
     92     el.__proto__ = ValuesListItem.prototype;
     93     el.decorate();
     94 
     95     return el;
     96   }
     97 
     98   ValuesListItem.prototype = {
     99     __proto__: InlineEditableItem.prototype,
    100 
    101     /** @inheritDoc */
    102     decorate: function() {
    103       InlineEditableItem.prototype.decorate.call(this);
    104 
    105       this.isPlaceholder = !this.value;
    106 
    107       // The stored value.
    108       var cell = this.createEditableTextCell(this.value);
    109       this.contentElement.appendChild(cell);
    110       this.input = cell.querySelector('input');
    111 
    112       this.addEventListener('commitedit', this.onEditCommitted_);
    113     },
    114 
    115     /**
    116      * Called when committing an edit.
    117      * @param {Event} e The end event.
    118      * @private
    119      */
    120     onEditCommitted_: function(e) {
    121       var i = this.list.items.indexOf(this);
    122       if (this.input.value == this.list.dataModel.item(i))
    123         return;
    124 
    125       if (this.input.value &&
    126           this.list.dataModel.indexOf(this.input.value) == -1) {
    127         // Update with new value.
    128         this.list.dataModel.splice(i, 1, this.input.value);
    129       } else {
    130         // Reject empty values and duplicates.
    131         this.list.dataModel.splice(i, 1);
    132       }
    133     },
    134   };
    135 
    136   /**
    137    * Creates a new list item for the Add New Item row, which doesn't represent
    138    * an actual entry in the values list but allows the user to add new
    139    * values.
    140    * @param {AutofillValuesList} entry The parent list of this item.
    141    * @constructor
    142    * @extends {cr.ui.ValuesListItem}
    143    */
    144   function ValuesAddRowListItem(list) {
    145     var el = cr.doc.createElement('div');
    146     el.list = list;
    147     el.__proto__ = ValuesAddRowListItem.prototype;
    148     el.decorate();
    149 
    150     return el;
    151   }
    152 
    153   ValuesAddRowListItem.prototype = {
    154     __proto__: ValuesListItem.prototype,
    155 
    156     decorate: function() {
    157       ValuesListItem.prototype.decorate.call(this);
    158       this.input.value = '';
    159       this.input.placeholder = this.list.getAttribute('placeholder');
    160       this.deletable = false;
    161     },
    162 
    163     /**
    164      * Called when committing an edit.  Committing a non-empty value adds it
    165      * to the end of the values list, leaving this "AddRow" in place.
    166      * @param {Event} e The end event.
    167      * @extends {options.ValuesListItem}
    168      * @private
    169      */
    170     onEditCommitted_: function(e) {
    171       var i = this.list.items.indexOf(this);
    172       if (i < 0 || i >= this.list.dataModel.length)
    173         return;
    174 
    175       if (this.input.value &&
    176           this.list.dataModel.indexOf(this.input.value) == -1) {
    177         this.list.dataModel.splice(i, 0, this.input.value);
    178       } else {
    179         this.input.value = '';
    180         this.list.dataModel.updateIndex(i);
    181       }
    182     },
    183   };
    184 
    185   /**
    186    * Create a new address list.
    187    * @constructor
    188    * @extends {options.DeletableItemList}
    189    */
    190   var AutofillAddressList = cr.ui.define('list');
    191 
    192   AutofillAddressList.prototype = {
    193     __proto__: DeletableItemList.prototype,
    194 
    195     decorate: function() {
    196       DeletableItemList.prototype.decorate.call(this);
    197 
    198       this.addEventListener('blur', this.onBlur_);
    199     },
    200 
    201     /**
    202      * When the list loses focus, unselect all items in the list.
    203      * @private
    204      */
    205     onBlur_: function() {
    206       this.selectionModel.unselectAll();
    207     },
    208 
    209     /** @inheritDoc */
    210     createItem: function(entry) {
    211       return new AddressListItem(entry);
    212     },
    213 
    214     /** @inheritDoc */
    215     activateItemAtIndex: function(index) {
    216       AutofillOptions.loadAddressEditor(this.dataModel.item(index)[0]);
    217     },
    218 
    219     /** @inheritDoc */
    220     deleteItemAtIndex: function(index) {
    221       AutofillOptions.removeAddress(this.dataModel.item(index)[0]);
    222     },
    223   };
    224 
    225   /**
    226    * Create a new credit card list.
    227    * @constructor
    228    * @extends {options.DeletableItemList}
    229    */
    230   var AutofillCreditCardList = cr.ui.define('list');
    231 
    232   AutofillCreditCardList.prototype = {
    233     __proto__: DeletableItemList.prototype,
    234 
    235     decorate: function() {
    236       DeletableItemList.prototype.decorate.call(this);
    237 
    238       this.addEventListener('blur', this.onBlur_);
    239     },
    240 
    241     /**
    242      * When the list loses focus, unselect all items in the list.
    243      * @private
    244      */
    245     onBlur_: function() {
    246       this.selectionModel.unselectAll();
    247     },
    248 
    249     /** @inheritDoc */
    250     createItem: function(entry) {
    251       return new CreditCardListItem(entry);
    252     },
    253 
    254     /** @inheritDoc */
    255     activateItemAtIndex: function(index) {
    256       AutofillOptions.loadCreditCardEditor(this.dataModel.item(index)[0]);
    257     },
    258 
    259     /** @inheritDoc */
    260     deleteItemAtIndex: function(index) {
    261       AutofillOptions.removeCreditCard(this.dataModel.item(index)[0]);
    262     },
    263   };
    264 
    265   /**
    266    * Create a new value list.
    267    * @constructor
    268    * @extends {options.InlineEditableItemList}
    269    */
    270   var AutofillValuesList = cr.ui.define('list');
    271 
    272   AutofillValuesList.prototype = {
    273     __proto__: InlineEditableItemList.prototype,
    274 
    275     decorate: function() {
    276       InlineEditableItemList.prototype.decorate.call(this);
    277 
    278       var self = this;
    279       function handleBlur(e) {
    280         // When the blur event happens we do not know who is getting focus so we
    281         // delay this a bit until we know if the new focus node is outside the
    282         // list.
    283         var doc = e.target.ownerDocument;
    284         window.setTimeout(function() {
    285           var activeElement = doc.activeElement;
    286           if (!self.contains(activeElement))
    287             self.selectionModel.unselectAll();
    288         }, 50);
    289       }
    290 
    291       this.addEventListener('blur', handleBlur, true);
    292     },
    293 
    294     /** @inheritDoc */
    295     createItem: function(entry) {
    296       if (entry != null)
    297         return new ValuesListItem(this, entry);
    298       else
    299         return new ValuesAddRowListItem(this);
    300     },
    301 
    302     /** @inheritDoc */
    303     deleteItemAtIndex: function(index) {
    304       this.dataModel.splice(index, 1);
    305     },
    306   };
    307 
    308   return {
    309     AddressListItem: AddressListItem,
    310     CreditCardListItem: CreditCardListItem,
    311     ValuesListItem: ValuesListItem,
    312     ValuesAddRowListItem: ValuesAddRowListItem,
    313     AutofillAddressList: AutofillAddressList,
    314     AutofillCreditCardList: AutofillCreditCardList,
    315     AutofillValuesList: AutofillValuesList,
    316   };
    317 });
    318