webgme
Version:
Web-based Generic Modeling Environment
345 lines (280 loc) • 10.8 kB
JavaScript
/*globals define, $, WebGMEGlobal*/
/*jshint browser: true*/
/**
* @author rkereskenyi / https://github.com/rkereskenyi
*/
define([
'js/Controls/PropertyGrid/Widgets/WidgetBase',
'blob/BlobClient',
'js/logger',
'common/regexp',
'css!./styles/AssetWidget.css'
], function (WidgetBase,
BlobClient,
Logger,
RegExp) {
'use strict';
var AssetWidget,
BTN_ATTACH = $('<a class="btn btn-mini btn-dialog-open"><i class="glyphicon glyphicon-file"/></a>'),
INPUT_FILE_UPLOAD = $('<input type="file" />'),
//MAX_FILE_SIZE = 100000000,
ASSET_WIDGET_BASE = $('<div class="asset-widget" />'),
ASSET_PROGRESS_BASE = $('<div class="upload-progress-bar" />'),
ASSET_LINK = $('<a class="blob-download-link" href="" target="_self"/>');
AssetWidget = function (propertyDesc) {
WidgetBase.call(this, propertyDesc);
var self = this;
if (propertyDesc.readOnly) {
this._alwaysReadOnly = true;
}
this._logger = Logger.create('gme:js:Controls:PropertyGrid:Widgets:AssetWidget',
WebGMEGlobal.gmeConfig.client.log);
this.__el = ASSET_WIDGET_BASE.clone();
this.el.append(this.__el);
this.__progressBar = ASSET_PROGRESS_BASE.clone();
this.__el.append(this.__progressBar);
this.__progressBar.hide();
this.__assetLink = ASSET_LINK.clone();
this.__el.append(this.__assetLink);
this.__editArea = $('<div>', {class: 'edit-area'});
this.__el.append(this.__editArea);
this.__fileDropTarget = this.__el;
this.__btnAttach = BTN_ATTACH.clone();
this.__el.append(this.__btnAttach);
this.__fileUploadInput = INPUT_FILE_UPLOAD.clone();
this.__files = [];
this.__timeoutId = null;
this._attachFileDropHandlers();
this.updateDisplay();
this.__el.on('dblclick', function () {
if (self._isReadOnly || self.__progressBar.is(':visible')) {
return;
}
self.__btnAttach.hide();
self.__assetLink.hide();
self.__editArea.editInPlace({
class: 'in-place-edit',
value: self.propertyValue,
enableEmpty: true,
css: {
'font-size': '11px'
},
onChange: function (oldValue, newValue) {
if (RegExp.BLOB_HASH.test(newValue) || newValue === '') {
self.setValue(newValue);
self.fireFinishChange();
}
},
onFinish: function () {
// Wait for the new value to be accepted..
self.__btnAttach.show();
self.__assetLink.show();
self.__editArea.empty();
}
});
});
};
AssetWidget.prototype = Object.create(WidgetBase.prototype);
AssetWidget.prototype.constructor = AssetWidget;
AssetWidget.prototype._attachFileDropHandlers = function () {
var self = this;
this.__btnAttach.on('click', function (e) {
e.stopPropagation();
e.preventDefault();
self.__fileUploadInput.click();
});
// file select
this.__fileUploadInput.on('change', function (event) {
event.stopPropagation();
event.preventDefault();
self._fileSelectHandler(event.originalEvent);
});
//filedrag
this.__fileDropTarget.on('dragover', function (event) {
event.stopPropagation();
event.preventDefault(); //IE 10 needs this to ba able to drop
});
this.__fileDropTarget.on('dragenter', function (event) {
event.stopPropagation();
event.preventDefault();
self.__fileDropTarget.addClass('hover');
});
this.__fileDropTarget.on('dragleave', function (event) {
event.stopPropagation();
event.preventDefault();
self.__fileDropTarget.removeClass('hover');
});
this.__fileDropTarget.on('drop', function (event) {
event.stopPropagation();
event.preventDefault();
self.__fileDropTarget.removeClass('hover');
self._fileSelectHandler(event.originalEvent);
});
};
AssetWidget.prototype._detachFileDropHandlers = function () {
// file select
this.__fileUploadInput.off('change');
//filedrag
this.__fileDropTarget.off('dragover');
this.__fileDropTarget.off('dragenter');
this.__fileDropTarget.off('dragleave');
this.__fileDropTarget.off('drop');
this.__btnAttach.off('click');
};
AssetWidget.prototype.updateDisplay = function () {
var bc = new BlobClient({logger: this._logger.fork('BlobClient')}),
urlDownload = this.propertyValue ? bc.getDownloadURL(this.propertyValue) : '',
text = this.propertyValue,
self = this;
this.__assetLink.text(text);
this.__assetLink.attr('title', text);
this.__assetLink.attr('href', urlDownload);
if (this.propertyValue) {
bc.getMetadata(this.propertyValue, function (err, fileInfo) {
if (err) {
//TODO: more meaningful error message
text = 'ERROR...';
} else {
text = fileInfo.name + ' (' + bc.getHumanSize(fileInfo.size) + ')';
}
self.__assetLink.text(text);
self.__assetLink.attr('title', text);
});
}
return WidgetBase.prototype.updateDisplay.call(this);
};
AssetWidget.prototype.setReadOnly = function (isReadOnly) {
WidgetBase.prototype.setReadOnly.call(this, isReadOnly);
if (this.__btnAttach) {
if (this._isReadOnly === true) {
this.__btnAttach.disable(true);
} else {
this.__btnAttach.disable(false);
}
}
this._detachFileDropHandlers();
if (this._isReadOnly !== true) {
this._attachFileDropHandlers();
}
};
AssetWidget.prototype._fileSelectHandler = function (event) {
var self = this,
blobClient,
i,
file,
files,
afName,
artifact,
remainingFiles,
addedFileAsSoftLink;
function uploadProgressHandler(fName, e) {
var currentFile = self.__progressBar.text();
if (self.__timeoutId) {
return;
}
if (currentFile === '' || currentFile === fName) {
if (typeof e.percent === 'number' && e.percent !== 100) {
self.__progressBar.width(e.percent + '%');
self.__progressBar.text(fName);
} else {
self.__progressBar.text('');
}
} else if (e.percent === 100) {
self.__progressBar.width(e.percent + '%');
self.__progressBar.text(fName);
self.__timeoutId = setTimeout(function () {
if (self.__progressBar) {
self.__progressBar.text('');
self.__progressBar.width(0);
}
self.__timeoutId = null;
}, 500);
}
}
function afterUpload(err, hash) {
self.__assetLink.show();
self.__progressBar.width(0);
self.__progressBar.text('');
self.__progressBar.hide();
self.__timeoutId = null;
if (err) {
self._logger.error(err);
} else {
self.setValue(hash);
self.fireFinishChange();
self._attachFileDropHandlers(false);
}
}
blobClient = new BlobClient({
logger: this._logger.fork('BlobClient'),
uploadProgressHandler: uploadProgressHandler
});
// cancel event and hover styling
event.stopPropagation();
event.preventDefault();
// fetch FileList object
files = event.target.files || event.dataTransfer.files;
// process all File objects
if (files && files.length > 0) {
this.__files = files;
this._detachFileDropHandlers(true);
this.__assetLink.hide();
this.__progressBar.show();
afName = self.propertyName;
artifact = blobClient.createArtifact(afName);
remainingFiles = files.length;
addedFileAsSoftLink = function (err, hash) {
remainingFiles -= 1;
if (err) {
//TODO: something went wrong, tell the user????
} else {
// successfully uploaded
}
if (remainingFiles === 0) {
if (files.length > 1) {
artifact.save(function (err, artifactHash) {
afterUpload(err, artifactHash);
});
} else {
afterUpload(err, hash);
}
}
};
for (i = 0; i < files.length; i += 1) {
file = files[i];
artifact.addFileAsSoftLink(file.name, file, addedFileAsSoftLink);
}
}
};
AssetWidget.prototype.getTargetAsJson = function (callback) {
var self = this,
file,
parsedContent = null,
reader;
if (this.__files && this.__files.length > 0) {
file = this.__files[0];
reader = new FileReader();
reader.onload = function (e) {
if (e.target && e.target.result) {
try {
parsedContent = JSON.parse(e.target.result);
} catch (exp) {
self._logger.error('failed to read asset on the client side', exp);
parsedContent = null;
}
}
callback(parsedContent);
};
reader.readAsText(file);
} else {
callback(null);
}
};
AssetWidget.prototype.destroy = function () {
this._detachFileDropHandlers();
this.__el.off('dblclick');
clearTimeout(this.__timeoutId);
WidgetBase.prototype.destroy.call(this);
};
return AssetWidget;
});