View file externals/jQuery/jquery.drag-n-crop.js

File size: 8.73Kb
/*!
 * jquery.drag-n-crop
 * https://github.com/lukaszfiszer/drag-n-crop
 *
 * Copyright (c) 2013 Lukasz Fiszer
 * Licensed under the MIT license.
 */

;(function ( $, window, document, undefined ) {
    $.widget( "lukaszfiszer.dragncrop" , {

        classes: {
          // Basic classes
          container: 'dragncrop',
          containerActive: 'dragncrop-dragging',
          containment: 'dragncrop-containment',
          horizontal: 'dragncrop-horizontal',
          vertical: 'dragncrop-vertical',

          // Options' classes
          overflow: 'dragncrop-overflow',
          overlay: 'dragncrop-overlay',
          instruction: 'dragncrop-instruction',
          instructionHide: 'dragncrop-instruction-autohide',
          instructionText: 'dragncrop-instruction-text'
        },

        options: {
          // Initial position
          position: {},
          centered: false,

          // Simple overflow:
          overflow: false,

          // Overflaid overflow
          overlay: false,

          // Drag instruction
          instruction: false,
          instructionText: 'Drag to crop',
          instructionHideOnHover: true,
        },

        move: function ( position ) {

          var left, top, x, y;

          if( !position ){
            throw new Error('position object must be provided');
          }

          if (position.offset === undefined && position.dimension === undefined ) {
            throw new Error('position object must contain "left" or "top" props');
          }

          if( this.axis === 'x' && position.offset ){
            left = -position.offset[0] * this.offsetX;
            this.element.css('left', left);
            this.element.css('top', 0);
          } else
          if( this.axis === 'x' && position.dimension ){
            left = -position.dimension[0] * this.width;
            this.element.css('left', left);
            this.element.css('top', 0);
          } else

          if( this.axis === 'y' && position.offset ){
            top = -position.offset[1] * this.offsetY;
            this.element.css('left', 0);
            this.element.css('top', top);
          } else
          if( this.axis === 'y' && position.dimension ){
            top = -position.dimension[1] * this.height;
            this.element.css('left', 0);
            this.element.css('top', top);
          }

          this._setPosition( { left: left, top: top });

        },

        _create: function () {

          this.container = $(this.element.parent());
          this.container.addClass(this.classes.container);

          if( this.options.overflow || this.options.overlay){
            $(this.container).addClass(this.classes.overflow);
          }

          var dfd = this.element.imagesLoaded();
          var self = this;

          dfd.done(function(){
            if(self._setAxis.call(self)){
              self._getDimensions.call(self);
              self._makeDraggable.call(self);
              if (self.options.loaded) {
                self.options.loaded();
              }
            }
          } );

        },

        _destroy: function() {
          this.draggable && this.draggable.draggable('destroy');
          this.container.find('.' + this.classes.containment + ',' +
                              '.' + this.classes.overlay  + ',' +
                              '.' + this.classes.instruction).remove();
          this.element.removeClass(this.classes.horizontal)
                      .removeClass(this.classes.vertical);
        },

        getPosition: function() {
          return {
            offset : [
              ( -this.position.left / this.offsetX) || 0,
              ( -this.position.top / this.offsetY) || 0
            ],
            dimension : [
              ( -this.position.left / this.width) || 0,
              ( -this.position.top / this.height) || 0
            ]
          };

        },

        _getDimensions: function() {

          this.width = this.element.width();
          this.height = this.element.height();

          this.containerWidth = this.container.width();
          this.containerHeight = this.container.height();

          this.offsetX = this.width - this.containerWidth;
          this.offsetY = this.height - this.containerHeight;

        },

        _setAxis: function() {

          this.photoRatio = this.element.width() / this.element.height();
          this.containerRatio = this.container.width() / this.container.height();

          if (this.photoRatio > this.containerRatio) {

            this.axis = 'x';
            $(this.element).addClass(this.classes.horizontal);
            return true;

          } else if (this.photoRatio < this.containerRatio) {

            this.axis = 'y';
            $(this.element).addClass(this.classes.vertical);
            return true;

          }else{

            return false;

          }

        },

        _setPosition: function( obj ) {
          this.position = obj;
        },

        _makeDraggable : function () {

          var axis         = this.axis;
          var position     = this.options.position;
          var containement = this._insertContainment();

          var draggable = this.draggable = this.element.draggable({
            axis: axis,
            containment: containement
          });

          this._on({
            dragstart: function (event, ui) {
              this._dragStart( event , ui );
              this.container.addClass( this.classes.containerActive );
            },
            drag: function( event, ui ){
              this._dragging( event , ui );
              if (this.options.overlay) {
                this._adaptOverlay( ui );
              }
            },
            dragstop: function( event, ui ){
              this._dragStop( event , ui );
              this.container.removeClass( this.classes.containerActive );
            }
          });

          if(this.options.overlay){
            this._insertOverlay();
          }

          if(this.options.instruction){
            this._insertInstruction();
          }

          if(this.options.centered){
            position = { offset : [0.5, 0.5] };
          }

          if( position && ( position.offset || position.coordinates)) {
            this.move(position);
          }else{
            this._setPosition({ left: 0, top: 0 });
          }

        },

        _dragStart: function( event, ui ) {
          this._setPosition(ui.position);
          this._trigger('start', event, this.getPosition() );
        },

        _dragging: function( event, ui ) {
          this._setPosition(ui.position);
          this._trigger('drag', event, this.getPosition() );
        },

        _dragStop: function( event, ui ) {
          this._setPosition(ui.position);
          this._trigger('stop', event, this.getPosition() );
        },


        _insertOverlay: function(){

          var overlay = $('<div>').addClass(this.classes.overlay);
          this.overlay = overlay.insertBefore(this.element);
          return this.overlay;

        },

        _adaptOverlay: function( ui ) {

          if ( this.axis === 'x' ) {

            this.overlay.css('left', ui.position.left)
                        .css('border-left-width', -ui.position.left)
                        .css('right', -ui.position.left - this.offsetX)
                        .css('border-right-width', ui.position.left + this.offsetX);

          } else if ( this.axis === 'y' ){

            this.overlay.css('top', ui.position.top)
                        .css('border-top-width', -ui.position.top)
                        .css('bottom', -ui.position.top - this.offsetY )
                        .css('border-bottom-width', ui.position.top + this.offsetY );
          }

        },

        _insertContainment: function() {

          var top    = - this.offsetY;
          var bottom = - this.offsetY;
          var left   = - this.offsetX;
          var right  = - this.offsetX;

          var containment = $('<div/>').addClass(this.classes.containment)
                            .css('top',top).css('bottom', bottom)
                            .css('left',left).css('right',right)
                            .css('position','absolute');

          this.containment = containment.insertBefore(this.element);
          return this.containment;

        },

        _insertInstruction: function() {
          this.instruction = $('<div>').addClass(this.classes.instruction);
          if(this.options.instructionHideOnHover){
            this.instruction.addClass(this.classes.instructionHide);
          }
          this.instruction.append(
            $('<span></span>').text(this.options.instructionText)
                              .addClass(this.classes.instructionText)
          );
          this.instruction.insertAfter(this.element);
          return this.instruction;
        },

    });

})( jQuery, window, document );