All Downloads are FREE. Search and download functionalities are using the official Maven repository.

META-INF.resources.primefaces.imagecropper.0-jcrop.js Maven / Gradle / Ivy

Go to download

PrimeFaces is one of the most popular UI libraries in Java EE Ecosystem and widely used by software companies, world renowned brands, banks, financial institutions, insurance companies, universities and more.

There is a newer version: 14.0.0-RC3
Show newest version
/*! Jcrop.js v2.0.4 - build: 20151117
 *  @copyright 2008-2015 Tapmodo Interactive LLC
 *  @license Free software under MIT License
 *  @website http://jcrop.org/
 **/
(function($){
  'use strict';

  // Jcrop constructor
  var Jcrop = function(element,opt){
    var _ua = navigator.userAgent.toLowerCase();

    this.opt = $.extend({},Jcrop.defaults,opt || {});

    this.container = $(element);

    this.opt.is_msie = /msie/.test(_ua);
    this.opt.is_ie_lt9 = /msie [1-8]\./.test(_ua);

    this.container.addClass(this.opt.css_container);

    this.ui = {};
    this.state = null;
    this.ui.multi = [];
    this.ui.selection = null;
    this.filter = {};

    this.init();
    this.setOptions(opt);
    this.applySizeConstraints();
    this.container.trigger('cropinit',this);
      
    // IE<9 doesn't work if mouse events are attached to window
    if (this.opt.is_ie_lt9)
      this.opt.dragEventTarget = document.body;
  };


  // Jcrop static functions
  $.extend(Jcrop,{
    component: { },
    filter: { },
    stage: { },
    registerComponent: function(name,component){
      Jcrop.component[name] = component;
    },
    registerFilter: function(name,filter){
      Jcrop.filter[name] = filter;
    },
    registerStageType: function(name,stage){
      Jcrop.stage[name] = stage;
    },
    // attach: function(element,opt){{{
    attach: function(element,opt){
      var obj = new $.Jcrop(element,opt);
      return obj;
    },
    // }}}
    // imgCopy: function(imgel){{{
    imgCopy: function(imgel){
      var img = new Image;
      img.src = imgel.src;
      return img;
    },
    // }}}
    // imageClone: function(imgel){{{
    imageClone: function(imgel){
      return $.Jcrop.supportsCanvas?
        Jcrop.canvasClone(imgel):
        Jcrop.imgCopy(imgel);
    },
    // }}}
    // canvasClone: function(imgel){{{
    canvasClone: function(imgel){
      var canvas = document.createElement('canvas'),
          ctx = canvas.getContext('2d');

      $(canvas).width(imgel.width).height(imgel.height),
      canvas.width = imgel.naturalWidth;
      canvas.height = imgel.naturalHeight;
      ctx.drawImage(imgel,0,0,imgel.naturalWidth,imgel.naturalHeight);
      return canvas;
    },
    // }}}
    // propagate: function(plist,config,obj){{{
    propagate: function(plist,config,obj){
      for(var i=0,l=plist.length;i ratio)
        return [ h * ratio, h ];
          else return [ w, w / ratio ];
    },
    // }}}
    // stageConstructor: function(el,options,callback){{{
    stageConstructor: function(el,options,callback){

      // Get a priority-ordered list of available stages
      var stages = [];
      $.each(Jcrop.stage,function(i,e){
        stages.push(e);
      });
      stages.sort(function(a,b){ return a.priority - b.priority; });

      // Find the first one that supports this element
      for(var i=0,l=stages.length;i').parent();

      obj.element.width(w).height(h);
      obj.imgsrc = el;

      if (typeof callback == 'function')
        callback.call(this,obj,options);
    });
  }
});
Jcrop.registerStageType('Image',ImageStage);


var CanvasStage = function(){
  this.angle = 0;
  this.scale = 1;
  this.scaleMin = 0.2;
  this.scaleMax = 1.25;
  this.offset = [0,0];
};

CanvasStage.prototype = new ImageStage();

$.extend(CanvasStage,{
  isSupported: function(el,o){
    if ($.Jcrop.supportsCanvas && (el.tagName == 'IMG')) return true;
  },
  priority: 60,
  create: function(el,options,callback){
    var $el = $(el);
    var opt = $.extend({},options);
    $.Jcrop.component.ImageLoader.attach(el,function(w,h){
      var obj = new CanvasStage;
      $el.hide();
      obj.createCanvas(el,w,h);
      $el.before(obj.element);
      obj.imgsrc = el;
      opt.imgsrc = el;

      if (typeof callback == 'function'){
        callback(obj,opt);
        obj.redraw();
      }
    });
  }
});

$.extend(CanvasStage.prototype,{
  init: function(core){
    this.core = core;
  },
  // setOffset: function(x,y) {{{
  setOffset: function(x,y) {
    this.offset = [x,y];
    return this;
  },
  // }}}
  // setAngle: function(v) {{{
  setAngle: function(v) {
    this.angle = v;
    return this;
  },
  // }}}
  // setScale: function(v) {{{
  setScale: function(v) {
    this.scale = this.boundScale(v);
    return this;
  },
  // }}}
  boundScale: function(v){
    if (vthis.scaleMax) v = this.scaleMax;
    return v;
  },
  createCanvas: function(img,w,h){
    this.width = w;
    this.height = h;
    this.canvas = document.createElement('canvas');
    this.canvas.width = w;
    this.canvas.height = h;
    this.$canvas = $(this.canvas).width('100%').height('100%');
    this.context = this.canvas.getContext('2d');
    this.fillstyle = "rgb(0,0,0)";
    this.element = this.$canvas.wrap('
').parent().width(w).height(h); }, triggerEvent: function(ev){ this.$canvas.trigger(ev); return this; }, // clear: function() {{{ clear: function() { this.context.fillStyle = this.fillstyle; this.context.fillRect(0, 0, this.canvas.width, this.canvas.height); return this; }, // }}} // redraw: function() {{{ redraw: function() { // Save the current context this.context.save(); this.clear(); // Translate to the center point of our image this.context.translate(parseInt(this.width * 0.5), parseInt(this.height * 0.5)); // Perform the rotation and scaling this.context.translate(this.offset[0]/this.core.opt.xscale,this.offset[1]/this.core.opt.yscale); this.context.rotate(this.angle * (Math.PI/180)); this.context.scale(this.scale,this.scale); // Translate back to the top left of our image this.context.translate(-parseInt(this.width * 0.5), -parseInt(this.height * 0.5)); // Finally we draw the image this.context.drawImage(this.imgsrc,0,0,this.width,this.height); // And restore the updated context this.context.restore(); this.$canvas.trigger('cropredraw'); return this; }, // }}} // setFillStyle: function(v) {{{ setFillStyle: function(v) { this.fillstyle = v; return this; } // }}} }); Jcrop.registerStageType('Canvas',CanvasStage); /** * BackoffFilter * move out-of-bounds selection into allowed position at same size */ var BackoffFilter = function(){ this.minw = 40; this.minh = 40; this.maxw = 0; this.maxh = 0; this.core = null; }; $.extend(BackoffFilter.prototype,{ tag: 'backoff', priority: 22, filter: function(b){ var r = this.bound; if (b.x < r.minx) { b.x = r.minx; b.x2 = b.w + b.x; } if (b.y < r.miny) { b.y = r.miny; b.y2 = b.h + b.y; } if (b.x2 > r.maxx) { b.x2 = r.maxx; b.x = b.x2 - b.w; } if (b.y2 > r.maxy) { b.y2 = r.maxy; b.y = b.y2 - b.h; } return b; }, refresh: function(sel){ this.elw = sel.core.container.width(); this.elh = sel.core.container.height(); this.bound = { minx: 0 + sel.edge.w, miny: 0 + sel.edge.n, maxx: this.elw + sel.edge.e, maxy: this.elh + sel.edge.s }; } }); Jcrop.registerFilter('backoff',BackoffFilter); /** * ConstrainFilter * a filter to constrain crop selection to bounding element */ var ConstrainFilter = function(){ this.core = null; }; $.extend(ConstrainFilter.prototype,{ tag: 'constrain', priority: 5, filter: function(b,ord){ if (ord == 'move') { if (b.x < this.minx) { b.x = this.minx; b.x2 = b.w + b.x; } if (b.y < this.miny) { b.y = this.miny; b.y2 = b.h + b.y; } if (b.x2 > this.maxx) { b.x2 = this.maxx; b.x = b.x2 - b.w; } if (b.y2 > this.maxy) { b.y2 = this.maxy; b.y = b.y2 - b.h; } } else { if (b.x < this.minx) { b.x = this.minx; } if (b.y < this.miny) { b.y = this.miny; } if (b.x2 > this.maxx) { b.x2 = this.maxx; } if (b.y2 > this.maxy) { b.y2 = this.maxy; } } b.w = b.x2 - b.x; b.h = b.y2 - b.y; return b; }, refresh: function(sel){ this.elw = sel.core.container.width(); this.elh = sel.core.container.height(); this.minx = 0 + sel.edge.w; this.miny = 0 + sel.edge.n; this.maxx = this.elw + sel.edge.e; this.maxy = this.elh + sel.edge.s; } }); Jcrop.registerFilter('constrain',ConstrainFilter); /** * ExtentFilter * a filter to implement minimum or maximum size */ var ExtentFilter = function(){ this.core = null; }; $.extend(ExtentFilter.prototype,{ tag: 'extent', priority: 12, offsetFromCorner: function(corner,box,b){ var w = box[0], h = box[1]; switch(corner){ case 'bl': return [ b.x2 - w, b.y, w, h ]; case 'tl': return [ b.x2 - w , b.y2 - h, w, h ]; case 'br': return [ b.x, b.y, w, h ]; case 'tr': return [ b.x, b.y2 - h, w, h ]; } }, getQuadrant: function(s){ var relx = s.opposite[0]-s.offsetx var rely = s.opposite[1]-s.offsety; if ((relx < 0) && (rely < 0)) return 'br'; else if ((relx >= 0) && (rely >= 0)) return 'tl'; else if ((relx < 0) && (rely >= 0)) return 'tr'; return 'bl'; }, filter: function(b,ord,sel){ if (ord == 'move') return b; var w = b.w, h = b.h, st = sel.state, r = this.limits; var quad = st? this.getQuadrant(st): 'br'; if (r.minw && (w < r.minw)) w = r.minw; if (r.minh && (h < r.minh)) h = r.minh; if (r.maxw && (w > r.maxw)) w = r.maxw; if (r.maxh && (h > r.maxh)) h = r.maxh; if ((w == b.w) && (h == b.h)) return b; return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,[w,h],b)); }, refresh: function(sel){ this.elw = sel.core.container.width(); this.elh = sel.core.container.height(); this.limits = { minw: sel.minSize[0], minh: sel.minSize[1], maxw: sel.maxSize[0], maxh: sel.maxSize[1] }; } }); Jcrop.registerFilter('extent',ExtentFilter); /** * GridFilter * a rudimentary grid effect */ var GridFilter = function(){ this.stepx = 1; this.stepy = 1; this.core = null; }; $.extend(GridFilter.prototype,{ tag: 'grid', priority: 19, filter: function(b){ var n = { x: Math.round(b.x / this.stepx) * this.stepx, y: Math.round(b.y / this.stepy) * this.stepy, x2: Math.round(b.x2 / this.stepx) * this.stepx, y2: Math.round(b.y2 / this.stepy) * this.stepy }; n.w = n.x2 - n.x; n.h = n.y2 - n.y; return n; } }); Jcrop.registerFilter('grid',GridFilter); /** * RatioFilter * implements aspectRatio locking */ var RatioFilter = function(){ this.ratio = 0; this.core = null; }; $.extend(RatioFilter.prototype,{ tag: 'ratio', priority: 15, offsetFromCorner: function(corner,box,b){ var w = box[0], h = box[1]; switch(corner){ case 'bl': return [ b.x2 - w, b.y, w, h ]; case 'tl': return [ b.x2 - w , b.y2 - h, w, h ]; case 'br': return [ b.x, b.y, w, h ]; case 'tr': return [ b.x, b.y2 - h, w, h ]; } }, getBoundRatio: function(b,quad){ var box = Jcrop.getLargestBox(this.ratio,b.w,b.h); return Jcrop.wrapFromXywh(this.offsetFromCorner(quad,box,b)); }, getQuadrant: function(s){ var relx = s.opposite[0]-s.offsetx var rely = s.opposite[1]-s.offsety; if ((relx < 0) && (rely < 0)) return 'br'; else if ((relx >= 0) && (rely >= 0)) return 'tl'; else if ((relx < 0) && (rely >= 0)) return 'tr'; return 'bl'; }, filter: function(b,ord,sel){ if (!this.ratio) return b; var rt = b.w / b.h; var st = sel.state; var quad = st? this.getQuadrant(st): 'br'; ord = ord || 'se'; if (ord == 'move') return b; switch(ord) { case 'n': b.x2 = this.elw; b.w = b.x2 - b.x; quad = 'tr'; break; case 's': b.x2 = this.elw; b.w = b.x2 - b.x; quad = 'br'; break; case 'e': b.y2 = this.elh; b.h = b.y2 - b.y; quad = 'br'; break; case 'w': b.y2 = this.elh; b.h = b.y2 - b.y; quad = 'bl'; break; } return this.getBoundRatio(b,quad); }, refresh: function(sel){ this.ratio = sel.aspectRatio; this.elw = sel.core.container.width(); this.elh = sel.core.container.height(); } }); Jcrop.registerFilter('ratio',RatioFilter); /** * RoundFilter * rounds coordinate values to integers */ var RoundFilter = function(){ this.core = null; }; $.extend(RoundFilter.prototype,{ tag: 'round', priority: 90, filter: function(b){ var n = { x: Math.round(b.x), y: Math.round(b.y), x2: Math.round(b.x2), y2: Math.round(b.y2) }; n.w = n.x2 - n.x; n.h = n.y2 - n.y; return n; } }); Jcrop.registerFilter('round',RoundFilter); /** * ShadeFilter * A filter that implements div-based shading on any element * * The shading you see is actually four semi-opaque divs * positioned inside the container, around the selection */ var ShadeFilter = function(opacity,color){ this.color = color || 'black'; this.opacity = opacity || 0.5; this.core = null; this.shades = {}; }; $.extend(ShadeFilter.prototype,{ tag: 'shader', fade: true, fadeEasing: 'swing', fadeSpeed: 320, priority: 95, init: function(){ var t = this; if (!t.attached) { t.visible = false; t.container = $('
').addClass(t.core.opt.css_shades) .prependTo(this.core.container).hide(); t.elh = this.core.container.height(); t.elw = this.core.container.width(); t.shades = { top: t.createShade(), right: t.createShade(), left: t.createShade(), bottom: t.createShade() }; t.attached = true; } }, destroy: function(){ this.container.remove(); }, setColor: function(color,instant){ var t = this; if (color == t.color) return t; this.color = color; var colorfade = Jcrop.supportsColorFade(); $.each(t.shades,function(u,i){ if (!t.fade || instant || !colorfade) i.css('backgroundColor',color); else i.animate({backgroundColor:color},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing}); }); return t; }, setOpacity: function(opacity,instant){ var t = this; if (opacity == t.opacity) return t; t.opacity = opacity; $.each(t.shades,function(u,i){ if (!t.fade || instant) i.css({opacity:opacity}); else i.animate({opacity:opacity},{queue:false,duration:t.fadeSpeed,easing:t.fadeEasing}); }); return t; }, createShade: function(){ return $('
').css({ position: 'absolute', backgroundColor: this.color, opacity: this.opacity }).appendTo(this.container); }, refresh: function(sel){ var m = this.core, s = this.shades; this.setColor(sel.bgColor?sel.bgColor:this.core.opt.bgColor); this.setOpacity(sel.bgOpacity?sel.bgOpacity:this.core.opt.bgOpacity); this.elh = m.container.height(); this.elw = m.container.width(); s.right.css('height',this.elh+'px'); s.left.css('height',this.elh+'px'); }, filter: function(b,ord,sel){ if (!sel.active) return b; var t = this, s = t.shades; s.top.css({ left: Math.round(b.x)+'px', width: Math.round(b.w)+'px', height: Math.round(b.y)+'px' }); s.bottom.css({ top: Math.round(b.y2)+'px', left: Math.round(b.x)+'px', width: Math.round(b.w)+'px', height: (t.elh-Math.round(b.y2))+'px' }); s.right.css({ left: Math.round(b.x2)+'px', width: (t.elw-Math.round(b.x2))+'px' }); s.left.css({ width: Math.round(b.x)+'px' }); if (!t.visible) { t.container.show(); t.visible = true; } return b; } }); Jcrop.registerFilter('shader',ShadeFilter); /** * CanvasAnimator * manages smooth cropping animation * * This object is called internally to manage animation. * An in-memory div is animated and a progress callback * is used to update the selection coordinates of the * visible selection in realtime. */ var CanvasAnimator = function(stage){ this.stage = stage; this.core = stage.core; this.cloneStagePosition(); }; CanvasAnimator.prototype = { cloneStagePosition: function(){ var s = this.stage; this.angle = s.angle; this.scale = s.scale; this.offset = s.offset; }, getElement: function(){ var s = this.stage; return $('
') .css({ position: 'absolute', top: s.offset[0]+'px', left: s.offset[1]+'px', width: s.angle+'px', height: s.scale+'px' }); }, animate: function(cb){ var t = this; this.scale = this.stage.boundScale(this.scale); t.stage.triggerEvent('croprotstart'); t.getElement().animate({ top: t.offset[0]+'px', left: t.offset[1]+'px', width: t.angle+'px', height: t.scale+'px' },{ easing: t.core.opt.animEasing, duration: t.core.opt.animDuration, complete: function(){ t.stage.triggerEvent('croprotend'); (typeof cb == 'function') && cb.call(this); }, progress: function(anim){ var props = {}, i, tw = anim.tweens; for(i=0;i') .css({ position: 'absolute', top: b.y+'px', left: b.x+'px', width: b.w+'px', height: b.h+'px' }); }, animate: function(x,y,w,h,cb){ var t = this; t.selection.allowResize(false); t.getElement().animate({ top: y+'px', left: x+'px', width: w+'px', height: h+'px' },{ easing: t.core.opt.animEasing, duration: t.core.opt.animDuration, complete: function(){ t.selection.allowResize(true); cb && cb.call(this); }, progress: function(anim){ var props = {}, i, tw = anim.tweens; for(i=0;i 0 || window.DocumentTouch && document instanceof DocumentTouch) return true; }, // }}} prototype: { // init: function(){{{ init: function(){ var t = this, p = $.Jcrop.component.DragState.prototype; // A bit of an ugly hack to make sure we modify prototype // only once, store a key on the prototype if (!p.touch) { t.initEvents(); t.shimDragState(); t.shimStageDrag(); p.touch = true; } }, // }}} // shimDragState: function(){{{ shimDragState: function(){ var t = this; $.Jcrop.component.DragState.prototype.initEvents = function(e){ // Attach subsequent drag event handlers based on initial // event type - avoids collecting "pseudo-mouse" events // generated by some mobile browsers in some circumstances if (e.type.substr(0,5) == 'touch') { $(this.eventTarget) .on('touchmove.jcrop.jcrop-touch',t.dragWrap(this.createDragHandler())) .on('touchend.jcrop.jcrop-touch',this.createStopHandler()); } // For other events, use the mouse handlers that // the default DragState.initEvents() method sets... else { $(this.eventTarget) .on('mousemove.jcrop',this.createDragHandler()) .on('mouseup.jcrop',this.createStopHandler()); } }; }, // }}} // shimStageDrag: function(){{{ shimStageDrag: function(){ this.core.container .addClass('jcrop-touch') .on('touchstart.jcrop.jcrop-stage',this.dragWrap(this.core.ui.manager.startDragHandler())); }, // }}} // dragWrap: function(cb){{{ dragWrap: function(cb){ return function(e){ e.preventDefault(); e.stopPropagation(); if (e.type.substr(0,5) == 'touch') { e.pageX = e.originalEvent.changedTouches[0].pageX; e.pageY = e.originalEvent.changedTouches[0].pageY; return cb(e); } return false; }; }, // }}} // initEvents: function(){{{ initEvents: function(){ var t = this, c = t.core; c.container.on( 'touchstart.jcrop.jcrop-touch', '.'+c.opt.css_drag, t.dragWrap(c.startDrag()) ); } // }}} } }); Jcrop.registerComponent('Touch',JcropTouch); /** * KeyWatcher * provides keyboard support */ // var KeyWatcher = function(core){{{ var KeyWatcher = function(core){ this.core = core; this.init(); }; // }}} $.extend(KeyWatcher,{ // defaults: {{{ defaults: { eventName: 'keydown.jcrop', passthru: [ 9 ], debug: false }, // }}} prototype: { // init: function(){{{ init: function(){ $.extend(this,KeyWatcher.defaults); this.enable(); }, // }}} // disable: function(){{{ disable: function(){ this.core.container.off(this.eventName); }, // }}} // enable: function(){{{ enable: function(){ var t = this, m = t.core; m.container.on(t.eventName,function(e){ var nudge = e.shiftKey? 16: 2; if ($.inArray(e.keyCode,t.passthru) >= 0) return true; switch(e.keyCode){ case 37: m.nudge(-nudge,0); break; case 38: m.nudge(0,-nudge); break; case 39: m.nudge(nudge,0); break; case 40: m.nudge(0,nudge); break; case 46: case 8: m.requestDelete(); return false; break; default: if (t.debug) console.log('keycode: ' + e.keyCode); break; } if (!e.metaKey && !e.ctrlKey) e.preventDefault(); }); } // }}} } }); Jcrop.registerComponent('Keyboard',KeyWatcher); /** * Selection * Built-in selection object */ var Selection = function(){}; $.extend(Selection,{ // defaults: {{{ defaults: { minSize: [ 8, 8 ], maxSize: [ 0, 0 ], aspectRatio: 0, edge: { n: 0, s: 0, e: 0, w: 0 }, bgColor: null, bgOpacity: null, last: null, state: null, active: true, linked: true, canDelete: true, canDrag: true, canResize: true, canSelect: true }, // }}} prototype: { // init: function(core){{{ init: function(core){ this.core = core; this.startup(); this.linked = this.core.opt.linked; this.attach(); this.setOptions(this.core.opt); core.container.trigger('cropcreate',[this]); }, // }}} // attach: function(){{{ attach: function(){ // For extending init() sequence }, // }}} // startup: function(){{{ startup: function(){ var t = this, o = t.core.opt; $.extend(t,Selection.defaults); t.filter = t.core.getDefaultFilters(); t.element = $('
').addClass(o.css_selection).data({ selection: t }); t.frame = $('




© 2015 - 2024 Weber Informatics LLC | Privacy Policy