diff --git a/core/client/assets/sass/modules/global.scss b/core/client/assets/sass/modules/global.scss
index 02be82aeee..d3d1048346 100644
--- a/core/client/assets/sass/modules/global.scss
+++ b/core/client/assets/sass/modules/global.scss
@@ -902,6 +902,7 @@ nav {
left: 0;
right: 0;
z-index: 999;
+ @include transition(background 300ms ease);
&.dark {
background: rgba(0,0,0,0.4);
@@ -920,8 +921,14 @@ nav {
}
body.blur > *:not(#modal-container) {
+ @include transition(all 300ms ease);
-webkit-filter: blur(2px);
- filter: blur(2px); // Not used yet
+ -moz-filter: blur(2px);
+ -ms-filter: blur(2px);
+ -o-filter: blur(2px);
+ filter: blur(2px);
+ @include transform(translateZ(0));
+
}
%modal, .modal {
diff --git a/core/client/markdown-actions.js b/core/client/markdown-actions.js
index d87c3a4af2..3823024109 100644
--- a/core/client/markdown-actions.js
+++ b/core/client/markdown-actions.js
@@ -1,6 +1,6 @@
// # Surrounds given text with Markdown syntax
-/*global $, window, CodeMirror, Showdown */
+/*global $, window, CodeMirror, Showdown, moment */
(function () {
"use strict";
var Markdown = {
@@ -15,8 +15,50 @@
self.replace();
},
replace: function () {
- var text = this.elem.getSelection(), pass = true, md, cursor, word, converter;
+ var text = this.elem.getSelection(), pass = true, md, cursor, line, word, converter;
switch (this.style) {
+ case "h1":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "# " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 2);
+ pass = false;
+ break;
+ case "h2":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "## " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 3);
+ pass = false;
+ break;
+ case "h3":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "### " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 4);
+ pass = false;
+ break;
+ case "h4":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "#### " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 5);
+ pass = false;
+ break;
+ case "h5":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "##### " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 6);
+ pass = false;
+ break;
+ case "h6":
+ cursor = this.elem.getCursor();
+ line = this.elem.getLine(cursor.line);
+ this.elem.setLine(cursor.line, "###### " + line);
+ this.elem.setCursor(cursor.line, cursor.ch + 7);
+ pass = false;
+ break;
case "link":
md = this.options.syntax.link.replace('$1', text);
this.elem.replaceSelection(md, "end");
@@ -58,9 +100,12 @@
break;
case "list":
md = text.replace(/^/gm, "* ");
- this.elem.replaceSelection("\n" + md + "\n", "end");
+ this.elem.replaceSelection(md, "end");
pass = false;
break;
+ case "currentDate":
+ md = moment(new Date()).format("D MMMM YYYY");
+ break;
default:
if (this.options.syntax[this.style]) {
md = this.options.syntax[this.style].replace('$1', text);
@@ -84,16 +129,9 @@
italic: "_$1_",
strike: "~~$1~~",
code: "`$1`",
- h1: "\n# $1\n",
- h2: "\n## $1\n",
- h3: "\n### $1\n",
- h4: "\n#### $1\n",
- h5: "\n##### $1\n",
- h6: "\n###### $1\n",
link: "[$1](http://)",
image: "!image[$1](http://)",
- blockquote: "> $1",
- currentDate: new Date().toLocaleString()
+ blockquote: "> $1"
}
};
diff --git a/core/client/tpl/modals/markdown.hbs b/core/client/tpl/modals/markdown.hbs
index ed631eb64f..612e4039df 100644
--- a/core/client/tpl/modals/markdown.hbs
+++ b/core/client/tpl/modals/markdown.hbs
@@ -50,37 +50,37 @@
H1 |
# Heading |
- Alt + 1 |
+ Ctrl + Alt + 1 |
H2 |
## Heading |
- Alt + 2 |
+ Ctrl + Alt + 2 |
H3 |
### Heading |
- Alt + 3 |
+ Ctrl + Alt + 3 |
H4 |
#### Heading |
- Alt + 4 |
+ Ctrl + Alt + 4 |
H5 |
##### Heading |
- Alt + 5 |
+ Ctrl + Alt + 5 |
H6 |
###### Heading |
- Alt + 6 |
+ Ctrl + Alt + 6 |
Select Word |
|
- Ctrl + Option + W |
+ Ctrl + Alt + W |
Uppercase |
@@ -95,7 +95,7 @@
Titlecase |
|
- Ctrl + Option + Shift + U |
+ Ctrl + Alt + Shift + U |
Insert Current Date |
diff --git a/core/client/views/base.js b/core/client/views/base.js
index 0f8371fd78..aab620edfc 100644
--- a/core/client/views/base.js
+++ b/core/client/views/base.js
@@ -173,99 +173,100 @@
}
});
- /**
- * This is the view to generate the markup for the individual
- * modal. Will be included into #modals.
- *
- *
- *
- * Types can be
- * - (empty)
- *
- */
+ // ## Modals
Ghost.Views.Modal = Ghost.View.extend({
el: '#modal-container',
templateName: 'modal',
className: 'js-bb-modal',
+ // Render and manages modal dismissal
initialize: function () {
this.render();
var self = this;
if (!this.model.options.confirm) {
shortcut.add("ESC", function () {
- self.removeItem();
+ self.removeElement();
});
$(document).on('click', '.modal-background', function (e) {
- self.removeItem(e);
+ self.removeElement(e);
});
} else {
// Initiate functions for buttons here so models don't get tied up.
this.acceptModal = function () {
this.model.options.confirm.accept.func();
- self.removeItem();
+ self.removeElement();
};
this.rejectModal = function () {
this.model.options.confirm.reject.func();
- self.removeItem();
+ self.removeElement();
};
shortcut.remove("ESC");
$(document).off('click', '.modal-background');
}
},
- template: function (data) {
- return JST[this.templateName](data);
+ templateData: function () {
+ return this.model;
},
events: {
- 'click .close': 'removeItem',
+ 'click .close': 'removeElement',
'click .js-button-accept': 'acceptModal',
'click .js-button-reject': 'rejectModal'
},
- render: function () {
- this.$el.html(this.template(this.model));
+ afterRender: function () {
this.$(".modal-content").html(this.addSubview(new Ghost.Views.Modal.ContentView({model: this.model})).render().el);
- this.$el.children(".js-modal").center();
- this.$el.addClass("active");
+ this.$el.children(".js-modal").center().css("max-height", $(window).height() - 120); // same as resize(), but the debounce causes init lag
+ this.$el.addClass("active dark");
+
if (document.body.style.webkitFilter !== undefined) { // Detect webkit filters
$("body").addClass("blur");
- } else {
- this.$el.addClass("dark");
}
- return this;
+
+ var self = this;
+ $(window).on('resize', self.resize);
+
},
+ // #### resize
+ // Center and resize modal based on window height
+ resize: _.debounce(function () {
+ $(".js-modal").center().css("max-height", $(window).height() - 120);
+ }, 50),
+ // #### remove
+ // Removes Backbone attachments from modals
remove: function () {
this.undelegateEvents();
this.$el.empty();
this.stopListening();
return this;
},
- removeItem: function (e) {
+ // #### removeElement
+ // Visually removes the modal from the user interface
+ removeElement: function (e) {
if (e) {
e.preventDefault();
e.stopPropagation();
}
+
+ var self = this;
+ this.$el.removeClass('dark');
$('.js-modal').fadeOut(300, function () {
$(this).remove();
- $("#modal-container").removeClass('active dark');
if (document.body.style.filter !== undefined) {
$("body").removeClass("blur");
}
+ self.remove();
+ self.$el.removeClass('active');
});
- this.remove();
+
}
});
- /**
- * Modal Content
- * @type {*}
- */
+ // ## Modal Content
Ghost.Views.Modal.ContentView = Ghost.View.extend({
template: function (data) {
return JST['modals/' + this.model.content.template](data);
},
-
- render: function () {
- this.$el.html(this.template(this.model));
- return this;
+ templateData: function () {
+ return this.model;
}
});
diff --git a/core/client/views/editor.js b/core/client/views/editor.js
index 45ecf7be78..11c1c82a00 100644
--- a/core/client/views/editor.js
+++ b/core/client/views/editor.js
@@ -23,14 +23,14 @@
{'key': 'Ctrl+Shift+L', 'style': 'link'},
{'key': 'Ctrl+Shift+I', 'style': 'image'},
{'key': 'Ctrl+Q', 'style': 'blockquote'},
- {'key': 'Ctrl+Shift+1', 'style': 'currentdate'},
+ {'key': 'Ctrl+Shift+1', 'style': 'currentDate'},
{'key': 'Ctrl+U', 'style': 'uppercase'},
{'key': 'Ctrl+Shift+U', 'style': 'lowercase'},
{'key': 'Ctrl+Alt+Shift+U', 'style': 'titlecase'},
{'key': 'Ctrl+Alt+W', 'style': 'selectword'},
{'key': 'Ctrl+L', 'style': 'list'},
{'key': 'Ctrl+Alt+C', 'style': 'copyHTML'},
- {'key': 'CMD+Alt+C', 'style': 'copyHTML'}
+ {'key': 'Meta+Alt+C', 'style': 'copyHTML'}
];
// The publish bar associated with a post, which has the TagWidget and