/**
* Yona, 21st Century Project Hosting SW
*
* Copyright Yona & Yobi Authors & NAVER Corp. & NAVER LABS Corp.
* https://yona.io
**/
yobi.Attachments = function(htOptions) {
var htVar = {};
var htElements = {};
/**
* initialize fileUploader
*
* @param {Hash Table} htOptions
* @param {Variant} htOptions.elContainer
* @param {Variant} htOptions.elTextarea
* @param {String} htOptions.sTplFileList
* @param {String} htOptions.sTplFileItem
* @param {String} htOptions.sResourceId
* @param {String} htOptions.sResourceType
* @param {String} htOptions.sUploaderID
*/
function _init(htOptions){
htOptions = htOptions || {};
_initVar(htOptions);
_initElement(htOptions);
// Request attachments only if the container is specified.
if (htVar.attachments) {
_updateAttachments(htVar.attachments);
} else if ((htVar.sResourceType && htVar.sResourceId) || htVar.attachments) {
_requestList();
}
if(htOptions.sUploaderId){
_attachUploaderEvent(htOptions.sUploaderId);
}
}
/**
* @param {Hash Table} htOptions
*/
function _initVar(htOptions){
var sFileLink = '${fileName}(${fileSizeReadable})';
var sFileDownloadLink = '';
htVar.sTplFileList = htOptions.sTplFileList || '
';
htVar.sTplFileItem = htOptions.sTplFileItem || '- '+ sFileDownloadLink + sFileLink + '
';
htVar.sResourceId = htOptions.sResourceId; // ResId: Optional
htVar.sResourceType = htOptions.sResourceType; // ResType: Required
}
/**
* @param {Hash Table} htOptions
*/
function _initElement(htOptions){
// parentForm
htElements.welToAttach = htOptions.targetFormId || $(htOptions.elContainer);
var sTagName = htOptions.sTagNameForTemporaryUploadFiles || "temporaryUploadFiles";
htElements.welTemporaryUploadFileList = $('');
htElements.welToAttach.prepend(htElements.welTemporaryUploadFileList);
htVar.aTemporaryFileIds = [];
// welContainer
htElements.welContainer = $(htOptions.elContainer);
htElements.welContainer.data("isYobiAttachment", true);
htVar.sResourceId = htVar.sResourceId || htElements.welContainer.data('resourceId');
htVar.sResourceType = htVar.sResourceType || htElements.welContainer.data('resourceType');
if (!htVar.attachments) {
htVar.attachments = htElements.welContainer.data('attachments');
}
// welTextarea (Optional)
htElements.welTextarea = $(htOptions.elTextarea);
// attached files list
htElements.welFileList = htElements.welContainer.find("ul.attached-files");
htElements.welFileListHelp = htElements.welContainer.find("p.help");
// -- help messages for additional uploader features
var htEnv = yobi.Files.getEnv();
htElements.welHelpDroppable = htElements.welContainer.find(".help-droppable");
htElements.welHelpPastable = htElements.welContainer.find(".help-pastable");
htElements.welHelpDroppable[htEnv.bDroppable ? "show" : "hide"]();
htElements.welHelpPastable[htEnv.bPastable ? "show" : "hide"]();
}
/**
* 이벤트 핸들러 설정
* attach Uploader custom event handlers
*
* @param {String} sUploaderId
*/
function _attachUploaderEvent(sUploaderId){
yobi.Files.attach({
"beforeUpload" : _onBeforeUpload,
"uploadProgress": _onUploadProgress,
"successUpload" : _onSuccessUpload,
"errorUpload" : _onErrorUpload,
"pasteFile" : _onPasteFile,
"pasteMarkdownTable" : _onPasteMarkdownTable,
"dropFile" : _onDropFile
}, sUploaderId);
}
/**
* attach Uploader custom event handlers
*
* @param {String} sUploaderId
*/
function _detachUploaderEvent(sUploaderId){
yobi.Files.detach({
"beforeUpload" : _onBeforeUpload,
"uploadProgress": _onUploadProgress,
"successUpload" : _onSuccessUpload,
"errorUpload" : _onErrorUpload,
"pasteFile" : _onPasteFile,
"dropFile" : _onDropFile
}, sUploaderId);
}
/**
* beforeUpload single file
*
* @param {File} htOptions.oFile
* @param {Number} htOptions.nSubmitId
*/
function _onBeforeUpload(htOptions){
_appendFileItem({
"vFile" : (htOptions.oFile.files ? htOptions.oFile.files[0] : htOptions.oFile), // Object
"bTemporary": true
});
}
/**
* @param {Hash Table} htData
* @param {Variant} htData.vFile
* @param {Boolean} htData.bTemporary
*
* @return {Number}
*/
function _appendFileItem(htData){
if(typeof htData.vFile === "undefined"){
return 0;
}
var welItem;
var nFileSize = 0;
var aWelItems = [];
var aFiles = (htData.vFile instanceof Array) ? htData.vFile : [htData.vFile]; // 배열 변수로 단일화
aFiles.forEach(function(oFile) {
welItem = _getFileItem(oFile, htData.bTemporary);
if(typeof oFile.id !== "undefined" && oFile.id !== ""){
welItem.addClass("complete");
if(htElements.welTextarea.length > 0){
welItem.click(_onClickListItem);
}
} else {
welItem.attr("id", oFile.nSubmitId);
welItem.css("opacity", "0.2");
welItem.data("progressBar", welItem.find(".progress > .bar"));
}
aWelItems.push(welItem);
nFileSize += parseInt(oFile.size, 10);
});
if(aWelItems.length > 0){
if(htElements.welFileList.length === 0){
htElements.welFileList = $(htVar.sTplFileList);
htElements.welContainer.append(htElements.welFileList);
}
htElements.welFileList.show();
htElements.welFileListHelp.show();
htElements.welFileList.append(aWelItems);
}
return nFileSize;
}
/**
* Create uploaded file item HTML element using template string
*
* @param {Hash Table} htFile
* @param {Boolean} bTemp
*
* @return {Wrapped Element}
*/
function _getFileItem(htFile, bTemp) {
var welItem = $.tmpl(htVar.sTplFileItem, {
"fileId" : htFile.id,
"fileName": htFile.name,
"fileHref": htFile.url,
"fileSize": htFile.size,
"fileSizeReadable": humanize.filesize(htFile.size),
"mimeType": htFile.mimeType
});
_showMimetypeIcon(welItem, htFile.mimeType);
if(bTemp){
welItem.addClass("temporary");
}
return welItem;
}
/**
* @param {Number} nSubmitId
* @param {Object} oRes
*/
function _updateFileItem(nSubmitId, oRes){
var welItem = $("#" + nSubmitId);
var welItemExists = htElements.welFileList.find('[data-id="' + oRes.id + '"]');
if(welItemExists.length > 0){
welItem.remove();
_blinkFileItem(welItemExists);
return false;
}
welItem.attr({
"data-id" : oRes.id,
"data-href": oRes.url,
"data-name": oRes.name,
"data-mime": oRes.mimeType
});
// for IE (uploadFileForm)
welItem.find(".name").html(oRes.name);
welItem.find(".size").html(humanize.filesize(oRes.size));
welItem.click(_onClickListItem);
}
function _blinkFileItem(welItem, sBlinkColor){
var sBgColor;
sBlinkColor = sBlinkColor || "#f36c22";
sBgColor = welItem.css("background");
welItem.css("background", sBlinkColor);
setTimeout(function(){
welItem.css("background", sBgColor);
}, 500);
}
function _addUploadFileIdToListAndForm(sFileId) {
if(htVar.aTemporaryFileIds.indexOf(sFileId) === -1) {
htVar.aTemporaryFileIds.push(sFileId);
htElements.welTemporaryUploadFileList.val(htVar.aTemporaryFileIds.join(","));
}
}
function _removeDeletedFileIdFromListAndForm(sFileId) {
var nIndex = htVar.aTemporaryFileIds.indexOf(sFileId.toString());
if( nIndex !== -1){
htVar.aTemporaryFileIds.splice(nIndex, 1);
htElements.welTemporaryUploadFileList.val(htVar.aTemporaryFileIds.join(","));
}
}
/**
* On success to submit temporary form created in onChangeFile()
*
* @param {Hash Table} htData
* @param {Number} htData.nSubmitId
* @param {Object} htData.oRes
* @return
*/
function _onSuccessUpload(htData){
var oRes = htData.oRes;
var nSubmitId = htData.nSubmitId;
_addUploadFileIdToListAndForm(htData.oRes.id);
// Validate server response
if(!(oRes instanceof Object) || !oRes.name || !oRes.url){
return _onErrorUpload(nSubmitId, oRes);
}
if(_updateFileItem(nSubmitId, oRes) !== false){
_setProgressBar(nSubmitId, 100);
}
var aFileItemQuery = [
"#" + htData.nSubmitId,
'.attached-file[data-id="' + htData.oRes.id + '"]'
];
var welFileItem = $(aFileItemQuery.join(", "));
var sTempLink = _getTempLinkText(htData.nSubmitId);
var sRealLink = _getLinkText(welFileItem);
_replaceLinkInTextarea(sTempLink, sRealLink);
_showMimetypeIcon(welFileItem, htData.oRes.mimeType);
}
/**
* uploadProgress event handler
*
* @param {Hash Table} htData
* @param {Number} htData.nSubmitId
* @param {Number} htData.nPercentComplete
*/
function _onUploadProgress(htData){
_setProgressBar(htData.nSubmitId, htData.nPercentComplete);
}
/**
* Set Progress Bar status
*
* @param {Number} nSubmitId
* @param {Number} nProgress
*/
function _setProgressBar(nSubmitId, nProgress) {
var welItem = $("#" + nSubmitId);
welItem.data("progressBar").css("width", nProgress + "%");
if(nProgress*1 === 100){
welItem.css("opacity", "1");
setTimeout(function(){
welItem.addClass("complete");
}, 1000);
}
}
/**
* On error to submit temporary form created in onChangeFile().
*
* @param {Hash Table} htData
* @param {Number} htData.nSubmitId
* @param {Object} htData.oRes
*/
function _onErrorUpload(htData){
$("#" + htData.nSubmitId).remove();
if(htElements.welFileList.children().length === 0){
htElements.welFileList.hide();
htElements.welFileListHelp.hide();
}
$yobi.notify(Messages("common.attach.error.upload", htData.oRes.status, htData.oRes.statusText));
_clearLinkInTextarea(_getTempLinkText(htData.nSubmitId + ".png"));
}
/**
* On Click attached files list
*
* @param {Wrapped Event} weEvt
*/
function _onClickListItem(weEvt){
var welTarget = $(weEvt.target);
var welItem = $(weEvt.currentTarget);
if(welTarget.hasClass("btn-delete")){
_deleteAttachedFile(welItem);
} else {
_insertLinkToTextarea(welItem);
}
}
/**
* @param {Wrapped Element} welItem
*/
function _deleteAttachedFile(welItem){
var sURL = welItem.attr("data-href");
yobi.Files.deleteFile({
"sURL" : sURL,
"fOnLoad": function(){
_removeDeletedFileIdFromListAndForm(welItem.data("id"))
_clearLinkInTextarea(welItem);
welItem.remove();
if(htElements.welFileList.children().length === 0){
htElements.welFileList.hide();
htElements.welFileListHelp.hide();
}
},
"fOnError": function(oRes){
$yobi.notify(Messages("common.attach.error.delete", oRes.status, oRes.statusText));
}
});
}
/**
* @param {Variant} vLink
*/
function _insertLinkToTextarea(vLink){
var welTextarea = htElements.welTextarea;
if(welTextarea.length === 0){
return false;
}
var nPos = welTextarea.prop("selectionStart");
var sText = welTextarea.val();
var sLink = (typeof vLink === "string") ? vLink : _getLinkText(vLink);
welTextarea.val(sText.substring(0, nPos) + sLink + sText.substring(nPos));
_setCursorPosition(welTextarea, nPos + sLink.length);
}
/**
* @return {Boolean} true if sMimeType is supported by HTML5 video element
*/
function isHtml5Video(sMimeType) {
return ["video/mp4", "video/ogg", "video/webm"]
.indexOf($.trim(sMimeType).toLowerCase()) >= 0;
}
/**
* Show a icon matches sMimeType on welFileItem
*/
function _showMimetypeIcon(welFileItem, sMimeType) {
if (isHtml5Video(sMimeType)) {
welFileItem.children('i.mimetype').addClass('yobicon-video2').show();
}
}
/**
* @param {Wrapped Element} welItem
* @return {String}
*/
function _getLinkText(welItem){
var sMimeType = welItem.attr("data-mime");
var sFileName = welItem.attr("data-name");
var sFilePath = welItem.attr("data-href");
var sLinkText = '[' + sFileName + '](' + sFilePath + ') ';
if (sMimeType.substr(0,5) === "image") {
return '!' + sLinkText;
} else if (isHtml5Video(sMimeType)) {
return $('').append(
$(`