Plato on Github
Report Home
space/documents/_documents_list.js
Maintainability
58.84
Lines of code
2610
Difficulty
73.84
Estimated Errors
29.33
Function weight
By Complexity
By SLOC
/*global Y, window, document, YUI, Image, flowplayer*/ /*jslint regexp: true, maxerr: 50, indent: 4 */ /** *
JavaScript for #documents-list Module
* ~/miiicasa/static/space/documents/_documents_list.js * * Spec: http://produce.corp.miiicasa.com/spec/space/20120627/ * Mockup: http://produce.corp.miiicasa.com/ued/charming/guidelines.html * * @author Mei Lin * @author Vivian Huang * @module space * @submodule _documents_list */ YUI.add("space/documents/_documents_list", function (Y) { var _api, _currentCoverUrl, // holding current cover url for set cover overlay _currentStorage = null, _deviceInfo, // holding deviceInfo _deviceConnector, _featureSupport, // holding flags those feature support or not, true is for support _fileList, // files in current folder _firstPhotoIndex = -1, // for genCover _lang = {}, // L10N language strings _mappings = {}, // Mappings for comment and share amount. _needReload = false, // if delete files from flash UI, need to reload page after flash closed _newFolderData = {}, _node, _photoList = [], // holding photo list instead of file list, for setCover use _sideNode, // side node (cover, setting link, etc...) _uploader, _player, // perform the music player instance _previewPlayer = { // holding preivew instance data : {}, photo : function () {}, music : function () {}, video: function () {}, film: function () {}, download: function () {} }, _videoTipAnim = { // holding tip animation in the player data : {}, anim : function () {}, hoverAnim: function () {} }, _preloadImages = {}, // holding preload images _descEditable, // Y.Editable, _folderDescEditable, // Y.Editable _viewer, // Y.Viewer _photoTemplate, _videoTemplate, _filmTemplate, //=========================== // Shortcut //=========================== MIIICASA = window.MIIICASA || {}, PAGE, currentPath, isLan, isWanShare, isShare, wsip, util, Lang, UPLOAD_URL, UA, VLC_INSTALL = false, //=========================== // Constants //=========================== MODULE_ID = "#documents-list", CONST = window.MIIICASA.CONST, PLAYER_EMBED_ID = "embed-player", PLAYER_OOPS_NODE = "oops-player", PLAYER_SWF = CONST.STATIC_URL + "lib/flowplayer/flowplayer-3.2.7.swf", CUR_PREVIEW_CLASS = "cur-preview", PROXY_URL = CONST.API_URL + "service/proxy?url=", AJAX_DOCS_LINK = "/ws/device/getDownloadFilesParam", GOOGLE_DOCS_LINK = "http://docs.google.com/viewer?url=", PREVIEW_FILE_TYPE = ["photo", "music", "video", "film", "docs", "vlc", "mac"], // set the file type to trigger preview handler //=========================== // Private Events //=========================== _createLinkHandler, _checkAllHandler, _commentClickHandler, _deleteButtonHandler, _downloadButtonHandler, _syncCheckAllBox, _syncSelectedItem, _itemSelectHandler, _showSetCoverOverlayHandler, _mouseEnterListHandler, _mouseLeaveListHandler, _pickerButtonHandler, _previewFileHandler, _videoTipHandler, _fileDrtHandler, //=========================== // Private Methods //=========================== _blockUploadButtons, _checkIsShared, _checkFileExtension, _doCreateDirectory, _doDeleteFiles, _doSetCover, _expandViewer, _getFileList, _initEmptyUI, _getFileThumb, _getSharedComments, _getSubFolderURL, _handleSharedFolders, _listStorages, _redirectToNewFolder, _setCoverURL, _slideShow, _performFileType, _performFilePreview, _fetchDesc, _uploadDesc, _performFileLink, _performFileDesc, _performEmptyDesc, _stickTaskRow, _uploadFileDesc, _resizePhoto, _checkButtonEvent, _embedPlayer, _handleVisibleChange, _secondsToHms, _encodeVideoLink, _vlcDetect, _vlcPreviewUrl, _fixErrorDrtFormat, _initPlayer, _initUI, _syncFileInfo, _previewerPanel, //=========================== // Public Methods //=========================== init, onviewload; //=========================== // Private Events //=========================== /** * When user click create album click * @event _createLinkHandler * @private */ _createLinkHandler = function (e) { var storagesData = [{ name : PAGE.label, free_space : _currentStorage === null ? -1 : _currentStorage.free_space }]; _api.broadcast("show-create-folder", { storages : storagesData, callback : _doCreateDirectory }); e.preventDefault(); }; /** * When user click checkall box * @event _checkAllHandler * @private */ _checkAllHandler = function (e) { var isChecked = e.currentTarget.get("checked"); if (isChecked) { _node.all("span.miii-checkbox a").addClass("miii-checkbox-checked"); _node.all("tbody input, #selectall").set("checked", "checked"); _node.all("tbody tr").addClass("selected"); } else { _node.all("span.miii-checkbox a").removeClass("miii-checkbox-checked"); _node.all("tbody input, #selectall").set("checked", ""); _node.all("tbody tr").removeClass("selected"); } }; _commentClickHandler = function (e) { _api.log("commentClickHandler(e) is executed."); e.preventDefault(); var queryString, href, needFocus, node, segments, media; node = e.currentTarget; href = node.get("href"); queryString = href.split("?")[1]; segments = href.split("?")[0].split("/"); media = segments[segments.length - 2]; queryString = queryString + "&type=" + media; if (Y.Array.indexOf(queryString.split("&"), "viewer") === -1) { return; } if (!_viewer) { _viewer = new Y.Viewer(); _viewer.render(); } needFocus = (node.hasClass("comment-reply-link")); _viewer.expand(queryString, needFocus); }; /** * When user click delete button. * * @event _deleteButtonHandler * @param e {Y.Event} The event instance * @private */ _deleteButtonHandler = function (e) { _api.log("_deleteButtonHandler() is executed.", "info", MODULE_ID); var data = {}, hasShared = false, attr, okHandler, selectedNodes; e.preventDefault(); e.stopPropagation(); selectedNodes = _checkButtonEvent(e); if (selectedNodes._nodes.length === 0) { attr = { title : _lang.oops, content : _lang.noFileSelected }; _api.alert(attr); return; } // check share status Y.each(selectedNodes, function (node) { var id = node.get("id"), fileInfo = id.split("-"), rowNode = _node.one("#" + id.replace("list-item", "filelist")).get("parentNode"); if (!Lang.isUndefined(_fileList[fileInfo[3]].shared) && _fileList[fileInfo[3]].shared === true) { hasShared = true; } }); data = { src_folderpath : currentPath, filelist : [], fullfilenames : [] }; okHandler = function (result) { if (!result) { return; } Y.each(selectedNodes, function (node) { var fileInfo = node.get("id").split("-"), filename = _fileList[fileInfo[3]].name; data.filelist.push("\"" + filename + "\""); data.fullfilenames.push("\"" + currentPath + "/" + filename + "\""); }); _api.broadcast("show-main-loading"); _doDeleteFiles(data); }; attr = { title : _api.getTrans("confirm_delete_title", "Confirm delete?"), content : hasShared ? _api.getTrans("confirm_shared_delete", "One or more folders have been shared, are you sure to delete these selected files?") : _api.getTrans("confirm_delete", "Are you sure to delete these selected files?") }; _api.confirm(attr, okHandler); e.preventDefault(); }; /** * When user click download button. * * @event _downloadButtonHandler * @param e {Y.Event} The event instance * @private */ _downloadButtonHandler = function (e) { _api.log("_downloadButtonHandler() is executed.", "info", MODULE_ID); var fileCnt = 0, filesArray = [], folderCnt = 0, selectedNodes, targetname = "", attr; e.preventDefault(); e.stopPropagation(); selectedNodes = _checkButtonEvent(e); if (!_featureSupport.download) { attr = { title : _lang.oops, content : _lang.featureNotSupported }; _api.alert(attr); return; } if (selectedNodes._nodes.length === 0) { attr = { title : _lang.oops, content : _lang.noFileSelected }; _api.alert(attr); return; } // downloadFilesByPost Y.each(selectedNodes, function (node) { var fileInfo = node.get("id").split("-"), theFile = _fileList[fileInfo[3]]; filesArray.push('"' + theFile.name + '"'); if (theFile.type === CONST.FILE_TYPE_FILE) { fileCnt += 1; } else { folderCnt += 1; } targetname = theFile.name; }); // target filename if (fileCnt === 0 && folderCnt === 1) { targetname += ".zip"; } else if (fileCnt + folderCnt > 1) { targetname = 'miiiCasa_' + Y.DataType.Date.format(new Date(), {format: "%Y-%m-%d"}) + '.zip'; } _deviceConnector.downloadFilesByPost({ base_path : isWanShare ? PAGE.subpath : currentPath, targetname : targetname, filenames : "[" + filesArray.join(",") + "]" }); e.preventDefault(); }; /** * Check/Uncheck "Select All" check box according to other check boxes' * check status. If one of the check boxes is not checked, "Select All" * check box shouldn't be checked then. * @method _syncCheckAllBox * @param e {Y.Node} The input checkbox node * @private * @return void */ _syncCheckAllBox = function (node) { var isChecked = node.get("checked"), checkNodes, i, j; if (isChecked) { checkNodes = _node.all("tbody input"); for (i = 0, j = checkNodes.size(); i < j; i += 1) { if (!checkNodes.item(i).get("checked")) { return; } } _node.all("#selectall").set("checked", "checked"); _node.all("#selectall-miii-checkbox").addClass("miii-checkbox-checked"); } else { _node.all("#selectall").set("checked", ""); _node.all("#selectall-miii-checkbox").removeClass("miii-checkbox-checked"); } }; /** * Sync checkbox status with miii-checkbox * @method _syncSelectedItem * @param e {Y.Node} The input checkbox node * @private * @return void */ _syncSelectedItem = function (node) { var isChecked = node.get("checked"), tr = node.get("parentNode").get("parentNode").get("parentNode"); if (isChecked) { tr.addClass("selected"); } else { tr.removeClass("selected"); } }; /** * Handles when the user select any folder/file. * * @event _itemSelectHandler * @private * @param e {Y.Event} The event instance * @return void */ _itemSelectHandler = function (e) { _api.log("_itemSelectHandler() is executed.", "info", MODULE_ID); _syncSelectedItem(e.currentTarget); _syncCheckAllBox(e.currentTarget); }; /** * Show set cover overlay * @event _showSetCoverOverlayHandler * @private */ _showSetCoverOverlayHandler = function (e) { _api.broadcast("show-set-cover-overlay", { currentPath : currentPath, currentCoverUrl : _currentCoverUrl, photoList : _photoList, callback : _doSetCover }); e.preventDefault(); }; /** * Handles when the user mouseenters any folder/file. * * @method _mouseEnterListHandler * @private * @param e {Y.Event} The event instance * @return void */ _mouseEnterListHandler = function (e) { var trNode = e.currentTarget, checkboxNode = trNode.one("input"); if (!checkboxNode.get("checked")) { trNode.addClass("hover"); } }; /** * Handles when the user mouseleaves any folder/file. * * @method _mouseLeaveListHandler * @private * @param e {Y.Event} The event instance * @return void */ _mouseLeaveListHandler = function (e) { var trNode = e.currentTarget, checkboxNode = trNode.one("input"); if (!checkboxNode.get("checked")) { trNode.removeClass("hover"); } }; /** * performEmptyDesc * When the description is empty, replace class 'desc-fill' with 'desc-empty' * When the textarea has attrs 'readonly', remove this. It means the user permission is under 'upload' * @method * @private * @param {Object}, the textarea node property */ _performEmptyDesc = function (option) { option.set("innerHTML", ""); if (option.get("parentNode").hasClass("status-readonly")) { option.get("parentNode").remove(); return; } }; /** * Preload images */ _preloadImages = { count: 0, // keep track of the number of images loaded: 0, // keeps track of how many images have loaded onComplete: function () {}, // fires when all images have finished loadng onLoaded: function () {}, // fires when an image finishes loading loaded_image: "", // access what has just been loaded images: [], // keeps an array of images that are loaded incoming: [], // this is for the process queue. queue_images: function (images) { this.id = images.id; this.loaded = 0; this.images = []; this.count = images.length; this.incoming = images; this.process_queue(); }, process_queue: function () { var img = this.incoming.shift(); this.load_image(img); }, load_image: function (image) { var this_ref, preload_image; this_ref = this; preload_image = new Image(); preload_image.onload = function () { this_ref.id = image.id; this_ref.loaded_image = preload_image; this_ref.images.push(preload_image); this_ref.loaded += 1; (this_ref.onLoaded)(); if (this_ref.count === this_ref.loaded) { (this_ref.onComplete)(); } else { this_ref.process_queue(); } }; try { preload_image.src = image.link; } catch (e) { _api.log("fail link"); } } }; /* Preview photos * * @method _previewplayer.photo * @return void */ _previewPlayer.photo = function () { var data = {}, myImg, // Image be preivewed playerData = {}, html, panel; data = this.data; html = Y.Handlebars.render(_photoTemplate, { id : data.id, name : data.name, type : data.type, link : data.link, size : data.size, src : "", imgW : 0, imgH : 0, margin : 0, loadingStatus : "" }); playerData = { previewID : data.id, content : html, imgW : 400, imgH : 300, padding : "10px 10px 10px 10px", type : "update", transition : "" }; panel = _api.createPopup(html, {width: 500}, "previewer"); myImg = { id : data.id, link : data.link }; _preloadImages.onLoaded = function () { _api.log("_preloadImages.onLoaded() is executed."); var previewNode, contentBoxNode, loadedImg, fileMargin = 10; loadedImg = this.loaded_image; if (data.id !== this.id) { _api.log("no img"); return; } playerData.menuH = 95; playerData = _resizePhoto(playerData, loadedImg); if (playerData.imgH < 200) { fileMargin = parseInt(200 - playerData.imgH, 10) / 2; } html = Y.Handlebars.render(_photoTemplate, { id : data.id, name : data.name, type : data.type, link : data.link, size : data.size, src : data.link, imgW : playerData.imgW, imgH : playerData.imgH, margin : fileMargin, loadingStatus : "loading-hidden-status" }); _api.createPopup(html, {width: playerData.width}, "previewer"); contentBoxNode = panel.get("contentBox"); contentBoxNode.one("input[name=download-button]").on("click", _previewPlayer.download); contentBoxNode.one("input[name=delete-button]").on("click", _previewPlayer.deleteFile); }; _preloadImages.queue_images([myImg]); }; /** download one photo file in the preview player */ _previewPlayer.download = function (e) { _downloadButtonHandler(e); }; /** delete one photo file in the preview player */ _previewPlayer.deleteFile = function (e) { _deleteButtonHandler(e); }; /** * Handles when user clicks preview music file link. * The file's class is 'ext-music' * @property _previewPlayer.music * @type object * @protected * @static * the music preview player */ _previewPlayer.music = function () { var data = this.data, url = data.link; if (_player) { _player.show(); _player.update("songs", [{"url": url}]); } else { _initPlayer(); _player.add("song", [{"url": url}]); _player.open(); } }; /** * _previewPlayer.video * Handles when user clicks preview video file link. * The file's class is 'ext-video' * @property _previewPlayer.video * @type object * @protected * @static * the video preview player */ _previewPlayer.video = function () { _api.log("_previewPlayer.video() is executed"); var data = this.data, optVLCPlayer, tip, html; optVLCPlayer = "
" + _lang.vlcPlayer + "
"; tip = Y.substitute(_lang.videoTip, {VLC_Player : optVLCPlayer}); html = Y.Handlebars.render(_videoTemplate, { name: data.name, id: PLAYER_EMBED_ID, tip: tip }); _previewerPanel = _api.createPopup(html, {width: 662}, "previewer"); _previewerPanel.on("visibleChange", _handleVisibleChange); _embedPlayer(); }; /** * _previewPlayer.film * Handles when user clicks preview video file not avi/mp4/mov/flv. * The file's class is 'ext-film' * @property _previewPlayer.film * @type object * @protected * @param option {String} node * @static */ _previewPlayer.film = function () { var html = Y.Handlebars.render(_filmTemplate, { name: _previewPlayer.data.name }); _api.createPopup(html, {width: 662}); }; /** * _previewPlayer.docs * Handles when user clicks preview file with google docs viewer. * Supports over 15 different file types, listed page: https://docs.google.com/support/bin/answer.py?hl=en&answer=1189935&ctx=top5&src=top5. * The file's class is 'ext-docs' * @property _previewPlayer.docs * @type object * @protected * @param option {String} node * @static */ _previewPlayer.docs = function (option) { var curID, fIndex, fName, postParams, cfg, request, attr, gUrl, confirmCallback, urlVars; curID = _node.one("." + CUR_PREVIEW_CLASS).get("id").split("-"); fIndex = curID[2]; fName = _fileList[fIndex].name; postParams = { tok : Y.Cookie.get("dt"), base_path : isShare ? PAGE.subpath : currentPath, filenames : "[\"" + fName + "\"]", targetname: fName, alt : "preview" }; if (isShare) { urlVars = util.getVars(); postParams.fid = urlVars.fid; } else { postParams.did = PAGE.did; } cfg = { method: "POST", on: { "success": function (ioId, o) { var result = Y.JSON.parse(o.responseText); if (result.status === "fail") { return; } gUrl = GOOGLE_DOCS_LINK + encodeURIComponent(result.url); }, "failure": function () { } }, data: postParams }; request = Y.io(AJAX_DOCS_LINK, cfg); confirmCallback = function (result) { if (!result) { return; } window.open(gUrl, "_blank"); }; attr = { title : _lang.preview_docs_title, content : _lang.preview_docs_content }; _api.confirm(attr, confirmCallback); }; _pickerButtonHandler = function (e) { _api.log("_pickerButtonHandler() is executed."); var type = e.target.getAttribute("name").split("-")[0]; Y.FilePicker.show(type, { nodes : _node.all("input[name=list-item]:checked"), files : [_fileList], path : currentPath, mediaType : CONST.SPACE_MEDIA_TYPE_FOLDERS.documents, type : type }, _api); }; /** * Fires when user clicks preview file link. * It shows different UI for previewing according to different file extension. * * @event _previewFileHandler * @private * @param {Y.Event} The YUI Event instance. * @return void */ _previewFileHandler = function (e) { _api.log("_previewFileHandler() is executed.", "info", MODULE_ID); var fileData, target, rowNode, ext, player = {}; target = e.currentTarget; rowNode = target.get("parentNode").get("parentNode").get("parentNode"); ext = target.get("className"); fileData = ""; _node.all("." + CUR_PREVIEW_CLASS).removeClass(CUR_PREVIEW_CLASS); if (ext.search(/main/gi) !== -1) { ext = ext.replace("main ", ""); } // type ext-none is folder. if (ext !== "ext-none") { rowNode.addClass(CUR_PREVIEW_CLASS); if (ext !== "ext-vlc" && ext !== "ext-mac") { e.preventDefault(); } } if (ext === "ext-photo") { fileData = { id : rowNode.get("id").replace("filelist", "preview"), type : ext, name : target.get("title"), size : rowNode.one(".file-size").get("innerHTML"), link : target.get("href") }; } if (ext === "ext-film" || ext === "ext-docs") { fileData = { name : target.get("title"), link : target.get("href") }; } // type ext-video is avi/mp4/mov/flv. if (ext === "ext-video") { fileData = { name : target.get("title"), link : target.getAttribute("data-path") }; } if (ext === "ext-music") { fileData = { link : target.get("href") }; } if (fileData === "") { return; } _previewPlayer.data = fileData; ext = ext.replace("ext-", ""); _previewPlayer[ext](); }; /**_videoTipHandler * Video tip fade out after 5 seconds. * When mouse over, show the tip. * When mouse out, hide the tip. * @method * @private * @return viod */ _videoTipHandler = function () { var anim; _videoTipAnim.data = Y.one("#player span.tip"); anim = _videoTipAnim.anim(); Y.later(5000, null, function () { anim.run(); }); }; /**_fileDrtHandler * Video Daration save in router when playing in the first time * @method * @private * @param duration {Number} Videos duration * @return viod */ _fileDrtHandler = function (duration) { if (duration < 0) { return; } var drt, node, valueNode, curNode, formNode, descTextArea, descForm, descValue, dataNode, data, txt; drt = _secondsToHms(duration); curNode = _node.one("." + CUR_PREVIEW_CLASS); node = curNode.one(".file-duration"); formNode = curNode.one("form"); descTextArea = curNode.one("textarea"); descValue = descTextArea.get("value") || descTextArea.get("innerText"); if (node.get("innerHTML") === "") { node.set("innerHTML", drt); data = { descFolder : formNode.one("input[name=descfoldername]").get("value"), descFile : formNode.one("input[name=descfilename]").get("value") + ".txt", descIndex : formNode.get("id").split("-")[1], descValue : descValue }; if (formNode.one("input[name=descfilecont]")) { dataNode = descForm.one("input[name=descfilecont]"); txt = Y.JSON.parse(dataNode.get("value")); txt.desc = descValue; txt.videoLength = drt; } else { _api.log("desc is not JSON fomat and create it now."); txt = { videoLength: drt }; dataNode = Y.Node.create("
"); formNode.append(dataNode); } data.descContent = Y.JSON.stringify(txt); dataNode.set("value", data.descContent); _uploadFileDesc(data); } }; /** * Handles when user clicks action link. * * @method _commentClickHandler * @private */ _commentClickHandler = function (e) { _api.log("_commentClickHandler() is executed.", "info", MODULE_ID); var queryString, href, segments, media; href = e.currentTarget.get("href"); queryString = href.split("?")[1]; segments = href.split("?")[0].split("/"); media = segments[segments.length - 2]; queryString = queryString + "&type=" + media; if (Y.Array.indexOf(queryString.split("&"), "viewer") === -1) { return; } e.preventDefault(); if (!_viewer) { _viewer = new Y.Viewer(); _viewer.render(); } _viewer.expand(queryString); }; /** * resize the photo in the player * @privat * @method * @param {Object}, The data of the image container with 'width','height','padding'(optional),'menuH'(optional) * @param {Object}, The image which be loaded * @return {Object}, The data of the image container with 'widht','height','imgW','imgH' */ _resizePhoto = function (container, img) { _api.log("_resizePhoto() is executed."); var defaults, paddingAy, gapW, gapH, boxW, boxH, maxW, maxH, minW, minH, imgW, imgH, menuH, maxRadio, radio, minHypotenuse, maxHypotenuse, imgHypotenuse, i; defaults = { width: 200, height: 200, imgW : 100, imgH : 100, padding: 0, menuH: 0 }; container.imgW = img.width; container.imgH = img.height; container = Y.merge(defaults, container); paddingAy = container.padding.split("px"); Y.each(paddingAy, function (item, i) { paddingAy[i] = Number(/\d+/.exec(item)); }); menuH = container.menuH; gapW = paddingAy[1] + paddingAy[3]; gapH = paddingAy[0] + paddingAy[2]; imgW = img.width; imgH = img.height; radio = imgW / imgH; minW = container.width - gapW; minH = container.height - gapH - menuH; boxW = Math.floor(_node.get("winWidth") * 0.8) > minW ? Math.floor(_node.get("winWidth") * 0.8) : minW; boxH = Math.floor(_node.get("winHeight") * 0.8) > minH ? Math.floor(_node.get("winHeight") * 0.8) : minH; maxW = boxW - gapW; maxH = boxH - gapH - menuH; maxRadio = maxW / maxH; minHypotenuse = Math.sqrt(Math.pow(minW, 2) + Math.pow(minH, 2)); maxHypotenuse = Math.sqrt(Math.pow(maxW, 2) + Math.pow(maxH, 2)); imgHypotenuse = Math.sqrt(Math.pow(imgW, 2) + Math.pow(imgH, 2)); minHypotenuse = minHypotenuse > imgHypotenuse || false; if (!minHypotenuse) { maxHypotenuse = imgHypotenuse < maxHypotenuse || false; } if (minHypotenuse) { _api.log("The hytotenuse is smaller than minimize."); if (imgW > minW) { container.width = imgW + gapW; return container; } if (imgH > minH) { container.height = imgH + gapH + menuH; return container; } return container; } if (maxHypotenuse) { _api.log("The hytotenuse is smaller than maximun."); container.width = img.width > minW ? img.width + gapW : container.width; container.height = img.height > minH ? img.height + gapH + menuH : container.height; if (container.height > boxH) { _api.log("The height of preview box is larger the max box."); container.height = boxH; container.imgH = container.height - gapH - menuH; container.imgW = container.imgH * radio; container.width = container.imgW + gapW; } if (container.width > boxW) { _api.log("The width of preview box is larger the max box."); container.width = boxW; container.imgW = container.width - gapW; container.imgH = container.imgW / radio; container.height = container.imgH + gapH + menuH; } return container; } _api.log("The hytotenuse is larger than maximun."); if (radio >= 1) { img.width = maxW; img.height = Math.floor(img.width / radio); } else { img.height = maxH; img.width = Math.floor(img.height * radio); } container.imgW = img.width; container.imgH = img.height; container.width = img.width > minW ? img.width + gapW : this; container.height = img.height > minH ? img.height + gapH + menuH : this; if (container.height > boxH) { _api.log("The height of preview box is larger the max box."); container.height = boxH; container.imgH = container.height - gapH - menuH; container.imgW = container.imgH * radio; container.width = container.imgW + gapW; } if (container.width > boxW) { _api.log("The width of preview box is larger the max box."); container.width = boxW; container.imgW = container.width - gapW; container.imgH = container.imgW / radio; container.height = container.imgH + gapH + menuH; } return container; }; //=========================== // Private Methods //=========================== /** * Block upload buttons if user's device not support upload * @method _blockUploadButtons * @private */ _blockUploadButtons = function () { var uploadLink = Y.one(".upload-link"), // Add Docs Node allNewUploadLink = _node.one(".allnew-upload-link"), // Add Documents Node on Empty Content attr; attr = { title : _lang.oops, content : _lang.featureNotSupported }; if (uploadLink) { uploadLink.on("click", function (e) { _api.alert(attr); e.preventDefault(); }); } if (allNewUploadLink) { allNewUploadLink.on("click", function (e) { _api.alert(attr); e.preventDefault(); }); } }; /** * Asking server to know if current folder and subfolders have been shared. * @method _checkIsShared * @private */ _checkIsShared = function (folderList) { _api.log("checkIsShared()"); var postData = []; if (isWanShare) { postData.push("fid=" + PAGE.fid); postData.push("subpath=" + encodeURIComponent(PAGE.subpath)); } else { postData.push("did=" + PAGE.did); postData.push("base_path=" + encodeURIComponent(currentPath)); } Y.each(folderList, function (folder) { postData.push("dirnames[]=" + encodeURIComponent(folder.folderName)); }); Y.io("/space/q/is_shared", { method: "POST", data: postData.join("&"), on : { success: function (id, o, a) { _api.log("success on checkIsShared"); try { var result = Y.JSON.parse(o.responseText); if (result.status === "ok") { _handleSharedFolders(folderList, result); } else { _api.log("error on checkIsShared", "error"); } } catch (e) { _api.log("json parse error:" + o); } } } }); }; /** * Call device api to create directory * @method _doCreateDirectory * @private */ _doCreateDirectory = function (storageName, folderName, folderDesc) { var afterCreateDirectory, failureHandler, timeoutHandler, loadingNode; afterCreateDirectory = function (o) { //_api.log("MIIICASA.documentsList.afterCreateDirectory"); var data, opt; if (o.status !== "ok") { _api.broadcast("hide-main-loading"); _api.broadcast("show-create-folder-errmsg", o); return false; } // upload folder desc if (_newFolderData.folderDesc === "") { _redirectToNewFolder(); return; } data = { tok : _deviceInfo.token, path : currentPath + "/" + _newFolderData.folderName + "/.miiithumbs" }; if (!isLan) { data.cp = Y.Cookie.get("p"); data.cs = Y.Cookie.get("s"); } opt = { fileVar : "uploadedfile", uploadTo: UPLOAD_URL, desc : _newFolderData.folderDesc, filename: "desc.txt" }; if (!isLan) { data.did = PAGE.did; } _uploader.uploadDesc(data, opt); _api.log("[uploadDesc] running..."); }; failureHandler = function () { _api.log("failureHandler()", "error"); }; timeoutHandler = function () { _api.log("timeoutHandler()", "error"); }; _newFolderData = { storageName : storageName, folderName : folderName, folderDesc : folderDesc }; _deviceConnector.createDirectory({ path : currentPath, dirname : folderName }, { on: { success: afterCreateDirectory, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); _api.log("[doCreateDirectory]" + storageName + "," + folderName + "," + folderDesc); // loading loadingNode = Y.one("#main-loading").setStyle("display", "block"); }; /** * Call device api to delete files * @method _doDeleteFiles * @private */ _doDeleteFiles = function (data) { var afterDeleteFiles, failureHandler, timeoutHandler; afterDeleteFiles = function (o) { _api.log("afterDeleteFiles()"); var syncData, syncCallback; syncData = { did : MIIICASA.env.did, act : "del", src_folderpath : data.src_folderpath, filelist : "[" + data.filelist.join(",") + "]" }; syncCallback = function () { util.pageReload(); }; _syncFileInfo(syncData, syncCallback); }; failureHandler = function () { _api.log("failureHandler()", "error"); }; timeoutHandler = function () { _api.log("timeoutHandler()", "error"); }; _deviceConnector.deleteFiles({ fullfilenames : "[" + data.fullfilenames.join(",") + "]" }, { on: { success: afterDeleteFiles, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); }; /** * Performing setCover * @method _doSetCover * @private */ _doSetCover = function (newCoverIndex) { _api.log(newCoverIndex); var loadingNode = Y.one("#main-loading").setStyle("display", "block"); }; /** * Expand the viewer. * * @method _expandViewer * @param queryString {String} The space query string. */ _expandViewer = function (queryString) { _api.log("_expandViewer(e) is executed."); var href, segments, media; if (!queryString) { href = window.location.href; if (href.indexOf("#") !== -1) { href = href.slice(0, href.indexOf("#")); } queryString = href.split("?")[1]; segments = href.split("?")[0].split("/"); media = segments[segments.length - 2]; queryString += "&type=" + media; if (queryString.indexOf("&viewer") === -1) { queryString += "&viewer"; } } if (!_viewer) { _viewer = new Y.Viewer(); _viewer.render(); } _viewer.expand(queryString); }; /** * Upload folder description. * * @method _uploadDesc * @param desc {String} Folder Description * @private * @return void */ _uploadDesc = function (desc) { var data, opt; data = { tok : _deviceInfo.token, path : currentPath + "/.miiithumbs" }; if (!isLan) { data.cp = Y.Cookie.get("p"); data.cs = Y.Cookie.get("s"); data.did = PAGE.did; } opt = { fileVar : "uploadedfile", uploadTo : UPLOAD_URL, desc : desc, filename : "desc.txt" }; _uploader.uploadDesc(data, opt); }; /** * Performing download text file for folder desc. * * @method _fetchDesc * @private * @return void */ _fetchDesc = function () { _api.log("_fetchDesc() is executed.", "info", MODULE_ID); var afterDownloadDesc, failureHandler, timeoutHandler, tooltip; afterDownloadDesc = function (o) { var txt = "", tooltip = ""; if (!Lang.isUndefined(o.data)) { txt = util.nl2br(util.htmlspecialchars(o.data)); txt = UA.gecko ? util.wbr(txt) : txt; if (PAGE.permission >= CONST.PERMISSION_MANAGE) { tooltip = o.data ? _lang.edit_desc_tooltip : ""; } } _sideNode.one(".desc").set("innerHTML", txt); _sideNode.one(".desc").set("title", tooltip); if (PAGE.permission >= CONST.PERMISSION_MANAGE) { _folderDescEditable = new Y.Editable({ "inputType" : "textarea", "selector" : ".desc", "node" : _sideNode, "emptyDefault" : _lang.edit_desc_tooltip, "tooltip" : tooltip, "validateRule" : "max_length[300]", "sync" : true }); _folderDescEditable.on("submit", function (e) { txt = e.details[0].value; _uploadDesc(txt); tooltip = txt ? _lang.edit_desc_tooltip : ""; _folderDescEditable.set("tooltip", tooltip); }); } }; failureHandler = function () { _api.log("failureHandler() is executed.", "error", MODULE_ID); }; timeoutHandler = function () { _api.log("timeoutHandler() is executed.", "error", MODULE_ID); }; _deviceConnector.downloadTextFile({ fullfilename : (isWanShare ? PAGE.subpath : currentPath) + "/.miiithumbs/desc.txt" }, { on: { success: afterDownloadDesc, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); }; /** * List all files for each storage. * Performing getFileList to know if there's a cover exists * * @method _getFileList * @private * @return void */ _getFileList = function () { _api.log("_getFileList() is executed.", "info", MODULE_ID); var afterGetFileList, failureHandler, timeoutHandler, getFileListArgvs = {}, folderTotal = 0, fileTotal = 0, showTotal = ""; afterGetFileList = function (o) { _api.log("afterGetFileList() is executed.", "info", MODULE_ID); var folderList = [], // holding folder info (to query is_shared) folderTotal = 0, fileTotal = 0, html = "", template = "", trans = "", allFiles = [], okHandler, attr; if (o.label_name && MIIICASA.env.label !== o.label_name) { util.showLabelName(o.label_name); } if (Lang.isUndefined(o.status) || o.status !== "ok") { okHandler = function (e) { window.location.href = "/"; }; if (o.errno === 6001) { _api.broadcast("show-access-fail-request", {isShare: Y.MiiiCasa.isShare}); return; } else if (!Lang.isUndefined(_lang.deviceMessage[o.errno])) { attr = { title : _lang.oops, content : _lang.deviceMessage[o.errno] }; _api.alert(attr, okHandler); } else { attr = { title : _lang.oops, content : _lang.deviceMessage["5001"] }; _api.alert(attr, okHandler); } _api.broadcast("hide-main-loading"); return; } if (Lang.isUndefined(o.count) || o.count === 0) { //empty _initEmptyUI(); return; } //has file(s) _fileList = o.files; Y.each(_fileList, function (file, i) { var folderLink, file_type, file_link, preview_link, commentLink, commentTotalId, shareLink; shareLink = Y.substitute(PAGE.shareSubDir, { SUBDIR: encodeURIComponent(file.name, false) }); commentTotalId = Y.guid(); if (file.type === CONST.FILE_TYPE_DIRECTORY) { folderLink = _getSubFolderURL(PAGE.listURL, file.name, file.mtime); commentLink = Y.substitute(PAGE.listURL, { SUB_DIR : encodeURIComponent(file.name), SORT : "" }) + "&viewer"; allFiles.push({ fileListId : ["filelist", 0, i].join("-"), fileType : "ext-none", thumbUrl : "folder", thumbLink : folderLink, checkboxId : ["list-item", 0, i].join("-"), fullFileName : util.htmlspecialchars(file.name), previewLink : folderLink, fileLink : folderLink, filePath : file.uri, hrefTarget : "_self", fileDuration : "", fileDescStatus : file.desc === 0 ? "yui3-editable-empty desc-empty" : "desc-fill", fileDescId : ["desc", 0, i].join("-"), fileDescFolder : "/" + file.name, fileDescName : "desc", fileDesc : (file.desc !== 0 && PAGE.permission >= CONST.PERMISSIOn_UPLOAD) ? _lang.edit_desc_tooltip : "", fileDate : Y.DataType.Date.format(new Date(file.mtime * 1000), {format: "%x"}), fileSize : "", fileShareStatus : "", isEditable : (PAGE.permission >= CONST.PERMISSION_UPLOAD) ? true : false, commentLink : commentLink, commentTotalId : commentTotalId, shareLink : shareLink }); folderList.push({ id : i, folderName: file.name }); folderTotal += 1; } else { commentLink = PAGE.listURL.replace("%2F{SUB_DIR}", "") + "&f=" + encodeURIComponent(file.name) + "&viewer"; file_type = _performFileType(file); file_link = util.encodeURIForDa(file.uri, false); //encode before ? //fileURI = util.encodeURIForDa(file.uri, false); if (util.isPhoto(file) && !Lang.isUndefined(file.thumb_l) && file.thumb_l === 1) { file_link = util.getThumbURL(file, currentPath, "l"); } if (file_type === "ext-vlc") { if (isLan) { preview_link = _vlcPreviewUrl(file.uri, wsip); } else { preview_link = _vlcPreviewUrl(file_link); } preview_link = preview_link + "&name=" + encodeURIComponent(file.name); } allFiles.push({ fileListId : ["filelist", 0, i].join("-"), fileType : file_type, thumbUrl : _checkFileExtension(file.ext), thumbLink : "javascript:void(0);", checkboxId : ["list-item", 0, i].join("-"), fullFileName : util.htmlspecialchars(file.name), previewLink : preview_link || file_link, fileLink : file_link, filePath : file.uri, hrefTarget : "_blank", fileDuration : "", fileDescStatus : file.desc === 0 ? "yui3-editable-empty desc-empty" : "desc-fill", fileDescId : ["desc", 0, i].join("-"), fileDescFolder : "", fileDescName : file.name, fileDesc : (file.desc !== 0 && PAGE.permission >= CONST.PERMISSIOn_UPLOAD) ? _lang.edit_desc_tooltip : "", fileDate : Y.DataType.Date.format(new Date(file.mtime * 1000), {format: "%x"}), fileSize : util.formatDiskSpace(file.size), fileShareStatus : "status-hidden", isEditable : (PAGE.permission >= CONST.PERMISSION_UPLOAD) ? true : false, commentLink : commentLink, commentTotalId : commentTotalId }); fileTotal += 1; } _mappings[file.name] = {}; _mappings[file.name].comment = commentTotalId; }); // perform the file count if (folderTotal > 0) { trans = (folderTotal > 1) ? _lang.folderTotalPlural : _lang.folderTotalSingular; showTotal = Y.substitute(trans, { folder_total : util.addComma(folderTotal) }); } if (folderTotal > 0 && fileTotal > 0) { showTotal += _lang.and; } if (fileTotal > 0) { trans = (fileTotal > 1) ? _lang.fileTotalPlural : _lang.fileTotalSingular; showTotal += Y.substitute(trans, { file_total : util.addComma(fileTotal) }); } _sideNode.one(".count").set("innerHTML", showTotal); // It doesn't work in IE8/IE7 //template = Y.one("#list-template").get("text"); template = Y.one("#list-template").get("innerHTML"); html = Y.Handlebars.render(template, {allFiles: allFiles}); _node.one("#storage-box").append(html); if (!Lang.isUndefined(o.mtime)) { _api.log("mtim:" + o.mtime); } if (folderList.length > 0) { _checkIsShared(folderList); } _performFileDesc(); _initUI(); }; failureHandler = function () { _api.log("failureHandler() is executed.", "error", MODULE_ID); }; timeoutHandler = function () { _api.log("timeoutHandler() is executed.", "error", MODULE_ID); _api.broadcast("show-access-fail-request", {isShare: Y.MiiiCasa.isShare}); }; if (isWanShare) { getFileListArgvs = { subpath : PAGE.subpath, sortby : PAGE.sort }; } else { getFileListArgvs = { path : currentPath, sortby : PAGE.sort }; } if (PAGE.width) { getFileListArgvs.width = PAGE.width; // for API, resize on the fly } _deviceConnector.getFileList(getFileListArgvs, { on: { success: afterGetFileList, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); }; /** * Get total count of share/comment for any album. * * @method _getSharedComments * @private * @param storageIndex {Number} * @return void */ _getSharedComments = function (storageIndex) { _api.log("_getSharedComments() is executed.", "info", MODULE_ID); Y.io("/space/q/get_shared_comments?" + PAGE.queryString, { method: "POST", on : { success: function (id, o, a) { var data = Y.JSON.parse(o.responseText); Y.each(data, function (o, key) { if (!Y.Object.hasKey(_mappings, key)) { return; } if (Y.Lang.isNumber(o.c)) { _node.one("#" + _mappings[key].comment).setContent(" (" + o.c + ")"); } }); } } }); }; /** * Get sub folder URL * @method _getSubFolderURL * @private */ _getSubFolderURL = function (template, dirName, mtime) { ///space/documents/lists?did=d123&s=USB_USB_Disk_172D56A_1&d=/ABC/{SUB_DIR}&sort=aa ///space/documents/lists?fid=f123&subpath=/ABC/{SUB_DIR}&sort=aa var url = Y.substitute(template, { SUB_DIR : encodeURIComponent(dirName) }); if (mtime) { url += "&mt=" + mtime; } return url; }; /** * Show share folder icon and add shard flag to the folder * @method _handleSharedFolders * @private */ _handleSharedFolders = function (folderList, result) { Y.each(folderList, function (folder, i) { // mark as shared, will confirm while delete if (result.self_or_sub[i] === 1) { _fileList[folder.id].shared = true; } }); }; /** * Check file extension * Receive the extension data (ext) from device then check it * Perform the thumbnail for each file depends on different extension * @method * @private * @param {String}, ext from device */ _checkFileExtension = function (option) { var extensionReg, thumbUrl, i; thumbUrl = "others"; extensionReg = { word : /^((doc)|(docx))$/, excel : /^((xls)|(xlsx))$/, powerpoint : /^((ppt)|(pptx)|(pps))$/, pdf : /^(pdf)$/, html : /^((htm)|(html))$/, text : /^(txt)$/, image : /^((jpg)|(gif)|(jpeg)|(png)|(gif)|(bmp))$/, music : /^((mp3)|(wma)|(wav)|(aif)|(mid)|(aac)|(iff)|(m3u)|(mpa)|(ra)|(m4a))$/, video : /^((mov)|(mp4)|(mp4v)|(avi)|(rm)|(rmvb)|(wmv)|(mpe)|(mpeg1)|(mpeg2)|(mpeg4)|(mpg)|(flv)|(mkv)|(m2t)|(m2ts)|(m4v)|(mpv2)|(divx)|(mts)|(3gp)|(asf)|(ts)|(vob)|(webm)|(ogg))$/, compressed : /^((zip)|(zipx)|(rar))$/ }; Y.each(extensionReg, function (item, i) { if (item.test(option.toLowerCase())) { thumbUrl = i; return thumbUrl; } }); return thumbUrl; }; /** * Check file extension and perform file type * Perform the class for each file depends on different type * Util.isPhoto: Check files extensions are "jpg", "png", "gif", or "jpeg". * Util.isVideo: Check files extensions are "flv", "mp4", "avi", or "mov" which is supprot by flowplayer. * Util.isMusic: Check files extensions are "mp3", "mp4", or "m4a". * Util.isFilm: Check files extensions are film which is not support by Flowplayer. * Util.isPhoto is true ,show 'ext-photo' classes * Util.isVideo is true ,show 'ext-video' classes * Util.isMusic is true ,show 'ext-music' classes * 'ext-vlc' means when pc is install VLC, all files play by VLC plugin. * 'ext-video' means not install VLC and could play by flowplayer. * 'ext-film' means when pc is not install VLC and video couldn't play by flowplayer. * The class will be used by the preview handler * @method * @private * @param {object} file: get it from device * @return {String} typeClass: the file classes */ _performFileType = function (file) { var filmReg = /\.((3gp)|(avi)|(divx)|(flv)|(m4v)|(mkv)|(mov)|(mp4)|(mp4v)|(mpg)|(ogg)|(rm)|(rmvb)|(wmv))$/, ext = file.ext.toLowerCase(), isMusic = util.isMusic(file), isPhoto = util.isPhoto(file), isVideo = util.isVideo(file), isDocuments = util.isDocuments(file), isFilm = filmReg.test("." + ext), isMac = Y.UA.os === "macintosh" || false, typeClass = "ext-" + ext; if (isFilm) { if (isMac) { return "ext-mac"; } if (VLC_INSTALL) { return "ext-vlc"; } } // Run before isMusic couse *.mp4 set to be video type. if (isVideo) { return "ext-video"; } if (isFilm) { return "ext-film"; } if (isMusic) { return "ext-music"; } if (isPhoto) { return "ext-photo"; } if (isDocuments) { return "ext-docs"; } return typeClass; }; /** * Performing photo file preview text * Show music player when files extensions are "mp3", "mp4", or "m4a". * Show preview anchor if the file could be previewed. * * @method _performFilePreview * @private * @return void */ _performFilePreview = function () { _api.log("_performFilePreview() is executed.", "info", MODULE_ID); var previewID, listNode; Y.each(PREVIEW_FILE_TYPE, function (type) { previewID = _node.one(".ext-" + type); if (!previewID) { _api.log("There is no classes:'ext-" + type + "', so couldn't trigger the preview handler", "warn", MODULE_ID); return; } else { previewID = _node.all(".ext-" + type).get("parentNode").get("parentNode").get("parentNode").get("id"); } Y.each(previewID, function (item, i) { listNode = _node.one("#" + item); listNode.one(".main").setContent(_lang.filePreview); listNode.one(".splitter").setStyle("display", "inline"); }); }); }; /** * Performing file link in the folder type which classes is "ext-none" * * @method _performFileLink * @private * @return void */ _performFileLink = function () { _api.log("_performFileLink() is executed.", "info", MODULE_ID); if (!_node.one(".ext-none")) { return; } var folderAy, fileName; folderAy = _node.all(".ext-none"); Y.each(folderAy, function (item, i) { fileName = item.get("parentNode").one(".name-text"); item.insert(fileName); }); }; /** * Performing download text file for folder & file description * * @method _performFileDesc * @private * @return void */ _performFileDesc = function () { _api.log("_performFileDesc() is executed.", "info", MODULE_ID); var descNodes = _node.all(".sub"), descProcessCount = descNodes.size(), downloadDescFinish; // Bind Y.Editable for folder/file descriptions after downloading. downloadDescFinish = function () { if (descProcessCount > 0) { return; } _node.all(".sub").setStyle("display", "block"); if (PAGE.permission >= CONST.PERMISSION_UPLOAD) { // Edit folder/file description. _descEditable = new Y.Editable({ "inputType" : "textarea", "selector" : ".sub", "node" : _node.one("#storage-box"), "emptyDefault" : _lang.edit_desc_tooltip, "tooltip" : _lang.edit_desc_tooltip, "validateRule" : "max_length[300]" }); _descEditable.on("hover", function (e) { var target = e.node, value = e.value; if (!value) { target.set("title", ""); } }); _descEditable.on("submit", function (e) { var details, descNode, descReg, data, txt; details = e.details[0]; descNode = details.target; txt = details.value; data = { descFolder : descNode.getAttribute("data-folder-name"), descFile : descNode.getAttribute("data-file-name") + ".txt", descIndex : descNode.get("id").split("-")[1], descValue : details.value }; _uploadFileDesc(data); if (!txt) { txt = _lang.edit_desc_tooltip; } e.target.updateText(txt); e.target.set("title", txt); }); } }; Y.each(descNodes, function (node, i) { var descNode, did, wsip, folderName, fileName, filePath, txt = "", tooltip = "", afterDownloadDesc, failureHandler, timeoutHandler; descNode = node; if (descNode.hasClass("desc-fill")) { folderName = descNode.getAttribute("data-folder-name"); fileName = descNode.getAttribute("data-file-name") + ".txt"; // /USB_JetFlash_Transcend_16GB_XAZBOVM_1/miiiCasa_Documents/Folder 20120419/Subfolder 20120424/.miiithumbs/desc.txt filePath = (isWanShare ? PAGE.subpath : currentPath) + folderName + "/.miiithumbs/" + fileName; afterDownloadDesc = function (o) { _api.log("afterDownloadDesc() is executed.", "info", MODULE_ID); var desc, duration, durationNode; desc = Y.Lang.trim(o.data); if (!Lang.isUndefined(desc)) { // If content is JSON format if (desc.substr(0, 1) === "{" && desc.substr(desc.length - 1, 1) === "}") { txt = Y.JSON.parse(desc); descNode.setAttribute("data-txt", txt); if (txt.videoLength) { duration = txt.videoLength; if (duration.length < 8) { duration = _fixErrorDrtFormat(duration); } durationNode = descNode.get("parentNode").get("parentNode").one(".file-duration"); durationNode.set("innerHTML", duration); } txt = txt.desc; } else { // Not JSON format txt = desc; } } if (txt) { descNode.set("text", txt); } if (!txt) { descNode.addClass("yui3-editable-empty"); } descNode.removeClass("desc-fill"); descProcessCount -= 1; downloadDescFinish(); }; failureHandler = function () { _api.log("failureHandler() is executed.", "error", MODULE_ID); descNode.removeClass("desc-fill"); descProcessCount -= 1; downloadDescFinish(); }; timeoutHandler = function () { _api.log("timeoutHandler() is executed.", "error", MODULE_ID); descNode.removeClass("desc-fill"); descProcessCount -= 1; downloadDescFinish(); }; _deviceConnector.downloadTextFile({ fullfilename : filePath }, { on: { success: afterDownloadDesc, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); } else { descProcessCount -= 1; downloadDescFinish(); } }); }; /** * Makes the taskrow stick inside viewport * @event _stickTaskRow * @private */ _stickTaskRow = function () { var firstTaskRowNode = _node.one("div.task-row-container"); if (firstTaskRowNode) { firstTaskRowNode.plug(Y.Plugin.NodeStickViewport); firstTaskRowNode.stickViewport.setDistance("top", 75); firstTaskRowNode.stickViewport.clone(); } }; /** * Upload file description to device. * * @event _uploadFileDesc * @param descData {Object} * @private */ _uploadFileDesc = function (descData) { _api.log("_uploadFileDesc() is exectued.", "info", MODULE_ID); var txt = {}, data = {}, opt, uploadURL = Y.MiiiCasa.uploadURL; data.tok = _deviceInfo.token; if (isWanShare) { data.subpath = PAGE.subpath + descData.descFolder + "/.miiithumbs"; } else { data.path = currentPath + descData.descFolder + "/.miiithumbs"; } if (!isLan) { data.cp = Y.Cookie.get("p"); data.cs = Y.Cookie.get("s"); } if (!isLan) { if (PAGE.did) { data.did = PAGE.did; } else if (PAGE.fid) { data.fid = PAGE.fid; } } opt = { fileVar : "uploadedfile", uploadTo: UPLOAD_URL, desc : descData.descValue, filename: descData.descFile }; // If the desc txt format is JSON and not folder desc, save desc file with JSON if (descData.descContent && opt.filename !== "desc.txt") { txt = Y.JSON.parse(descData.descContent); txt.desc = descData.descValue; opt.desc = Y.JSON.stringify(txt); } _uploader.uploadDesc(data, opt); }; /** * Initialize Music Player. * * @method _initPlayer * @private * @return void */ _initPlayer = function () { _api.log("_initPlayer() is executed.", "info", MODULE_ID); _player = new Y.MusicPlayer({useIframe: true}); }; /** * Initialize empty UI. * * @method _initEmptyUI * @private * @return void */ _initEmptyUI = function () { _node.one(".sort-row").setStyle("display", "none"); _node.one(".task-row-container").remove(); _node.one(".empty").setStyle("display", "block"); _initUI(); }; /** * Initialize main UI / binding events * * @method _initUI * @private * @return void */ _initUI = function () { _api.log("_initUI() is executed.", "info", MODULE_ID); _node.all("input[name=download-button]").on("click", _downloadButtonHandler); // handle UI & events by permission if (PAGE.permission >= CONST.PERMISSION_MANAGE) { _node.all("input[name=delete-button]").on("click", _deleteButtonHandler); Y.one(".create-link").on("click", _createLinkHandler); } // attach event for devices not support upload if (!_featureSupport.canTryUpload && PAGE.permission >= CONST.PERMISSION_UPLOAD) { _blockUploadButtons(); } // show _node.setStyle("visibility", "visible"); //fetch storage data for free_space _listStorages(); // fetch folder desc _fetchDesc(); // perform folder Link _performFileLink(); // perform file preivew button with photo type _performFilePreview(); // makes taskrow stick inside viewport Y.later(100, this, _stickTaskRow); Y.delegate("mouseenter", _mouseEnterListHandler, _node, "tbody tr"); Y.delegate("mouseleave", _mouseLeaveListHandler, _node, "tbody tr"); Y.delegate("click", _itemSelectHandler, _node, "input[name=list-item]"); _node.delegate("click", _commentClickHandler, "a.comment-link"); _node.all("input[name=copyto-button]").on("click", _pickerButtonHandler); _node.all("input[name=moveto-button]").on("click", _pickerButtonHandler); // Preview Y.delegate("click", _previewFileHandler, _node, ".main"); // Download Y.delegate("click", _downloadButtonHandler, _node, ".download-link"); _getSharedComments(); _api.broadcast("hide-main-loading"); }; /** * List all storges for each device * * @method _listStorages * @private * @return void */ _listStorages = function () { _api.log("_listStorages() is executed.", "info", MODULE_ID); var afterListStorages, failureHandler, timeoutHandler; afterListStorages = function (o) { _api.log("afterListStorages() is executed.", "info", MODULE_ID); var storagesData, thisDeviceLabels = {}, labelUpdated = false; Y.each(o.storages, function (storage) { Y.each(storage.mountpoints, function (partition) { thisDeviceLabels[partition.mountpoint.substr(1)] = partition.name; if ("/" + PAGE.storage === partition.mountpoint) { if (!Lang.isUndefined(MIIICASA.env.label) && MIIICASA.env.label !== partition.name) { labelUpdated = true; } _currentStorage = { model : storage.model, type : storage.type, mountpoint : partition.mountpoint, name : util.formatLabelName(partition.name), storage : partition.storage, used_space : partition.used_space, free_space : partition.storage - partition.used_space }; PAGE.label = _currentStorage.name; } }); }); if (labelUpdated) { util.saveLabel(PAGE.did, thisDeviceLabels); } // update create folder overlay ui storagesData = [{ name : PAGE.label, free_space : _currentStorage.free_space }]; _api.broadcast("show-create-folder-update-ui", { storages : storagesData, callback : _doCreateDirectory }); }; failureHandler = function () { _api.log("failureHandler() is executed.", "error", MODULE_ID); }; timeoutHandler = function () { _api.log("timeoutHandler() is executed.", "error", MODULE_ID); }; _deviceConnector.listStorages({}, { on: { success: afterListStorages, failure: failureHandler, timeout: timeoutHandler }, timeout: CONST.CLIENT_TIMEOUT }); }; /** * Redirect to new folder after create folder * @method _redirectToNewFolder * @private */ _redirectToNewFolder = function (e) { if (!_newFolderData.folderName) { _api.broadcast("hide-main-loading"); return; } var url = Y.substitute(PAGE.listURL, { SUB_DIR : encodeURIComponent(_newFolderData.folderName) }); window.location.href = url; }; /** * After renaming or deleting folder or files, send the request to delete record in database. * Also, delete shared record. * * @method _syncFileInfo * @private * @param data{Object} The data synchronized with comments and sharing. * @param callback{Function} The callback function. * @return void */ _syncFileInfo = function (data, callback) { _api.log("_syncFileInfo() is executed."); data = util.composeData(data); var url = "/space/q/sync_file_info", cfg; cfg = { method: "POST", data: data, on: { complete: function (id, o, a) { var response = Y.JSON.parse(o.responseText); if (response.status === "ok") { _api.log("_syncFileInfo() is success."); if (callback) { callback(); } } else { _api.log("_syncFileInfo() is failed.", "error", MODULE_ID); } } } }; Y.io(url, cfg); }; /** * Check button event when delete, download, share * * @method _checkButtonEvent * @private * @param e {Y.Event} The event instance * @return selectedNodes */ _checkButtonEvent = function (e) { var targetID, selectID, selectedNodes, previewNode; previewNode = Y.one(".previewer") || false; if (_node.one("." + CUR_PREVIEW_CLASS)) { if (previewNode && !previewNode.hasClass("yui3-panel-hidden")) { _api.log("click file in preview player"); selectedNodes = _node.all("." + CUR_PREVIEW_CLASS + " input[name=list-item]"); return selectedNodes; } } if (e.container) { _api.log("click file in row"); selectID = e.currentTarget.get("parentNode").get("parentNode").get("id"); selectedNodes = _node.all("#" + selectID + " input[name=list-item]"); return selectedNodes; } _api.log("no select any file to delete."); selectedNodes = _node.all("input[name=list-item]:checked"); return selectedNodes; }; /** * _embedPlayer * Embed object for playing video. * Embed Player with Flowplayer API * @method * @return void */ _embedPlayer = function () { var src, encode; src = _encodeVideoLink(_previewPlayer.data.link); flowplayer(PLAYER_EMBED_ID, { src: PLAYER_SWF, // we need at least this Flash version version: [9, 115], // older versions will see a custom message onFail: function () { Y.one("#" + PLAYER_EMBED_ID).set("innerHTML", "You need the latest Flash version to see movies.Your version is " + this.getVersion()); } }, { clip: { url: src, urlEncoding: false, autoPlay: true }, onStart: function (clip) { _fileDrtHandler(clip.duration); }, onLoad: function () { _videoTipHandler(); }, onError: function () { this.hide(); this.close(); _previewerPanel.hide(); _previewPlayer.film(); }, showErrors: false }); }; /** * _handleVisibleChange * Close Player with Flowplayer API * @method * @return void */ _handleVisibleChange = function (e) { _api.log("Close player."); if (e.prevVal && !e.newVal) { flowplayer(0).close(); } }; /** * _encodeVideoLink * encode the link when isLan or not. * @method * @return URL {String} Video location */ _encodeVideoLink = function (src) { var url; url = util.encodeURIForDa(src, false); _api.log("file path:" + src); _api.log("file path encodeURIForDa:" + url); // Flowplayer will decode agian show encode again url = url.replace(/'/g, "%27"); url = encodeURIComponent(url); _api.log("file path for flowplayer:" + url); return url; }; /** * _videoTipAnim.anim * Fade out tip animation. * Fade in tip animation. * @method * @property * @return anim {Object} tip animation */ _videoTipAnim.anim = function () { var option, anim, hover; option = this.data; anim = new Y.Anim({ node: option, from: { opacity: 1 }, to: { opacity: 0 }, duration: 0.5 }); hover = this.hoverAnim; option.on("mouseover", hover, Y, anim); option.on("mouseout", hover, Y, anim); return anim; }; /** * _videoTipAnim.hover * Fade out tip animation when mouse out. * Fade in tip animation when mouse in. * @method * @property * @return void */ _videoTipAnim.hoverAnim = function (e, anim) { var reverse; reverse = false; if (anim.get("running")) { anim.pause(); } if (e.type === "mouseover") { reverse = true; } anim.set("reverse", reverse); anim.run(); }; /* _secondsToHms * */ _secondsToHms = function (data) { var d, h, m, s; d = Number(data); h = Math.floor(d / 3600); m = Math.floor(d % 3600 / 60); s = Math.floor(d % 3600 % 60); return ((h > 0 ? h + ":" : "") + (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:") + (s < 10 ? "0" : "") + s); }; /**_vlcDetect * @private * @method * @param result {boolean} VLC detect result */ _vlcDetect = function (result) { VLC_INSTALL = result; //VLC_INSTALL = false; if (VLC_INSTALL) { _api.log("vlc is installed."); } else { _api.log("vlc is not installed."); } }; /** * Contruct href url to preview by VLC. * * @private * @method _vlcPreviewUrl * @param url {String} file location * @param wsip {String} wsip */ _vlcPreviewUrl = function (Url, wsip) { _api.log("_vlcPreviewUrl is excuted."); var hash, path, pUrl, sUrl, cfg, urlVars, uri, request, IOsuccess, IOFailure; if (isLan) { path = Url.replace("http://" + wsip + "/da", ""); Url = "http://" + wsip + "/ws/api/getFile?"; Url += "tok=" + _deviceInfo.token; Url += "&fullfilename=" + encodeURIComponent(path); } pUrl = "/space/videos/preview?video=" + encodeURIComponent(Url) + "&"; urlVars = util.getVars(); if (isLan) { if (isShare) { pUrl += "fid=" + urlVars.fid; } else { pUrl += "did=" + urlVars.did; } return pUrl; } if (isShare) { pUrl += "fid=" + urlVars.fid; } else { pUrl += "did=" + urlVars.did; } pUrl += "&alt=json"; return pUrl; }; /** * _fixErrorDrtFormat * Fix error duration format to 00:00:00 * @param duration {String} video duration * @access protected * @return duration */ _fixErrorDrtFormat = function (duration) { var length = duration.length; if (length < 5) { return "00:0" + duration; } if (length < 6) { return "00:" + duration; } if (length < 7) { return "0" + duration; } }; //=========================== // Public Methods //=========================== /** * Module initialization * @event init * @param api {Y.Sandbox} Module API * @public * @return void */ init = function (sandbox) { _api = sandbox; _api.log("init() is executed"); _lang = { accessDenied : _api.getTrans("access_denied", "Access Denied"), cancel : _api.getTrans("cancel_button", "Cancel"), featureNotSupported : _api.getTrans("feature_not_supported", "This feature is not supported for your device!"), noAlbumSelected : _api.getTrans("no_album_selected", "You don't select any albums."), noFileSelected : _api.getTrans("no_file_selected", "You don't select any files."), noPhotoFound : _api.getTrans("no_photo_found", "We can't find any photo in the folder."), noPhotoSelected : _api.getTrans("no_photo_selected", "You don't select any documents."), noSuchFileOrDirectory : _api.getTrans("no_such_file_or_dir", "No such file or directory"), ok : _api.getTrans("ok_button", "Ok"), oops : _api.getTrans("oops", "Oops"), pleaseSelectAnAlbum : _api.getTrans("please_select_an_album", "Please select an album to share."), pleaseSelectOneAlbum : _api.getTrans("please_select_one_album", "Please just select one album instead of selecting multiple documents or albums."), pleaseSelectPhoto : _api.getTrans("please_select_photo", "Please select single/multiple documents first."), pleaseSelectPhotoInstead : _api.getTrans("please_select_photo_instead", "Please select single/multiple documents instead of selecting albums."), shareOneFolderOnly : _api.getTrans("share_one_folder_only", "Share one folder only"), shareFolderOnly : _api.getTrans("share_folder_only", "Share folder only"), tooManyAlbumsToShare : _api.getTrans("too_many_albums_to_share", "You can share only one album at one time."), filePreview : _api.getTrans("file_Preview", "Preview"), videoTip : _api.getTrans("video_tip", "We encourage you to install {VLC_Player} for best video viewing experience!"), vlcPlayer : _api.getTrans("vlc_player", "VLC Player"), videoDownload : _api.getTrans("video_download", "download"), documents : _api.getTrans("documents", "document(s)"), tooLongDescError : _api.getTrans("too_long_desc_error", "The description is too long.(600 characters max.)"), fileTotalSingular : _api.getTrans("file_total_singular", "{file_total} file"), fileTotalPlural : _api.getTrans("file_total_plural", "{file_total} files"), folderTotalSingular : _api.getTrans("folder_total_singular", "{folder_total} folder"), folderTotalPlural : _api.getTrans("folder_total_plural", "{folder_total} folders"), and : _api.getTrans("and", " & "), preview_docs_title : _api.getTrans("preview_docs_title", "Preview Google Docs"), preview_docs_content : _api.getTrans("preview_docs_content", 'Preview this file with "Google Docs"'), edit_desc_tooltip : _api.getTrans("edit_desc_tooltip", "Edit Description"), cant_move_files_cross_media : _api.getTrans("cant_move_files_cross_media", "You can't move files cross different media types.") }; _api.broadcast("get-device-message", { callback : function (msg) { _lang.deviceMessage = msg; _lang.storageReadOnly = msg["5010"]; _api.lang = _lang; } }); _api.listen("expand-viewer", function (name, id, queryString) { _expandViewer(queryString); }); }; /** * Module content ready * @event onviewload * @public * @return void */ onviewload = function () { if (!_lang.deviceMessage) { Y.later(50, this, onviewload); return; } _api.log("onviewload() is executed"); _node = _api.getViewNode(); _sideNode = Y.one("#sidebar"); PAGE = MIIICASA.PAGE.documentsList; currentPath = PAGE.currentPath; _deviceInfo = Y.MiiiCasa.deviceInfo; isLan = MIIICASA.env.isLan; isShare = Y.MiiiCasa.isShare; isWanShare = !isLan && Y.MiiiCasa.isShare; util = Y.MiiiCasa.util; CONST = Y.merge(CONST, Y.MiiiCasa.CONST); Lang = Y.Lang; UPLOAD_URL = Y.MiiiCasa.uploadURL; UA = Y.UA; _photoTemplate = Y.one("#preview-photo-template").get("innerHTML"); _videoTemplate = Y.one("#preview-video-template").get("innerHTML"); _filmTemplate = Y.one("#preview-film-template").get("innerHTML"); _featureSupport = util.featureDetect(); wsip = isLan ? _deviceInfo.wsip : CONST.API_URL; // If viewer exists, expand the viewer. var queryString, hash, hashes, vlcObject = new Y.VLCPlugin(), params; queryString = window.location.href.split("?")[1]; if (queryString.indexOf("#") !== -1) { queryString = queryString.substring(0, queryString.indexOf("#")); } hash = window.location.hash; queryString += "&type=documents"; params = Y.QueryString.parse(queryString); hashes = Y.QueryString.parse(hash.substr(hash.indexOf("?") + 1)); if (!Y.Lang.isUndefined(params.viewer)) { _expandViewer(Y.QueryString.stringify(params)); } else if (!Y.Lang.isUndefined(hashes.viewer)) { _expandViewer(Y.QueryString.stringify(hashes)); } // create device connector instance and performs getFileList _deviceConnector = new Y.DeviceConnector({ wsip : wsip, did : PAGE.did, isLan : isLan, isShare : Y.MiiiCasa.isShare, fid : PAGE.fid, tok : _deviceInfo.token }); _getFileList(); if (_featureSupport.upload) { _uploader = new Y.Uploader({ containerID : "uploader-container", swfURL : CONST.STATIC_URL + "lib/mui/uploader/assets/uploader.swf?" + CONST.VER_UPLOADER, bindings : { contentReady : MIIICASA.docsList.uploaderContentReadyHandler, uploadDescComplete : MIIICASA.docsList.uploaderUploadDescCompleteHandler } }); } VLC_INSTALL = vlcObject.get("installState"); // uncheck "checkall" - for chrome _node.all("#selectall").set("checked", ""); // checkall _node.all("#selectall").on("click", _checkAllHandler); Y.delegate("click", _commentClickHandler, _node, ".comment-link"); if (!MIIICASA.env.is_login) { _api.trackEvent("documents", "View"); } }; //============================= // callback & global functions //============================= MIIICASA.docsList = {}; MIIICASA.docsList.savDesc = function () { }; // uploader callback functions MIIICASA.docsList.uploaderContentReadyHandler = function (e) { _api.log('uploader content ready'); }; MIIICASA.docsList.uploaderUploadDescCompleteHandler = function () { _api.log("UploadDescComplete"); _redirectToNewFolder(); }; /** * Trigger by "video-preview" module * When play video with VLC, save duration to router. * @class YUI.drtsave * @public * @return void */ YUI.namespace("drtsave"); YUI.drtsave = function (seconds) { _fileDrtHandler(seconds); }; _api = new Y.Module({ selector: MODULE_ID, langModule: "space", init: init, on: { viewload: onviewload } }); }, "0.0.1", { "group" : "space", "js" : "space/documents/_document_list.js", "css" : "space/documents/_document_list.css", "requires": [ "module", "module-intl", "module-popup", "module-analytics", "editable", "viewer", "datatype-date-format", "node-style", "substitute", "handlebars", "cookie", "json", "io-base", "space", "node-stickviewport", "music-player", "event-delegate", "anim", "querystring", "device-connector", "vlc-plugin" ] });