(function($K)
|
|
{
|
|
$K.add('module', 'upload', {
|
|
init: function(app, context)
|
|
{
|
|
this.app = app;
|
|
this.utils = app.utils;
|
|
this.animate = app.animate;
|
|
this.response = app.response;
|
|
this.progress = app.progress;
|
|
|
|
// defaults
|
|
var defaults = {
|
|
size: 120, // pixels
|
|
url: false,
|
|
urlRemove: false,
|
|
param: false,
|
|
type: false, // image, file
|
|
multiple: false,
|
|
placeholder: 'Drop files here or click to upload',
|
|
progress: false,
|
|
target: false,
|
|
append: false
|
|
};
|
|
|
|
// context
|
|
this.context = context;
|
|
this.params = context.getParams(defaults);
|
|
this.$element = context.getElement();
|
|
this.$target = context.getTarget();
|
|
|
|
// local
|
|
this.statusMap = ['hover', 'error', 'success', 'drop'];
|
|
|
|
},
|
|
// public
|
|
start: function()
|
|
{
|
|
this._buildBox();
|
|
this._buildInput();
|
|
this._buildCount();
|
|
this._buildType();
|
|
this._buildPlaceholder();
|
|
this._buildSize();
|
|
this._buildMultiple();
|
|
this._buildItems();
|
|
this._buildEvents();
|
|
|
|
},
|
|
stop: function()
|
|
{
|
|
this.$box.remove();
|
|
this.$element.off('.kube.upload');
|
|
},
|
|
|
|
// private
|
|
_buildBox: function()
|
|
{
|
|
if (this.params.type === 'image')
|
|
{
|
|
this.$box = this.$element.find('.upload-item');
|
|
}
|
|
else
|
|
{
|
|
this.$box = this.$element;
|
|
}
|
|
},
|
|
_buildInput: function()
|
|
{
|
|
this.$input = $K.dom('<input>');
|
|
this.$input.attr('type', 'file');
|
|
this.$input.attr('name', this._getParamName());
|
|
this.$input.hide();
|
|
|
|
this.$element.before(this.$input);
|
|
},
|
|
_buildCount: function()
|
|
{
|
|
this.$inputCount = $K.dom('<input>');
|
|
this.$inputCount.attr('type', 'hidden');
|
|
this.$inputCount.attr('name', this._getParamName() + '-count');
|
|
this.$inputCount.val(0);
|
|
|
|
this.$element.before(this.$inputCount);
|
|
},
|
|
_buildType: function()
|
|
{
|
|
this.isBox = this.$element.hasClass('upload');
|
|
},
|
|
_buildPlaceholder: function()
|
|
{
|
|
if (this.isBox)
|
|
{
|
|
var $placeholder = $K.dom('<span>');
|
|
$placeholder.addClass('upload-placeholder');
|
|
$placeholder.html(this.params.placeholder);
|
|
|
|
this.$element.append($placeholder);
|
|
}
|
|
},
|
|
_buildSize: function()
|
|
{
|
|
if (this.isBox)
|
|
{
|
|
this.$box.css({
|
|
height: this.params.size + 'px'
|
|
});
|
|
}
|
|
else if (this.params.type === 'image')
|
|
{
|
|
this.$box.css({
|
|
width: this.params.size + 'px',
|
|
height: this.params.size + 'px'
|
|
});
|
|
}
|
|
},
|
|
_buildMultiple: function()
|
|
{
|
|
this.isMultiple = this.params.multiple;
|
|
if (this.isMultiple)
|
|
{
|
|
this.$input.attr('multiple', 'true');
|
|
}
|
|
},
|
|
_buildItems: function()
|
|
{
|
|
if (!this.params.type) return;
|
|
|
|
var isFile = (this.params.type === 'file');
|
|
var $target = (isFile) ? this.$target : this.$element;
|
|
var fn = (isFile) ? '_removeFile' : '_removeImage';
|
|
|
|
var $closes = $target.find('.close');
|
|
$closes.on('click', this[fn].bind(this));
|
|
|
|
if (!isFile)
|
|
{
|
|
$closes.closest('.upload-item').addClass('is-uploaded');
|
|
}
|
|
|
|
this.$inputCount.val($closes.length);
|
|
},
|
|
_buildEvents: function()
|
|
{
|
|
this.$input.on('change.redactor.upload', this._change.bind(this));
|
|
this.$box.on('click.redactor.upload', this._click.bind(this));
|
|
this.$box.on('drop.redactor.upload', this._drop.bind(this));
|
|
this.$box.on('dragover.redactor.upload', this._dragover.bind(this));
|
|
this.$box.on('dragleave.redactor.upload', this._dragleave.bind(this));
|
|
},
|
|
|
|
|
|
// Events
|
|
_click: function(e)
|
|
{
|
|
e.preventDefault();
|
|
|
|
var $el = $K.dom(e.target);
|
|
if ($el.hasClass('close')) return;
|
|
|
|
this.$input.click();
|
|
},
|
|
_change: function(e)
|
|
{
|
|
this.app.broadcast('upload.start', this);
|
|
this._send(e, this.$input.get().files);
|
|
},
|
|
_drop: function(e)
|
|
{
|
|
e.preventDefault();
|
|
|
|
this._clearStatuses();
|
|
this._setStatus('drop');
|
|
|
|
this.app.broadcast('upload.start', this);
|
|
this._send(e);
|
|
},
|
|
_dragover: function(e)
|
|
{
|
|
e.preventDefault();
|
|
this._setStatus('hover');
|
|
|
|
return false;
|
|
},
|
|
_dragleave: function(e)
|
|
{
|
|
e.preventDefault();
|
|
this._removeStatus('hover');
|
|
|
|
return false;
|
|
},
|
|
|
|
// Count
|
|
_upCount: function()
|
|
{
|
|
var val = this.$inputCount.val();
|
|
val++;
|
|
|
|
this.$inputCount.val(val);
|
|
},
|
|
_downCount: function()
|
|
{
|
|
var val = this.$inputCount.val();
|
|
val--;
|
|
val = (val < 0) ? 0 : val;
|
|
|
|
this.$inputCount.val(val);
|
|
},
|
|
_clearCount: function()
|
|
{
|
|
this.$inputCount.val(0);
|
|
},
|
|
|
|
// Name
|
|
_getParamName: function()
|
|
{
|
|
return (this.params.param) ? this.params.param : 'file';
|
|
},
|
|
_getHiddenName: function()
|
|
{
|
|
var name = this._getParamName();
|
|
return (this.isMultiple) ? name + '-uploaded[]' : name + '-uploaded';
|
|
},
|
|
|
|
// Status
|
|
_clearStatuses: function()
|
|
{
|
|
this.$box.removeClass('is-upload-' + this.statusMap.join(' is-upload-'));
|
|
},
|
|
_setStatus: function(status)
|
|
{
|
|
this.$box.addClass('is-upload-' + status);
|
|
},
|
|
_removeStatus: function(status)
|
|
{
|
|
this.$box.removeClass('is-upload-' + status);
|
|
},
|
|
|
|
|
|
// Target
|
|
_clearTarget: function()
|
|
{
|
|
var $items = this.$target.find('.upload-item');
|
|
$items.each(function(node)
|
|
{
|
|
var $node = $K.dom(node);
|
|
this._removeFileRequest($node.attr('data-id'));
|
|
}.bind(this));
|
|
|
|
this._clearCount();
|
|
this.$target.html('');
|
|
},
|
|
_clearBox: function()
|
|
{
|
|
var $items = this.$target.find('.upload-item');
|
|
$items.each(function(node)
|
|
{
|
|
var $node = $K.dom(node);
|
|
this._removeFileRequest($node.attr('data-id'));
|
|
}.bind(this));
|
|
|
|
this._clearCount();
|
|
this.$target.html('');
|
|
},
|
|
|
|
|
|
// Remove
|
|
_removeFile: function(e)
|
|
{
|
|
e.preventDefault();
|
|
|
|
var $el = $K.dom(e.target);
|
|
var $item = $el.closest('.upload-item');
|
|
var id = $item.attr('data-id');
|
|
|
|
this.animate.run($item, 'fadeOut', function()
|
|
{
|
|
$item.remove();
|
|
this._downCount();
|
|
this._removeFileRequest(id);
|
|
|
|
// clear target
|
|
if (this.$target.find('.upload-item').length === 0)
|
|
{
|
|
this.$target.html('');
|
|
}
|
|
|
|
}.bind(this))
|
|
},
|
|
_removeImage: function(e)
|
|
{
|
|
e.preventDefault();
|
|
|
|
var $el = $K.dom(e.target);
|
|
var $item = $el.closest('.upload-item');
|
|
var id = $item.attr('data-id');
|
|
|
|
|
|
if (this.isMultiple)
|
|
{
|
|
this.animate.run($item, 'fadeOut', function()
|
|
{
|
|
$item.remove();
|
|
this._downCount();
|
|
this._removeFileRequest(id);
|
|
|
|
}.bind(this))
|
|
}
|
|
else
|
|
{
|
|
var $img = $item.find('img');
|
|
|
|
$el.hide();
|
|
this.animate.run($img, 'fadeOut', function()
|
|
{
|
|
this.$box.html('');
|
|
this.$box.removeClass('is-uploaded');
|
|
this._clearCount();
|
|
this._removeFileRequest(id);
|
|
|
|
}.bind(this))
|
|
}
|
|
},
|
|
_removeFileRequest: function(id)
|
|
{
|
|
if (this.params.urlRemove)
|
|
{
|
|
$K.ajax.post({
|
|
url: this.params.urlRemove,
|
|
data: { id: id }
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
// Send
|
|
_send: function(e, files)
|
|
{
|
|
e = e.originalEvent || e;
|
|
|
|
files = (files) ? files : e.dataTransfer.files;
|
|
|
|
var data = new FormData();
|
|
var name = this._getParamName();
|
|
|
|
data = this._buildData(name, files, data);
|
|
|
|
if (this.params.append)
|
|
{
|
|
data = this.utils.extendData(data, this.params.append);
|
|
}
|
|
|
|
this._sendData(data, files, e);
|
|
},
|
|
_sendData: function(data, files, e)
|
|
{
|
|
if (this.params.progress) this.progress.show();
|
|
|
|
$K.ajax.post({
|
|
url: this.params.url,
|
|
data: data,
|
|
before: function(xhr)
|
|
{
|
|
return this.app.broadcast('upload.beforeSend', this, xhr);
|
|
|
|
}.bind(this),
|
|
success: function(response)
|
|
{
|
|
this._complete(response, e);
|
|
}.bind(this)
|
|
});
|
|
},
|
|
_buildData: function(name, files, data)
|
|
{
|
|
for (var i = 0; i < files.length; i++)
|
|
{
|
|
data.append(name + '[]', files[i]);
|
|
}
|
|
|
|
return data;
|
|
},
|
|
_complete: function (response, e)
|
|
{
|
|
this._clearStatuses();
|
|
|
|
if (this.params.progress) this.progress.hide();
|
|
|
|
// error
|
|
var json = (Array.isArray(response)) ? response[0] : response;
|
|
|
|
if (typeof json.type !== 'undefined' && json.type === 'error')
|
|
{
|
|
this._setStatus('error');
|
|
this.response.parse(response);
|
|
this.app.broadcast('upload.error', this, response);
|
|
}
|
|
// complete
|
|
else
|
|
{
|
|
this._setStatus('success');
|
|
|
|
switch (this.params.type)
|
|
{
|
|
case 'image':
|
|
this._completeBoxImage(response);
|
|
break;
|
|
case 'file':
|
|
this._completeBoxFile(response);
|
|
break;
|
|
default:
|
|
this._completeBoxUpload(response);
|
|
}
|
|
|
|
this.app.broadcast('upload.complete', this, response);
|
|
setTimeout(this._clearStatuses.bind(this), 500);
|
|
}
|
|
},
|
|
_completeBoxUpload: function(response)
|
|
{
|
|
this.response.parse(response);
|
|
},
|
|
_completeBoxImage: function(response)
|
|
{
|
|
for (var key in response)
|
|
{
|
|
// img
|
|
var $img = $K.dom('<img>');
|
|
$img.attr('src', response[key].url);
|
|
|
|
// close
|
|
var $close = $K.dom('<span>');
|
|
$close.addClass('close');
|
|
$close.on('click', this._removeImage.bind(this));
|
|
|
|
// hidden
|
|
var $hidden = $K.dom('<input>');
|
|
$hidden.attr('type', 'hidden');
|
|
$hidden.attr('name', this._getHiddenName());
|
|
$hidden.val(response[key].id);
|
|
|
|
// item
|
|
var $item = $K.dom('<div>');
|
|
$item.addClass('upload-item is-uploaded');
|
|
$item.attr('data-id', response[key].id);
|
|
|
|
if (this.isMultiple)
|
|
{
|
|
// append
|
|
$item.append($close);
|
|
$item.append($img);
|
|
$item.append($hidden);
|
|
|
|
this.$box.last().before($item);
|
|
}
|
|
// single
|
|
else
|
|
{
|
|
var $lastImg = this.$box.find('img');
|
|
if ($lastImg.length !== 0)
|
|
{
|
|
this._removeFileRequest(this.$box.attr('data-id'));
|
|
}
|
|
|
|
this.$box.html('');
|
|
this.$box.attr('data-id', response[key].id);
|
|
this.$box.append($close);
|
|
this.$box.append($img);
|
|
this.$box.append($hidden);
|
|
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
_completeBoxFile: function(response)
|
|
{
|
|
if (!this.isMultiple) this._clearTarget();
|
|
|
|
for (var key in response)
|
|
{
|
|
// item
|
|
var $item = $K.dom('<div>');
|
|
$item.addClass('upload-item');
|
|
$item.attr('data-id', response[key].id);
|
|
|
|
// file
|
|
var $file = $K.dom('<span>');
|
|
$file.html(response[key].name);
|
|
|
|
// close
|
|
var $close = $K.dom('<span>');
|
|
$close.addClass('close');
|
|
$close.on('click', this._removeFile.bind(this));
|
|
|
|
// hidden
|
|
var $hidden = $K.dom('<input>');
|
|
$hidden.attr('type', 'hidden');
|
|
$hidden.attr('name', this._getHiddenName());
|
|
$hidden.val(response[key].id);
|
|
|
|
// size
|
|
if (typeof response[key].size !== 'undefined')
|
|
{
|
|
var $size = $K.dom('<em>');
|
|
$size.html(response[key].size);
|
|
|
|
$file.append($size);
|
|
}
|
|
|
|
// append
|
|
$item.append($close);
|
|
$item.append($file);
|
|
$item.append($hidden);
|
|
|
|
// target
|
|
this.$target.append($item);
|
|
this._upCount();
|
|
}
|
|
}
|
|
});
|
|
})(Kube);
|