Source: device/fullscreen.js

/**
 * Mobizen - Mobizen/Device/FullScreen
 *
 * 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) {
  "use strict";

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

  /**
   * @constructs FullScreen
   * @memberof Mobizen.Device
   * @param {Mobizen.Device} device - parent object
   */
  function FullScreen(device) {
    /**
     * @typedef {Mobizen.Device}
     * @private
     */
    this.d = device;
    /**
     * @typedef {Mobizen.<modeName>}
     * @private
     */
    this.m = device.m;

    /** @type {number} */
    this.offsetTop = this.m.$.header.is(':visible') ? this.m.$.header.height() : 0;
    /** @typedef {Mobizen.Device.Screen} */
    this.screen = device.screen;
    /** @type {jQueryObject} */
    this.$el = $('#fullscreen');
    /** @type {boolean} */
    this.active = false;

    /** @virtual */
    this.onopen = function() {};
    /** @virtual */
    this.onclose = function() {};
  }

  FullScreen.prototype = /** @lends Mobizen.Device.FullScreen# */ {
    /**
     * @method
     */
    update: function() {
      if (!this.active) return;

      this.set();
      this.resize();
      this.rescale();
    },

    /**
     * @method
     */
    set: function() {
      this.resize();

      /** @type {number} */
      this.landscape = this.d._rotate == 90 || this.d._rotate == 270;
      /** @type {number} */
      this.width = this.d.$rswp[this.landscape && 'height' || 'width']();
      /** @type {number} */
      this.height = this.d.$rswp[this.landscape && 'width' || 'height']();

      /** @type {number} */
      this.maxwidth = this.screen.device[this.landscape && 'height' || 'width'];
      /** @type {number} */
      this.maxheight = this.screen.device[this.landscape && 'width' || 'height'];
    },

    /**
     * @method
     */
    open: function() {
      this.set();

      var that = this
        , device = this.d
        , target = null
        , scale = null
        , landscape = this.landscape
        , width = this.width
        , height = this.height
        // 스크린 영역의 모션 시작 위치 및 크기
        , offset = device.$rswp.offset()
        , $parent = device.$rswp.parent();

      device.m.$.contents.addClass('backward effect');
      //device.m.$.body.addClass('backward');
      device.overlay.show('fullscreen');

      if (!device._recording) {
        device.screen.pause();
      }

      this.$el = $('<div id="fullscreen" class="active"></div>').css({
        top: offset.top,
        left: offset.left,
        width: width,
        height: height
      }).mousedown(function(e) {
        target = e.target;
      }).mouseup(function(e) {
        if (e.target !== this || e.target !== target) return;

        // 로테이션이 어긋난 상황
        var changed = landscape != that.landscape;

        // 스케일 상태에서 옵셋 값을 병신같이 반환해서 교정
        offset = $parent.offset();
        scale = device.m.$.device.transform();
        scale = width / scale / device.$rswp.width();

        var _width = width;
        width = (changed && height || width);
        height = (changed && _width || height);

        that.resize();

        if (!device._recording) {
          device.screen.pause();
        }

        var bScale = device.m.$.contents.transform()
          , diffHeight = that.docHeight - that.docHeight * bScale
          , realTop = offset.top - diffHeight / 2
          , diffWidth = that.winWidth - that.winWidth * bScale
          , realLeft = offset.left - diffWidth / 2;

        offset.top = realTop / bScale;
        offset.left = realLeft / bScale;

        //FIXME 로테이션이 어긋난 상황에서 아구 안맞음
        //console.log(changed, that.landscape, scale, width, height);

        if (changed) {
          var abs = Math.abs((width - height) / 2);
          if (that.landscape) {
            offset.top += abs;
            offset.left -= abs + 96;
          } else {
            offset.top -= abs;
            offset.left += abs + 96;
          }
        }

        // 에니가 안되는 경우 발생
        setTimeout(function() {
          that.$el.css({
            width: width,
            height: height,
            paddingTop: 0,
            top: offset.top,
            left: offset.left
          });

          device.$rswp.transform(scale, rotate(device._rotate));
          device.m.$.contents.removeClass('backward effect');
          //device.m.$.body.removeClass('backward');
          device.overlay.hide('fullscreen');

          device.t && device.t.change();
          device.rotate();
        }, 1);

        setTimeout(function() {
          $parent.append(device.$rswp);
          that.$el.remove();
          device.update();
        }, 400);

        if (!device._recording) {
          device.screen.resume();
          device.activate(true);
        }

        device.screen.hooked = that.active = false;
        that.onclose();
      }).addClass('deg' + this.d._rotate);

      this.m.$.doc.find('body').append(this.$el.append(device.$rswp));
      device.t && device.t.change('fullscreen');

      this.rescale();
    },

    /**
     * @method
     */
    rescale: function() {
      /**
       * @type {number}
       * @private
       */
      this._scale = this.winHeight / this.height;

      if (this.winHeight < this.height * this._scale) {
        this._scale = this.winHeight / this.height;
      }

      if (this.winWidth < this.width * this._scale) {
        this._scale = this.winWidth / this.width;
      }

      // 컨트롤 영역의 모션 시작 위치 및 크기
      this.d.$rswp.css({
        marginLeft: (this.landscape && this.height || this.width) / -2,
        marginTop: (this.landscape && this.width || this.height) / -2,
        height: this.landscape && this.width || this.height,
        width: this.landscape && this.height || this.width
      }).transform(1, rotate(this.d._rotate));

      setTimeout(function() {
        // 스크린 영역 모션 될 포지션
        this.$el.addClass('ani').css({
          width: this.winWidth,
          height: this.winHeight + this.offsetTop,
          paddingTop: this.offsetTop,
          top: 0,
          left: 0
        });

        // 스케일 모션(중복 코드 아님)
        this.d.$rswp.transform(this._scale, rotate(this.d._rotate));
      }.bind(this), 1);

      setTimeout(function() {
        // for rescaling
        this.$el.removeClass('ani');

        this.width *= this._scale;
        this.height *= this._scale;

        this.d.$rswp.css({
          marginLeft: (this.landscape && this.height || this.width) / -2,
          marginTop: (this.landscape && this.width || this.height) / -2,
          height: this.landscape && this.width || this.height,
          width: this.landscape && this.height || this.width
        }).transform(1, rotate(this.d._rotate));

        this.d.update();
        this.$el.addClass('ani');
      }.bind(this), 400);

      if (!this.d._recording) {
        this.screen.resume();
        this.d.activate(true);
      }

      this.screen.hooked = this.active = true;
      this.onopen();
    },

    /**
     * @method
     */
    resize: function() {
      /** @type {number} */
      this.winWidth = this.m.$.win.width();
      /** @type {number} */
      this.winHeight = this.m.$.win.height() - this.offsetTop;
      /** @type {number} */
      this.docWidth = this.m.$.doc.width();
      /** @type {number} */
      this.docHeight = this.m.$.doc.height() - this.offsetTop;
    },

    /**
     * @method
     */
    close: function() {
      this.$el.mousedown().mouseup();
    }
  };


  /**
   * @param {number} degree
   * @return {number} css rotate
   */
  function rotate(deg) {
    return {
      '0': 0,
      '90': 90,
      '180': 180,
      '270': -90
    }[deg];
  }


  /*
   * Exporting modules
   */

  Device.FullScreen = FullScreen;

})(this);
comments powered by Disqus