Home | History | Annotate | Download | only in search
      1 // Copyright (c) 2012 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('print_preview', function() {
      6   'use strict';
      7 
      8   /**
      9    * Component that renders a destination item in a destination list.
     10    * @param {!cr.EventTarget} eventTarget Event target to dispatch selection
     11    *     events to.
     12    * @param {!print_preview.Destination} destination Destination data object to
     13    *     render.
     14    * @param {RegExp} query Active filter query.
     15    * @constructor
     16    * @extends {print_preview.Component}
     17    */
     18   function DestinationListItem(eventTarget, destination, query) {
     19     print_preview.Component.call(this);
     20 
     21     /**
     22      * Event target to dispatch selection events to.
     23      * @type {!cr.EventTarget}
     24      * @private
     25      */
     26     this.eventTarget_ = eventTarget;
     27 
     28     /**
     29      * Destination that the list item renders.
     30      * @type {!print_preview.Destination}
     31      * @private
     32      */
     33     this.destination_ = destination;
     34 
     35     /**
     36      * Active filter query text.
     37      * @type {RegExp}
     38      * @private
     39      */
     40     this.query_ = query;
     41 
     42     /**
     43      * FedEx terms-of-service widget or {@code null} if this list item does not
     44      * render the FedEx Office print destination.
     45      * @type {print_preview.FedexTos}
     46      * @private
     47      */
     48     this.fedexTos_ = null;
     49   };
     50 
     51   /**
     52    * Event types dispatched by the destination list item.
     53    * @enum {string}
     54    */
     55   DestinationListItem.EventType = {
     56     // Dispatched when the list item is activated.
     57     SELECT: 'print_preview.DestinationListItem.SELECT',
     58     REGISTER_PROMO_CLICKED:
     59         'print_preview.DestinationListItem.REGISTER_PROMO_CLICKED'
     60   };
     61 
     62   /**
     63    * CSS classes used by the destination list item.
     64    * @enum {string}
     65    * @private
     66    */
     67   DestinationListItem.Classes_ = {
     68     ICON: 'destination-list-item-icon',
     69     NAME: 'destination-list-item-name',
     70     STALE: 'stale'
     71   };
     72 
     73   DestinationListItem.prototype = {
     74     __proto__: print_preview.Component.prototype,
     75 
     76     /** @override */
     77     createDom: function() {
     78       this.setElementInternal(this.cloneTemplateInternal(
     79           'destination-list-item-template'));
     80 
     81       var iconImg = this.getElement().getElementsByClassName(
     82           print_preview.DestinationListItem.Classes_.ICON)[0];
     83       iconImg.src = this.destination_.iconUrl;
     84 
     85       var nameEl = this.getElement().getElementsByClassName(
     86           DestinationListItem.Classes_.NAME)[0];
     87       var textContent = this.destination_.displayName;
     88       if (this.query_) {
     89         // When search query is specified, make it obvious why the particular
     90         // printer made it to the list. Display name is always visible, even if
     91         // it does not match the search query.
     92         this.addTextWithHighlight_(nameEl, textContent);
     93         // Show the first matching property.
     94         this.destination_.extraPropertiesToMatch.some(function(property) {
     95           if (property.match(this.query_)) {
     96             var hintSpan = document.createElement('span');
     97             hintSpan.className = 'search-hint';
     98             nameEl.appendChild(hintSpan);
     99             this.addTextWithHighlight_(hintSpan, property);
    100             // Add the same property to the element title.
    101             textContent += ' (' + property + ')';
    102             return true;
    103           }
    104         }, this);
    105       } else {
    106         // Show just the display name and nothing else to lessen visual clutter.
    107         nameEl.textContent = textContent;
    108       }
    109       nameEl.title = textContent;
    110 
    111       this.initializeOfflineStatusElement_();
    112       this.initializeRegistrationPromoElement_();
    113     },
    114 
    115     /** @override */
    116     enterDocument: function() {
    117       print_preview.Component.prototype.enterDocument.call(this);
    118       this.tracker.add(this.getElement(), 'click', this.onActivate_.bind(this));
    119     },
    120 
    121     /**
    122      * Initializes the element which renders the print destination's
    123      * offline status.
    124      * @private
    125      */
    126     initializeOfflineStatusElement_: function() {
    127       if (this.destination_.isOffline) {
    128         this.getElement().classList.add(DestinationListItem.Classes_.STALE);
    129         var offlineStatusEl = this.getChildElement('.offline-status');
    130         offlineStatusEl.textContent = this.destination_.offlineStatusText;
    131         setIsVisible(offlineStatusEl, true);
    132       }
    133     },
    134 
    135     /**
    136      * Initialize registration promo element for Privet unregistered printers.
    137      */
    138     initializeRegistrationPromoElement_: function() {
    139       if (this.destination_.connectionStatus ==
    140           print_preview.Destination.ConnectionStatus.UNREGISTERED) {
    141         var registerBtnEl = this.getChildElement('.register-promo-button');
    142         registerBtnEl.addEventListener('click',
    143                                        this.onRegisterPromoClicked_.bind(this));
    144 
    145         var registerPromoEl = this.getChildElement('.register-promo');
    146         setIsVisible(registerPromoEl, true);
    147       }
    148     },
    149 
    150     /**
    151      * Adds text to parent element wrapping search query matches in highlighted
    152      * spans.
    153      * @param {!Element} parent Element to build the text in.
    154      * @param {string} text The text string to highlight segments in.
    155      * @private
    156      */
    157     addTextWithHighlight_: function(parent, text) {
    158       var sections = text.split(this.query_);
    159       for (var i = 0; i < sections.length; ++i) {
    160         if (i % 2 == 0) {
    161           parent.appendChild(document.createTextNode(sections[i]));
    162         } else {
    163           var span = document.createElement('span');
    164           span.className = 'destination-list-item-query-highlight';
    165           span.textContent = sections[i];
    166           parent.appendChild(span);
    167         }
    168       }
    169     },
    170 
    171     /**
    172      * Called when the destination item is activated. Dispatches a SELECT event
    173      * on the given event target.
    174      * @private
    175      */
    176     onActivate_: function() {
    177       if (this.destination_.id ==
    178               print_preview.Destination.GooglePromotedId.FEDEX &&
    179           !this.destination_.isTosAccepted) {
    180         if (!this.fedexTos_) {
    181           this.fedexTos_ = new print_preview.FedexTos();
    182           this.fedexTos_.render(this.getElement());
    183           this.tracker.add(
    184               this.fedexTos_,
    185               print_preview.FedexTos.EventType.AGREE,
    186               this.onTosAgree_.bind(this));
    187         }
    188         this.fedexTos_.setIsVisible(true);
    189       } else if (this.destination_.connectionStatus !=
    190                      print_preview.Destination.ConnectionStatus.UNREGISTERED) {
    191         var selectEvt = new Event(DestinationListItem.EventType.SELECT);
    192         selectEvt.destination = this.destination_;
    193         this.eventTarget_.dispatchEvent(selectEvt);
    194       }
    195     },
    196 
    197     /**
    198      * Called when the user agrees to the print destination's terms-of-service.
    199      * Selects the print destination that was agreed to.
    200      * @private
    201      */
    202     onTosAgree_: function() {
    203       var selectEvt = new Event(DestinationListItem.EventType.SELECT);
    204       selectEvt.destination = this.destination_;
    205       this.eventTarget_.dispatchEvent(selectEvt);
    206     },
    207 
    208     /**
    209      * Called when the registration promo is clicked.
    210      * @private
    211      */
    212     onRegisterPromoClicked_: function() {
    213       var promoClickedEvent = new Event(
    214           DestinationListItem.EventType.REGISTER_PROMO_CLICKED);
    215       promoClickedEvent.destination = this.destination_;
    216       this.eventTarget_.dispatchEvent(promoClickedEvent);
    217     }
    218   };
    219 
    220   // Export
    221   return {
    222     DestinationListItem: DestinationListItem
    223   };
    224 });
    225