| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 /** |    5 cr.define('policy', function() { | 
|    6  * This variable structure is here to document the structure that the template |    6   /** | 
|    7  * expects to correctly populate the page. |    7    * A box that shows the status of cloud policy for a device or user. | 
|    8  */ |    8    * @constructor | 
|    9 var policyDataFormat = { |    9    * @extends {HTMLFieldSetElement} | 
|   10   // Whether any of the policies in 'policies' have a value. |   10    */ | 
|   11   'anyPoliciesSet': true, |   11   var StatusBox = cr.ui.define(function() { | 
|   12  |   12     var node = $('status-box-template').cloneNode(true); | 
|   13   'policies': [ |   13     node.removeAttribute('id'); | 
|   14     { |   14     return node; | 
|   15       'level': 'managed', |   15   }); | 
|   16       'name': 'AllowXYZ', |   16  | 
|   17       'set': true, |   17   StatusBox.prototype = { | 
|   18       'scope': 'Machine', |   18     // Set up the prototype chain. | 
|   19       'status': 'ok', |   19     __proto__: HTMLFieldSetElement.prototype, | 
|   20       'value': true |   20  | 
|   21     } |   21     /** | 
|   22   ], |   22      * Initialization function for the cr.ui framework. | 
|   23   'status': { |   23      */ | 
|   24     'deviceFetchInterval': '8min', |   24     decorate: function() { | 
|   25     'deviceId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C', |   25     }, | 
|   26     'deviceLastFetchTime': '9:50 PM', |   26  | 
|   27     'devicePolicyDomain': 'google.com', |   27     /** | 
|   28     'deviceStatusMessage': 'OK', |   28      * Populate the box with the given cloud policy status. | 
|   29     'displayDeviceStatus': true, |   29      * @param {string} scope The policy scope, either "device" or "user". | 
|   30     'displayStatusSection': true, |   30      * @param {Object} status Dictionary with information about the status. | 
|   31     'displayUserStatus': true, |   31      */ | 
|   32     'user': 'simo@google.com', |   32     initialize: function(scope, status) { | 
|   33     'userFetchInterval': '8min', |   33       if (scope == 'device') { | 
|   34     'userId': 'D2AC39A2-3C8FC-E2C0-E45D2DC3782C', |   34         // For device policy, set the appropriate title and populate the topmost | 
|   35     'userLastFetchTime': '9:50 PM', |   35         // status item with the domain the device is enrolled into. | 
|   36     'userStatusMessage': 'OK' |   36         this.querySelector('.legend').textContent = | 
 |   37             loadTimeData.getString('statusDevice'); | 
 |   38         var domain = this.querySelector('.domain'); | 
 |   39         domain.textContent = status.domain; | 
 |   40         domain.parentElement.hidden = false; | 
 |   41       } else { | 
 |   42         // For user policy, set the appropriate title and populate the topmost | 
 |   43         // status item with the username that policies apply to. | 
 |   44         this.querySelector('.legend').textContent = | 
 |   45             loadTimeData.getString('statusUser'); | 
 |   46         // Populate the topmost item with the username. | 
 |   47         var username = this.querySelector('.username'); | 
 |   48         username.textContent = status.username; | 
 |   49         username.parentElement.hidden = false; | 
 |   50       } | 
 |   51       // Populate all remaining items. | 
 |   52       this.querySelector('.client-id').textContent = status.clientId || ''; | 
 |   53       this.querySelector('.time-since-last-refresh').textContent = | 
 |   54           status.timeSinceLastRefresh || ''; | 
 |   55       this.querySelector('.refresh-interval').textContent = | 
 |   56           status.refreshInterval || ''; | 
 |   57       this.querySelector('.status').textContent = status.status || ''; | 
 |   58     }, | 
 |   59   }; | 
 |   60  | 
 |   61   /** | 
 |   62    * A single policy's entry in the policy table. | 
 |   63    * @constructor | 
 |   64    * @extends {HTMLTableSectionElement} | 
 |   65    */ | 
 |   66   var Policy = cr.ui.define(function() { | 
 |   67     var node = $('policy-template').cloneNode(true); | 
 |   68     node.removeAttribute('id'); | 
 |   69     return node; | 
 |   70   }); | 
 |   71  | 
 |   72   Policy.prototype = { | 
 |   73     // Set up the prototype chain. | 
 |   74     __proto__: HTMLTableSectionElement.prototype, | 
 |   75  | 
 |   76     /** | 
 |   77      * Initialization function for the cr.ui framework. | 
 |   78      */ | 
 |   79     decorate: function() { | 
 |   80       this.updateToggleExpandedValueText_(); | 
 |   81       this.querySelector('.toggle-expanded-value').addEventListener( | 
 |   82           'click', this.toggleExpandedValue_.bind(this)); | 
 |   83     }, | 
 |   84  | 
 |   85     /** | 
 |   86      * Populate the table columns with information about the policy name, value | 
 |   87      * and status. | 
 |   88      * @param {string} name The policy name. | 
 |   89      * @param {Object} value Dictionary with information about the policy value. | 
 |   90      * @param {boolean} unknown Whether the policy name is not recognized. | 
 |   91      */ | 
 |   92     initialize: function(name, value, unknown) { | 
 |   93       this.name = name; | 
 |   94       this.unset = !value; | 
 |   95  | 
 |   96       // Populate the name column. | 
 |   97       this.querySelector('.name').textContent = name; | 
 |   98  | 
 |   99       // Populate the remaining columns with policy scope, level and value if a | 
 |  100       // value has been set. Otherwise, leave them blank. | 
 |  101       if (value) { | 
 |  102         this.querySelector('.scope').textContent = | 
 |  103             loadTimeData.getString(value.scope == 'user' ? | 
 |  104                 'scopeUser' : 'scopeDevice'); | 
 |  105         this.querySelector('.level').textContent = | 
 |  106             loadTimeData.getString(value.level == 'recommended' ? | 
 |  107                 'levelRecommended' : 'levelMandatory'); | 
 |  108         this.querySelector('.value').textContent = value.value; | 
 |  109         this.querySelector('.expanded-value').textContent = value.value; | 
 |  110       } | 
 |  111  | 
 |  112       // Populate the status column. | 
 |  113       var status; | 
 |  114       if (!value) { | 
 |  115         // If the policy value has not been set, show an error message. | 
 |  116         status = loadTimeData.getString('unset'); | 
 |  117       } else if (unknown) { | 
 |  118         // If the policy name is not recognized, show an error message. | 
 |  119         status = loadTimeData.getString('unknown'); | 
 |  120       } else if (value.error) { | 
 |  121         // If an error occurred while parsing the policy value, show the error | 
 |  122         // message. | 
 |  123         status = value.error; | 
 |  124       } else { | 
 |  125         // Otherwise, indicate that the policy value was parsed correctly. | 
 |  126         status = loadTimeData.getString('ok'); | 
 |  127       } | 
 |  128       this.querySelector('.status').textContent = status; | 
 |  129     }, | 
 |  130  | 
 |  131     /** | 
 |  132      * Check the table columns for overflow. Most columns are automatically | 
 |  133      * elided when overflow occurs. The only action required is to add a tooltip | 
 |  134      * that shows the complete content. The value column is an exception. If | 
 |  135      * overflow occurs here, the contents is replaced with a link that toggles | 
 |  136      * the visibility of an additional row containing the complete value. | 
 |  137      */ | 
 |  138     checkOverflow: function() { | 
 |  139       // Set a tooltip on all overflowed columns except the value column. | 
 |  140       var divs = this.querySelectorAll('div.elide'); | 
 |  141       for (var i = 0; i < divs.length; i++) { | 
 |  142         var div = divs[i]; | 
 |  143         div.title = div.offsetWidth < div.scrollWidth ? div.textContent : ''; | 
 |  144       } | 
 |  145  | 
 |  146       // Cache the width of the value column's contents when it is first shown. | 
 |  147       // This is required to be able to check whether the contents would still | 
 |  148       // overflow the column once it has been hidden and replaced by a link. | 
 |  149       var valueContainer = this.querySelector('.value-container'); | 
 |  150       if (valueContainer.valueWidth == undefined) { | 
 |  151         valueContainer.valueWidth = | 
 |  152             valueContainer.querySelector('.value').offsetWidth; | 
 |  153       } | 
 |  154  | 
 |  155       // Determine whether the contents of the value column overflows. The | 
 |  156       // visibility of the contents, replacement link and additional row | 
 |  157       // containing the complete value that depend on this are handled by CSS. | 
 |  158       this.classList.toggle( | 
 |  159           'has-overflowed-value', | 
 |  160           valueContainer.offsetWidth < valueContainer.valueWidth); | 
 |  161     }, | 
 |  162  | 
 |  163     /** | 
 |  164      * Update the text of the link that toggles the visibility of an additional | 
 |  165      * row containing the complete policy value, depending on the toggle state. | 
 |  166      * @private | 
 |  167      */ | 
 |  168     updateToggleExpandedValueText_: function(event) { | 
 |  169       this.querySelector('.toggle-expanded-value').textContent = | 
 |  170           loadTimeData.getString( | 
 |  171               this.classList.contains('show-overflowed-value') ? | 
 |  172                   'hideExpandedValue' : 'showExpandedValue'); | 
 |  173     }, | 
 |  174  | 
 |  175     /** | 
 |  176      * Toggle the visibility of an additional row containing the complete policy | 
 |  177      * value. | 
 |  178      * @private | 
 |  179      */ | 
 |  180     toggleExpandedValue_: function() { | 
 |  181       this.classList.toggle('show-overflowed-value'); | 
 |  182       this.updateToggleExpandedValueText_(); | 
 |  183     }, | 
 |  184   }; | 
 |  185  | 
 |  186   /** | 
 |  187    * A table of policies and their values. | 
 |  188    * @constructor | 
 |  189    * @extends {HTMLTableSectionElement} | 
 |  190    */ | 
 |  191   var PolicyTable = cr.ui.define('tbody'); | 
 |  192  | 
 |  193   PolicyTable.prototype = { | 
 |  194     // Set up the prototype chain. | 
 |  195     __proto__: HTMLTableSectionElement.prototype, | 
 |  196  | 
 |  197     /** | 
 |  198      * Initialization function for the cr.ui framework. | 
 |  199      */ | 
 |  200     decorate: function() { | 
 |  201       this.policies_ = {}; | 
 |  202       this.filterPattern_ = ''; | 
 |  203       window.addEventListener('resize', this.checkOverflow_.bind(this)); | 
 |  204     }, | 
 |  205  | 
 |  206     /** | 
 |  207      * Initialize the list of all known policies. | 
 |  208      * @param {Object} names Dictionary containing all known policy names. | 
 |  209      */ | 
 |  210     setPolicyNames: function(names) { | 
 |  211       this.policies_ = names; | 
 |  212       this.setPolicyValues({}); | 
 |  213     }, | 
 |  214  | 
 |  215     /** | 
 |  216      * Populate the table with the currently set policy values and any errors | 
 |  217      * detected while parsing these. | 
 |  218      * @param {Object} values Dictionary containing the current policy values. | 
 |  219      */ | 
 |  220     setPolicyValues: function(values) { | 
 |  221       // Remove all policies from the table. | 
 |  222       var policies = this.getElementsByTagName('tbody'); | 
 |  223       while (policies.length > 0) | 
 |  224         this.removeChild(policies.item(0)); | 
 |  225  | 
 |  226       // First, add known policies whose value is currently set. | 
 |  227       var unset = []; | 
 |  228       for (var name in this.policies_) { | 
 |  229         if (name in values) | 
 |  230           this.setPolicyValue_(name, values[name], false); | 
 |  231         else | 
 |  232           unset.push(name); | 
 |  233       } | 
 |  234  | 
 |  235       // Second, add policies whose value is currently set but whose name is not | 
 |  236       // recognized. | 
 |  237       for (var name in values) { | 
 |  238         if (!(name in this.policies_)) | 
 |  239           this.setPolicyValue_(name, values[name], true); | 
 |  240       } | 
 |  241  | 
 |  242       // Finally, add known policies whose value is not currently set. | 
 |  243       for (var i = 0; i < unset.length; i++) | 
 |  244         this.setPolicyValue_(unset[i], undefined, false); | 
 |  245  | 
 |  246       // Filter the policies. | 
 |  247       this.filter(); | 
 |  248     }, | 
 |  249  | 
 |  250     /** | 
 |  251      * Set the filter pattern. Only policies whose name contains |pattern| are | 
 |  252      * shown in the policy table. The filter is case insensitive. It can be | 
 |  253      * disabled by setting |pattern| to an empty string. | 
 |  254      * @param {string} pattern The filter pattern. | 
 |  255      */ | 
 |  256     setFilterPattern: function(pattern) { | 
 |  257       this.filterPattern_ = pattern.toLowerCase(); | 
 |  258       this.filter(); | 
 |  259     }, | 
 |  260  | 
 |  261     /** | 
 |  262      * Filter policies. Only policies whose name contains the filter pattern are | 
 |  263      * shown in the table. Furthermore, policies whose value is not currently | 
 |  264      * set are only shown if the corresponding checkbox is checked. | 
 |  265      */ | 
 |  266     filter: function() { | 
 |  267       var showUnset = $('show-unset').checked; | 
 |  268       var policies = this.getElementsByTagName('tbody'); | 
 |  269       for (var i = 0; i < policies.length; i++) { | 
 |  270         var policy = policies[i]; | 
 |  271         policy.hidden = | 
 |  272             policy.unset && !showUnset || | 
 |  273             policy.name.toLowerCase().indexOf(this.filterPattern_) == -1; | 
 |  274       } | 
 |  275       this.parentElement.classList.toggle( | 
 |  276           'empty', !this.querySelector('tbody:not([hidden])')); | 
 |  277       setTimeout(this.checkOverflow_.bind(this), 0); | 
 |  278     }, | 
 |  279  | 
 |  280     /** | 
 |  281      * Check the table columns for overflow. | 
 |  282      * @private | 
 |  283      */ | 
 |  284     checkOverflow_: function() { | 
 |  285       var policies = this.getElementsByTagName('tbody'); | 
 |  286       for (var i = 0; i < policies.length; i++) { | 
 |  287         if (!policies[i].hidden) | 
 |  288           policies[i].checkOverflow(); | 
 |  289       } | 
 |  290     }, | 
 |  291  | 
 |  292     /** | 
 |  293      * Add a policy with the given |name| and |value| to the table. | 
 |  294      * @param {string} name The policy name. | 
 |  295      * @param {Object} value Dictionary with information about the policy value. | 
 |  296      * @param {boolean} unknown Whether the policy name is not recoginzed. | 
 |  297      * @private | 
 |  298      */ | 
 |  299     setPolicyValue_: function(name, value, unknown) { | 
 |  300       var policy = new Policy; | 
 |  301       policy.initialize(name, value, unknown); | 
 |  302       this.appendChild(policy); | 
 |  303     }, | 
 |  304   }; | 
 |  305  | 
 |  306   /** | 
 |  307    * A singelton object that handles communication between browser and WebUI. | 
 |  308    * @constructor | 
 |  309    */ | 
 |  310   function Page() { | 
|   37   } |  311   } | 
|   38 }; |  312  | 
|   39  |  313   // Make Page a singleton. | 
|   40 cr.define('policies', function() { |  314   cr.addSingletonGetter(Page); | 
|   41  |  315  | 
|   42   function Policy() { |  316   /** | 
|   43   } |  317    * Provide a list of all known policies to the UI. Called by the browser on | 
|   44  |  318    * page load. | 
|   45   cr.addSingletonGetter(Policy); |  319    * @param {Object} names Dictionary containing all known policy names. | 
|   46  |  320    */ | 
|   47   Policy.prototype = { |  321   Page.setPolicyNames = function(names) { | 
|   48     /** |  322     this.getInstance().policyTable.setPolicyNames(names); | 
|   49      * True if none of the received policies are actually set, false otherwise. |  323   }; | 
|   50      * @type {boolean} |  324  | 
|   51      */ |  325   /** | 
|   52     noActivePolicies_: false, |  326    * Provide a list of the currently set policy values and any errors detected | 
|   53  |  327    * while parsing these to the UI. Called by the browser on page load and | 
|   54     /** |  328    * whenever policy values change. | 
|   55      * The current search term for filtering of the policy table. |  329    * @param {Object} values Dictionary containing the current policy values. | 
|   56      * @type {string} |  330    */ | 
|   57      * @private |  331   Page.setPolicyValues = function(values) { | 
|   58      */ |  332     this.getInstance().policyTable.setPolicyValues(values); | 
|   59     searchTerm_: '', |  333   }; | 
|   60  |  334  | 
|   61     /** |  335   /** | 
|   62      * Takes the |policyData| argument and populates the page with this data. It |  336    * Provide the current cloud policy status to the UI. Called by the browser on | 
|   63      * expects an object structure like the policyDataFormat above. |  337    * page load if cloud policy is present and whenever the status changes. | 
|   64      * @param {Object} policyData Detailed info about policies. |  338    * @param {Object} status Dictionary containing the current policy status. | 
|   65      */ |  339    */ | 
|   66     renderTemplate: function(policyData) { |  340   Page.setStatus = function(status) { | 
|   67       this.noActivePolicies_ = !policyData.anyPoliciesSet; |  341     this.getInstance().setStatus(status); | 
|   68  |  342   }; | 
|   69       if (this.noActivePolicies_) |  343  | 
|   70         $('no-policies').hidden = false; |  344   /** | 
|   71       if (policyData.status.displayStatusSection) |  345    * Notify the UI that a request to reload policy values has completed. Called | 
|   72         $('status-section').hidden = false; |  346    * by the browser after a request to reload policy has been sent by the UI. | 
|   73  |  347    */ | 
|   74       // This is the javascript code that processes the template: |  348   Page.reloadPoliciesDone = function() { | 
|   75       var input = new JsEvalContext(policyData); |  349     this.getInstance().reloadPoliciesDone(); | 
|   76       var output = $('data-template'); |  350   }; | 
|   77       jstProcess(input, output); |  351  | 
|   78  |  352   Page.prototype = { | 
|   79       var toggles = document.querySelectorAll('.policy-set * .toggler'); |  353     /** | 
|   80       for (var i = 0; i < toggles.length; i++) { |  354      * Main initialization function. Called by the browser on page load. | 
|   81         toggles[i].hidden = true; |  355      */ | 
|   82         toggles[i].onclick = function() { |  356     initialize: function() { | 
|   83           Policy.getInstance().toggleCellExpand_(this); |  357       uber.onContentFrameLoaded(); | 
|   84         }; |  358       this.policyTable = $('policy-table'); | 
|   85       } |  359       cr.ui.decorate(this.policyTable, PolicyTable); | 
|   86  |  360  | 
|   87       var containers = document.querySelectorAll('.text-container'); |  361       // Place the initial focus on the filter input field. | 
|   88       for (var i = 0; i < containers.length; i++) |  362       $('filter').focus(); | 
|   89         this.initTextContainer_(containers[i]); |  363  | 
|   90     }, |  364       var self = this; | 
|   91  |  365       $('filter').onsearch = function(event) { | 
|   92     /** |  366         self.policyTable.setFilterPattern(this.value); | 
|   93      * Filters the table of policies by name. |  367       }; | 
|   94      * @param {string} term The search string. |  368       $('reload-policies').onclick = function(event) { | 
|   95      */ |  369         this.disabled = true; | 
|   96     filterTable: function(term) { |  370         chrome.send('reloadPolicies'); | 
|   97       this.searchTerm_ = term.toLowerCase(); |  371       }; | 
|   98       var table = $('policy-table'); |  372       $('show-unset').onchange = this.policyTable.filter.bind(this.policyTable); | 
|   99       var showUnsent = $('toggle-unsent-policies').checked; |  373  | 
|  100       for (var r = 1; r < table.rows.length; r++) { |  374       // Notify the browser that the page has loaded, causing it to send the | 
|  101         var row = table.rows[r]; |  375       // list of all known policies, the current policy values and the cloud | 
|  102  |  376       // policy status. | 
|  103         // Don't change visibility of policies that aren't set if the checkbox |  377       chrome.send('initialized'); | 
|  104         // isn't checked. |  378     }, | 
|  105         if (!showUnsent && row.className == 'policy-unset') |  379  | 
|  106           continue; |  380     /** | 
|  107  |  381      * Update the status section of the page to show the current cloud policy | 
|  108         var nameCell = row.querySelector('.policy-name'); |  382      * status. | 
|  109         var cellContents = nameCell.textContent; |  383      * @param {Object} status Dictionary containing the current policy status. | 
|  110         row.hidden = |  384      */ | 
|  111             !(cellContents.toLowerCase().indexOf(this.searchTerm_) >= 0); |  385     setStatus: function(status) { | 
|  112       } |  386       // Remove any existing status boxes. | 
|  113     }, |  387       var container = $('status-box-container'); | 
|  114  |  388       while (container.firstChild) | 
|  115     /** |  389         container.removeChild(container.firstChild); | 
|  116      * Updates the visibility of the policies depending on the state of the |  390       // Hide the status section. | 
|  117      * 'toggle-unsent-policies' checkbox. |  391       var section = $('status'); | 
|  118      */ |  392       section.hidden = true; | 
|  119     updatePolicyVisibility: function() { |  393  | 
|  120       if ($('toggle-unsent-policies').checked) |  394       // Add a status box for each scope that has a cloud policy status. | 
|  121         $('policies').style.display = ''; |  395       for (var scope in status) { | 
|  122       else if (this.noActivePolicies_) |  396         var box = new StatusBox; | 
|  123         $('policies').style.display = 'none'; |  397         box.initialize(scope, status[scope]); | 
|  124  |  398         container.appendChild(box); | 
|  125       var tableRows = document.getElementsByClassName('policy-unset'); |  399         // Show the status section. | 
|  126       for (var i = 0; i < tableRows.length; i++) |  400         section.hidden = false; | 
|  127         tableRows[i].hidden = !($('toggle-unsent-policies').checked); |  401       } | 
|  128  |  402     }, | 
|  129       // Filter table again in case a search was active. |  403  | 
|  130       this.filterTable(this.searchTerm_); |  404     /** | 
|  131     }, |  405      * Re-enable the reload policies button when the previous request to reload | 
|  132  |  406      * policies values has completed. | 
|  133     /** |  407      */ | 
|  134      * Expands or collapses a table cell that has overflowing text. |  408     reloadPoliciesDone: function() { | 
|  135      * @param {Object} toggler The toggler that was clicked on. |  409       $('reload-policies').disabled = false; | 
|  136      * @private |  410     }, | 
|  137      */ |  411   }; | 
|  138     toggleCellExpand_: function(toggler) { |  412  | 
|  139       var textContainer = toggler.parentElement; |  | 
|  140       textContainer.collapsed = !textContainer.collapsed; |  | 
|  141  |  | 
|  142       if (textContainer.collapsed) |  | 
|  143         this.collapseCell_(textContainer); |  | 
|  144       else |  | 
|  145         this.expandCell_(textContainer); |  | 
|  146     }, |  | 
|  147  |  | 
|  148     /** |  | 
|  149      * Collapses all expanded table cells and updates the visibility of the |  | 
|  150      * toggles accordingly. Should be called before the policy information in |  | 
|  151      * the table is updated. |  | 
|  152      */ |  | 
|  153     collapseExpandedCells: function() { |  | 
|  154       var textContainers = document.querySelectorAll('.text-expanded'); |  | 
|  155       for (var i = 0; i < textContainers.length; i++) |  | 
|  156         this.collapseCell_(textContainers[i]); |  | 
|  157     }, |  | 
|  158  |  | 
|  159     /** |  | 
|  160      * Expands a table cell so that all the text it contains is visible. |  | 
|  161      * @param {Object} textContainer The cell's div element that contains the |  | 
|  162      * text. |  | 
|  163      * @private |  | 
|  164      */ |  | 
|  165     expandCell_: function(textContainer) { |  | 
|  166       textContainer.classList.remove('text-collapsed'); |  | 
|  167       textContainer.classList.add('text-expanded'); |  | 
|  168       textContainer.querySelector('.expand').hidden = true; |  | 
|  169       textContainer.querySelector('.collapse').hidden = false; |  | 
|  170     }, |  | 
|  171  |  | 
|  172     /** |  | 
|  173      * Collapses a table cell so that overflowing text is hidden. |  | 
|  174      * @param {Object} textContainer The cell's div element that contains the |  | 
|  175      * text. |  | 
|  176      * @private |  | 
|  177      */ |  | 
|  178     collapseCell_: function(textContainer) { |  | 
|  179       textContainer.classList.remove('text-expanded'); |  | 
|  180       textContainer.classList.add('text-collapsed'); |  | 
|  181       textContainer.querySelector('.expand').hidden = false; |  | 
|  182       textContainer.querySelector('.collapse').hidden = true; |  | 
|  183     }, |  | 
|  184  |  | 
|  185     /** |  | 
|  186      * Initializes a text container, showing the expand toggle if necessary. |  | 
|  187      * @param {Object} textContainer The text container element. |  | 
|  188      */ |  | 
|  189     initTextContainer_: function(textContainer) { |  | 
|  190       textContainer.collapsed = true; |  | 
|  191       var textValue = textContainer.querySelector('.text-value'); |  | 
|  192  |  | 
|  193       // If the text is wider than the text container, the expand toggler should |  | 
|  194       // appear. |  | 
|  195       if (textContainer.offsetWidth < textValue.offsetWidth || |  | 
|  196           textContainer.offsetHeight < textValue.offsetHeight) { |  | 
|  197         this.collapseCell_(textContainer); |  | 
|  198       } |  | 
|  199     } |  | 
|  200   }; |  | 
|  201  |  | 
|  202   /** |  | 
|  203    * Asks the C++ PolicyUIHandler to get details about policies and status |  | 
|  204    * information. The PolicyUIHandler should reply to returnData() (below). |  | 
|  205    */ |  | 
|  206   Policy.requestData = function() { |  | 
|  207     chrome.send('requestData'); |  | 
|  208   }; |  | 
|  209  |  | 
|  210   /** |  | 
|  211    * Called by the C++ PolicyUIHandler when it has the requested data. |  | 
|  212    * @param {Object} policyData The policy information in the format described |  | 
|  213    * by the policyDataFormat. |  | 
|  214    */ |  | 
|  215   Policy.returnData = function(policyData) { |  | 
|  216     var policy = Policy.getInstance(); |  | 
|  217     policy.collapseExpandedCells(); |  | 
|  218     policy.renderTemplate(policyData); |  | 
|  219     policy.updatePolicyVisibility(); |  | 
|  220   }; |  | 
|  221  |  | 
|  222   /** |  | 
|  223    * Called by the C++ PolicyUIHandler when a requested policy refresh has |  | 
|  224    * completed. |  | 
|  225    */ |  | 
|  226   Policy.refreshDone = function() { |  | 
|  227     $('fetch-policies-button').disabled = false; |  | 
|  228   }; |  | 
|  229  |  | 
|  230   /** |  | 
|  231    * Asks the C++ PolicyUIHandler to re-fetch policy information. |  | 
|  232    */ |  | 
|  233   Policy.triggerPolicyFetch = function() { |  | 
|  234     chrome.send('fetchPolicy'); |  | 
|  235   }; |  | 
|  236  |  | 
|  237   /** |  | 
|  238    * Determines whether a policy should be visible or not. |  | 
|  239    * @param {Object} policy An entry in the 'policies' array given by the above |  | 
|  240    * PolicyDataFormat. |  | 
|  241    */ |  | 
|  242   Policy.shouldDisplayPolicy = function(policy) { |  | 
|  243     return $('toggle-unsent-policies').checked || policy.set; |  | 
|  244   }; |  | 
|  245  |  | 
|  246   /** |  | 
|  247    * Initializes the page and loads the list of policies and the policy |  | 
|  248    * status data. |  | 
|  249    */ |  | 
|  250   Policy.initialize = function() { |  | 
|  251     Policy.requestData(); |  | 
|  252  |  | 
|  253     // Set HTML event handlers. |  | 
|  254     $('fetch-policies-button').onclick = function(event) { |  | 
|  255       this.disabled = true; |  | 
|  256       Policy.triggerPolicyFetch(); |  | 
|  257     }; |  | 
|  258  |  | 
|  259     $('toggle-unsent-policies').onchange = function(event) { |  | 
|  260       Policy.getInstance().updatePolicyVisibility(); |  | 
|  261     }; |  | 
|  262  |  | 
|  263     $('search-field').onsearch = function(event) { |  | 
|  264       Policy.getInstance().filterTable(this.value); |  | 
|  265     }; |  | 
|  266   }; |  | 
|  267  |  | 
|  268   // Export |  | 
|  269   return { |  413   return { | 
|  270     Policy: Policy |  414     Page: Page | 
|  271   }; |  415   }; | 
|  272 }); |  416 }); | 
|  273  |  417  | 
|  274 var Policy = policies.Policy; |  418 // Have the main initialization function be called when the page finishes | 
|  275  |  419 // loading. | 
|  276 // Get data and have it displayed upon loading. |  420 document.addEventListener( | 
|  277 document.addEventListener('DOMContentLoaded', policies.Policy.initialize); |  421     'DOMContentLoaded', | 
 |  422     policy.Page.getInstance().initialize.bind(policy.Page.getInstance())); | 
| OLD | NEW |