From 54eda5c03ce6015a1d5f04b76439d0bc7ddefdfc Mon Sep 17 00:00:00 2001 From: David Arvelo Date: Tue, 24 Jun 2014 02:19:20 -0400 Subject: [PATCH] Mobile Interactions closes #3018 - split clientold mobile interactions into their respective Ember routes/views - create PostsView and SettingsView with mobile interactions - place interactions for the publish bar into ApplicationRoute on init --- ghost/admin/routes/application.js | 15 +++++++ ghost/admin/templates/posts.hbs | 70 +++++++++++++++--------------- ghost/admin/templates/settings.hbs | 48 ++++++++++---------- ghost/admin/utils/mobile-utils.js | 48 ++++++++++++++++++++ ghost/admin/views/posts.js | 30 +++++++++++++ ghost/admin/views/settings.js | 31 +++++++++++++ 6 files changed, 181 insertions(+), 61 deletions(-) create mode 100644 ghost/admin/utils/mobile-utils.js create mode 100644 ghost/admin/views/posts.js create mode 100644 ghost/admin/views/settings.js diff --git a/ghost/admin/routes/application.js b/ghost/admin/routes/application.js index 0d45d3d63b..bf2f4fb7e6 100644 --- a/ghost/admin/routes/application.js +++ b/ghost/admin/routes/application.js @@ -1,9 +1,24 @@ import ShortcutsRoute from 'ghost/mixins/shortcuts-route'; +import mobileUtils from 'ghost/utils/mobile-utils'; var ApplicationRoute = Ember.Route.extend(ShortcutsRoute, { shortcuts: { 'esc': 'closePopups' }, + + mobileInteractions: function () { + var responsiveAction = mobileUtils.responsiveAction; + + Ember.run.scheduleOnce('afterRender', document, function () { + // ### Toggle the sidebar menu + $('[data-off-canvas]').on('click', function (event) { + responsiveAction(event, '(max-width: 650px)', function () { + $('body').toggleClass('off-canvas'); + }); + }); + }); + }.on('init'), + actions: { closePopups: function () { this.get('popover').closePopovers(); diff --git a/ghost/admin/templates/posts.hbs b/ghost/admin/templates/posts.hbs index 5d34716772..92778bb618 100644 --- a/ghost/admin/templates/posts.hbs +++ b/ghost/admin/templates/posts.hbs @@ -1,37 +1,35 @@ -
-
-
-
- All Posts -
- {{#link-to "editor.new" class="button button-add" title="New Post"}}{{/link-to}} -
- {{#view "content-list-content-view" tagName="section"}} -
    - {{#each itemController="posts/post" itemView="post-item-view" itemTagName="li"}} - {{#link-to "posts.post" this class="permalink" title="Edit this post"}} -

    {{title}}

    - - {{/link-to}} - {{/each}} -
- {{/view}} -
-
- {{outlet}} -
+
+
+
+ All Posts +
+ {{#link-to "editor.new" class="button button-add" title="New Post"}}{{/link-to}} +
+ {{#view "content-list-content-view" tagName="section"}} +
    + {{#each itemController="posts/post" itemView="post-item-view" itemTagName="li"}} + {{#link-to "posts.post" this class="permalink" title="Edit this post"}} +

    {{title}}

    + + {{/link-to}} + {{/each}} +
+ {{/view}} +
+
+ {{outlet}}
diff --git a/ghost/admin/templates/settings.hbs b/ghost/admin/templates/settings.hbs index fa900e6f9f..1b5c12bde5 100644 --- a/ghost/admin/templates/settings.hbs +++ b/ghost/admin/templates/settings.hbs @@ -1,28 +1,26 @@ -
- -
- {{outlet}} -
-
+
+ {{outlet}} +
diff --git a/ghost/admin/utils/mobile-utils.js b/ghost/admin/utils/mobile-utils.js new file mode 100644 index 0000000000..2fd658aadc --- /dev/null +++ b/ghost/admin/utils/mobile-utils.js @@ -0,0 +1,48 @@ +/*global DocumentTouch,FastClick*/ +var hasTouchScreen, + smallScreen, + initFastClick, + responsiveAction; + +// Taken from "Responsive design & the Guardian" with thanks to Matt Andrews +// Added !window._phantom so that the functional tests run as though this is not a touch screen. +// In future we can do something more advanced here for testing both touch and non touch +hasTouchScreen = function () { + return !window._phantom && + ( + ('ontouchstart' in window) || + (window.DocumentTouch && document instanceof DocumentTouch) + ); +}; + +smallScreen = function () { + if (window.matchMedia('(max-width: 1000px)').matches) { + return true; + } + + return false; +}; + +initFastClick = function () { + Ember.run.scheduleOnce('afterRender', null, function () { + FastClick.attach(document.body); + }); +}; + +responsiveAction = function responsiveAction(event, mediaCondition, cb) { + if (!window.matchMedia(mediaCondition).matches) { + return; + } + + event.preventDefault(); + event.stopPropagation(); + cb(); +}; + +export { hasTouchScreen, smallScreen }; +export default { + hasTouchScreen: hasTouchScreen, + smallScreen: smallScreen, + initFastClick: initFastClick, + responsiveAction: responsiveAction +}; diff --git a/ghost/admin/views/posts.js b/ghost/admin/views/posts.js new file mode 100644 index 0000000000..79afb751af --- /dev/null +++ b/ghost/admin/views/posts.js @@ -0,0 +1,30 @@ +import mobileUtils from 'ghost/utils/mobile-utils'; + +var PostsView = Ember.View.extend({ + classNames: ['content-view-container'], + tagName: 'section', + + mobileInteractions: function () { + var responsiveAction = mobileUtils.responsiveAction; + + Ember.run.scheduleOnce('afterRender', this, function () { + // ### Show content preview when swiping left on content list + $('.manage').on('click', '.content-list ol li', function (event) { + responsiveAction(event, '(max-width: 800px)', function () { + $('.content-list').animate({right: '100%', left: '-100%', 'margin-right': '15px'}, 300); + $('.content-preview').animate({right: '0', left: '0', 'margin-left': '0'}, 300); + }); + }); + + // ### Hide content preview + $('.manage').on('click', '.content-preview .button-back', function (event) { + responsiveAction(event, '(max-width: 800px)', function () { + $('.content-list').animate({right: '0', left: '0', 'margin-right': '0'}, 300); + $('.content-preview').animate({right: '-100%', left: '100%', 'margin-left': '15px'}, 300); + }); + }); + }); + }.on('didInsertElement'), +}); + +export default PostsView; diff --git a/ghost/admin/views/settings.js b/ghost/admin/views/settings.js new file mode 100644 index 0000000000..4143ab627e --- /dev/null +++ b/ghost/admin/views/settings.js @@ -0,0 +1,31 @@ +import mobileUtils from 'ghost/utils/mobile-utils'; + +var SettingsView = Ember.View.extend({ + classNames: ['wrapper'], + + mobileInteractions: function () { + var responsiveAction = mobileUtils.responsiveAction; + + Ember.run.scheduleOnce('afterRender', this, function () { + // ### Show settings options page when swiping left on settings menu link + $('.settings').on('click', '.settings-menu li', function (event) { + responsiveAction(event, '(max-width: 800px)', function () { + $('.settings-sidebar').animate({right: '100%', left: '-102%', 'margin-right': '15px'}, 300); + $('.settings-content').animate({right: '0', left: '0', 'margin-left': '0'}, 300); + $('.settings-content .button-back, .settings-content .button-save').css('display', 'inline-block'); + }); + }); + + // ### Hide settings options page + $('.settings').on('click', '.settings-content .button-back', function (event) { + responsiveAction(event, '(max-width: 800px)', function () { + $('.settings-sidebar').animate({right: '0', left: '0', 'margin-right': '0'}, 300); + $('.settings-content').animate({right: '-100%', left: '100%', 'margin-left': '15'}, 300); + $('.settings-content .button-back, .settings-content .button-save').css('display', 'none'); + }); + }); + }); + }.on('didInsertElement') +}); + +export default SettingsView;