mirror of
https://github.com/TryGhost/Ghost.git
synced 2025-02-03 23:00:14 -05:00
Added popover component
Closes #2418, #2714 Ref #2446, #2565 - Added and injected `popover` service to globally control popovers - Added `gh-popover-button` component - Added `popover-mixin` for popover and popover-buttons to mixin - Added body-event-listener mixin for popover service to watch for body clicks with - Post settings and post save button both now use `gh-popover` - Added hacks to `ember-hacks.css` to make popovers work until ghost-ui consolidates functionality
This commit is contained in:
parent
a8164c7d3f
commit
37fd17c084
11 changed files with 183 additions and 49 deletions
|
@ -16,17 +16,22 @@
|
|||
}
|
||||
|
||||
/*
|
||||
By default nav menu should be displayed as it's visibility is controllerd
|
||||
by GhostPopover
|
||||
Styles for GhostPopoverComponent
|
||||
|
||||
hack the user menu and for the post-save button popup,
|
||||
until ghost-ui gets a rehaul
|
||||
*/
|
||||
.navbar .subnav ul {
|
||||
.navbar .subnav ul.ghost-popover,
|
||||
#publish-bar .splitbutton-save .editor-options.ghost-popover,
|
||||
#publish-bar .splitbutton-delete .editor-options.ghost-popover{
|
||||
display: none;
|
||||
}
|
||||
#publish-bar .splitbutton-save .editor-options.ghost-popover.open,
|
||||
#publish-bar .splitbutton-delete .editor-options.ghost-popover.open,
|
||||
.navbar .subnav ul.ghost-popover.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*
|
||||
Styles for GhostPopoverComponent
|
||||
*/
|
||||
|
||||
.ghost-popover {
|
||||
display: none;
|
||||
}
|
||||
|
@ -34,11 +39,14 @@
|
|||
.ghost-popover.open {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
/* Fade in animation */
|
||||
.fade-in {
|
||||
animation: fadein 0.5s;
|
||||
-o-animation: fadein 0.5s; /* Opera */
|
||||
-moz-animation: fadein 0.5s; /* Firefox */
|
||||
-webkit-animation: fadein 0.5s; /* Safari and Chrome */
|
||||
-o-animation: fadein 0.5s; /* Opera */
|
||||
animation: fadein 0.5s;
|
||||
}
|
||||
@keyframes fadein {
|
||||
from {
|
||||
|
@ -48,6 +56,14 @@
|
|||
opacity:1;
|
||||
}
|
||||
}
|
||||
@-o-keyframes fadein { /* Opera */
|
||||
from {
|
||||
opacity:0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@-moz-keyframes fadein { /* Firefox */
|
||||
from {
|
||||
opacity:0;
|
||||
|
@ -64,11 +80,3 @@
|
|||
opacity:1;
|
||||
}
|
||||
}
|
||||
@-o-keyframes fadein { /* Opera */
|
||||
from {
|
||||
opacity:0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
|
14
core/client/components/gh-popover-button.js
Normal file
14
core/client/components/gh-popover-button.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import PopoverMixin from 'ghost/mixins/popover-mixin';
|
||||
|
||||
var PopoverButton = Ember.Component.extend(PopoverMixin, {
|
||||
tagName: "button",
|
||||
/*matches with the popover this button toggles*/
|
||||
popoverName: null,
|
||||
/*Notify popover service this popover should be toggled*/
|
||||
click: function (event) {
|
||||
this._super(event);
|
||||
this.get('popover').togglePopover(this.get('popoverName'));
|
||||
}
|
||||
});
|
||||
|
||||
export default PopoverButton;
|
|
@ -1,8 +1,46 @@
|
|||
import PopoverMixin from 'ghost/mixins/popover-mixin';
|
||||
|
||||
var GhostPopover = Ember.Component.extend({
|
||||
classNames: 'ghost-popover',
|
||||
var GhostPopover = Ember.Component.extend(PopoverMixin, {
|
||||
classNames: 'ghost-popover fade-in',
|
||||
classNameBindings: ['open'],
|
||||
open: false
|
||||
name: null,
|
||||
closeOnClick: false,
|
||||
didInsertElement: function () {
|
||||
this._super();
|
||||
|
||||
var popoverService = this.get('popover');
|
||||
|
||||
popoverService.on('close', this, this.close);
|
||||
popoverService.on('toggle', this, this.toggle);
|
||||
},
|
||||
willDestroyElement: function () {
|
||||
this._super();
|
||||
var popoverService = this.get('popover');
|
||||
|
||||
popoverService.off('close', this, this.close);
|
||||
popoverService.off('toggle', this, this.toggle);
|
||||
},
|
||||
click: function (event) {
|
||||
this._super(event);
|
||||
if (this.get('closeOnClick')) {
|
||||
return this.close();
|
||||
}
|
||||
},
|
||||
close: function () {
|
||||
return this.set('open', false);
|
||||
},
|
||||
toggle: function (options) {
|
||||
/*
|
||||
Close all popovers whose button was not clicked,
|
||||
and toggle the actual target.
|
||||
*/
|
||||
var targetPopoverName = options.target;
|
||||
if (this.get('name') === targetPopoverName) {
|
||||
this.toggleProperty('open');
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
export default GhostPopover;
|
25
core/client/initializers/popover.js
Normal file
25
core/client/initializers/popover.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
import BodyEventListener from 'ghost/mixins/body-event-listener';
|
||||
|
||||
var PopoverService = Ember.Object.extend(Ember.Evented, BodyEventListener, {
|
||||
bodyClick: function (event) {
|
||||
/*jshint unused:false */
|
||||
this.closePopovers();
|
||||
},
|
||||
closePopovers: function () {
|
||||
this.trigger('close');
|
||||
},
|
||||
togglePopover: function (popoverName) {
|
||||
this.trigger('toggle', {target: popoverName});
|
||||
}
|
||||
});
|
||||
|
||||
export default {
|
||||
name: 'popover',
|
||||
|
||||
initialize: function (container, application) {
|
||||
application.register('popover:service', PopoverService);
|
||||
|
||||
application.inject('component:gh-popover', 'popover', 'popover:service');
|
||||
application.inject('component:gh-popover-button', 'popover', 'popover:service');
|
||||
}
|
||||
};
|
38
core/client/mixins/body-event-listener.js
Normal file
38
core/client/mixins/body-event-listener.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
Code modified from Addepar/ember-widgets
|
||||
https://github.com/Addepar/ember-widgets/blob/master/src/mixins.coffee#L39
|
||||
*/
|
||||
var BodyEventListener = Ember.Mixin.create({
|
||||
bodyElementSelector: 'html',
|
||||
bodyClick: Ember.K,
|
||||
init: function () {
|
||||
this._super();
|
||||
return Ember.run.next(this, this._setupDocumentHandlers);
|
||||
},
|
||||
willDestroy: function () {
|
||||
this._super();
|
||||
return this._removeDocumentHandlers();
|
||||
},
|
||||
_setupDocumentHandlers: function () {
|
||||
if (this._clickHandler) {
|
||||
return;
|
||||
}
|
||||
var self = this;
|
||||
this._clickHandler = function () {
|
||||
return self.bodyClick();
|
||||
};
|
||||
return $(this.get('bodyElementSelector')).on('click', this._clickHandler);
|
||||
},
|
||||
_removeDocumentHandlers: function () {
|
||||
$(this.get('bodyElementSelector')).off('click', this._clickHandler);
|
||||
this._clickHandler = null;
|
||||
},
|
||||
/*
|
||||
http://stackoverflow.com/questions/152975/how-to-detect-a-click-outside-an-element
|
||||
*/
|
||||
click: function (event) {
|
||||
return event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
export default BodyEventListener;
|
11
core/client/mixins/popover-mixin.js
Normal file
11
core/client/mixins/popover-mixin.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
Popovers and their buttons are evented and do not propagate clicks.
|
||||
*/
|
||||
var PopoverMixin = Ember.Mixin.create(Ember.Evented, {
|
||||
click: function (event) {
|
||||
this._super(event);
|
||||
return event.stopPropagation();
|
||||
}
|
||||
});
|
||||
|
||||
export default PopoverMixin;
|
|
@ -14,8 +14,11 @@
|
|||
{{#link-to "editor" this class="post-edit" title="Edit Post"}}
|
||||
<span class="hidden">Edit Post</span>
|
||||
{{/link-to}}
|
||||
<a class="post-settings" title="Post Settings" {{action 'editSettings'}}><span class="hidden">Post Settings</span></a>
|
||||
<!-- @TODO use Ghost Popover (#2565) --->
|
||||
{{#gh-popover-button popoverName="post-settings-menu" tagName="a" classNames="post-settings" title="Post Settings"}}
|
||||
<span class="hidden">Post Settings</span>
|
||||
{{/gh-popover-button}}
|
||||
{{#gh-popover name="post-settings-menu" classNames="post-settings-menu menu-drop-right"}}
|
||||
{{view "post-settings-menu-view"}}
|
||||
{{/gh-popover}}
|
||||
</section>
|
||||
</header>
|
||||
|
|
|
@ -9,23 +9,21 @@
|
|||
{{gh-activating-list-item route="settings" title="Settings" classNames="settings"}}
|
||||
|
||||
<li id="usermenu" class="usermenu subnav">
|
||||
<a href="javascript:void(0);" {{action 'toggleMenu'}} class="dropdown">
|
||||
{{#gh-popover-button popoverName="user-menu" tagName="a" href="#" classNames="dropdown"}}
|
||||
{{#if user.image}}
|
||||
<img class="avatar" {{bind-attr src="user.image"}} alt="Avatar" />
|
||||
{{else}}
|
||||
<img class="avatar" src="/shared/img/user-image.png" alt="Avatar" />
|
||||
{{/if}}
|
||||
<span class="name">{{user.name}}</span>
|
||||
</a>
|
||||
{{/gh-popover-button}}
|
||||
{{!-- @TODO: add functionality to allow for dropdown to work --}}
|
||||
{{#gh-popover open=showMenu}}
|
||||
<ul class="overlay">
|
||||
{{#gh-popover tagName="ul" classNames="overlay" name="user-menu" closeOnClick="true"}}
|
||||
<li class="usermenu-profile">{{#link-to 'settings.user'}}Your Profile{{/link-to}}</li>
|
||||
<li class="divider"></li>
|
||||
<li class="usermenu-help"><a href="http://ghost.org/forum/">Help / Support</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="usermenu-signout"><a href="#">Sign Out</a></li>
|
||||
</ul>
|
||||
{{/gh-popover}}
|
||||
</li>
|
||||
</ul>
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
<div class="right">
|
||||
|
||||
<section id="entry-controls">
|
||||
<a class="post-settings" title="Post Settings" {{action 'editSettings'}}><span class="hidden">Post Settings</span></a>
|
||||
<!-- @TODO Use Ghost Popover (#2565) and style arrow down -->
|
||||
{{#gh-popover-button popoverName="post-settings-menu" tagName="a" href="#" classNames="post-settings" title="Post Settings"}}
|
||||
<span class="hidden">Post Settings</span>
|
||||
{{/gh-popover-button}}
|
||||
{{#gh-popover name="post-settings-menu" classNames="post-settings-menu menu-right"}}
|
||||
{{view "post-settings-menu-view"}}
|
||||
{{/gh-popover}}
|
||||
</section>
|
||||
|
||||
{{view "editor-save-button" id="entry-actions"}}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
<button type="button" {{action "save"}} {{bind-attr class="view.isDangerous:button-delete:button-save :js-publish-button" }}>{{view.save-text}}</button>
|
||||
<button {{action 'viewSaveTypes'}} {{bind-attr class="controller.isViewingSaveTypes:active :options :up" }} title="Post Settings"><span class="hidden">Post Settings</span>
|
||||
<button type="button" {{action "save"}} {{bind-attr class="view.isDangerous:button-delete:button-save :js-publish-button" }}>
|
||||
{{view.save-text}}
|
||||
</button>
|
||||
{{!-- @TODO: implement popover --}}
|
||||
<ul {{bind-attr class="controller.isViewingSaveTypes::hidden :editor-options :overlay" }}>
|
||||
<li {{bind-attr class="controller.willPublish:active"}}>
|
||||
<a {{action "setSaveType" "publish"}} href="#">{{view.publish-text}}</a>
|
||||
{{#gh-popover-button popoverName="post-save-menu" classNameBindings="open:active :options :up" title="Post Settings"}}
|
||||
<span class="hidden">Post Settings</span>
|
||||
{{/gh-popover-button}}
|
||||
{{#gh-popover name="post-save-menu" closeOnClick="true" tagName="ul" classNames="editor-options overlay" publishTextBinding=view.publish-text draftTextBinding=view.draft-text}}
|
||||
<li {{bind-attr class="controller.willPublish:active" }}>
|
||||
<a {{action "setSaveType" "publish"}} href="#">{{view.publishText}}</a>
|
||||
</li>
|
||||
<li {{bind-attr class="controller.willPublish::active"}}>
|
||||
<a {{action "setSaveType" "draft"}} href="#">{{view.draft-text}}</a>
|
||||
<li {{bind-attr class="controller.willPublish::active" }}>
|
||||
<a {{action "setSaveType" "draft"}} href="#">{{view.draftText}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
{{/gh-popover}}
|
|
@ -3,13 +3,7 @@ import {formatDate} from 'ghost/utils/date-formatting';
|
|||
|
||||
var PostSettingsMenuView = Ember.View.extend({
|
||||
templateName: 'post-settings-menu',
|
||||
classNames: ['post-settings-menu', 'menu-drop-right', 'overlay'],
|
||||
classNameBindings: ['controller.isEditingSettings::hidden'],
|
||||
publishedAtBinding: Ember.Binding.oneWay('controller.publishedAt'),
|
||||
click: function (event) {
|
||||
//Stop click propagation to prevent window closing
|
||||
event.stopPropagation();
|
||||
},
|
||||
datePlaceholder: function () {
|
||||
return formatDate(moment());
|
||||
}.property('controller.publishedAt')
|
||||
|
|
Loading…
Add table
Reference in a new issue