diff --git a/src/_h5ai/client/js/inc/view/content.js b/src/_h5ai/client/js/inc/view/content.js index cc78c89d..8c2a1c69 100644 --- a/src/_h5ai/client/js/inc/view/content.js +++ b/src/_h5ai/client/js/inc/view/content.js @@ -1,160 +1,8 @@ -modulejs.define('view/content', ['_', '$', 'core/event', 'core/format', 'core/location', 'core/resource', 'core/settings', 'view/mainrow'], function (_, $, event, format, location, resource, allsettings, mainrow) { +modulejs.define('view/content', ['$', 'view/mainrow'], function ($, mainrow) { - var settings = _.extend({ - binaryPrefix: false, - hideFolders: false, - hideParentFolder: false, - setParentFolderLabels: false - }, allsettings.view); - var itemTemplate = - '
  • ' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
  • '; - var contentTemplate = - '
    ' + - '
    ' + - '' + - '
    ' + - '
    ' + - '
    '; - var $content = $(contentTemplate); - var $view = $content.find('#view'); - var $items = $view.find('#items'); - var $empty = $view.find('.empty'); - - - function update(item) { - - var $html = $(itemTemplate); - var $a = $html.find('a'); - var $iconImg = $html.find('.icon img'); - var $label = $html.find('.label'); - var $date = $html.find('.date'); - var $size = $html.find('.size'); - - $html - .addClass(item.isFolder() ? 'folder' : 'file') - .data('item', item); - - location.setLink($a, item); - - $label.text(item.label).attr('title', item.label); - $date.data('time', item.time).text(format.formatDate(item.time)); - $size.data('bytes', item.size).text(format.formatSize(item.size)); - item.icon = resource.icon(item.type); - - if (item.isFolder() && !item.isManaged) { - $html.addClass('page'); - item.icon = resource.icon('folder-page'); - } - - if (item.isCurrentParentFolder()) { - item.icon = resource.icon('folder-parent'); - if (!settings.setParentFolderLabels) { - $label.addClass('l10n-parentDirectory'); - } - $html.addClass('folder-parent'); - } - $iconImg.attr('src', item.icon).attr('alt', item.type); - - item.$view = $html; - - return $html; - } - - function onMouseenter() { - - var item = $(this).closest('.item').data('item'); - event.pub('item.mouseenter', item); - } - - function onMouseleave() { - - var item = $(this).closest('.item').data('item'); - event.pub('item.mouseleave', item); - } - - function onLocationChanged(item) { - - $items.find('.item').remove(); - - if (item.parent && !settings.hideParentFolder) { - $items.append(update(item.parent)); - } - - _.each(item.content, function (e) { - - if (!(e.isFolder() && settings.hideFolders)) { - $items.append(update(e)); - } - }); - - if (item.isEmpty()) { - $empty.show(); - } else { - $empty.hide(); - } - - $content.scrollLeft(0).scrollTop(0); - } - - function onLocationRefreshed(item, added, removed) { - - _.each(added, function (item) { - - if (!(item.isFolder() && settings.hideFolders)) { - update(item).hide().appendTo($items).fadeIn(400); - } - }); - - _.each(removed, function (item) { - - item.$view.fadeOut(400, function () { - item.$view.remove(); - }); - }); - - if (item.isEmpty()) { - setTimeout(function () { $empty.show(); }, 400); - } else { - $empty.hide(); - } - } - - function init() { - - $content.appendTo(mainrow.$el); - $empty.hide(); - - format.setDefaultMetric(settings.binaryPrefix); - - $items - .on('mouseenter', '.item a', onMouseenter) - .on('mouseleave', '.item a', onMouseleave); - - event.sub('location.changed', onLocationChanged); - event.sub('location.refreshed', onLocationRefreshed); - } - - - init(); + var $content = $('
    ').appendTo(mainrow.$el); return { - $el: $content, - $view: $view, - $items: $items + $el: $content }; }); diff --git a/src/_h5ai/client/js/inc/view/item.js b/src/_h5ai/client/js/inc/view/item.js new file mode 100644 index 00000000..ed42ec4f --- /dev/null +++ b/src/_h5ai/client/js/inc/view/item.js @@ -0,0 +1,60 @@ +modulejs.define('view/item', ['_', '$', 'core/format', 'core/location', 'core/resource', 'core/settings'], function (_, $, format, location, resource, allsettings) { + + var settings = _.extend({ + setParentFolderLabels: false + }, allsettings.view); + var template = + '
  • ' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '
  • '; + + + function renderItem(item) { + + var $html = $(template); + var $a = $html.find('a'); + var $iconImg = $html.find('.icon img'); + var $label = $html.find('.label'); + var $date = $html.find('.date'); + var $size = $html.find('.size'); + + $html + .addClass(item.isFolder() ? 'folder' : 'file') + .data('item', item); + + location.setLink($a, item); + + $label.text(item.label).attr('title', item.label); + $date.data('time', item.time).text(format.formatDate(item.time)); + $size.data('bytes', item.size).text(format.formatSize(item.size)); + item.icon = resource.icon(item.type); + + if (item.isFolder() && !item.isManaged) { + $html.addClass('page'); + item.icon = resource.icon('folder-page'); + } + + if (item.isCurrentParentFolder()) { + item.icon = resource.icon('folder-parent'); + if (!settings.setParentFolderLabels) { + $label.addClass('l10n-parentDirectory'); + } + $html.addClass('folder-parent'); + } + $iconImg.attr('src', item.icon).attr('alt', item.type); + + item.$view = $html; + + return $html; + } + + return { + render: renderItem + }; +}); diff --git a/src/_h5ai/client/js/inc/view/view.js b/src/_h5ai/client/js/inc/view/view.js new file mode 100644 index 00000000..9a0fa82c --- /dev/null +++ b/src/_h5ai/client/js/inc/view/view.js @@ -0,0 +1,106 @@ +modulejs.define('view/view', ['_', '$', 'core/event', 'core/format', 'core/settings', 'view/content', 'view/item'], function (_, $, event, format, allsettings, content, viewitem) { + + var settings = _.extend({ + binaryPrefix: false, + hideFolders: false, + hideParentFolder: false + }, allsettings.view); + var template = + '
    ' + + '
      ' + + '
    • ' + + '' + + '' + + '' + + '' + + '
    • ' + + '
    ' + + '
    ' + + '
    '; + var $view = $(template); + var $items = $view.find('#items'); + var $empty = $view.find('.empty'); + + + function onMouseenter() { + + var item = $(this).closest('.item').data('item'); + event.pub('item.mouseenter', item); + } + + function onMouseleave() { + + var item = $(this).closest('.item').data('item'); + event.pub('item.mouseleave', item); + } + + function onLocationChanged(item) { + + $items.find('.item').remove(); + + if (item.parent && !settings.hideParentFolder) { + $items.append(viewitem.render(item.parent)); + } + + _.each(item.content, function (e) { + + if (!(e.isFolder() && settings.hideFolders)) { + $items.append(viewitem.render(e)); + } + }); + + if (item.isEmpty()) { + $empty.show(); + } else { + $empty.hide(); + } + + content.$el.scrollLeft(0).scrollTop(0); + } + + function onLocationRefreshed(item, added, removed) { + + _.each(added, function (item) { + + if (!(item.isFolder() && settings.hideFolders)) { + viewitem.render(item).hide().appendTo($items).fadeIn(400); + } + }); + + _.each(removed, function (item) { + + item.$view.fadeOut(400, function () { + item.$view.remove(); + }); + }); + + if (item.isEmpty()) { + setTimeout(function () { $empty.show(); }, 400); + } else { + $empty.hide(); + } + } + + function init() { + + $view.appendTo(content.$el); + $empty.hide(); + + format.setDefaultMetric(settings.binaryPrefix); + + $items + .on('mouseenter', '.item a', onMouseenter) + .on('mouseleave', '.item a', onMouseleave); + + event.sub('location.changed', onLocationChanged); + event.sub('location.refreshed', onLocationRefreshed); + } + + + init(); + + return { + $el: $view, + $items: $items + }; +}); diff --git a/src/_h5ai/client/js/inc/view/viewmode.js b/src/_h5ai/client/js/inc/view/viewmode.js index b70570df..588b5cdf 100644 --- a/src/_h5ai/client/js/inc/view/viewmode.js +++ b/src/_h5ai/client/js/inc/view/viewmode.js @@ -1,4 +1,4 @@ -modulejs.define('view/viewmode', ['_', '$', 'core/resource', 'core/settings', 'core/store', 'view/content', 'view/sidebar'], function (_, $, resource, allsettings, store, content, sidebar) { +modulejs.define('view/viewmode', ['_', '$', 'core/resource', 'core/settings', 'core/store', 'view/sidebar', 'view/view'], function (_, $, resource, allsettings, store, sidebar, view) { var modes = ['details', 'grid', 'icons']; var settings = _.extend({}, { @@ -66,23 +66,23 @@ modulejs.define('view/viewmode', ['_', '$', 'core/resource', 'core/settings', 'c _.each(modes, function (m) { if (m === mode) { $('#view-' + m).addClass('active'); - content.$view.addClass('view-' + m); + view.$el.addClass('view-' + m); } else { $('#view-' + m).removeClass('active'); - content.$view.removeClass('view-' + m); + view.$el.removeClass('view-' + m); } }); _.each(sortedSizes, function (s) { if (s === size) { - content.$view.addClass('view-size-' + s); + view.$el.addClass('view-size-' + s); } else { - content.$view.removeClass('view-size-' + s); + view.$el.removeClass('view-size-' + s); } }); $('#view-size').val(_.indexOf(sortedSizes, size)); - content.$view.show(); + view.$el.show(); } function addViewSettings() { diff --git a/test/tests/unit/view/content.js b/test/tests/unit/view/content.js index 43cc58b4..9c23e34c 100644 --- a/test/tests/unit/view/content.js +++ b/test/tests/unit/view/content.js @@ -2,7 +2,7 @@ 'use strict'; var ID = 'view/content'; -var DEPS = ['_', '$', 'core/event', 'core/format', 'core/location', 'core/resource', 'core/settings', 'view/mainrow']; +var DEPS = ['$', 'view/mainrow']; describe('module \'' + ID + '\'', function () { @@ -10,35 +10,10 @@ describe('module \'' + ID + '\'', function () { this.definition = modulejs._private.definitions[ID]; - this.xSettings = util.uniqObj(); - this.xResource = { - icon: sinon.stub().returns(util.uniqPath('-icon.png')) - }; - this.xFormat = { - formatSize: sinon.stub().returns(util.uniqId()), - formatDate: sinon.stub().returns(util.uniqId()), - setDefaultMetric: sinon.stub() - }; - this.xEvent = { - sub: sinon.stub(), - pub: sinon.stub() - }; - this.xLocation = { - setLink: sinon.stub() - }; this.xMainrow = {$el: null}; - this.applyFn = function () { - this.xResource.icon.reset(); - this.xFormat.formatSize.reset(); - this.xFormat.formatDate.reset(); - this.xFormat.setDefaultMetric.reset(); - this.xEvent.sub.reset(); - this.xEvent.pub.reset(); - this.xLocation.setLink.reset(); - - return this.definition.fn(_, $, this.xEvent, this.xFormat, this.xLocation, this.xResource, this.xSettings, this.xMainrow); + return this.definition.fn($, this.xMainrow); }; }); @@ -88,11 +63,11 @@ describe('module \'' + ID + '\'', function () { describe('application', function () { - it('returns object with 3 properties', function () { + it('returns object with 1 property', function () { var instance = this.applyFn(); assert.isPlainObject(instance); - assert.lengthOfKeys(instance, 3); + assert.lengthOfKeys(instance, 1); }); it('adds HTML #content to #mainrow', function () { @@ -100,44 +75,6 @@ describe('module \'' + ID + '\'', function () { this.applyFn(); assert.lengthOf($('#mainrow > #content'), 1); }); - - it('adds HTML #view to #content', function () { - - this.applyFn(); - assert.lengthOf($('#content > #view'), 1); - }); - - it('adds HTML #items to #view', function () { - - this.applyFn(); - assert.lengthOf($('#view > #items'), 1); - }); - - it('sets default metric', function () { - - this.applyFn(); - assert.isTrue(this.xFormat.setDefaultMetric.calledOnce); - }); - - it('subscribes to 2 events', function () { - - this.applyFn(); - assert.isTrue(this.xEvent.sub.calledTwice); - }); - - it('subscribes to location.changed', function () { - - this.applyFn(); - assert.strictEqual(this.xEvent.sub.firstCall.args[0], 'location.changed'); - assert.isFunction(this.xEvent.sub.firstCall.args[1]); - }); - - it('subscribes to location.refreshed', function () { - - this.applyFn(); - assert.strictEqual(this.xEvent.sub.secondCall.args[0], 'location.refreshed'); - assert.isFunction(this.xEvent.sub.secondCall.args[1]); - }); }); describe('.$el', function () { @@ -151,30 +88,6 @@ describe('module \'' + ID + '\'', function () { assert.strictEqual(instance.$el.attr('id'), 'content'); }); }); - - describe('.$view', function () { - - it('is $(\'#view\')', function () { - - var instance = this.applyFn(); - assert.isObject(instance.$view); - assert.lengthOf(instance.$view, 1); - assert.isString(instance.$view.jquery); - assert.strictEqual(instance.$view.attr('id'), 'view'); - }); - }); - - describe('.$items', function () { - - it('is $(\'#items\')', function () { - - var instance = this.applyFn(); - assert.isObject(instance.$items); - assert.lengthOf(instance.$items, 1); - assert.isString(instance.$items.jquery); - assert.strictEqual(instance.$items.attr('id'), 'items'); - }); - }); }); }()); diff --git a/test/tests/unit/view/view.js b/test/tests/unit/view/view.js new file mode 100644 index 00000000..0058a9e9 --- /dev/null +++ b/test/tests/unit/view/view.js @@ -0,0 +1,152 @@ +(function () { +'use strict'; + +var ID = 'view/view'; +var DEPS = ['_', '$', 'core/event', 'core/format', 'core/settings', 'view/content', 'view/item']; + +describe('module \'' + ID + '\'', function () { + + before(function () { + + this.definition = modulejs._private.definitions[ID]; + + this.xEvent = { + sub: sinon.stub(), + pub: sinon.stub() + }; + this.xFormat = { + setDefaultMetric: sinon.stub() + }; + this.xSettings = util.uniqObj(); + this.xContent = {$el: null}; + this.xItem = {render: sinon.stub()}; + + this.applyFn = function () { + + this.xEvent.sub.reset(); + this.xEvent.pub.reset(); + this.xFormat.setDefaultMetric.reset(); + this.xItem.render.reset(); + + return this.definition.fn(_, $, this.xEvent, this.xFormat, this.xSettings, this.xContent, this.xItem); + }; + }); + + after(function () { + + util.restoreHtml(); + }); + + beforeEach(function () { + + util.restoreHtml(); + this.xContent.$el = $('
    ').appendTo('body'); + }); + + describe('definition', function () { + + it('is defined', function () { + + assert.isPlainObject(this.definition); + }); + + it('has correct id', function () { + + assert.strictEqual(this.definition.id, ID); + }); + + it('requires correct', function () { + + assert.deepEqual(this.definition.deps, DEPS); + }); + + it('args for each request', function () { + + assert.strictEqual(this.definition.deps.length, this.definition.fn.length); + }); + + it('has no instance', function () { + + assert.notProperty(modulejs._private.instances, ID); + }); + + it('inits without errors', function () { + + this.applyFn(); + }); + }); + + describe('application', function () { + + it('returns object with 2 properties', function () { + + var instance = this.applyFn(); + assert.isPlainObject(instance); + assert.lengthOfKeys(instance, 2); + }); + + it('adds HTML #view to #content', function () { + + this.applyFn(); + assert.lengthOf($('#content > #view'), 1); + }); + + it('adds HTML #items to #view', function () { + + this.applyFn(); + assert.lengthOf($('#view > #items'), 1); + }); + + it('sets default metric', function () { + + this.applyFn(); + assert.isTrue(this.xFormat.setDefaultMetric.calledOnce); + }); + + it('subscribes to 2 events', function () { + + this.applyFn(); + assert.isTrue(this.xEvent.sub.calledTwice); + }); + + it('subscribes to location.changed', function () { + + this.applyFn(); + assert.strictEqual(this.xEvent.sub.firstCall.args[0], 'location.changed'); + assert.isFunction(this.xEvent.sub.firstCall.args[1]); + }); + + it('subscribes to location.refreshed', function () { + + this.applyFn(); + assert.strictEqual(this.xEvent.sub.secondCall.args[0], 'location.refreshed'); + assert.isFunction(this.xEvent.sub.secondCall.args[1]); + }); + }); + + describe('.$el', function () { + + it('is $(\'#view\')', function () { + + var instance = this.applyFn(); + assert.isObject(instance.$el); + assert.lengthOf(instance.$el, 1); + assert.isString(instance.$el.jquery); + assert.strictEqual(instance.$el.attr('id'), 'view'); + }); + }); + + describe('.$items', function () { + + it('is $(\'#items\')', function () { + + var instance = this.applyFn(); + assert.isObject(instance.$items); + assert.lengthOf(instance.$items, 1); + assert.isString(instance.$items.jquery); + assert.strictEqual(instance.$items.attr('id'), 'items'); + }); + }); +}); + +}()); diff --git a/test/tests/unit/view/viewmode.js b/test/tests/unit/view/viewmode.js index f915e5b7..5324b328 100644 --- a/test/tests/unit/view/viewmode.js +++ b/test/tests/unit/view/viewmode.js @@ -2,7 +2,7 @@ 'use strict'; var ID = 'view/viewmode'; -var DEPS = ['_', '$', 'core/resource', 'core/settings', 'core/store', 'view/content', 'view/sidebar']; +var DEPS = ['_', '$', 'core/resource', 'core/settings', 'core/store', 'view/sidebar', 'view/view']; describe('module \'' + ID + '\'', function () { @@ -10,18 +10,18 @@ describe('module \'' + ID + '\'', function () { this.definition = modulejs._private.definitions[ID]; - this.xSettings = { - view: {} - }; this.xResource = { image: sinon.stub().returns(util.uniqPath('-image.png')) }; + this.xSettings = { + view: {} + }; this.xStore = { get: sinon.stub(), put: sinon.stub() }; - this.xContent = {$view: null}; this.xSidebar = {$el: null}; + this.xView = {$el: null}; this.applyFn = function () { @@ -29,7 +29,7 @@ describe('module \'' + ID + '\'', function () { this.xStore.get.reset(); this.xStore.put.reset(); - return this.definition.fn(_, $, this.xResource, this.xSettings, this.xStore, this.xContent, this.xSidebar); + return this.definition.fn(_, $, this.xResource, this.xSettings, this.xStore, this.xSidebar, this.xView); }; }); @@ -41,8 +41,8 @@ describe('module \'' + ID + '\'', function () { beforeEach(function () { util.restoreHtml(); - this.xContent.$view = $('
    ').appendTo('body'); this.xSidebar.$el = $('