Merge pull request #393 from matthojo/Modal-Fixes

Several Modal Fixes
This commit is contained in:
Hannah Wolfe 2013-08-18 09:05:49 -07:00
commit e794e8de7a
5 changed files with 103 additions and 57 deletions

View File

@ -902,6 +902,7 @@ nav {
left: 0; left: 0;
right: 0; right: 0;
z-index: 999; z-index: 999;
@include transition(background 300ms ease);
&.dark { &.dark {
background: rgba(0,0,0,0.4); background: rgba(0,0,0,0.4);
@ -920,8 +921,14 @@ nav {
} }
body.blur > *:not(#modal-container) { body.blur > *:not(#modal-container) {
@include transition(all 300ms ease);
-webkit-filter: blur(2px); -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 { %modal, .modal {

View File

@ -1,6 +1,6 @@
// # Surrounds given text with Markdown syntax // # Surrounds given text with Markdown syntax
/*global $, window, CodeMirror, Showdown */ /*global $, window, CodeMirror, Showdown, moment */
(function () { (function () {
"use strict"; "use strict";
var Markdown = { var Markdown = {
@ -15,8 +15,50 @@
self.replace(); self.replace();
}, },
replace: function () { 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) { 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": case "link":
md = this.options.syntax.link.replace('$1', text); md = this.options.syntax.link.replace('$1', text);
this.elem.replaceSelection(md, "end"); this.elem.replaceSelection(md, "end");
@ -58,9 +100,12 @@
break; break;
case "list": case "list":
md = text.replace(/^/gm, "* "); md = text.replace(/^/gm, "* ");
this.elem.replaceSelection("\n" + md + "\n", "end"); this.elem.replaceSelection(md, "end");
pass = false; pass = false;
break; break;
case "currentDate":
md = moment(new Date()).format("D MMMM YYYY");
break;
default: default:
if (this.options.syntax[this.style]) { if (this.options.syntax[this.style]) {
md = this.options.syntax[this.style].replace('$1', text); md = this.options.syntax[this.style].replace('$1', text);
@ -84,16 +129,9 @@
italic: "_$1_", italic: "_$1_",
strike: "~~$1~~", strike: "~~$1~~",
code: "`$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://)", link: "[$1](http://)",
image: "!image[$1](http://)", image: "!image[$1](http://)",
blockquote: "> $1", blockquote: "> $1"
currentDate: new Date().toLocaleString()
} }
}; };

View File

@ -50,37 +50,37 @@
<tr> <tr>
<td>H1</td> <td>H1</td>
<td># Heading</td> <td># Heading</td>
<td>Alt + 1</td> <td>Ctrl + Alt + 1</td>
</tr> </tr>
<tr> <tr>
<td>H2</td> <td>H2</td>
<td>## Heading</td> <td>## Heading</td>
<td>Alt + 2</td> <td>Ctrl + Alt + 2</td>
</tr> </tr>
<tr> <tr>
<td>H3</td> <td>H3</td>
<td>### Heading</td> <td>### Heading</td>
<td>Alt + 3</td> <td>Ctrl + Alt + 3</td>
</tr> </tr>
<tr> <tr>
<td>H4</td> <td>H4</td>
<td>#### Heading</td> <td>#### Heading</td>
<td>Alt + 4</td> <td>Ctrl + Alt + 4</td>
</tr> </tr>
<tr> <tr>
<td>H5</td> <td>H5</td>
<td>##### Heading</td> <td>##### Heading</td>
<td>Alt + 5</td> <td>Ctrl + Alt + 5</td>
</tr> </tr>
<tr> <tr>
<td>H6</td> <td>H6</td>
<td>###### Heading</td> <td>###### Heading</td>
<td>Alt + 6</td> <td>Ctrl + Alt + 6</td>
</tr> </tr>
<tr> <tr>
<td>Select Word</td> <td>Select Word</td>
<td></td> <td></td>
<td>Ctrl + Option + W</td> <td>Ctrl + Alt + W</td>
</tr> </tr>
<tr> <tr>
<td>Uppercase</td> <td>Uppercase</td>
@ -95,7 +95,7 @@
<tr> <tr>
<td>Titlecase</td> <td>Titlecase</td>
<td></td> <td></td>
<td>Ctrl + Option + Shift + U</td> <td>Ctrl + Alt + Shift + U</td>
</tr> </tr>
<tr> <tr>
<td>Insert Current Date</td> <td>Insert Current Date</td>

View File

@ -173,99 +173,100 @@
} }
}); });
/** // ## Modals
* This is the view to generate the markup for the individual
* modal. Will be included into #modals.
*
*
*
* Types can be
* - (empty)
*
*/
Ghost.Views.Modal = Ghost.View.extend({ Ghost.Views.Modal = Ghost.View.extend({
el: '#modal-container', el: '#modal-container',
templateName: 'modal', templateName: 'modal',
className: 'js-bb-modal', className: 'js-bb-modal',
// Render and manages modal dismissal
initialize: function () { initialize: function () {
this.render(); this.render();
var self = this; var self = this;
if (!this.model.options.confirm) { if (!this.model.options.confirm) {
shortcut.add("ESC", function () { shortcut.add("ESC", function () {
self.removeItem(); self.removeElement();
}); });
$(document).on('click', '.modal-background', function (e) { $(document).on('click', '.modal-background', function (e) {
self.removeItem(e); self.removeElement(e);
}); });
} else { } else {
// Initiate functions for buttons here so models don't get tied up. // Initiate functions for buttons here so models don't get tied up.
this.acceptModal = function () { this.acceptModal = function () {
this.model.options.confirm.accept.func(); this.model.options.confirm.accept.func();
self.removeItem(); self.removeElement();
}; };
this.rejectModal = function () { this.rejectModal = function () {
this.model.options.confirm.reject.func(); this.model.options.confirm.reject.func();
self.removeItem(); self.removeElement();
}; };
shortcut.remove("ESC"); shortcut.remove("ESC");
$(document).off('click', '.modal-background'); $(document).off('click', '.modal-background');
} }
}, },
template: function (data) { templateData: function () {
return JST[this.templateName](data); return this.model;
}, },
events: { events: {
'click .close': 'removeItem', 'click .close': 'removeElement',
'click .js-button-accept': 'acceptModal', 'click .js-button-accept': 'acceptModal',
'click .js-button-reject': 'rejectModal' 'click .js-button-reject': 'rejectModal'
}, },
render: function () { afterRender: function () {
this.$el.html(this.template(this.model));
this.$(".modal-content").html(this.addSubview(new Ghost.Views.Modal.ContentView({model: this.model})).render().el); this.$(".modal-content").html(this.addSubview(new Ghost.Views.Modal.ContentView({model: this.model})).render().el);
this.$el.children(".js-modal").center(); 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"); this.$el.addClass("active dark");
if (document.body.style.webkitFilter !== undefined) { // Detect webkit filters if (document.body.style.webkitFilter !== undefined) { // Detect webkit filters
$("body").addClass("blur"); $("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 () { remove: function () {
this.undelegateEvents(); this.undelegateEvents();
this.$el.empty(); this.$el.empty();
this.stopListening(); this.stopListening();
return this; return this;
}, },
removeItem: function (e) { // #### removeElement
// Visually removes the modal from the user interface
removeElement: function (e) {
if (e) { if (e) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
var self = this;
this.$el.removeClass('dark');
$('.js-modal').fadeOut(300, function () { $('.js-modal').fadeOut(300, function () {
$(this).remove(); $(this).remove();
$("#modal-container").removeClass('active dark');
if (document.body.style.filter !== undefined) { if (document.body.style.filter !== undefined) {
$("body").removeClass("blur"); $("body").removeClass("blur");
} }
self.remove();
self.$el.removeClass('active');
}); });
this.remove();
} }
}); });
/** // ## Modal Content
* Modal Content
* @type {*}
*/
Ghost.Views.Modal.ContentView = Ghost.View.extend({ Ghost.Views.Modal.ContentView = Ghost.View.extend({
template: function (data) { template: function (data) {
return JST['modals/' + this.model.content.template](data); return JST['modals/' + this.model.content.template](data);
}, },
templateData: function () {
render: function () { return this.model;
this.$el.html(this.template(this.model));
return this;
} }
}); });

View File

@ -23,14 +23,14 @@
{'key': 'Ctrl+Shift+L', 'style': 'link'}, {'key': 'Ctrl+Shift+L', 'style': 'link'},
{'key': 'Ctrl+Shift+I', 'style': 'image'}, {'key': 'Ctrl+Shift+I', 'style': 'image'},
{'key': 'Ctrl+Q', 'style': 'blockquote'}, {'key': 'Ctrl+Q', 'style': 'blockquote'},
{'key': 'Ctrl+Shift+1', 'style': 'currentdate'}, {'key': 'Ctrl+Shift+1', 'style': 'currentDate'},
{'key': 'Ctrl+U', 'style': 'uppercase'}, {'key': 'Ctrl+U', 'style': 'uppercase'},
{'key': 'Ctrl+Shift+U', 'style': 'lowercase'}, {'key': 'Ctrl+Shift+U', 'style': 'lowercase'},
{'key': 'Ctrl+Alt+Shift+U', 'style': 'titlecase'}, {'key': 'Ctrl+Alt+Shift+U', 'style': 'titlecase'},
{'key': 'Ctrl+Alt+W', 'style': 'selectword'}, {'key': 'Ctrl+Alt+W', 'style': 'selectword'},
{'key': 'Ctrl+L', 'style': 'list'}, {'key': 'Ctrl+L', 'style': 'list'},
{'key': 'Ctrl+Alt+C', 'style': 'copyHTML'}, {'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 // The publish bar associated with a post, which has the TagWidget and