<commit_before>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2014 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

/**
  Separate browser event handling into its own extension for cleaner
  code and testing.

  @module juju.browser
*/

YUI.add('subapp-browser-events', function(Y) {
  var browser = Y.namespace('juju.browser');

  /**
    Event handling for the browser subapp.

    @method BrowserEventsExtension
  */
  function BrowserEventsExtension() {}

  BrowserEventsExtension.prototype = {
    /**
      Handle changes in state, typically navigation requests.

      @method _onChangeState
      @param {Object} e The event facade.
    */
    _onChangeState: function(e) {
      // Cancel the inspectorRetryTimer, if there is one.
      // The user may be navigating away from the inspector, but first
      // triggered the inspector's retry mechanism. This makes sure the timer
      // won't suddenly have the inspector show up after the user navigates
      // away.
      var timer = this.get('inspectorRetryTimer');
      if (timer) {
        timer.cancel();
        this.set('inspectorRetries', 0);
      }
      this.state.set('allowInspector', true);
      var state = e.details[0];
      var url = this.state.generateUrl(state);
      this.navigate(url);
    },

    /**
      Handle service deploys by opening up the appropriate inspector.

      @method _onServiceDeployed
      @param {Object} e The event facade.
    */
    _onServiceDeployed: function(e) {
      var activeInspector = this._inspector;
      if (activeInspector && !activeInspector.get('destroyed')) {
        var activeClientId = activeInspector.get('model')
          .get('clientId');
        // Because multiple services can be deployed at once we only want to
        // switch to a deployed inspector if there is currently one open.
        // And we only want to switch to that specific inspector.
        if (activeClientId === e.clientId) {
          this.fire('changeState', {
            sectionA: {
              component: 'inspector',
              metadata: { id: e.serviceName }
            }});
        }
      }
    },

    /**
      Fire a change event on all machine models associated with a service.

      @method _fireMachineChanges
      @param {Object} service The service that the machines are associated with
          via units.
    */
    _fireMachineChanges: function(service) {
      var db = this.get('db'),
          services;
      if (service) {
        services = [service];
      } else {
        services = db.services.toArray();
      }
      // We also need to fire change events for the related machines in order
      // to trigger re-rendering in machine view
      services.forEach(function(service) {
        var changedMachines = [];
        service.get('units').each(function(unit) {
          var machine = unit.machine;
          if (changedMachines.indexOf(machine) < 0) {
            changedMachines.push(machine);
          }
        });
        changedMachines.forEach(function(machineId) {
          db.machines.fire('change', {
            changed: true,
            instance: db.machines.getById(machineId)
          });
        });
      });
    },

    /**
      Handle highlight events for services/units.

      @method _onHighlight
      @param {Object} e The event facade.
    */
    _onHighlight: function(e) {
      var serviceName = e.serviceName,
          db = this.get('db'),
          changedMachines = [];
      var service = db.services.getServiceByName(serviceName);
      service.set('highlight', true);
      db.updateUnitFlags(service, 'highlight');
      // Need to toggle fade off.
      this._onShow({serviceNames: [serviceName]});
      // Unrelated services need to be faded.
      var unrelated = db.findUnrelatedServices(service);
      unrelated.each(function(model) {
        model.set('hide', true);
      });
      db.setMVVisibility(serviceName, true);
    },

    /**
      Handle unhighlight events for services/units.

      @method _onUnhighlight
      @param {Object} e The event facade.
    */
    _onUnhighlight: function(e) {
      var db = this.get('db'),
          serviceName = e.serviceName,
          changedMachines = [];
      var service = db.services.getServiceByName(serviceName);
      service.set('highlight', false);
      db.updateUnitFlags(service, 'highlight');
      // Unrelated services need to be unfaded.
      var unrelated = db.findUnrelatedServices(service);
      unrelated.each(function(model) {
        model.set('hide', false);
      });
      db.setMVVisibility(serviceName, false);
    },

    /**
      Handle fade events for services/units.

      @method _onFade
      @param {Object} e The event facade.
    */
    _onFade: function(e) {
      var serviceNames = e.serviceNames,
          db = this.get('db'),
          service;
      serviceNames.forEach(function(serviceName) {
        service = db.services.getServiceByName(serviceName);
        service.set('fade', true);
        db.updateUnitFlags(service, 'fade');
        // Need to toggle highlight off.
        this._onUnhighlight({serviceName: service.get('name')});
        this._fireMachineChanges(service);
      }, this);
    },

    /**
      Handle show events for services/units.

      @method _onShow
      @param {Object} e The event facade.
    */
    _onShow: function(e) {
      var serviceNames = e.serviceNames,
          db = this.get('db'),
          service;
      serviceNames.forEach(function(serviceName) {
        service = db.services.getServiceByName(serviceName);
        service.set('fade', false);
        db.updateUnitFlags(service, 'fade');
        this._fireMachineChanges(service);<commit_msg>Only unhighlight when the user clicks fade if the service isn't already hidden<commit_after>/*
This file is part of the Juju GUI, which lets users view and manage Juju
environments within a graphical interface (https://launchpad.net/juju-gui).
Copyright (C) 2012-2014 Canonical Ltd.

This program is free software: you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License version 3, as published by
the Free Software Foundation.

This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranties of MERCHANTABILITY,
SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero
General Public License for more details.

You should have received a copy of the GNU Affero General Public License along
with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

'use strict';

/**
  Separate browser event handling into its own extension for cleaner
  code and testing.

  @module juju.browser
*/

YUI.add('subapp-browser-events', function(Y) {
  var browser = Y.namespace('juju.browser');

  /**
    Event handling for the browser subapp.

    @method BrowserEventsExtension
  */
  function BrowserEventsExtension() {}

  BrowserEventsExtension.prototype = {
    /**
      Handle changes in state, typically navigation requests.

      @method _onChangeState
      @param {Object} e The event facade.
    */
    _onChangeState: function(e) {
      // Cancel the inspectorRetryTimer, if there is one.
      // The user may be navigating away from the inspector, but first
      // triggered the inspector's retry mechanism. This makes sure the timer
      // won't suddenly have the inspector show up after the user navigates
      // away.
      var timer = this.get('inspectorRetryTimer');
      if (timer) {
        timer.cancel();
        this.set('inspectorRetries', 0);
      }
      this.state.set('allowInspector', true);
      var state = e.details[0];
      var url = this.state.generateUrl(state);
      this.navigate(url);
    },

    /**
      Handle service deploys by opening up the appropriate inspector.

      @method _onServiceDeployed
      @param {Object} e The event facade.
    */
    _onServiceDeployed: function(e) {
      var activeInspector = this._inspector;
      if (activeInspector && !activeInspector.get('destroyed')) {
        var activeClientId = activeInspector.get('model')
          .get('clientId');
        // Because multiple services can be deployed at once we only want to
        // switch to a deployed inspector if there is currently one open.
        // And we only want to switch to that specific inspector.
        if (activeClientId === e.clientId) {
          this.fire('changeState', {
            sectionA: {
              component: 'inspector',
              metadata: { id: e.serviceName }
            }});
        }
      }
    },

    /**
      Fire a change event on all machine models associated with a service.

      @method _fireMachineChanges
      @param {Object} service The service that the machines are associated with
          via units.
    */
    _fireMachineChanges: function(service) {
      var db = this.get('db'),
          services;
      if (service) {
        services = [service];
      } else {
        services = db.services.toArray();
      }
      // We also need to fire change events for the related machines in order
      // to trigger re-rendering in machine view
      services.forEach(function(service) {
        var changedMachines = [];
        service.get('units').each(function(unit) {
          var machine = unit.machine;
          if (changedMachines.indexOf(machine) < 0) {
            changedMachines.push(machine);
          }
        });
        changedMachines.forEach(function(machineId) {
          db.machines.fire('change', {
            changed: true,
            instance: db.machines.getById(machineId)
          });
        });
      });
    },

    /**
      Handle highlight events for services/units.

      @method _onHighlight
      @param {Object} e The event facade.
    */
    _onHighlight: function(e) {
      var serviceName = e.serviceName,
          db = this.get('db'),
          changedMachines = [];
      var service = db.services.getServiceByName(serviceName);
      service.set('highlight', true);
      db.updateUnitFlags(service, 'highlight');
      // Need to toggle fade off.
      this._onShow({serviceNames: [serviceName]});
      // Unrelated services need to be faded.
      var unrelated = db.findUnrelatedServices(service);
      unrelated.each(function(model) {
        model.set('hide', true);
      });
      db.setMVVisibility(serviceName, true);
    },

    /**
      Handle unhighlight events for services/units.

      @method _onUnhighlight
      @param {Object} e The event facade.
    */
    _onUnhighlight: function(e) {
      var db = this.get('db'),
          serviceName = e.serviceName,
          changedMachines = [];
      var service = db.services.getServiceByName(serviceName);
      service.set('highlight', false);
      db.updateUnitFlags(service, 'highlight');
      // Unrelated services need to be unfaded.
      var unrelated = db.findUnrelatedServices(service);
      unrelated.each(function(model) {
        model.set('hide', false);
      });
      db.setMVVisibility(serviceName, false);
    },

    /**
      Handle fade events for services/units.

      @method _onFade
      @param {Object} e The event facade.
    */
    _onFade: function(e) {
      var serviceNames = e.serviceNames,
          db = this.get('db'),
          service;
      serviceNames.forEach(function(serviceName) {
        service = db.services.getServiceByName(serviceName);
        service.set('fade', true);
        db.updateUnitFlags(service, 'fade');
        // Need to toggle highlight off but only if it's not already hidden.
        if (!service.get('hide')) {
          this._onUnhighlight({serviceName: service.get('name')});
          this._fireMachineChanges(service);
        }
      }, this);
    },

    /**
      Handle show events for services/units.

      @method _onShow
      @param {Object} e The event facade.
    */
    _onShow: function(e) {
      var serviceNames = e.serviceNames,
          db = this.get('db'),
          service;
      serviceNames.forEach(function(serviceName) {
        service = db.services.getServiceByName(serviceName);
        service.set('fade', false);
        db.updateUnitFlags(service, 'fade');
        this._fireMachineChanges(service);
{'fraction_non_alphanumeric': 0.10315318788065685, 'fraction_numerical': 0.0018502813969624547, 'mean_word_length': 2.436291390728477, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3091301', 'n_tokens_mistral': 3607, 'n_tokens_neox': 3456, 'n_words': 1084}