jcrop3
Version:
The Javascript cropping widget
177 lines (151 loc) • 4.35 kB
JavaScript
import extend from '../util/extend';
import Widget from '../widget';
import Shade from '../shade';
import Dragger from '../dragger';
import ConfObj from '../confobj';
import Sticker from '../sticker';
class Stage extends ConfObj {
constructor (el,options) {
super(el,options);
this.scalex = 1;
this.scaley = 1;
this.crops = new Set();
this.active = null;
this.enabled = true;
this.init();
}
init () {
this.initStageDrag();
Shade.Manager.attach(this);
}
initOptions () {
this._optconf['multi'] = v => { if (!v) this.limitWidgets(); };
}
setEnabled (v=true) {
const clname = this.options.disabledClass || 'jcrop-disable';
this[v?'removeClass':'addClass'](clname);
this.enabled = !!v;
return this;
}
focus () {
if (!this.enabled) return false;
if (this.active) this.active.el.focus();
else this.el.focus();
return this;
}
limitWidgets (n=1) {
if (!this.crops || (n<1)) return false;
const crops = Array.from(this.crops);
while (crops.length > n) this.removeWidget(crops.shift());
return this;
}
canCreate () {
const n = this.crops.size;
const o = this.options;
if (!this.enabled) return false;
if ((o.multiMax!==null) && (n >= o.multiMax)) return false;
if (!o.multi && (n >= o.multiMin)) return false;
return true;
}
canRemove () {
const n = this.crops.size;
const o = this.options;
if (!this.enabled) return false;
if (this.active && !this.active.options.canRemove) return false;
if (!o.canRemove || (n <= o.multiMin)) return false;
return true;
}
initStageDrag () {
var crop, pos, w, h, stick;
Dragger(this.el,
(x,y,e) => {
if (!this.canCreate()) return false;
crop = (this.options.widgetConstructor || Widget).create(this.options);
pos = crop.pos;
pos.x = e.pageX - this.el.offsetParent.offsetLeft - this.el.offsetLeft;
pos.y = e.pageY - this.el.offsetParent.offsetTop - this.el.offsetTop;
w = this.el.offsetWidth;
h = this.el.offsetHeight;
this.addWidget(crop);
stick = Sticker.create(pos,w,h,'se');
if (this.options.aspectRatio) stick.aspect = this.options.aspectRatio;
crop.render(pos);
this.focus();
return true;
},
(x,y) => {
crop.render(stick.move(x,y));
},
() => {
crop.emit('crop.change');
}
);
}
reorderWidgets () {
var z = 10;
this.crops.forEach(crop => {
crop.el.style.zIndex = z++;
if (this.active === crop) crop.addClass('active');
else crop.removeClass('active');
});
this.refresh();
}
activate (widget) {
if (!this.enabled) return this;
widget = widget || Array.from(this.crops).pop();
if (widget) {
if (this.active === widget) return;
this.active = widget;
this.crops.delete(widget);
this.crops.add(widget);
this.reorderWidgets();
this.active.el.focus();
this.options.shade && this.shades.enable();
widget.emit('crop.activate');
} else {
this.shades.disable();
}
return this;
}
addWidget (widget) {
widget.attachToStage(this);
widget.appendTo(this.el);
this.activate(widget);
return this;
}
newWidget (rect,options={}) {
options = extend({},this.options,options);
const crop = (this.options.widgetConstructor || Widget).create(options);
crop.render(rect.unscale(this.scalex,this.scaley));
this.addWidget(crop);
crop.el.focus();
return crop;
}
removeWidget (widget) {
if (!this.canRemove()) return false;
widget.emit('crop.remove');
widget.el.remove();
this.crops.delete(widget);
this.activate();
}
refresh () {
this.crops.forEach(crop => { crop.render(); });
this.options.shade && this.active &&
this.shades.adjust(this.active.pos);
}
updateShades () {
if (!this.shades) return;
if (this.options.shade) this.shades.enable();
else this.shades.disable();
this.options.shade && this.active &&
this.shades.adjust(this.active.pos);
return this;
}
setOptions (options={}) {
super.setOptions(options);
if (this.crops) Array.from(this.crops).forEach(i => i.setOptions(options));
}
destroy () {
}
}
export default Stage;