Commit 24ce32da authored by Nicolas Widart's avatar Nicolas Widart

Add 'Modules/Media/' from commit '519e6a0f'

git-subtree-dir: Modules/Media
git-subtree-mainline: 1e18d75c
git-subtree-split: 519e6a0f
parents 1e18d75c 519e6a0f
rules:
php.interface_has_no_interface_suffix:
enabled: false
language: php
php:
- 5.6
- 5.5
- 5.4
- hhvm
/* The MIT License */
.dropzone,
.dropzone *,
.dropzone-previews,
.dropzone-previews * {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.dropzone {
position: relative;
border: 1px solid rgba(0,0,0,0.08);
background: rgba(0,0,0,0.02);
padding: 1em;
}
.dropzone.dz-clickable {
cursor: pointer;
}
.dropzone.dz-clickable .dz-message,
.dropzone.dz-clickable .dz-message span {
cursor: pointer;
}
.dropzone.dz-clickable * {
cursor: default;
}
.dropzone .dz-message {
opacity: 1;
-ms-filter: none;
filter: none;
}
.dropzone.dz-drag-hover {
border-color: rgba(0,0,0,0.15);
background: rgba(0,0,0,0.04);
}
.dropzone.dz-started .dz-message {
display: none;
}
.dropzone .dz-preview,
.dropzone-previews .dz-preview {
background: rgba(255,255,255,0.8);
position: relative;
display: inline-block;
margin: 17px;
vertical-align: top;
border: 1px solid #acacac;
padding: 6px 6px 6px 6px;
}
.dropzone .dz-preview.dz-file-preview [data-dz-thumbnail],
.dropzone-previews .dz-preview.dz-file-preview [data-dz-thumbnail] {
display: none;
}
.dropzone .dz-preview .dz-details,
.dropzone-previews .dz-preview .dz-details {
width: 100px;
height: 100px;
position: relative;
background: #ebebeb;
padding: 5px;
margin-bottom: 22px;
}
.dropzone .dz-preview .dz-details .dz-filename,
.dropzone-previews .dz-preview .dz-details .dz-filename {
overflow: hidden;
height: 100%;
}
.dropzone .dz-preview .dz-details img,
.dropzone-previews .dz-preview .dz-details img {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
}
.dropzone .dz-preview .dz-details .dz-size,
.dropzone-previews .dz-preview .dz-details .dz-size {
position: absolute;
bottom: -28px;
left: 3px;
height: 28px;
line-height: 28px;
}
.dropzone .dz-preview.dz-error .dz-error-mark,
.dropzone-previews .dz-preview.dz-error .dz-error-mark {
display: block;
}
.dropzone .dz-preview.dz-success .dz-success-mark,
.dropzone-previews .dz-preview.dz-success .dz-success-mark {
display: block;
}
.dropzone .dz-preview:hover .dz-details img,
.dropzone-previews .dz-preview:hover .dz-details img {
display: none;
}
.dropzone .dz-preview .dz-success-mark,
.dropzone-previews .dz-preview .dz-success-mark,
.dropzone .dz-preview .dz-error-mark,
.dropzone-previews .dz-preview .dz-error-mark {
display: none;
position: absolute;
width: 40px;
height: 40px;
font-size: 30px;
text-align: center;
right: -10px;
top: -10px;
}
.dropzone .dz-preview .dz-success-mark,
.dropzone-previews .dz-preview .dz-success-mark {
color: #8cc657;
}
.dropzone .dz-preview .dz-error-mark,
.dropzone-previews .dz-preview .dz-error-mark {
color: #ee162d;
}
.dropzone .dz-preview .dz-progress,
.dropzone-previews .dz-preview .dz-progress {
position: absolute;
top: 100px;
left: 6px;
right: 6px;
height: 6px;
background: #d7d7d7;
display: none;
}
.dropzone .dz-preview .dz-progress .dz-upload,
.dropzone-previews .dz-preview .dz-progress .dz-upload {
display: block;
position: absolute;
top: 0;
bottom: 0;
left: 0;
width: 0%;
background-color: #8cc657;
}
.dropzone .dz-preview.dz-processing .dz-progress,
.dropzone-previews .dz-preview.dz-processing .dz-progress {
display: block;
}
.dropzone .dz-preview .dz-error-message,
.dropzone-previews .dz-preview .dz-error-message {
display: none;
position: absolute;
top: -5px;
left: -20px;
background: rgba(245,245,245,0.8);
padding: 8px 10px;
color: #800;
min-width: 140px;
max-width: 500px;
z-index: 500;
}
.dropzone .dz-preview:hover.dz-error .dz-error-message,
.dropzone-previews .dz-preview:hover.dz-error .dz-error-message {
display: block;
}
.dropzone {
border: 1px solid rgba(0,0,0,0.03);
min-height: 360px;
-webkit-border-radius: 3px;
border-radius: 3px;
background: rgba(0,0,0,0.03);
padding: 23px;
}
.dropzone .dz-default.dz-message {
opacity: 1;
-ms-filter: none;
filter: none;
-webkit-transition: opacity 0.3s ease-in-out;
-moz-transition: opacity 0.3s ease-in-out;
-o-transition: opacity 0.3s ease-in-out;
-ms-transition: opacity 0.3s ease-in-out;
transition: opacity 0.3s ease-in-out;
background-image: url("../images/spritemap.png");
background-repeat: no-repeat;
background-position: 0 0;
position: absolute;
width: 428px;
height: 123px;
margin-left: -214px;
margin-top: -61.5px;
top: 50%;
left: 50%;
}
@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {
.dropzone .dz-default.dz-message {
background-image: url("../images/spritemap@2x.png");
-webkit-background-size: 428px 406px;
-moz-background-size: 428px 406px;
background-size: 428px 406px;
}
}
.dropzone .dz-default.dz-message span {
display: none;
}
.dropzone.dz-square .dz-default.dz-message {
background-position: 0 -123px;
width: 268px;
margin-left: -134px;
height: 174px;
margin-top: -87px;
}
.dropzone.dz-drag-hover .dz-message {
opacity: 0.15;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=15)";
filter: alpha(opacity=15);
}
.dropzone.dz-started .dz-message {
display: block;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
}
.dropzone .dz-preview,
.dropzone-previews .dz-preview {
-webkit-box-shadow: 1px 1px 4px rgba(0,0,0,0.16);
box-shadow: 1px 1px 4px rgba(0,0,0,0.16);
font-size: 14px;
}
.dropzone .dz-preview.dz-image-preview:hover .dz-details img,
.dropzone-previews .dz-preview.dz-image-preview:hover .dz-details img {
display: block;
opacity: 0.1;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=10)";
filter: alpha(opacity=10);
}
.dropzone .dz-preview.dz-success .dz-success-mark,
.dropzone-previews .dz-preview.dz-success .dz-success-mark {
opacity: 1;
-ms-filter: none;
filter: none;
}
.dropzone .dz-preview.dz-error .dz-error-mark,
.dropzone-previews .dz-preview.dz-error .dz-error-mark {
opacity: 1;
-ms-filter: none;
filter: none;
}
.dropzone .dz-preview.dz-error .dz-progress .dz-upload,
.dropzone-previews .dz-preview.dz-error .dz-progress .dz-upload {
background: #ee1e2d;
}
.dropzone .dz-preview .dz-error-mark,
.dropzone-previews .dz-preview .dz-error-mark,
.dropzone .dz-preview .dz-success-mark,
.dropzone-previews .dz-preview .dz-success-mark {
display: block;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-webkit-transition: opacity 0.4s ease-in-out;
-moz-transition: opacity 0.4s ease-in-out;
-o-transition: opacity 0.4s ease-in-out;
-ms-transition: opacity 0.4s ease-in-out;
transition: opacity 0.4s ease-in-out;
background-image: url("../images/spritemap.png");
background-repeat: no-repeat;
}
@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {
.dropzone .dz-preview .dz-error-mark,
.dropzone-previews .dz-preview .dz-error-mark,
.dropzone .dz-preview .dz-success-mark,
.dropzone-previews .dz-preview .dz-success-mark {
background-image: url("../images/spritemap@2x.png");
-webkit-background-size: 428px 406px;
-moz-background-size: 428px 406px;
background-size: 428px 406px;
}
}
.dropzone .dz-preview .dz-error-mark span,
.dropzone-previews .dz-preview .dz-error-mark span,
.dropzone .dz-preview .dz-success-mark span,
.dropzone-previews .dz-preview .dz-success-mark span {
display: none;
}
.dropzone .dz-preview .dz-error-mark,
.dropzone-previews .dz-preview .dz-error-mark {
background-position: -268px -123px;
}
.dropzone .dz-preview .dz-success-mark,
.dropzone-previews .dz-preview .dz-success-mark {
background-position: -268px -163px;
}
.dropzone .dz-preview .dz-progress .dz-upload,
.dropzone-previews .dz-preview .dz-progress .dz-upload {
-webkit-animation: loading 0.4s linear infinite;
-moz-animation: loading 0.4s linear infinite;
-o-animation: loading 0.4s linear infinite;
-ms-animation: loading 0.4s linear infinite;
animation: loading 0.4s linear infinite;
-webkit-transition: width 0.3s ease-in-out;
-moz-transition: width 0.3s ease-in-out;
-o-transition: width 0.3s ease-in-out;
-ms-transition: width 0.3s ease-in-out;
transition: width 0.3s ease-in-out;
-webkit-border-radius: 2px;
border-radius: 2px;
position: absolute;
top: 0;
left: 0;
width: 0%;
height: 100%;
background-image: url("../images/spritemap.png");
background-repeat: repeat-x;
background-position: 0px -400px;
}
@media all and (-webkit-min-device-pixel-ratio:1.5),(min--moz-device-pixel-ratio:1.5),(-o-min-device-pixel-ratio:1.5/1),(min-device-pixel-ratio:1.5),(min-resolution:138dpi),(min-resolution:1.5dppx) {
.dropzone .dz-preview .dz-progress .dz-upload,
.dropzone-previews .dz-preview .dz-progress .dz-upload {
background-image: url("../images/spritemap@2x.png");
-webkit-background-size: 428px 406px;
-moz-background-size: 428px 406px;
background-size: 428px 406px;
}
}
.dropzone .dz-preview.dz-success .dz-progress,
.dropzone-previews .dz-preview.dz-success .dz-progress {
display: block;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-webkit-transition: opacity 0.4s ease-in-out;
-moz-transition: opacity 0.4s ease-in-out;
-o-transition: opacity 0.4s ease-in-out;
-ms-transition: opacity 0.4s ease-in-out;
transition: opacity 0.4s ease-in-out;
}
.dropzone .dz-preview .dz-error-message,
.dropzone-previews .dz-preview .dz-error-message {
display: block;
opacity: 0;
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)";
filter: alpha(opacity=0);
-webkit-transition: opacity 0.3s ease-in-out;
-moz-transition: opacity 0.3s ease-in-out;
-o-transition: opacity 0.3s ease-in-out;
-ms-transition: opacity 0.3s ease-in-out;
transition: opacity 0.3s ease-in-out;
}
.dropzone .dz-preview:hover.dz-error .dz-error-message,
.dropzone-previews .dz-preview:hover.dz-error .dz-error-message {
opacity: 1;
-ms-filter: none;
filter: none;
}
.dropzone a.dz-remove,
.dropzone-previews a.dz-remove {
background-image: -webkit-linear-gradient(top, #fafafa, #eee);
background-image: -moz-linear-gradient(top, #fafafa, #eee);
background-image: -o-linear-gradient(top, #fafafa, #eee);
background-image: -ms-linear-gradient(top, #fafafa, #eee);
background-image: linear-gradient(to bottom, #fafafa, #eee);
-webkit-border-radius: 2px;
border-radius: 2px;
border: 1px solid #eee;
text-decoration: none;
display: block;
padding: 4px 5px;
text-align: center;
color: #aaa;
margin-top: 26px;
}
.dropzone a.dz-remove:hover,
.dropzone-previews a.dz-remove:hover {
color: #666;
}
@-moz-keyframes loading {
from {
background-position: 0 -400px;
}
to {
background-position: -7px -400px;
}
}
@-webkit-keyframes loading {
from {
background-position: 0 -400px;
}
to {
background-position: -7px -400px;
}
}
@-o-keyframes loading {
from {
background-position: 0 -400px;
}
to {
background-position: -7px -400px;
}
}
@keyframes loading {
from {
background-position: 0 -400px;
}
to {
background-position: -7px -400px;
}
}
;(function(){
/**
* Require the module at `name`.
*
* @param {String} name
* @return {Object} exports
* @api public
*/
function require(name) {
var module = require.modules[name];
if (!module) throw new Error('failed to require "' + name + '"');
if (!('exports' in module) && typeof module.definition === 'function') {
module.client = module.component = true;
module.definition.call(this, module.exports = {}, module);
delete module.definition;
}
return module.exports;
}
/**
* Registered modules.
*/
require.modules = {};
/**
* Register module at `name` with callback `definition`.
*
* @param {String} name
* @param {Function} definition
* @api private
*/
require.register = function (name, definition) {
require.modules[name] = {
definition: definition
};
};
/**
* Define a module's exports immediately with `exports`.
*
* @param {String} name
* @param {Generic} exports
* @api private
*/
require.define = function (name, exports) {
require.modules[name] = {
exports: exports
};
};
require.register("component~emitter@1.1.2", function (exports, module) {
/**
* Expose `Emitter`.
*/
module.exports = Emitter;
/**
* Initialize a new `Emitter`.
*
* @api public
*/
function Emitter(obj) {
if (obj) return mixin(obj);
};
/**
* Mixin the emitter properties.
*
* @param {Object} obj
* @return {Object}
* @api private
*/
function mixin(obj) {
for (var key in Emitter.prototype) {
obj[key] = Emitter.prototype[key];
}
return obj;
}
/**
* Listen on the given `event` with `fn`.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.on =
Emitter.prototype.addEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
(this._callbacks[event] = this._callbacks[event] || [])
.push(fn);
return this;
};
/**
* Adds an `event` listener that will be invoked a single
* time then automatically removed.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.once = function(event, fn){
var self = this;
this._callbacks = this._callbacks || {};
function on() {
self.off(event, on);
fn.apply(this, arguments);
}
on.fn = fn;
this.on(event, on);
return this;
};
/**
* Remove the given callback for `event` or all
* registered callbacks.
*
* @param {String} event
* @param {Function} fn
* @return {Emitter}
* @api public
*/
Emitter.prototype.off =
Emitter.prototype.removeListener =
Emitter.prototype.removeAllListeners =
Emitter.prototype.removeEventListener = function(event, fn){
this._callbacks = this._callbacks || {};
// all
if (0 == arguments.length) {
this._callbacks = {};
return this;
}
// specific event
var callbacks = this._callbacks[event];
if (!callbacks) return this;
// remove all handlers
if (1 == arguments.length) {
delete this._callbacks[event];
return this;
}
// remove specific handler
var cb;
for (var i = 0; i < callbacks.length; i++) {
cb = callbacks[i];
if (cb === fn || cb.fn === fn) {
callbacks.splice(i, 1);
break;
}
}
return this;
};
/**
* Emit `event` with the given args.
*
* @param {String} event
* @param {Mixed} ...
* @return {Emitter}
*/
Emitter.prototype.emit = function(event){
this._callbacks = this._callbacks || {};
var args = [].slice.call(arguments, 1)
, callbacks = this._callbacks[event];
if (callbacks) {
callbacks = callbacks.slice(0);
for (var i = 0, len = callbacks.length; i < len; ++i) {
callbacks[i].apply(this, args);
}
}
return this;
};
/**
* Return array of callbacks for `event`.
*
* @param {String} event
* @return {Array}
* @api public
*/
Emitter.prototype.listeners = function(event){
this._callbacks = this._callbacks || {};
return this._callbacks[event] || [];
};
/**
* Check if this emitter has `event` handlers.
*
* @param {String} event
* @return {Boolean}
* @api public
*/
Emitter.prototype.hasListeners = function(event){
return !! this.listeners(event).length;
};
});
require.register("dropzone", function (exports, module) {
/**
* Exposing dropzone
*/
module.exports = require("dropzone/lib/dropzone.js");
});
require.register("dropzone/lib/dropzone.js", function (exports, module) {
/*
*
* More info at [www.dropzonejs.com](http://www.dropzonejs.com)
*
* Copyright (c) 2012, Matias Meno
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
(function() {
var Dropzone, Em, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without,
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
__slice = [].slice;
Em = typeof Emitter !== "undefined" && Emitter !== null ? Emitter : require("component~emitter@1.1.2");
noop = function() {};
Dropzone = (function(_super) {
var extend;
__extends(Dropzone, _super);
/*
This is a list of all available events you can register on a dropzone object.
You can register an event handler like this:
dropzone.on("dragEnter", function() { });
*/
Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached"];
Dropzone.prototype.defaultOptions = {
url: null,
method: "post",
withCredentials: false,
parallelUploads: 2,
uploadMultiple: false,
maxFilesize: 256,
paramName: "file",
createImageThumbnails: true,
maxThumbnailFilesize: 10,
thumbnailWidth: 100,
thumbnailHeight: 100,
maxFiles: null,
params: {},
clickable: true,
ignoreHiddenFiles: true,
acceptedFiles: null,
acceptedMimeTypes: null,
autoProcessQueue: true,
autoQueue: true,
addRemoveLinks: false,
previewsContainer: null,
dictDefaultMessage: "Drop files here to upload",
dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.",
dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.",
dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.",
dictInvalidFileType: "You can't upload files of this type.",
dictResponseError: "Server responded with {{statusCode}} code.",
dictCancelUpload: "Cancel upload",
dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?",
dictRemoveFile: "Remove file",
dictRemoveFileConfirmation: null,
dictMaxFilesExceeded: "You can not upload any more files.",
accept: function(file, done) {
return done();
},
init: function() {
return noop;
},
forceFallback: false,
fallback: function() {
var child, messageElement, span, _i, _len, _ref;
this.element.className = "" + this.element.className + " dz-browser-not-supported";
_ref = this.element.getElementsByTagName("div");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
child = _ref[_i];
if (/(^| )dz-message($| )/.test(child.className)) {
messageElement = child;
child.className = "dz-message";
continue;
}
}
if (!messageElement) {
messageElement = Dropzone.createElement("<div class=\"dz-message\"><span></span></div>");
this.element.appendChild(messageElement);
}
span = messageElement.getElementsByTagName("span")[0];
if (span) {
span.textContent = this.options.dictFallbackMessage;
}
return this.element.appendChild(this.getFallbackForm());
},
resize: function(file) {
var info, srcRatio, trgRatio;
info = {
srcX: 0,
srcY: 0,
srcWidth: file.width,
srcHeight: file.height
};
srcRatio = file.width / file.height;
info.optWidth = this.options.thumbnailWidth;
info.optHeight = this.options.thumbnailHeight;
if ((info.optWidth == null) && (info.optHeight == null)) {
info.optWidth = info.srcWidth;
info.optHeight = info.srcHeight;
} else if (info.optWidth == null) {
info.optWidth = srcRatio * info.optHeight;
} else if (info.optHeight == null) {
info.optHeight = (1 / srcRatio) * info.optWidth;
}
trgRatio = info.optWidth / info.optHeight;
if (file.height < info.optHeight || file.width < info.optWidth) {
info.trgHeight = info.srcHeight;
info.trgWidth = info.srcWidth;
} else {
if (srcRatio > trgRatio) {
info.srcHeight = file.height;
info.srcWidth = info.srcHeight * trgRatio;
} else {
info.srcWidth = file.width;
info.srcHeight = info.srcWidth / trgRatio;
}
}
info.srcX = (file.width - info.srcWidth) / 2;
info.srcY = (file.height - info.srcHeight) / 2;
return info;
},
/*
Those functions register themselves to the events on init and handle all
the user interface specific stuff. Overwriting them won't break the upload
but can break the way it's displayed.
You can overwrite them if you don't like the default behavior. If you just
want to add an additional event handler, register it on the dropzone object
and don't overwrite those options.
*/
drop: function(e) {
return this.element.classList.remove("dz-drag-hover");
},
dragstart: noop,
dragend: function(e) {
return this.element.classList.remove("dz-drag-hover");
},
dragenter: function(e) {
return this.element.classList.add("dz-drag-hover");
},
dragover: function(e) {
return this.element.classList.add("dz-drag-hover");
},
dragleave: function(e) {
return this.element.classList.remove("dz-drag-hover");
},
paste: noop,
reset: function() {
return this.element.classList.remove("dz-started");
},
addedfile: function(file) {
var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results;
if (this.element === this.previewsContainer) {
this.element.classList.add("dz-started");
}
if (this.previewsContainer) {
file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim());
file.previewTemplate = file.previewElement;
this.previewsContainer.appendChild(file.previewElement);
_ref = file.previewElement.querySelectorAll("[data-dz-name]");
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
node.textContent = file.name;
}
_ref1 = file.previewElement.querySelectorAll("[data-dz-size]");
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
node = _ref1[_j];
node.innerHTML = this.filesize(file.size);
}
if (this.options.addRemoveLinks) {
file._removeLink = Dropzone.createElement("<a class=\"dz-remove\" href=\"javascript:undefined;\" data-dz-remove>" + this.options.dictRemoveFile + "</a>");
file.previewElement.appendChild(file._removeLink);
}
removeFileEvent = (function(_this) {
return function(e) {
e.preventDefault();
e.stopPropagation();
if (file.status === Dropzone.UPLOADING) {
return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() {
return _this.removeFile(file);
});
} else {
if (_this.options.dictRemoveFileConfirmation) {
return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() {
return _this.removeFile(file);
});
} else {
return _this.removeFile(file);
}
}
};
})(this);
_ref2 = file.previewElement.querySelectorAll("[data-dz-remove]");
_results = [];
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
removeLink = _ref2[_k];
_results.push(removeLink.addEventListener("click", removeFileEvent));
}
return _results;
}
},
removedfile: function(file) {
var _ref;
if (file.previewElement) {
if ((_ref = file.previewElement) != null) {
_ref.parentNode.removeChild(file.previewElement);
}
}
return this._updateMaxFilesReachedClass();
},
thumbnail: function(file, dataUrl) {
var thumbnailElement, _i, _len, _ref, _results;
if (file.previewElement) {
file.previewElement.classList.remove("dz-file-preview");
file.previewElement.classList.add("dz-image-preview");
_ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
thumbnailElement = _ref[_i];
thumbnailElement.alt = file.name;
_results.push(thumbnailElement.src = dataUrl);
}
return _results;
}
},
error: function(file, message) {
var node, _i, _len, _ref, _results;
if (file.previewElement) {
file.previewElement.classList.add("dz-error");
if (typeof message !== "String" && message.error) {
message = message.error;
}
_ref = file.previewElement.querySelectorAll("[data-dz-errormessage]");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.textContent = message);
}
return _results;
}
},
errormultiple: noop,
processing: function(file) {
if (file.previewElement) {
file.previewElement.classList.add("dz-processing");
if (file._removeLink) {
return file._removeLink.textContent = this.options.dictCancelUpload;
}
}
},
processingmultiple: noop,
uploadprogress: function(file, progress, bytesSent) {
var node, _i, _len, _ref, _results;
if (file.previewElement) {
_ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]");
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
node = _ref[_i];
_results.push(node.style.width = "" + progress + "%");
}
return _results;
}
},
totaluploadprogress: noop,
sending: noop,
sendingmultiple: noop,
success: function(file) {
if (file.previewElement) {
return file.previewElement.classList.add("dz-success");
}
},
successmultiple: noop,
canceled: function(file) {
return this.emit("error", file, "Upload canceled.");
},
canceledmultiple: noop,
complete: function(file) {
if (file._removeLink) {
return file._removeLink.textContent = this.options.dictRemoveFile;
}
},
completemultiple: noop,
maxfilesexceeded: noop,
maxfilesreached: noop,
previewTemplate: "<div class=\"dz-preview dz-file-preview\">\n <div class=\"dz-details\">\n <div class=\"dz-filename\"><span data-dz-name></span></div>\n <div class=\"dz-size\" data-dz-size></div>\n <img data-dz-thumbnail />\n </div>\n <div class=\"dz-progress\"><span class=\"dz-upload\" data-dz-uploadprogress></span></div>\n <div class=\"dz-success-mark\"><span>✔</span></div>\n <div class=\"dz-error-mark\"><span>✘</span></div>\n <div class=\"dz-error-message\"><span data-dz-errormessage></span></div>\n</div>"
};
extend = function() {
var key, object, objects, target, val, _i, _len;
target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
for (_i = 0, _len = objects.length; _i < _len; _i++) {
object = objects[_i];
for (key in object) {
val = object[key];
target[key] = val;
}
}
return target;
};
function Dropzone(element, options) {
var elementOptions, fallback, _ref;
this.element = element;
this.version = Dropzone.version;
this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, "");
this.clickableElements = [];
this.listeners = [];
this.files = [];
if (typeof this.element === "string") {
this.element = document.querySelector(this.element);
}
if (!(this.element && (this.element.nodeType != null))) {
throw new Error("Invalid dropzone element.");
}
if (this.element.dropzone) {
throw new Error("Dropzone already attached.");
}
Dropzone.instances.push(this);
this.element.dropzone = this;
elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {};
this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {});
if (this.options.forceFallback || !Dropzone.isBrowserSupported()) {
return this.options.fallback.call(this);
}
if (this.options.url == null) {
this.options.url = this.element.getAttribute("action");
}
if (!this.options.url) {
throw new Error("No URL provided.");
}
if (this.options.acceptedFiles && this.options.acceptedMimeTypes) {
throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated.");
}
if (this.options.acceptedMimeTypes) {
this.options.acceptedFiles = this.options.acceptedMimeTypes;
delete this.options.acceptedMimeTypes;
}
this.options.method = this.options.method.toUpperCase();
if ((fallback = this.getExistingFallback()) && fallback.parentNode) {
fallback.parentNode.removeChild(fallback);
}
if (this.options.previewsContainer !== false) {
if (this.options.previewsContainer) {
this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer");
} else {
this.previewsContainer = this.element;
}
}
if (this.options.clickable) {
if (this.options.clickable === true) {
this.clickableElements = [this.element];
} else {
this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable");
}
}
this.init();
}
Dropzone.prototype.getAcceptedFiles = function() {
var file, _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.accepted) {
_results.push(file);
}
}
return _results;
};
Dropzone.prototype.getRejectedFiles = function() {
var file, _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (!file.accepted) {
_results.push(file);
}
}
return _results;
};
Dropzone.prototype.getFilesWithStatus = function(status) {
var file, _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.status === status) {
_results.push(file);
}
}
return _results;
};
Dropzone.prototype.getQueuedFiles = function() {
return this.getFilesWithStatus(Dropzone.QUEUED);
};
Dropzone.prototype.getUploadingFiles = function() {
return this.getFilesWithStatus(Dropzone.UPLOADING);
};
Dropzone.prototype.getActiveFiles = function() {
var file, _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) {
_results.push(file);
}
}
return _results;
};
Dropzone.prototype.init = function() {
var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1;
if (this.element.tagName === "form") {
this.element.setAttribute("enctype", "multipart/form-data");
}
if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) {
this.element.appendChild(Dropzone.createElement("<div class=\"dz-default dz-message\"><span>" + this.options.dictDefaultMessage + "</span></div>"));
}
if (this.clickableElements.length) {
setupHiddenFileInput = (function(_this) {
return function() {
if (_this.hiddenFileInput) {
document.body.removeChild(_this.hiddenFileInput);
}
_this.hiddenFileInput = document.createElement("input");
_this.hiddenFileInput.setAttribute("type", "file");
if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) {
_this.hiddenFileInput.setAttribute("multiple", "multiple");
}
_this.hiddenFileInput.className = "dz-hidden-input";
if (_this.options.acceptedFiles != null) {
_this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles);
}
_this.hiddenFileInput.style.visibility = "hidden";
_this.hiddenFileInput.style.position = "absolute";
_this.hiddenFileInput.style.top = "0";
_this.hiddenFileInput.style.left = "0";
_this.hiddenFileInput.style.height = "0";
_this.hiddenFileInput.style.width = "0";
document.body.appendChild(_this.hiddenFileInput);
return _this.hiddenFileInput.addEventListener("change", function() {
var file, files, _i, _len;
files = _this.hiddenFileInput.files;
if (files.length) {
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
_this.addFile(file);
}
}
return setupHiddenFileInput();
});
};
})(this);
setupHiddenFileInput();
}
this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL;
_ref1 = this.events;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
eventName = _ref1[_i];
this.on(eventName, this.options[eventName]);
}
this.on("uploadprogress", (function(_this) {
return function() {
return _this.updateTotalUploadProgress();
};
})(this));
this.on("removedfile", (function(_this) {
return function() {
return _this.updateTotalUploadProgress();
};
})(this));
this.on("canceled", (function(_this) {
return function(file) {
return _this.emit("complete", file);
};
})(this));
this.on("complete", (function(_this) {
return function(file) {
if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) {
return setTimeout((function() {
return _this.emit("queuecomplete");
}), 0);
}
};
})(this));
noPropagation = function(e) {
e.stopPropagation();
if (e.preventDefault) {
return e.preventDefault();
} else {
return e.returnValue = false;
}
};
this.listeners = [
{
element: this.element,
events: {
"dragstart": (function(_this) {
return function(e) {
return _this.emit("dragstart", e);
};
})(this),
"dragenter": (function(_this) {
return function(e) {
noPropagation(e);
return _this.emit("dragenter", e);
};
})(this),
"dragover": (function(_this) {
return function(e) {
var efct;
try {
efct = e.dataTransfer.effectAllowed;
} catch (_error) {}
e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy';
noPropagation(e);
return _this.emit("dragover", e);
};
})(this),
"dragleave": (function(_this) {
return function(e) {
return _this.emit("dragleave", e);
};
})(this),
"drop": (function(_this) {
return function(e) {
noPropagation(e);
return _this.drop(e);
};
})(this),
"dragend": (function(_this) {
return function(e) {
return _this.emit("dragend", e);
};
})(this)
}
}
];
this.clickableElements.forEach((function(_this) {
return function(clickableElement) {
return _this.listeners.push({
element: clickableElement,
events: {
"click": function(evt) {
if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) {
return _this.hiddenFileInput.click();
}
}
}
});
};
})(this));
this.enable();
return this.options.init.call(this);
};
Dropzone.prototype.destroy = function() {
var _ref;
this.disable();
this.removeAllFiles(true);
if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) {
this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput);
this.hiddenFileInput = null;
}
delete this.element.dropzone;
return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1);
};
Dropzone.prototype.updateTotalUploadProgress = function() {
var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref;
totalBytesSent = 0;
totalBytes = 0;
activeFiles = this.getActiveFiles();
if (activeFiles.length) {
_ref = this.getActiveFiles();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
totalBytesSent += file.upload.bytesSent;
totalBytes += file.upload.total;
}
totalUploadProgress = 100 * totalBytesSent / totalBytes;
} else {
totalUploadProgress = 100;
}
return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent);
};
Dropzone.prototype._getParamName = function(n) {
if (typeof this.options.paramName === "function") {
return this.options.paramName(n);
} else {
return "" + this.options.paramName + (this.options.uploadMultiple ? "[" + n + "]" : "");
}
};
Dropzone.prototype.getFallbackForm = function() {
var existingFallback, fields, fieldsString, form;
if (existingFallback = this.getExistingFallback()) {
return existingFallback;
}
fieldsString = "<div class=\"dz-fallback\">";
if (this.options.dictFallbackText) {
fieldsString += "<p>" + this.options.dictFallbackText + "</p>";
}
fieldsString += "<input type=\"file\" name=\"" + (this._getParamName(0)) + "\" " + (this.options.uploadMultiple ? 'multiple="multiple"' : void 0) + " /><input type=\"submit\" value=\"Upload!\"></div>";
fields = Dropzone.createElement(fieldsString);
if (this.element.tagName !== "FORM") {
form = Dropzone.createElement("<form action=\"" + this.options.url + "\" enctype=\"multipart/form-data\" method=\"" + this.options.method + "\"></form>");
form.appendChild(fields);
} else {
this.element.setAttribute("enctype", "multipart/form-data");
this.element.setAttribute("method", this.options.method);
}
return form != null ? form : fields;
};
Dropzone.prototype.getExistingFallback = function() {
var fallback, getFallback, tagName, _i, _len, _ref;
getFallback = function(elements) {
var el, _i, _len;
for (_i = 0, _len = elements.length; _i < _len; _i++) {
el = elements[_i];
if (/(^| )fallback($| )/.test(el.className)) {
return el;
}
}
};
_ref = ["div", "form"];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
tagName = _ref[_i];
if (fallback = getFallback(this.element.getElementsByTagName(tagName))) {
return fallback;
}
}
};
Dropzone.prototype.setupEventListeners = function() {
var elementListeners, event, listener, _i, _len, _ref, _results;
_ref = this.listeners;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
elementListeners = _ref[_i];
_results.push((function() {
var _ref1, _results1;
_ref1 = elementListeners.events;
_results1 = [];
for (event in _ref1) {
listener = _ref1[event];
_results1.push(elementListeners.element.addEventListener(event, listener, false));
}
return _results1;
})());
}
return _results;
};
Dropzone.prototype.removeEventListeners = function() {
var elementListeners, event, listener, _i, _len, _ref, _results;
_ref = this.listeners;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
elementListeners = _ref[_i];
_results.push((function() {
var _ref1, _results1;
_ref1 = elementListeners.events;
_results1 = [];
for (event in _ref1) {
listener = _ref1[event];
_results1.push(elementListeners.element.removeEventListener(event, listener, false));
}
return _results1;
})());
}
return _results;
};
Dropzone.prototype.disable = function() {
var file, _i, _len, _ref, _results;
this.clickableElements.forEach(function(element) {
return element.classList.remove("dz-clickable");
});
this.removeEventListeners();
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
_results.push(this.cancelUpload(file));
}
return _results;
};
Dropzone.prototype.enable = function() {
this.clickableElements.forEach(function(element) {
return element.classList.add("dz-clickable");
});
return this.setupEventListeners();
};
Dropzone.prototype.filesize = function(size) {
var string;
if (size >= 1024 * 1024 * 1024 * 1024 / 10) {
size = size / (1024 * 1024 * 1024 * 1024 / 10);
string = "TiB";
} else if (size >= 1024 * 1024 * 1024 / 10) {
size = size / (1024 * 1024 * 1024 / 10);
string = "GiB";
} else if (size >= 1024 * 1024 / 10) {
size = size / (1024 * 1024 / 10);
string = "MiB";
} else if (size >= 1024 / 10) {
size = size / (1024 / 10);
string = "KiB";
} else {
size = size * 10;
string = "b";
}
return "<strong>" + (Math.round(size) / 10) + "</strong> " + string;
};
Dropzone.prototype._updateMaxFilesReachedClass = function() {
if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
if (this.getAcceptedFiles().length === this.options.maxFiles) {
this.emit('maxfilesreached', this.files);
}
return this.element.classList.add("dz-max-files-reached");
} else {
return this.element.classList.remove("dz-max-files-reached");
}
};
Dropzone.prototype.drop = function(e) {
var files, items;
if (!e.dataTransfer) {
return;
}
this.emit("drop", e);
files = e.dataTransfer.files;
if (files.length) {
items = e.dataTransfer.items;
if (items && items.length && (items[0].webkitGetAsEntry != null)) {
this._addFilesFromItems(items);
} else {
this.handleFiles(files);
}
}
};
Dropzone.prototype.paste = function(e) {
var items, _ref;
if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) {
return;
}
this.emit("paste", e);
items = e.clipboardData.items;
if (items.length) {
return this._addFilesFromItems(items);
}
};
Dropzone.prototype.handleFiles = function(files) {
var file, _i, _len, _results;
_results = [];
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
_results.push(this.addFile(file));
}
return _results;
};
Dropzone.prototype._addFilesFromItems = function(items) {
var entry, item, _i, _len, _results;
_results = [];
for (_i = 0, _len = items.length; _i < _len; _i++) {
item = items[_i];
if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) {
if (entry.isFile) {
_results.push(this.addFile(item.getAsFile()));
} else if (entry.isDirectory) {
_results.push(this._addFilesFromDirectory(entry, entry.name));
} else {
_results.push(void 0);
}
} else if (item.getAsFile != null) {
if ((item.kind == null) || item.kind === "file") {
_results.push(this.addFile(item.getAsFile()));
} else {
_results.push(void 0);
}
} else {
_results.push(void 0);
}
}
return _results;
};
Dropzone.prototype._addFilesFromDirectory = function(directory, path) {
var dirReader, entriesReader;
dirReader = directory.createReader();
entriesReader = (function(_this) {
return function(entries) {
var entry, _i, _len;
for (_i = 0, _len = entries.length; _i < _len; _i++) {
entry = entries[_i];
if (entry.isFile) {
entry.file(function(file) {
if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') {
return;
}
file.fullPath = "" + path + "/" + file.name;
return _this.addFile(file);
});
} else if (entry.isDirectory) {
_this._addFilesFromDirectory(entry, "" + path + "/" + entry.name);
}
}
};
})(this);
return dirReader.readEntries(entriesReader, function(error) {
return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0;
});
};
Dropzone.prototype.accept = function(file, done) {
if (file.size > this.options.maxFilesize * 1024 * 1024) {
return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize));
} else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) {
return done(this.options.dictInvalidFileType);
} else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) {
done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles));
return this.emit("maxfilesexceeded", file);
} else {
return this.options.accept.call(this, file, done);
}
};
Dropzone.prototype.addFile = function(file) {
file.upload = {
progress: 0,
total: file.size,
bytesSent: 0
};
this.files.push(file);
file.status = Dropzone.ADDED;
this.emit("addedfile", file);
this._enqueueThumbnail(file);
return this.accept(file, (function(_this) {
return function(error) {
if (error) {
file.accepted = false;
_this._errorProcessing([file], error);
} else {
file.accepted = true;
if (_this.options.autoQueue) {
_this.enqueueFile(file);
}
}
return _this._updateMaxFilesReachedClass();
};
})(this));
};
Dropzone.prototype.enqueueFiles = function(files) {
var file, _i, _len;
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
this.enqueueFile(file);
}
return null;
};
Dropzone.prototype.enqueueFile = function(file) {
if (file.status === Dropzone.ADDED && file.accepted === true) {
file.status = Dropzone.QUEUED;
if (this.options.autoProcessQueue) {
return setTimeout(((function(_this) {
return function() {
return _this.processQueue();
};
})(this)), 0);
}
} else {
throw new Error("This file can't be queued because it has already been processed or was rejected.");
}
};
Dropzone.prototype._thumbnailQueue = [];
Dropzone.prototype._processingThumbnail = false;
Dropzone.prototype._enqueueThumbnail = function(file) {
if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) {
this._thumbnailQueue.push(file);
return setTimeout(((function(_this) {
return function() {
return _this._processThumbnailQueue();
};
})(this)), 0);
}
};
Dropzone.prototype._processThumbnailQueue = function() {
if (this._processingThumbnail || this._thumbnailQueue.length === 0) {
return;
}
this._processingThumbnail = true;
return this.createThumbnail(this._thumbnailQueue.shift(), (function(_this) {
return function() {
_this._processingThumbnail = false;
return _this._processThumbnailQueue();
};
})(this));
};
Dropzone.prototype.removeFile = function(file) {
if (file.status === Dropzone.UPLOADING) {
this.cancelUpload(file);
}
this.files = without(this.files, file);
this.emit("removedfile", file);
if (this.files.length === 0) {
return this.emit("reset");
}
};
Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) {
var file, _i, _len, _ref;
if (cancelIfNecessary == null) {
cancelIfNecessary = false;
}
_ref = this.files.slice();
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) {
this.removeFile(file);
}
}
return null;
};
Dropzone.prototype.createThumbnail = function(file, callback) {
var fileReader;
fileReader = new FileReader;
fileReader.onload = (function(_this) {
return function() {
var img;
img = document.createElement("img");
img.onload = function() {
var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3;
file.width = img.width;
file.height = img.height;
resizeInfo = _this.options.resize.call(_this, file);
if (resizeInfo.trgWidth == null) {
resizeInfo.trgWidth = resizeInfo.optWidth;
}
if (resizeInfo.trgHeight == null) {
resizeInfo.trgHeight = resizeInfo.optHeight;
}
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
canvas.width = resizeInfo.trgWidth;
canvas.height = resizeInfo.trgHeight;
drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight);
thumbnail = canvas.toDataURL("image/png");
_this.emit("thumbnail", file, thumbnail);
if (callback != null) {
return callback();
}
};
return img.src = fileReader.result;
};
})(this);
return fileReader.readAsDataURL(file);
};
Dropzone.prototype.processQueue = function() {
var i, parallelUploads, processingLength, queuedFiles;
parallelUploads = this.options.parallelUploads;
processingLength = this.getUploadingFiles().length;
i = processingLength;
if (processingLength >= parallelUploads) {
return;
}
queuedFiles = this.getQueuedFiles();
if (!(queuedFiles.length > 0)) {
return;
}
if (this.options.uploadMultiple) {
return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength));
} else {
while (i < parallelUploads) {
if (!queuedFiles.length) {
return;
}
this.processFile(queuedFiles.shift());
i++;
}
}
};
Dropzone.prototype.processFile = function(file) {
return this.processFiles([file]);
};
Dropzone.prototype.processFiles = function(files) {
var file, _i, _len;
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
file.processing = true;
file.status = Dropzone.UPLOADING;
this.emit("processing", file);
}
if (this.options.uploadMultiple) {
this.emit("processingmultiple", files);
}
return this.uploadFiles(files);
};
Dropzone.prototype._getFilesWithXhr = function(xhr) {
var file, files;
return files = (function() {
var _i, _len, _ref, _results;
_ref = this.files;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
file = _ref[_i];
if (file.xhr === xhr) {
_results.push(file);
}
}
return _results;
}).call(this);
};
Dropzone.prototype.cancelUpload = function(file) {
var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref;
if (file.status === Dropzone.UPLOADING) {
groupedFiles = this._getFilesWithXhr(file.xhr);
for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) {
groupedFile = groupedFiles[_i];
groupedFile.status = Dropzone.CANCELED;
}
file.xhr.abort();
for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) {
groupedFile = groupedFiles[_j];
this.emit("canceled", groupedFile);
}
if (this.options.uploadMultiple) {
this.emit("canceledmultiple", groupedFiles);
}
} else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) {
file.status = Dropzone.CANCELED;
this.emit("canceled", file);
if (this.options.uploadMultiple) {
this.emit("canceledmultiple", [file]);
}
}
if (this.options.autoProcessQueue) {
return this.processQueue();
}
};
Dropzone.prototype.uploadFile = function(file) {
return this.uploadFiles([file]);
};
Dropzone.prototype.uploadFiles = function(files) {
var file, formData, handleError, headerName, headerValue, headers, i, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
xhr = new XMLHttpRequest();
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
file.xhr = xhr;
}
xhr.open(this.options.method, this.options.url, true);
xhr.withCredentials = !!this.options.withCredentials;
response = null;
handleError = (function(_this) {
return function() {
var _j, _len1, _results;
_results = [];
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
_results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr));
}
return _results;
};
})(this);
updateProgress = (function(_this) {
return function(e) {
var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results;
if (e != null) {
progress = 100 * e.loaded / e.total;
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
file.upload = {
progress: progress,
total: e.total,
bytesSent: e.loaded
};
}
} else {
allFilesFinished = true;
progress = 100;
for (_k = 0, _len2 = files.length; _k < _len2; _k++) {
file = files[_k];
if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) {
allFilesFinished = false;
}
file.upload.progress = progress;
file.upload.bytesSent = file.upload.total;
}
if (allFilesFinished) {
return;
}
}
_results = [];
for (_l = 0, _len3 = files.length; _l < _len3; _l++) {
file = files[_l];
_results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent));
}
return _results;
};
})(this);
xhr.onload = (function(_this) {
return function(e) {
var _ref;
if (files[0].status === Dropzone.CANCELED) {
return;
}
if (xhr.readyState !== 4) {
return;
}
response = xhr.responseText;
if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) {
try {
response = JSON.parse(response);
} catch (_error) {
e = _error;
response = "Invalid JSON response from server.";
}
}
updateProgress();
if (!((200 <= (_ref = xhr.status) && _ref < 300))) {
return handleError();
} else {
return _this._finished(files, response, e);
}
};
})(this);
xhr.onerror = (function(_this) {
return function() {
if (files[0].status === Dropzone.CANCELED) {
return;
}
return handleError();
};
})(this);
progressObj = (_ref = xhr.upload) != null ? _ref : xhr;
progressObj.onprogress = updateProgress;
headers = {
"Accept": "application/json",
"Cache-Control": "no-cache",
"X-Requested-With": "XMLHttpRequest"
};
if (this.options.headers) {
extend(headers, this.options.headers);
}
for (headerName in headers) {
headerValue = headers[headerName];
xhr.setRequestHeader(headerName, headerValue);
}
formData = new FormData();
if (this.options.params) {
_ref1 = this.options.params;
for (key in _ref1) {
value = _ref1[key];
formData.append(key, value);
}
}
for (_j = 0, _len1 = files.length; _j < _len1; _j++) {
file = files[_j];
this.emit("sending", file, xhr, formData);
}
if (this.options.uploadMultiple) {
this.emit("sendingmultiple", files, xhr, formData);
}
if (this.element.tagName === "FORM") {
_ref2 = this.element.querySelectorAll("input, textarea, select, button");
for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
input = _ref2[_k];
inputName = input.getAttribute("name");
inputType = input.getAttribute("type");
if (input.tagName === "SELECT" && input.hasAttribute("multiple")) {
_ref3 = input.options;
for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) {
option = _ref3[_l];
if (option.selected) {
formData.append(inputName, option.value);
}
}
} else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) {
formData.append(inputName, input.value);
}
}
}
for (i = _m = 0, _ref5 = files.length - 1; 0 <= _ref5 ? _m <= _ref5 : _m >= _ref5; i = 0 <= _ref5 ? ++_m : --_m) {
formData.append(this._getParamName(i), files[i], files[i].name);
}
return xhr.send(formData);
};
Dropzone.prototype._finished = function(files, responseText, e) {
var file, _i, _len;
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
file.status = Dropzone.SUCCESS;
this.emit("success", file, responseText, e);
this.emit("complete", file);
}
if (this.options.uploadMultiple) {
this.emit("successmultiple", files, responseText, e);
this.emit("completemultiple", files);
}
if (this.options.autoProcessQueue) {
return this.processQueue();
}
};
Dropzone.prototype._errorProcessing = function(files, message, xhr) {
var file, _i, _len;
for (_i = 0, _len = files.length; _i < _len; _i++) {
file = files[_i];
file.status = Dropzone.ERROR;
this.emit("error", file, message, xhr);
this.emit("complete", file);
}
if (this.options.uploadMultiple) {
this.emit("errormultiple", files, message, xhr);
this.emit("completemultiple", files);
}
if (this.options.autoProcessQueue) {
return this.processQueue();
}
};
return Dropzone;
})(Em);
Dropzone.version = "3.10.2";
Dropzone.options = {};
Dropzone.optionsForElement = function(element) {
if (element.getAttribute("id")) {
return Dropzone.options[camelize(element.getAttribute("id"))];
} else {
return void 0;
}
};
Dropzone.instances = [];
Dropzone.forElement = function(element) {
if (typeof element === "string") {
element = document.querySelector(element);
}
if ((element != null ? element.dropzone : void 0) == null) {
throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone.");
}
return element.dropzone;
};
Dropzone.autoDiscover = true;
Dropzone.discover = function() {
var checkElements, dropzone, dropzones, _i, _len, _results;
if (document.querySelectorAll) {
dropzones = document.querySelectorAll(".dropzone");
} else {
dropzones = [];
checkElements = function(elements) {
var el, _i, _len, _results;
_results = [];
for (_i = 0, _len = elements.length; _i < _len; _i++) {
el = elements[_i];
if (/(^| )dropzone($| )/.test(el.className)) {
_results.push(dropzones.push(el));
} else {
_results.push(void 0);
}
}
return _results;
};
checkElements(document.getElementsByTagName("div"));
checkElements(document.getElementsByTagName("form"));
}
_results = [];
for (_i = 0, _len = dropzones.length; _i < _len; _i++) {
dropzone = dropzones[_i];
if (Dropzone.optionsForElement(dropzone) !== false) {
_results.push(new Dropzone(dropzone));
} else {
_results.push(void 0);
}
}
return _results;
};
Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i];
Dropzone.isBrowserSupported = function() {
var capableBrowser, regex, _i, _len, _ref;
capableBrowser = true;
if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) {
if (!("classList" in document.createElement("a"))) {
capableBrowser = false;
} else {
_ref = Dropzone.blacklistedBrowsers;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
regex = _ref[_i];
if (regex.test(navigator.userAgent)) {
capableBrowser = false;
continue;
}
}
}
} else {
capableBrowser = false;
}
return capableBrowser;
};
without = function(list, rejectedItem) {
var item, _i, _len, _results;
_results = [];
for (_i = 0, _len = list.length; _i < _len; _i++) {
item = list[_i];
if (item !== rejectedItem) {
_results.push(item);
}
}
return _results;
};
camelize = function(str) {
return str.replace(/[\-_](\w)/g, function(match) {
return match.charAt(1).toUpperCase();
});
};
Dropzone.createElement = function(string) {
var div;
div = document.createElement("div");
div.innerHTML = string;
return div.childNodes[0];
};
Dropzone.elementInside = function(element, container) {
if (element === container) {
return true;
}
while (element = element.parentNode) {
if (element === container) {
return true;
}
}
return false;
};
Dropzone.getElement = function(el, name) {
var element;
if (typeof el === "string") {
element = document.querySelector(el);
} else if (el.nodeType != null) {
element = el;
}
if (element == null) {
throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element.");
}
return element;
};
Dropzone.getElements = function(els, name) {
var e, el, elements, _i, _j, _len, _len1, _ref;
if (els instanceof Array) {
elements = [];
try {
for (_i = 0, _len = els.length; _i < _len; _i++) {
el = els[_i];
elements.push(this.getElement(el, name));
}
} catch (_error) {
e = _error;
elements = null;
}
} else if (typeof els === "string") {
elements = [];
_ref = document.querySelectorAll(els);
for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) {
el = _ref[_j];
elements.push(el);
}
} else if (els.nodeType != null) {
elements = [els];
}
if (!((elements != null) && elements.length)) {
throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those.");
}
return elements;
};
Dropzone.confirm = function(question, accepted, rejected) {
if (window.confirm(question)) {
return accepted();
} else if (rejected != null) {
return rejected();
}
};
Dropzone.isValidFile = function(file, acceptedFiles) {
var baseMimeType, mimeType, validType, _i, _len;
if (!acceptedFiles) {
return true;
}
acceptedFiles = acceptedFiles.split(",");
mimeType = file.type;
baseMimeType = mimeType.replace(/\/.*$/, "");
for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) {
validType = acceptedFiles[_i];
validType = validType.trim();
if (validType.charAt(0) === ".") {
if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== -1) {
return true;
}
} else if (/\/\*$/.test(validType)) {
if (baseMimeType === validType.replace(/\/.*$/, "")) {
return true;
}
} else {
if (mimeType === validType) {
return true;
}
}
}
return false;
};
if (typeof jQuery !== "undefined" && jQuery !== null) {
jQuery.fn.dropzone = function(options) {
return this.each(function() {
return new Dropzone(this, options);
});
};
}
if (typeof module !== "undefined" && module !== null) {
module.exports = Dropzone;
} else {
window.Dropzone = Dropzone;
}
Dropzone.ADDED = "added";
Dropzone.QUEUED = "queued";
Dropzone.ACCEPTED = Dropzone.QUEUED;
Dropzone.UPLOADING = "uploading";
Dropzone.PROCESSING = Dropzone.UPLOADING;
Dropzone.CANCELED = "canceled";
Dropzone.ERROR = "error";
Dropzone.SUCCESS = "success";
/*
Bugfix for iOS 6 and 7
Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios
based on the work of https://github.com/stomita/ios-imagefile-megapixel
*/
detectVerticalSquash = function(img) {
var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy;
iw = img.naturalWidth;
ih = img.naturalHeight;
canvas = document.createElement("canvas");
canvas.width = 1;
canvas.height = ih;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
data = ctx.getImageData(0, 0, 1, ih).data;
sy = 0;
ey = ih;
py = ih;
while (py > sy) {
alpha = data[(py - 1) * 4 + 3];
if (alpha === 0) {
ey = py;
} else {
sy = py;
}
py = (ey + sy) >> 1;
}
ratio = py / ih;
if (ratio === 0) {
return 1;
} else {
return ratio;
}
};
drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) {
var vertSquashRatio;
vertSquashRatio = detectVerticalSquash(img);
return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio);
};
/*
* contentloaded.js
*
* Author: Diego Perini (diego.perini at gmail.com)
* Summary: cross-browser wrapper for DOMContentLoaded
* Updated: 20101020
* License: MIT
* Version: 1.2
*
* URL:
* http://javascript.nwbox.com/ContentLoaded/
* http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE
*/
contentLoaded = function(win, fn) {
var add, doc, done, init, poll, pre, rem, root, top;
done = false;
top = true;
doc = win.document;
root = doc.documentElement;
add = (doc.addEventListener ? "addEventListener" : "attachEvent");
rem = (doc.addEventListener ? "removeEventListener" : "detachEvent");
pre = (doc.addEventListener ? "" : "on");
init = function(e) {
if (e.type === "readystatechange" && doc.readyState !== "complete") {
return;
}
(e.type === "load" ? win : doc)[rem](pre + e.type, init, false);
if (!done && (done = true)) {
return fn.call(win, e.type || e);
}
};
poll = function() {
var e;
try {
root.doScroll("left");
} catch (_error) {
e = _error;
setTimeout(poll, 50);
return;
}
return init("poll");
};
if (doc.readyState !== "complete") {
if (doc.createEventObject && root.doScroll) {
try {
top = !win.frameElement;
} catch (_error) {}
if (top) {
poll();
}
}
doc[add](pre + "DOMContentLoaded", init, false);
doc[add](pre + "readystatechange", init, false);
return win[add](pre + "load", init, false);
}
};
Dropzone._autoDiscoverFunction = function() {
if (Dropzone.autoDiscover) {
return Dropzone.discover();
}
};
contentLoaded(window, Dropzone._autoDiscoverFunction);
}).call(this);
});
if (typeof exports == "object") {
module.exports = require("dropzone");
} else if (typeof define == "function" && define.amd) {
define([], function(){ return require("dropzone"); });
} else {
this["Dropzone"] = require("dropzone");
}
})()
<?php namespace Modules\Media\Composers;
use Illuminate\Contracts\View\View;
use Modules\Core\Composers\BaseSidebarViewComposer;
class SidebarViewComposer extends BaseSidebarViewComposer
{
public function compose(View $view)
{
$view->items->put('medias', [
'weight' => 6,
'request' => "*/$view->prefix/media*",
'route' => 'dashboard.media.index',
'icon-class' => 'fa fa-camera',
'title' => 'Medias',
'permission' => $this->auth->hasAccess('media.index')
]);
}
}
<?php
return [
/*
|--------------------------------------------------------------------------
| The path where the media files will be uploaded
|--------------------------------------------------------------------------
*/
'files-path' => '/assets/media/',
/*
|--------------------------------------------------------------------------
| Specify all the allowed file extensions a user can upload on the server
|--------------------------------------------------------------------------
*/
'allowed-types' => '.jpg,.png',
/*
|--------------------------------------------------------------------------
| Determine the max file size upload rate
| Defined in MB
|--------------------------------------------------------------------------
*/
'max-file-size' => '5'
];
<?php
return [
'media' => [
'index',
'create',
'store',
'edit',
'update',
'destroy',
]
];
<?php
return [
'smallThumb' => [
'fit' => [
'width' => 50,
'height' => 50,
'callback' => function($constraint) {
$constraint->upsize();
}
],
]
];
<?php namespace Modules\Media\Console;
use Illuminate\Console\Command;
use Modules\Media\Image\Imagy;
use Modules\Media\Repositories\FileRepository;
class RefreshThumbnailCommand extends Command
{
protected $name = 'asgard:media:refresh';
protected $description = 'Create and or refresh the thumbnails';
/**
* @var Imagy
*/
private $imagy;
/**
* @var FileRepository
*/
private $file;
public function __construct(Imagy $imagy, FileRepository $file)
{
parent::__construct();
$this->imagy = $imagy;
$this->file = $file;
}
/**
* Execute the console command.
*
* @return mixed
*/
public function fire()
{
$this->line('Preparing to regenerate all thumbnails...');
foreach ($this->file->all() as $file) {
$this->imagy->createAll($file->path);
}
$this->info('All thumbnails refreshed');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateFilesTable extends Migration {
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('files', function(Blueprint $table)
{
$table->increments('id');
$table->string('filename');
$table->string('path');
$table->string('extension');
$table->string('mimetype');
$table->string('filesize');
$table->integer('folder_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('files');
}
}
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateFileTranslationsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create(
'file_translations',
function (Blueprint $table) {
$table->increments('id');
$table->integer('file_id')->unsigned();
$table->string('locale')->index();
$table->string('description');
$table->string('alt_attribute');
$table->string('keywords');
$table->unique(['file_id', 'locale']);
$table->foreign('file_id')->references('id')->on('files')->onDelete('cascade');
}
);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('file_translations');
}
}
<?php namespace Modules\Media\Database\Seeders;
use Illuminate\Database\Seeder;
use Illuminate\Database\Eloquent\Model;
class MediaDatabaseSeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Model::unguard();
}
}
<?php namespace Modules\Media\Entities;
use Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
use Translatable;
public $translatedAttributes = ['description', 'alt_attribute', 'keywords'];
protected $fillable = [
'description',
'alt_attribute',
'keywords',
'filename',
'path',
'extension',
'mimetype',
'width',
'height',
'filesize',
'folder_id'
];
}
<?php namespace Modules\Media\Entities;
use Illuminate\Database\Eloquent\Model;
class FileTranslation extends Model
{
public $timestamps = false;
protected $fillable = ['description', 'alt_attribute', 'keywords'];
}
<?php namespace Modules\Media\Helpers;
use Illuminate\Support\Str;
class FileHelper
{
public static function slug($name)
{
$extension = self::getExtension($name);
$name = str_replace($extension, '', $name);
$name = Str::slug($name);
return $name . $extension;
}
/**
* Get the extension from the given name
* @param $name
* @return string
*/
private static function getExtension($name)
{
return substr($name, strrpos($name, '.'));
}
}
<?php namespace Modules\Media\Http\Controllers\Admin;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\View;
use Laracasts\Flash\Flash;
use Modules\Core\Http\Controllers\Admin\AdminBaseController;
use Modules\Media\Entities\File;
use Modules\Media\Http\Requests\UpdateMediaRequest;
use Modules\Media\Image\Imagy;
use Modules\Media\Repositories\FileRepository;
class MediaController extends AdminBaseController
{
/**
* @var FileRepository
*/
private $file;
/**
* @var Repository
*/
private $config;
/**
* @var Imagy
*/
private $imagy;
public function __construct(FileRepository $file, Repository $config, Imagy $imagy)
{
$this->file = $file;
$this->config = $config;
$this->imagy = $imagy;
}
/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{
$files = $this->file->all();
$config = $this->config->get('media::config');
return View::make('media::admin.index', compact('files', 'config'));
}
public function gridFiles()
{
$files = $this->file->all();
return View::make('media::admin.grid', compact('files'));
}
/**
* Show the form for creating a new resource.
*
* @return Response
*/
public function create()
{
return \View::make('media.create');
}
/**
* Store a newly created resource in storage.
*
* @return Response
*/
public function store()
{
//
}
/**
* Show the form for editing the specified resource.
*
* @param File $file
* @return Response
*/
public function edit(File $file)
{
return View::make('media::admin.edit', compact('file'));
}
/**
* Update the specified resource in storage.
*
* @param File $file
* @param UpdateMediaRequest $request
* @return Response
*/
public function update(File $file, UpdateMediaRequest $request)
{
$this->file->update($file, $request->all());
Flash::success('File updated');
return Redirect::route('dashboard.media.index');
}
/**
* Remove the specified resource from storage.
*
* @param File $file
* @internal param int $id
* @return Response
*/
public function destroy(File $file)
{
$this->imagy->deleteAllFor($file);
$this->file->destroy($file);
Flash::success('File deleted');
return Redirect::route('dashboard.media.index');
}
}
<?php namespace Modules\Media\Http\Controllers\Api;
use Illuminate\Support\Facades\Response;
use Modules\Media\Http\Requests\UploadMediaRequest;
use Modules\Media\Services\FileService;
class MediaController
{
/**
* @var FileService
*/
private $fileService;
public function __construct(FileService $fileService)
{
$this->fileService = $fileService;
}
/**
* Store a newly created resource in storage.
*
* @param UploadMediaRequest $request
* @return Response
*/
public function store(UploadMediaRequest $request)
{
$savedFile = $this->fileService->store($request->file('file'));
return Response::json($savedFile->toArray());
}
}
<?php namespace Modules\Media\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UpdateMediaRequest extends FormRequest
{
public function rules()
{
return [];
}
public function authorize()
{
return true;
}
public function messages()
{
return [];
}
}
<?php namespace Modules\Media\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UploadMediaRequest extends FormRequest
{
public function rules()
{
return [];
}
public function authorize()
{
return true;
}
public function messages()
{
return [];
}
}
<?php
use Illuminate\Routing\Router;
$router->model('media', 'Modules\Media\Entities\File');
$router->group(['prefix' => LaravelLocalization::setLocale(), 'before' => 'LaravelLocalizationRedirectFilter|auth.admin|permissions'], function(Router $router)
{
$router->group(['prefix' => Config::get('core::core.admin-prefix'), 'namespace' => 'Modules\Media\Http\Controllers'], function(Router $router)
{
$router->resource('media', 'Admin\MediaController', ['except' => ['show'], 'names' => [
'index' => 'dashboard.media.index',
'create' => 'dashboard.media.create',
'store' => 'dashboard.media.store',
'edit' => 'dashboard.media.edit',
'update' => 'dashboard.media.update',
'destroy' => 'dashboard.media.destroy',
]]);
});
});
$router->get('admin/grid-files', 'Modules\Media\Http\Controllers\Admin\MediaController@gridFiles');
$router->group(['prefix' => 'api', 'namespace' => 'Modules\Media\Http\Controllers'], function (Router $router) {
$router->resource('file', 'Api\MediaController', ['only' => ['store']]);
});
<?php namespace Modules\Media\Image\Facade;
use Illuminate\Support\Facades\Facade;
class Imagy extends Facade
{
protected static function getFacadeAccessor() { return 'imagy'; }
}
<?php namespace Modules\Media\Image;
interface ImageFactoryInterface
{
/**
* Return a new Manipulation class
* @param string $manipulation
* @return \Modules\Media\Image\ImageHandlerInterface
*/
public function make($manipulation);
}
<?php namespace Modules\Media\Image;
interface ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options);
}
<?php namespace Modules\Media\Image;
use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\ServiceProvider;
use Modules\Media\Image\Intervention\InterventionFactory;
class ImageServiceProvider extends ServiceProvider
{
public function boot()
{
$this->package('nwidart/imagy');
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->bind(
'Modules\Media\Image\ImageFactoryInterface',
'Modules\Media\Image\Intervention\InterventionFactory'
);
$this->app['imagy'] = $this->app->share(function ($app) {
$factory = new InterventionFactory;
$thumbnailManager = new ThumbnailsManager($app['config'], $app['modules']);
return new Imagy($factory, $thumbnailManager, $app['config']);
});
$this->app->booting(function()
{
$loader = AliasLoader::getInstance();
$loader->alias('Modules\Media\Image\Facade\Imagy', 'Imagy');
});
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return ['imagy'];
}
}
<?php namespace Modules\Media\Image;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\Facades\App;
use Modules\Media\Entities\File;
class Imagy
{
/**
* @var \Intervention\Image\Image
*/
private $image;
/**
* @var \Illuminate\Filesystem\Filesystem
*/
private $finder;
/**
* @var ImageFactoryInterface
*/
private $imageFactory;
/**
* @var ThumbnailsManager
*/
private $manager;
/**
* All the different images types where thumbnails should be created
* @var array
*/
private $imageExtensions = ['jpg', 'png', 'jpeg', 'gif'];
/**
* @var Repository
*/
private $config;
/**
* @param ImageFactoryInterface $imageFactory
* @param ThumbnailsManager $manager
* @param Repository $config
*/
public function __construct(ImageFactoryInterface $imageFactory, ThumbnailsManager $manager, Repository $config)
{
$this->image = App::make('Intervention\Image\ImageManager');
$this->finder = App::make('Illuminate\Filesystem\Filesystem');
$this->imageFactory = $imageFactory;
$this->manager = $manager;
$this->config = $config;
}
/**
* Get an image in the given thumbnail options
* @param string $path
* @param string $thumbnail
* @param bool $forceCreate
* @return string
*/
public function get($path, $thumbnail, $forceCreate = false)
{
if (!$this->isImage($path)) {
return;
}
$filename = $this->config->get('media::config.files-path') . $this->newFilename($path, $thumbnail);
if ($this->returnCreatedFile($filename, $forceCreate)) {
return $filename;
}
$this->makeNew($path, $filename, $thumbnail);
return $filename;
}
/**
* Return the thumbnail path
* @param string $originalImage
* @param string $thumbnail
* @return string
*/
public function getThumbnail($originalImage, $thumbnail)
{
if (!$this->isImage($originalImage)) {
return $originalImage;
}
return $this->config->get('media::config.files-path') . $this->newFilename($originalImage, $thumbnail);
}
/**
* Create all thumbnails for the given image path
* @param string $path
*/
public function createAll($path)
{
if (!$this->isImage($path)) {
return;
}
foreach ($this->manager->all() as $thumbName => $filters) {
$image = $this->image->make(public_path() . $path);
$filename = $this->config->get('media::config.files-path') . $this->newFilename($path, $thumbName);
foreach ($filters as $manipulation => $options) {
$image = $this->imageFactory->make($manipulation)->handle($image, $options);
}
$image = $image->encode(pathinfo($path, PATHINFO_EXTENSION));
$this->writeImage($filename, $image);
}
}
/**
* Prepend the thumbnail name to filename
* @param $path
* @param $thumbnail
* @return mixed|string
*/
private function newFilename($path, $thumbnail)
{
$filename = pathinfo($path, PATHINFO_FILENAME);
return $filename . '_' . $thumbnail . '.' . pathinfo($path, PATHINFO_EXTENSION);
}
/**
* Return the already created file if it exists and force create is false
* @param string $filename
* @param bool $forceCreate
* @return bool
*/
private function returnCreatedFile($filename, $forceCreate)
{
return $this->finder->isFile(public_path() . $filename) && !$forceCreate;
}
/**
* Write the given image
* @param string $filename
* @param string $image
*/
private function writeImage($filename, $image)
{
$this->finder->put(public_path() . $filename, $image);
}
/**
* Make a new image
* @param string $path
* @param string $filename
* @param string null $thumbnail
*/
private function makeNew($path, $filename, $thumbnail)
{
$image = $this->image->make(public_path() . $path);
foreach ($this->manager->find($thumbnail) as $manipulation => $options) {
$image = $this->imageFactory->make($manipulation)->handle($image, $options);
}
$image = $image->encode(pathinfo($path, PATHINFO_EXTENSION));
$this->writeImage($filename, $image);
}
/**
* Check if the given path is en image
* @param string $path
* @return bool
*/
public function isImage($path)
{
return in_array(pathinfo($path, PATHINFO_EXTENSION), $this->imageExtensions);
}
/**
* Delete all files on disk for the given file in storage
* This means the original and the thumbnails
* @param $file
* @return bool
*/
public function deleteAllFor(File $file)
{
if (!$this->isImage($file->path)) {
return $this->finder->delete($file->path);
}
$paths[] = public_path() . $file->path;
$fileName = pathinfo($file->path, PATHINFO_FILENAME);
$extension = pathinfo($file->path, PATHINFO_EXTENSION);
foreach ($this->manager->all() as $thumbnail => $filters) {
$paths[] = public_path() . $this->config->get(
'media::config.files-path'
) . "{$fileName}_{$thumbnail}.{$extension}";
}
return $this->finder->delete($paths);
}
}
<?php namespace Modules\Media\Image\Intervention;
use Modules\Media\Image\ImageFactoryInterface;
class InterventionFactory implements ImageFactoryInterface
{
/**
* @param string $manipulation
* @return \Modules\Media\Image\ImageHandlerInterface
*/
public function make($manipulation)
{
$class = 'Modules\\Media\\Image\\Intervention\\Manipulations\\'. ucfirst($manipulation);
return new $class;
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Blur implements ImageHandlerInterface
{
private $defaults = [
'amount' => 1
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->blur($options['amount']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Brightness implements ImageHandlerInterface
{
private $defaults = [
'level' => 1
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->brightness($options['level']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Colorize implements ImageHandlerInterface
{
private $defaults = [
'red' => 100,
'green' => 100,
'blue' => 100,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->colorize($options['red'], $options['green'], $options['blue']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Contrast implements ImageHandlerInterface
{
private $defaults = [
'level' => 0
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->contrast($options['level']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Crop implements ImageHandlerInterface
{
private $defaults = [
'width' => '100',
'height' => '100',
'x' => null,
'y' => null,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return mixed
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->crop($options['width'], $options['height'], $options['x'], $options['y']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Fit implements ImageHandlerInterface
{
private $defaults = [
'width' => 100,
'height' => null,
'position' => 'center'
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->fit($options['width'], $options['height'], $callback, $options['position']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Flip implements ImageHandlerInterface
{
private $defaults = [
'mode' => 'h'
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->flip($options['mode']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Gamma implements ImageHandlerInterface
{
private $defaults = [
'correction' => 0
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->gamma($options['correction']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Greyscale implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->greyscale();
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Heighten implements ImageHandlerInterface
{
private $defaults = [
'height' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->heighten($options['height'], $callback);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Invert implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->invert();
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class LimitColors implements ImageHandlerInterface
{
private $defaults = [
'count' => 255,
'matte' => null
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->limitColors($options['count'], $options['matte']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Opacity implements ImageHandlerInterface
{
private $defaults = [
'transparency' => 50
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->opacity($options['transparency']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Orientate implements ImageHandlerInterface
{
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
return $image->orientate();
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Pixelate implements ImageHandlerInterface
{
private $defaults = [
'size' => 0
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->pixelate($options['size']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Resize implements ImageHandlerInterface
{
private $defaults = [
'width' => 200,
'height' => 200,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->resize($options['width'], $options['height'], $callback);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Rotate implements ImageHandlerInterface
{
private $defaults = [
'angle' => 45,
'bgcolor' => '#000000'
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->rotate($options['angle'], $options['bgcolor']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Sharpen implements ImageHandlerInterface
{
private $defaults = [
'amount' => 10
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->sharpen($options['amount']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Trim implements ImageHandlerInterface
{
private $defaults = [
'base' => 'top-left',
'away' => ['top', 'bottom', 'left', 'right'],
'tolerance' => 0,
'feather' => 0,
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
return $image->trim($options['base'], $options['away'], $options['tolerance'], $options['feather']);
}
}
<?php namespace Modules\Media\Image\Intervention\Manipulations;
use Modules\Media\Image\ImageHandlerInterface;
class Widen implements ImageHandlerInterface
{
private $defaults = [
'width' => 0
];
/**
* Handle the image manipulation request
* @param \Intervention\Image\Image $image
* @param array $options
* @return \Intervention\Image\Image
*/
public function handle($image, $options)
{
$options = array_merge($this->defaults, $options);
$callback = isset($options['callback']) ? $options['callback'] : null;
return $image->widen($options['width'], $callback);
}
}
<?php namespace Modules\Media\Image;
use Illuminate\Contracts\Config\Repository;
class ThumbnailsManager
{
/**
* @var Module
*/
private $module;
/**
* @var Repository
*/
private $config;
/**
* @param Repository $config
*/
public function __construct(Repository $config)
{
$this->module = app('modules');
$this->config = $config;
}
/**
* Return all thumbnails for all modules
* @return array
*/
public function all()
{
$thumbnails = [];
foreach ($this->module->enabled() as $enabledModule) {
$configuration = $this->config->get(strtolower($enabledModule->getName()) . '::thumbnails');
$thumbnails = array_merge($thumbnails, $configuration);
}
return $thumbnails;
}
/**
* Find the filters for the given thumbnail
* @param $thumbnail
*/
public function find($thumbnail)
{
foreach ($this->all() as $thumbName => $filters) {
if ($thumbName == $thumbnail) {
return $filters;
}
}
}
}
<?php namespace Modules\Media\Providers;
use Illuminate\Support\ServiceProvider;
use Modules\Media\Console\RefreshThumbnailCommand;
use Modules\Media\Entities\File;
use Modules\Media\Image\Imagy;
use Modules\Media\Image\Intervention\InterventionFactory;
use Modules\Media\Image\ThumbnailsManager;
use Modules\Media\Repositories\Eloquent\EloquentFileRepository;
class MediaServiceProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* @var bool
*/
protected $defer = false;
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
$this->app->booted(function () {
$this->registerBindings();
});
$this->registerCommands();
}
/**
* Get the services provided by the provider.
*
* @return array
*/
public function provides()
{
return array();
}
private function registerBindings()
{
$this->app->bind(
'Modules\Media\Repositories\FileRepository',
function($app) {
return new EloquentFileRepository(new File, $app['filesystem.disk']);
}
);
}
/**
* Register all commands for this module
*/
private function registerCommands()
{
$this->registerRefreshCommand();
}
/**
* Register the refresh thumbnails command
*/
private function registerRefreshCommand()
{
$this->app->bindShared('command.media.refresh', function($app) {
$thumbnailManager = new ThumbnailsManager($app['config'], $app['modules']);
$imagy = new Imagy(new InterventionFactory, $thumbnailManager, $app['config']);
return new RefreshThumbnailCommand($imagy, $app['Modules\Media\Repositories\FileRepository']);
});
$this->commands(
'command.media.refresh'
);
}
}
<?php namespace Modules\Media\Providers;
use Illuminate\Routing\Router;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
/**
* The root namespace to assume when generating URLs to actions.
*
* @var string
*/
protected $rootUrlNamespace = 'Modules\Setting\Http\Controllers';
/**
* The controllers to scan for route annotations.
*
* @var array
*/
protected $scan = [
'Modules\Setting\Http\Controllers',
];
/**
* Called before routes are registered.
*
* Register any model bindings or pattern based filters.
*
* @param Router $router
* @return void
*/
public function before(Router $router)
{
//
}
/**
* Define the routes for the application.
*
* @return void
*/
public function map(Router $router)
{
require __DIR__ . '/../Http/routes.php';
}
}
<?php namespace Modules\Media\Repositories\Eloquent;
use Modules\Core\Repositories\Eloquent\EloquentBaseRepository;
use Modules\Media\Entities\File;
use Modules\Media\Helpers\FileHelper;
use Modules\Media\Repositories\FileRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class EloquentFileRepository extends EloquentBaseRepository implements FileRepository
{
/**
* Update a resource
* @param File $file
* @param $data
* @return mixed
*/
public function update($file, $data)
{
$file->update($data);
return $file;
}
/**
* Create a file row from the given file
* @param UploadedFile $file
* @return mixed
*/
public function createFromFile(UploadedFile $file)
{
$fileName = FileHelper::slug($file->getClientOriginalName());
return $this->model->create([
'filename' => $fileName,
'path' => "/assets/media/{$fileName}",
'extension' => $file->guessClientExtension(),
'mimetype' => $file->getClientMimeType(),
'filesize' => $file->getFileInfo()->getSize(),
]);
}
public function destroy($file)
{
$file->delete();
}
}
<?php namespace Modules\Media\Repositories;
use Modules\Core\Repositories\BaseRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
interface FileRepository extends BaseRepository
{
/**
* Create a file row from the given file
* @param UploadedFile $file
* @return mixed
*/
public function createFromFile(UploadedFile $file);
}
<?php
return [
'title' => [
'media' => 'Media',
'edit media' => 'Edit media'
],
'breadcrumb' => [
'media' => 'Media'
],
'table' => [
'filename' => 'Filename',
'width' => 'Width',
'height' => 'Height'
],
'form' => [
'alt_attribute' => 'Alt attribute',
'description' => 'Description',
'keywords' => 'Keywords',
],
'choose file' => 'Choose a file',
'insert' => 'Insert this file',
'file picker' => 'File Picker'
];
<?php
return [
'title' => [
'media' => 'Média',
'edit media' => 'Edition de média'
],
'breadcrumb' => [
'media' => 'Média'
],
'table' => [
'filename' => 'Nom de fichier',
'width' => 'Largeur',
'height' => 'Hauteur'
],
'choose file' => 'Choissisez un fichier',
'insert' => 'Sélectionner ce fichier',
'file picker' => 'Sélectionneur de fichier'
];
@extends('core::layouts.master')
@section('content-header')
<h1>
{{ trans('media::media.title.edit media') }} <small>{{ $file->name }}</small>
</h1>
<ol class="breadcrumb">
<li><a href="{{ URL::route('dashboard.index') }}"><i class="fa fa-dashboard"></i> {{ trans('core::core.breadcrumb.home') }}</a></li>
<li><a href="{{ URL::route('dashboard.media.index') }}">{{ trans('media::media.title.media') }}</a></li>
<li class="active">{{ trans('media::media.title.edit media') }}</li>
</ol>
@stop
@section('content')
{!! Form::open(['route' => ['dashboard.media.update', $file->id], 'method' => 'put']) !!}
<div class="row">
<div class="col-md-8">
<div class="nav-tabs-custom">
@include('core::partials.form-tab-headers')
<div class="tab-content">
<?php $i = 0; ?>
<?php foreach(LaravelLocalization::getSupportedLocales() as $locale => $language): ?>
<?php $i++; ?>
<div class="tab-pane {{ App::getLocale() == $locale ? 'active' : '' }}" id="tab_{{ $i }}">
@include('media::admin.partials.edit-fields', ['lang' => $locale])
</div>
<?php endforeach; ?>
<div class="box-footer">
<button type="submit" class="btn btn-primary btn-flat">{{ trans('core::core.button.update') }}</button>
<a class="btn btn-danger pull-right btn-flat" href="{{ URL::route('dashboard.media.index')}}"><i class="fa fa-times"></i> {{ trans('core::core.button.cancel') }}</a>
</div>
</div>
</div> {{-- end nav-tabs-custom --}}
</div>
<div class="col-md-4">
<img src="{{ $file->path }}" alt="" style="width: 100%;"/>
</div>
</div>
{!! Form::close() !!}
@stop
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ trans('media::media.file picker') }}</title>
<link href="{!! Module::asset('core:css/vendor/bootstrap.min.css') !!}" rel="stylesheet" type="text/css" />
<script src="{!! Module::asset('core:js/vendor/jquery.min.js') !!}"></script>
<style>
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8">
<h1>{{ trans('media::media.choose file') }}</h1>
<?php if ($files): ?>
<ul class="list-unstyled">
<?php foreach($files as $file): ?>
<li class="pull-left" style="margin-right: 20px">
<img src="{{ $file->path }}" alt="" class="img-thumbnail" style="width: 250px;"/>
<a class="jsInsertImage btn btn-primary btn-flat" href="#" style="display: block">{{ trans('media::media.insert') }}</a>
</li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</div>
</div>
</div>
<script>
$( document ).ready(function() {
$('.jsInsertImage').on('click', function(e) {
e.preventDefault();
function getUrlParam( paramName ) {
var reParam = new RegExp( '(?:[\?&]|&)' + paramName + '=([^&]+)', 'i' ) ;
var match = window.location.search.match(reParam) ;
return ( match && match.length > 1 ) ? match[ 1 ] : null ;
}
var funcNum = getUrlParam( 'CKEditorFuncNum' );
window.opener.CKEDITOR.tools.callFunction( funcNum, $(this).parent().find('img').attr('src') );
window.close();
});
});
</script>
</body>
</html>
@extends('core::layouts.master')
@section('content-header')
<h1>
{{ trans('media::media.title.media') }}
</h1>
<ol class="breadcrumb">
<li><a href="{{ URL::route('dashboard.index') }}"><i class="fa fa-dashboard"></i> {{ trans('core::core.breadcrumb.home') }}</a></li>
<li><i class="fa fa-camera"></i> {{ trans('media::media.breadcrumb.media') }}</li>
</ol>
@stop
@section('styles')
<link href="{!! Module::asset('media:css/dropzone.css') !!}" rel="stylesheet" type="text/css" />
<style>
.dropzone {
border: 1px dashed #CCC;
min-height: 227px;
margin-bottom: 20px;
}
</style>
@stop
@section('content')
<div class="row col-md-12">
<form action="{{ URL::route('api.file.store')}}" method="POST" class="dropzone">
{!! Form::token() !!}
</form>
</div>
<div class="row">
<div class="col-md-12">
<div class="box box-info">
<div class="box-body table-responsive">
<table class="data-table table table-bordered table-hover jsFileList">
<thead>
<tr>
<th>{{ trans('media::media.table.filename') }}</th>
<th>{{ trans('core::core.table.thumbnail') }}</th>
<th>{{ trans('media::media.table.filename') }}</th>
<th>{{ trans('core::core.table.actions') }}</th>
</tr>
</thead>
<tbody>
<?php if ($files): ?>
<?php foreach($files as $file): ?>
<tr>
<td>
<a href="{{ URL::route('dashboard.media.edit', [$file->id]) }}">
{{ $file->created_at }}
</a>
</td>
<td>
<img src="{{ Imagy::getThumbnail($file->path, 'smallThumb') }}" alt=""/>
</td>
<td>
<a href="{{ URL::route('dashboard.media.edit', [$file->id]) }}">
{{ $file->filename }}
</a>
</td>
<td>
<div class="btn-group">
<a href="{{ URL::route('dashboard.media.edit', [$file->id]) }}" class="btn btn-default btn-flat"><i class="glyphicon glyphicon-pencil"></i></a>
<button class="btn btn-danger btn-flat" data-toggle="modal" data-target="#confirmation-{{ $file->id }}"><i class="glyphicon glyphicon-trash"></i></button>
</div>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
<tfoot>
<tr>
<th>{{ trans('core::core.table.created at') }}</th>
<th>{{ trans('core::core.table.thumbnail') }}</th>
<th>{{ trans('media::media.table.filename') }}</th>
<th>{{ trans('core::core.table.actions') }}</th>
</tr>
</tfoot>
</table>
<!-- /.box-body -->
</div>
</div>
</div>
</div>
<?php if ($files): ?>
<?php foreach($files as $file): ?>
<!-- Modal -->
<div class="modal fade" id="confirmation-{{ $file->id }}" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="myModalLabel">{{ trans('core::core.modal.title') }}</h4>
</div>
<div class="modal-body">
{{ trans('core::core.modal.confirmation-message') }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('core::core.button.cancel') }}</button>
{!! Form::open(['route' => ['dashboard.media.destroy', $file->id], 'method' => 'delete', 'class' => 'pull-left']) !!}
<button type="submit" class="btn btn-danger btn-flat"><i class="glyphicon glyphicon-trash"></i> {{ trans('core::core.button.delete') }}</button>
{!! Form::close() !!}
</div>
</div>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
@stop
@section('scripts')
<script src="{!! Module::asset('media:js/dropzone.js') !!}"></script>
<script>
$( document ).ready(function() {
Dropzone.autoDiscover = false;
var myDropzone = new Dropzone(".dropzone", {
url: $(this).attr('action'),
autoProcessQueue: true,
maxFilesize: '<?php echo $config["max-file-size"] ?>',
acceptedFiles : '<?php echo $config["allowed-types"] ?>'
});
myDropzone.on("success", function(file, http) {
var _this = this;
window.setTimeout(function(){
$(file.previewElement).fadeOut('fast', function(){
_this.removeFile(file);
});
var tableRow = '<tr><td>' + http.created_at + '</td><td></td><td>'+http.filename+'</td><td></td></tr>';
var elem = $(tableRow).css('display', 'none');
$('.jsFileList tbody').prepend(elem);
elem.fadeIn();
}, 1000);
});
});
</script>
<?php $locale = App::getLocale(); ?>
<script type="text/javascript">
$(function () {
$('.data-table').dataTable({
"bPaginate": true,
"bLengthChange": true,
"bFilter": true,
"bSort": true,
"bInfo": true,
"bAutoWidth": true,
"oLanguage": {
"sUrl": '<?php echo Module::asset("core:js/vendor/datatables/{$locale}.json") ?>'
},
"aoColumns": [
null,
null,
null,
{ "bSortable": false }
]
});
});
</script>
@stop
<?php $altAttribute = isset($file->translate($lang)->alt_attribute) ? $file->translate($lang)->alt_attribute : '' ?>
<div class='form-group{{ $errors->has("{$lang}[alt_attribute]") ? ' has-error' : '' }}'>
{!! Form::label("{$lang}[alt_attribute]", trans('media::media.form.alt_attribute')) !!}
{!! Form::text("{$lang}[alt_attribute]", Input::old("{$lang}[alt_attribute]", $altAttribute), ['class' => 'form-control', 'placeholder' => trans('media::media.form.alt_attribute')]) !!}
{!! $errors->first("{$lang}[alt_attribute]", '<span class="help-block">:message</span>') !!}
</div>
<?php $description = isset($file->translate($lang)->description) ? $file->translate($lang)->alt_attribute : '' ?>
<div class='form-group{{ $errors->has("{$lang}[description]") ? ' has-error' : '' }}'>
{!! Form::label("{$lang}[description]", trans('media::media.form.description')) !!}
{!! Form::textarea("{$lang}[description]", Input::old("{$lang}[description]", $description), ['class' => 'form-control', 'placeholder' => trans('media::media.form.description')]) !!}
{!! $errors->first("{$lang}[description]", '<span class="help-block">:message</span>') !!}
</div>
<?php $keywords = isset($file->translate($lang)->keywords) ? $file->translate($lang)->alt_attribute : '' ?>
<div class='form-group{{ $errors->has("{$lang}[keywords]") ? ' has-error' : '' }}'>
{!! Form::label("{$lang}[keywords]", trans('media::media.form.keywords')) !!}
{!! Form::text("{$lang}[keywords]", Input::old("{$lang}[keywords]", $keywords), ['class' => 'form-control', 'placeholder' => trans('media::media.form.keywords')]) !!}
{!! $errors->first("{$lang}[keywords]", '<span class="help-block">:message</span>') !!}
</div>
<?php namespace Modules\Media\Services;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Queue\Queue;
use Illuminate\Queue\Jobs\Job;
use Illuminate\Support\Facades\App;
use Modules\Media\Repositories\FileRepository;
use Symfony\Component\HttpFoundation\File\UploadedFile;
class FileService
{
/**
* @var FileRepository
*/
private $file;
/**
* @var Repository
*/
private $config;
/**
* @var Queue
*/
private $queue;
public function __construct(
FileRepository $file,
Repository $config,
Queue $queue)
{
$this->file = $file;
$this->config = $config;
$this->queue = $queue;
}
/**
* @param UploadedFile $file
* @return mixed
*/
public function store(UploadedFile $file)
{
// Save the file info to db
$savedFile = $this->file->createFromFile($file);
// Move the uploaded file to files path
$file->move(public_path() . $this->config->get('media::config.files-path'), $savedFile->filename);
$this->createThumbnails($savedFile);
return $savedFile;
}
/**
* Create the necessary thumbnails for the given file
* @param $savedFile
*/
private function createThumbnails($savedFile)
{
$this->queue->push(function(Job $job) use ($savedFile)
{
App::make('imagy')->createAll($savedFile->path);
$job->delete();
});
}
}
<?php namespace Modules\Media\Tests;
use Modules\Core\Tests\BaseTestCase;
use Modules\Media\Helpers\FileHelper;
class FileHelperTest extends BaseTestCase
{
/** @test */
public function it_should_return_slugged_name_with_extension()
{
$expected = 'file-name.png';
$name = FileHelper::slug('File Name.png');
$this->assertEquals($expected, $name);
}
}
<?php namespace Modules\Media\Tests;
use Illuminate\Support\Facades\App;
use Modules\Core\Tests\BaseTestCase;
use Modules\Media\Image\Imagy;
use Modules\Media\Image\Intervention\InterventionFactory;
use Modules\Media\Image\ThumbnailsManager;
class ImagyTest extends BaseTestCase
{
/**
* @var Imagy
*/
protected $imagy;
/**
* @var \Illuminate\Filesystem\Filesystem
*/
protected $finder;
/**
* @var \Illuminate\Contracts\Config\Repository
*/
protected $config;
/**
* @var string
*/
protected $mediaPath;
/**
*
*/
public function setUp()
{
parent::setUp();
$this->config = App::make('Illuminate\Contracts\Config\Repository');
$module = App::make('modules');
$this->finder = App::make('Illuminate\Filesystem\Filesystem');
$this->imagy = new Imagy(new InterventionFactory, new ThumbnailsManager($this->config, $module), $this->config);
$this->mediaPath = $this->config->get('media::config.files-path');
}
/** @test */
public function it_should_create_a_file()
{
if ($this->finder->isFile(public_path() . "{$this->mediaPath}google-map_smallThumb.png")) {
$this->finder->delete(public_path() . "{$this->mediaPath}google-map_smallThumb.png");
}
$this->imagy->get("{$this->mediaPath}google-map.png", 'smallThumb', true);
$this->assertTrue($this->finder->isFile(public_path() . "{$this->mediaPath}google-map_smallThumb.png"));
}
/** @test */
public function it_should_not_create_thumbs_for_pdf_files()
{
$this->imagy->get("{$this->mediaPath}test-pdf.pdf", 'smallThumb', true);
$this->assertFalse($this->finder->isFile(public_path() . "{$this->mediaPath}test-pdf_smallThumb.png"));
}
/** @test */
public function it_should_return_thumbnail_path()
{
$path = $this->imagy->getThumbnail("{$this->mediaPath}google-map.png", 'smallThumb');
$expected = "{$this->mediaPath}google-map_smallThumb.png";
$this->assertEquals($expected, $path);
}
/** @test */
public function it_should_return_same_path_for_non_images()
{
$path = $this->imagy->getThumbnail("{$this->mediaPath}test-pdf.pdf", 'smallThumb');
$expected = "{$this->mediaPath}test-pdf.pdf";
$this->assertEquals($expected, $path);
}
/** @test */
public function it_should_detect_an_image()
{
$jpg = $this->imagy->isImage('image.jpg');
$png = $this->imagy->isImage('image.png');
$pdf = $this->imagy->isImage('pdf.pdf');
$this->assertTrue($jpg);
$this->assertTrue($png);
$this->assertFalse($pdf);
}
}
<?php
View::composer('core::partials.sidebar-nav', 'Modules\Media\Composers\SidebarViewComposer');
{
"name": "Media",
"alias": "media",
"description": "",
"keywords": [
],
"active": 1,
"require": {
"intervention/image": "~2.0"
},
"providers": [
"Modules\\Media\\Providers\\MediaServiceProvider",
"Modules\\Media\\Providers\\RouteServiceProvider",
"Modules\\Media\\Image\\ImageServiceProvider"
]
}
# Media Module
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/648270bf-8b9c-4994-b006-a948fef307b2/mini.png)](https://insight.sensiolabs.com/projects/648270bf-8b9c-4994-b006-a948fef307b2)
[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/AsgardCms/Media/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/AsgardCms/Media/?branch=master)
[![Code Climate](https://codeclimate.com/github/AsgardCms/Media/badges/gpa.svg)](https://codeclimate.com/github/AsgardCms/Media)
<?php
/*
|--------------------------------------------------------------------------
| Register The Module Namespaces
|--------------------------------------------------------------------------
|
| Here is you can register the namespace for this module.
| You may to edit this namespace if you want.
|
*/
View::addNamespace('media', __DIR__ . '/Resources/views/');
Lang::addNamespace('media', __DIR__ . '/Resources/lang/');
Config::addNamespace('media', __DIR__ . '/Config/');
require __DIR__ . '/composers.php';
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment