From 3ea5b0ee37e1d245a7b17051b892a4f4550ef90b Mon Sep 17 00:00:00 2001 From: coderaiser Date: Thu, 16 Feb 2017 15:02:10 +0200 Subject: [PATCH] refactor(view) es2015-ify --- client/cloudcmd.js | 7 +- client/view.js | 746 ++++++++++++++++++++++----------------------- package.json | 1 + webpack.config.js | 1 + 4 files changed, 366 insertions(+), 389 deletions(-) diff --git a/client/cloudcmd.js b/client/cloudcmd.js index b21cd738..ef079ee0 100644 --- a/client/cloudcmd.js +++ b/client/cloudcmd.js @@ -31,15 +31,14 @@ window.CloudCmd = (config) => { const dir = '/dist'; + const notEmpty = (a) => a; + // does not work in development mode const moduleFiles = [ window.Promise ? '' : `${dir}/promise`, Object.assign ? '' : `${dir}/object.assign`, - ].filter((name) => { - return name; - }); + ].filter(notEmpty); const allFiles = moduleFiles - .concat('/join/join') .map((name) => `${name}.js`); const urlFiles = getJoinURL(allFiles); diff --git a/client/view.js b/client/view.js index 2c6b2bd1..3f903506 100644 --- a/client/view.js +++ b/client/view.js @@ -1,407 +1,383 @@ 'use strict'; -/* global CloudCmd, Util, DOM, CloudFunc, $ */ +/* global CloudCmd, DOM, CloudFunc, $ */ const itype = require('itype/legacy'); const rendy = require('rendy'); const exec = require('execon'); +const {time} = require('../common/util'); +const Files = require('./files'); +const Events = require('./events'); + CloudCmd.View = ViewProto; -function ViewProto(CallBack) { - var Name = 'View', - Loading = false, - Events = DOM.Events, - Info = DOM.CurrentInfo, - Key = CloudCmd.Key, - Images = DOM.Images, - View = exec.bind(Util), - Element, TemplateAudio, Overlay; +module.exports = exec.bind(); + +module.exports.show = show; +module.exports.hide = hide; + +let Loading = false; + +const Name = 'View'; +const Info = DOM.CurrentInfo; +const Images = DOM.Images; +const Key = CloudCmd.Key; + +let Element, TemplateAudio, Overlay; + +const Config = { + beforeShow: (callback) => { + Images.hide(); + Key.unsetBind(); + showOverlay(); + exec(callback); + }, + beforeClose: (callback) => { + Key.setBind(); + exec(callback); + hideOverlay(); + }, + afterShow: (callback) => { + Element.focus(); + exec(callback); + }, + afterClose : exec, + fitToView : true, + loop : false, + openEffect : 'none', + closeEffect : 'none', + autoSize : false, + height : '100%', + width : '100%', + minWidth : 0, + minHeight : 0, + padding : 0, + preload : 0, + keys : null, + mouseWheel : false, + arrows : false, + helpers : { + overlay : null, + title : null + } +}; + +function ViewProto(callback) { + const func = callback || exec.with(show, null); - const Config = { - beforeShow: (callback) => { - Images.hide(); - Key.unsetBind(); - showOverlay(); + Loading = true; + + exec.series([ + DOM.loadJquery, + load, + (callback) => { + Loading = false; exec(callback); - }, - beforeClose: (callback) => { - Key.setBind(); - exec(callback); - hideOverlay(); - }, - afterShow: (callback) => { - Element.focus(); - exec(callback); - }, - afterClose: (callback) => { - exec(callback); - }, - fitToView : true, - loop : false, - openEffect : 'none', - closeEffect : 'none', - autoSize : false, - height : '100%', - width : '100%', - minWidth : 0, - minHeight : 0, - padding : 0, - preload : 0, - keys : null, - mouseWheel : false, - arrows : false, - helpers : { - overlay : null, - title : null } - }; + ], func); - View.show = show; - View.hide = hide; + Config.parent = Overlay = DOM.load({ + id : 'js-view', + name : 'div', + className : 'fancybox-overlay fancybox-overlay-fixed' + }); - function init() { - var func = CallBack || exec.with(show, null); - - Loading = true; - - exec.series([ - DOM.loadJquery, - load, - function(callback) { - Loading = false; - exec(callback); - } - ], func); - - Config.parent = Overlay = DOM.load({ - id : 'js-view', - name : 'div', - className : 'fancybox-overlay fancybox-overlay-fixed' + ['click', 'contextmenu'].forEach((name) => { + Events.add(name, Overlay, onOverLayClick); + }); + + Events.addKey(listener); + + return module.exports; +} + +function show(data, options) { + const prefixUrl = CloudCmd.PREFIX_URL + CloudFunc.FS; + + if (Loading) + return; + + Element = $('
'); + + let element; + + if (data) { + element = $(Element).append(data); + $.fancybox(element, initConfig(Config, options)); + return; + } + + Images.show.load(); + + const path = prefixUrl + Info.path; + const type = getType(path); + + switch(type) { + default: + return Info.getData((error, data) => { + if (error) + return Images.hide(); + + const element = document.createTextNode(data); + /* add margin only for view text documents */ + Element.css('margin', '2%'); + + $.fancybox(Element.append(element), Config); }); - - ['click', 'contextmenu'].forEach(function(name) { - Events.add(name, Overlay, onOverLayClick); - }); - - Events.addKey(listener); - } - /** - * function shows FancyBox - */ - function show(data, options) { - var path, element, type; - var prefixUrl = CloudCmd.PREFIX_URL + CloudFunc.FS; - - if (Loading) - return; - - Element = $('
'); - - if (data) { - element = $(Element).append(data); + case 'image': + return showImage(path, prefixUrl); + + case 'media': + return getMediaElement(path, (element) => { + const media = DOM.getByDataName('js-media', element); + const onKey = exec.with(onMediaKey, media); - var config = initConfig(Config, options); - - $.fancybox(element, config); - } else { - Images.show.load(); - path = prefixUrl + Info.path; - type = getType(path); - - switch(type) { - default: - Info.getData(function(error, data) { - if (error) - return Images.hide(); - - var element = document.createTextNode(data); - /* add margin only for view text documents */ - Element.css('margin', '2%'); - - $.fancybox(Element.append(element), Config); - }); - break; - - case 'image': - showImage(path, prefixUrl); - break; - - case 'media': - getMediaElement(path, function(element) { - var media = DOM.getByDataName('js-media', element); - var onKey = exec.with(onMediaKey, media); - - $.fancybox.open(element, { - parent : Overlay, - beforeShow : function() { - Config.beforeShow(); - Events.addKey(onKey); - }, - beforeClose : function() { - Config.beforeClose(); - Events.rmKey(onKey); - }, - afterShow: function() { - element - .querySelector('audio, video') - .focus(); - }, - helpers: { - overlay : null, - title : null - } - }); - }); - break; - } - } - } - - function initConfig(Config, options) { - var config = {}; - - Util.copyObj(config, Config); - - if (!options) - return config; - - Object.keys(options).forEach(function(name) { - var isConfig = !!config[name]; - var item = options[name]; - var isFunc = itype.function(item); - - if (!isFunc || !isConfig) { - config[name] = options[name]; - } else { - var func = config[name]; - config[name] = function() { - exec.series([func, item]); - }; - } - }); - - return config; - } - - function hide() { - $.fancybox.close(); - } - - function showImage(path, prefixUrl) { - var config, - current = Info.name, - files = [].slice.call(Info.files), - names = files - .filter(function(file) { - var name = DOM.getCurrentName(file); - return isImage(name); - }) - .filter(function(file) { - var name = DOM.getCurrentName(file); - return name !== current; - }).map(function(file) { - var path = DOM.getCurrentPath(file), - name = DOM.getCurrentName(file); - - return { - href: prefixUrl + path, - title: name - }; - }); - - names.unshift({ - href: path, - title: current - }); - - config = Util.copyObj({ - }, Config); - - config = Util.copyObj(config, { - autoSize : true, - type : 'image', - prevEffect : 'none', - nextEffect : 'none', - arrows : true, - keys : true, - helpers : { - overlay : null, - title : {} - } - }); - - $.fancybox.open(names, config); - } - - function isImage(name) { - var isMatch; - - isMatch = [ - 'jp(e|g|eg)', - 'gif', - 'png', - 'bmp', - 'webp', - 'svg', - 'ico' - ].some(function(ext) { - var reg = RegExp('\\.' + ext + '$', 'i'); - return reg.test(name); - }); - - return isMatch; - } - - function isMedia(name) { - var isMatch; - - isMatch = isAudio(name) || isVideo(name); - - return isMatch; - } - - function isAudio(name) { - return /\.(mp3|ogg|m4a)$/i.test(name); - } - - function isVideo(name) { - return /\.(mp4|avi)$/i.test(name); - } - - function getType(name) { - var type; - - if (isImage(name)) - type = 'image'; - else if (isMedia(name)) - type = 'media'; - - return type; - } - - function getMediaElement(src, callback) { - check(src, callback); - - DOM.Files.get('view/media-tmpl', function(error, template) { - var rendered, element, type, is, - name = Info.name; - - if (error) { - alert(error); - } else { - if (!TemplateAudio) - TemplateAudio = template; - - is = isAudio(name); - type = is ? 'audio' : 'video'; - - rendered = rendy(TemplateAudio, { - src : src, - type: type, - name: Info.name - }); - - element = $(rendered)[0]; - callback(element); - } - }); - } - - function check(src, callback) { - if (typeof src !== 'string') - throw Error('src should be a string!'); - - if (typeof callback !== 'function') - throw Error('callback should be a function'); - } - - function onMediaKey(media, event) { - var key = event.keyCode; - - if (key === Key.SPACE) { - if (media.paused) - media.play(); - else - media.pause(); - } - } - - /** - * function loads css and js of FancyBox - * @callback - executes, when everything loaded - */ - function load(callback) { - Util.time(Name + ' load'); - - DOM.loadRemote('fancybox', function() { - var prefix = CloudCmd.PREFIX; - - DOM.load.css(prefix + '/css/view.css', callback); - - DOM.load.style({ - id : 'view-inlince-css', - inner : [ - '.fancybox-title-float-wrap .child {', - '-webkit-border-radius: 0;', - '-moz-border-radius: 0;', - 'border-radius: 0;', - '}' - ].join('') + $.fancybox.open(element, { + parent : Overlay, + beforeShow : () => { + Config.beforeShow(); + Events.addKey(onKey); + }, + beforeClose : () => { + Config.beforeClose(); + Events.rmKey(onKey); + }, + afterShow: () => { + element + .querySelector('audio, video') + .focus(); + }, + helpers: { + overlay : null, + title : null + } }); }); } - - function onOverLayClick(event) { - var isCurrent, isFiles, isFilesPassive, - files = Info.files, - filesPassive = Info.filesPassive, - element = event.target, - isOverlay = element === Overlay, - position = { - x: event.clientX, - y: event.clientY - }; - - if (isOverlay) { - hideOverlay(); - element = DOM.getCurrentByPosition(position); - - if (element) { - isFiles = ~files.indexOf(element); - isFilesPassive = ~filesPassive.indexOf(element); - - if (isFiles || isFilesPassive) { - isCurrent = DOM.isCurrentFile(element); - - if (!isCurrent) - DOM.setCurrentFile(element); - } - } - - View.hide(); - } - } - - function hideOverlay() { - Overlay.classList.remove('view-overlay'); - } - - function showOverlay() { - Overlay.classList.add('view-overlay'); - } - - function listener(event) { - var keyCode = event.keyCode, - ESC = Key.ESC; - - if (keyCode === ESC) - hide(); - } - - init(); - - return View; +} + +function initConfig(Config, options) { + const config = Object.assign({}, Config); + + if (!options) + return config; + + Object.keys(options).forEach((name) => { + const isConfig = !!config[name]; + const item = options[name]; + const isFunc = itype.function(item); + + if (!isFunc || !isConfig) + return config[name] = options[name]; + + const func = config[name]; + config[name] = () => { + exec.series([func, item]); + }; + }); + + return config; +} + +function hide() { + $.fancybox.close(); +} + +function showImage(href, prefixUrl) { + const title = Info.name; + const names = Info.file + .filter((file) => { + const name = DOM.getCurrentName(file); + return isImage(name); + }) + .filter((file) => { + const name = DOM.getCurrentName(file); + return name !== title; + }).map((file) => { + const href = prefixUrl + DOM.getCurrentPath(file); + const title = DOM.getCurrentName(file); + + return { + href, + title, + }; + }).unshift({ + href, + title, + }); + + const config = Object.assign({}, Config, { + autoSize : true, + type : 'image', + prevEffect : 'none', + nextEffect : 'none', + arrows : true, + keys : true, + helpers : { + overlay : null, + title : {} + } + }); + + $.fancybox.open(names, config); +} + +function isImage(name) { + const images = [ + 'jp(e|g|eg)', + 'gif', + 'png', + 'bmp', + 'webp', + 'svg', + 'ico' + ]; + + return images + .map((ext) => RegExp(`\\.${ext}$`, 'i')) + .some((reg) => reg.test(name)); +} + +function isMedia(name) { + return isAudio(name) || isVideo(name); +} + +function isAudio(name) { + return /\.(mp3|ogg|m4a)$/i.test(name); +} + +function isVideo(name) { + return /\.(mp4|avi)$/i.test(name); +} + +function getType(name) { + if (isImage(name)) + return 'image'; + + if (isMedia(name)) + return 'media'; +} + +function getMediaElement(src, callback) { + check(src, callback); + + Files.get('view/media-tmpl', (error, template) => { + var rendered, element, type, is, + name = Info.name; + + if (error) { + alert(error); + } else { + if (!TemplateAudio) + TemplateAudio = template; + + is = isAudio(name); + type = is ? 'audio' : 'video'; + + rendered = rendy(TemplateAudio, { + src : src, + type: type, + name: Info.name + }); + + element = $(rendered)[0]; + callback(element); + } + }); +} + +function check(src, callback) { + if (typeof src !== 'string') + throw Error('src should be a string!'); + + if (typeof callback !== 'function') + throw Error('callback should be a function'); +} + +function onMediaKey(media, event) { + var key = event.keyCode; + + if (key === Key.SPACE) { + if (media.paused) + media.play(); + else + media.pause(); + } +} + +/** + * function loads css and js of FancyBox + * @callback - executes, when everything loaded + */ +function load(callback) { + time(Name + ' load'); + + DOM.loadRemote('fancybox', function() { + var prefix = CloudCmd.PREFIX; + + DOM.load.css(prefix + '/css/view.css', callback); + + DOM.load.style({ + id : 'view-inlince-css', + inner : [ + '.fancybox-title-float-wrap .child {', + '-webkit-border-radius: 0;', + '-moz-border-radius: 0;', + 'border-radius: 0;', + '}' + ].join('') + }); + }); +} + +function onOverLayClick(event) { + const files = Info.files; + const filesPassive = Info.filesPassive; + const {target} = event; + const isOverlay = target === Overlay; + const position = { + x: event.clientX, + y: event.clientY + }; + + if (!isOverlay) + return; + + hideOverlay(); + + const element = DOM.getCurrentByPosition(position); + + if (!element) + return; + + const isFiles = ~files.indexOf(element); + const isFilesPassive = ~filesPassive.indexOf(element); + + if (!isFiles && !isFilesPassive) + return; + + const isCurrent = DOM.isCurrentFile(element); + + if (isCurrent) + return; + + DOM.setCurrentFile(element); + + hide(); +} + +function hideOverlay() { + Overlay.classList.remove('view-overlay'); +} + +function showOverlay() { + Overlay.classList.add('view-overlay'); +} + +function listener({keyCode}) { + if (keyCode === Key.ESC) + hide(); } diff --git a/package.json b/package.json index 13fb1ba6..fa68aeef 100644 --- a/package.json +++ b/package.json @@ -167,6 +167,7 @@ "nodemon": "^1.9.1", "nsp": "^2.2.1", "nyc": "^10.1.2", + "object.assign": "^4.0.4", "place": "^1.1.4", "promise-polyfill": "^6.0.2", "readjson": "^1.1.3", diff --git a/webpack.config.js b/webpack.config.js index ff6d4df2..ce71a6b3 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -44,6 +44,7 @@ module.exports = { cloud: `${dir}/cloud.js`, promise: `${dirExternal}/promise-polyfill/promise.js`, + 'object.assign': `${dirExternal}/object.assign/dist/browser.js`, }, output: { filename: '[name].js',