Source: tools/progress.js

/**
 * Mobizen - Mobizen/Tools/Progress
 *
 * IMPORTANT NOTE: This file is licensed only for use in providing the RSUPPORT services,
 *
 * @copyright 2015 RSUPPORT CO., LTD. All rights reserved.
 * @license Dedicated to the public domain.
 * @author Joon Kyoung <firejune@gmail.com>
 *
 */

(function($, exports, undefined) {
  "use strict";

  /**
   * @typedef {Mobizen}
   */
  var Mobizen = exports.Mobizen || (exports.Mobizen = {})
  /**
   * @typedef {Mobizen.Tools}
   */
    , Tools = Mobizen.Tools || (Mobizen.Tools = {})
  /**
   * @typedef {Mobizen.i18n|function}
   */
    , i18n = Mobizen.i18n || function() {};

  /**
   * @constructs Progress
   * @memberof Mobizen.Tools
   * @param {Mobizen.Tools} tools - parent object
   *
   * @requires {@linkplain Mobizen.Tools.Progress~Task}
   *
   */
  function Progress(tools) {
    console.info('Tools.Progress');

    /**
     * @typedef {Mobizen.Tools}
     * @private
     */
    this.t = tools;
    /**
     * @typedef {Mobizen.Apps}
     * @private
     */
    this.a = tools.a;

    /** @type {number} */
    this.id = 0;
    /** @type {object} */
    this.tasks = {};
    /** @type {boolean} */
    this.running = false;

    /** @type {jQueryObject} */
    this.$element = $('#progress');
    /** @type {jQueryObject} */
    this.$count = this.$element.find('label .count');
    /** @type {jQueryObject} */
    this.$tool = this.t.menu.$switchtool.find('[data-cmd=progress]');
  }

  Progress.prototype = /** @lends Mobizen.Tools.Progress# */ {
    /**
     * @param {object} settings
     * @param {boolean} [noupdate]
     * @return {Mobizen.Tools.Progress~Task}
     */
    start: function(settings, noupdate) {
      this.activate();

      var tasks = this.items();
      for (var i = 0; i < tasks.length; i++) {
        if (tasks[i].visible) {
          tasks[i].fade();
        }
      }

      this._count(tasks.length);

      /**
       * @typedef {Mobizen.Tools.Progress~Task} Mobizen.Tools.Progress#tasks[index]
       */
      return this.tasks[++this.id] = new Task(this, $.extend({
        id: this.id,
        total: 0,
        count: 0,
        title: i18n('tools.progress.title'),
        label: i18n('tools.progress.label'),
        justwait: false,
        noupdate: false,
        cancel: false
      }, settings), noupdate);
    },

    /**
     * @param {number} count
     * @private
     */
    _count: function(count) {
      if (!count || count == 1) {
        return this.$count.hide();
      }

      this.a.count(this.$count, count);
    },

    /**
     * @return {array} tasks
     */
    items: function() {
      var tasks = [];
      for (var id in this.tasks) {
        if (this.tasks[id] && !this.tasks[id].paused) {
          tasks.push(this.tasks[id]);
        }
      }

      return tasks;
    },

    /**
     * @fires Apps#progress․start
     */
    activate: function() {
      //console.debug('Progress.activate');

      this.$tool.removeClass('disable');

      if (!this.running) {
        this.t.change('progress');
      }

      this.running = true;
      //console.debug('progress.running', this.running);

      var app = this.a.instance();
      /**
       * @event Apps#progress․start
       * @type {Mobizen.Event}
       */
      app && app.emit('progress.start');
    },

    /**
     * @fires Apps#progress․end
     */
    deactivate: function() {
      //console.debug('Progress.deactivate');

      this.$tool.addClass('disable');

      // fixed #17905 issue form ntt
      if (this.t.is != 'fullscreen') {
        setTimeout(this.t.change.bind(this.t), 200);
      }

      this.running = false;
      //console.debug('progress.running', this.running);

      var app = this.a.instance();

      /**
       * @event Apps#progress․end
       * @type {Mobizen.Event}
       */
      app && app.emit('progress.end');
    },

    /**
     * @param {number} id
     */
    end: function(id) {
      //console.log('Progress.end', id);

      this.tasks[id] = null;
      delete this.tasks[id];

      var tasks = this.items();
      this._count(tasks.length);

      //console.debug('Progress.end', tasks);

      if (tasks.length) {
        tasks[0].appear();
      } else {
        this.deactivate();
      }
    }
  };


  /**
   * @constructs Task
   * @memberof Mobizen.Tools.Progress~
   * @param {Mobizen.Tools.Progress} progress - parent object
   * @param {objects} settings
   *
   */
  function Task(progress, settings) {
    console.info('Progress.Task', [progress, settings]);

    progress.$element.toggleClass('pending', settings.justwait).append([
      '<p id="_' + settings.id + '">',
        '<span class="text title">' + i18n('tools.loading') + '</span>',
        '<span class="guage"><b class="progress" style="width: 0;"></b></span>',
        '<span class="text alt"></span>',
        '<span class="button cancel icon-times-circle-o"></span>',
      '</p>'
    ].join(''));

    /** @typedef {Mobizen.Tools.Progress} */
    this.progress = progress;
    /** @type {boolean} */
    this.paused = false;
    /** @type {boolean} */
    this.visible = true;

    /** @type {jQueryObject} */
    this.$el = progress.$element.find('#_' + settings.id);
    /** @type {jQueryObject} */
    this.$title = this.$el.find('.title');
    /** @type {jQueryObject} */
    this.$label = this.$el.find('.alt');
    /** @type {jQueryObject} */
    this.$progress = this.$el.find('.progress');
    /** @type {jQueryObject} */
    this.$cancel = this.$el.find('.cancel');

    this.reset(settings);
  }

  Task.prototype = /** @lends Mobizen.Tools.Progress~Task.prototype */ {
    /**
     * @param {object} options
     */
    reset: function(options) {
      //console.log('Progress.Task.reset', options.id);

      this.options = $.extend(this.options, options);
      this.$cancel[options.cancel && 'show' || 'hide']();

      if (options.title) {
        this.$title.html(options.title);
      }

      if (options.cancel) {
        this.$cancel.click(this.cancel.bind(this, true));
      }

      if (options.label) {
        if (options.justwait) {
          this.$label.html(options.label);
        } else {
          this.update(!options.noupdate && 1 || 0, options.label, options.noupdate);
        }
      }
    },

    /**
     * @param {number} num
     */
    change: function(num) {
      this.options.total += num;
      this.$label.find('b').html(this.options.total);
    },

    /**
     * @param {number} percent
     */
    draw: function(percent) {
      var now = new Date();
      percent = Math.round(percent);

      //console.debug('Progress.Task.draw', percent, this.$progress.width());
      if (!this.updated || now - this.updated > 100 && this.percent != percent) {
        this.$progress.width(percent + '%');
        this.percent = percent;
        this.updated = now;
      }
    },

    /**
     * @param {string} title
     * @param {number} total
     * return {Mobizen.Tools.Progress.Task} self for chaine.
     */
    title: function(title, total) {
      this.$title.html(title);

      if (total) {
        this.options.total = total;
      }

      return this;
    },

    /**
     * @param {string} label
     * return {Mobizen.Tools.Progress.Task} self for chaine.
     */
    label: function(label) {
      this.$label.html(label);

      return this;
    },

    /**
     * @param {number} count
     * @param {string} label
     * @param {boolean} [noupdate]
     */
    update: function(count, label, noupdate) {
      var options = this.options;

      if (options.count > options.total) {
        console.warn('WTF?');
        return;
      }

      label = i18n('tools.progress.count', {
        count: options.count,
        total: options.total
      }) + ' ' + (label && label || options.label);

      this.label(label);

      if (!noupdate) {
        this.draw(options.count / options.total * 100);
      }

      options.count += count !== undefined ? count : 1;
    },

    /**
     * @method
     */
    clear: function() {
      //console.log('Progress.Task.clear', this.options.id);
      this.$el.remove();
    },

    /**
     * @method
     */
    fade: function() {
      console.log('Progress.Task.fade', this.options.id);
      this.$el.hide();
      this.visible = false;
    },

    /**
     * @method
     */
    appear: function() {
      console.log('Progress.Task.appear', this.options.id, new Error().stack);
      this.$el.show();
      this.visible = true;
    },

    /**
     * @method
     */
    pause: function() {
      console.log('Progress.Task.pause', this.options.id);
      this.paused = true;

      var tasks = this.progress.items();
      this.progress._count(tasks.length);

      if (tasks.length) {
        tasks[0].appear();
        this.fade();
      } else {
        this.progress.deactivate();
        this.fade.timer = setTimeout(this.fade.bind(this), 100);
      }
    },

    /**
     * @method
     */
    resume: function() {
      console.log('Progress.Task.resume', this.options.id);

      var tasks = this.progress.items();
      this.progress._count(tasks.length);
      clearTimeout(this.fade.timer);

      if (tasks.length) {
        for (var i = 0; i < tasks.length; i++) {
          if (tasks[i].visible) tasks[i].fade();
        }
      } else {
        this.progress.activate();
      }

      this.appear();
      this.paused = false;
    },

    /**
     * @method
     */
    cancel: function() {
      //console.log('Progress.Task.cancel', this.options.id);

      if (typeof this.options.cancel == 'function') {
        this.options.cancel();
      }

      this.options.cancel = null;
      this.close();
    },

    /**
     * @method
     */
    close: function() {
      console.log('Progress.Task.close', this.options.id);

      setTimeout(this.clear.bind(this), 100);
      this.progress.end(this.options.id);
    }
  };


  /*
   * Exporting modules
   */

  Tools.Progress = Progress;

})(jQuery, this);
comments powered by Disqus