/*global Markdown:true assetPath:true */ /** This view handles rendering of the composer @class ComposerView @extends Discourse.View @namespace Discourse @module Discourse **/ Discourse.ComposerView = Discourse.View.extend({ templateName: 'composer', elementId: 'reply-control', classNameBindings: ['content.creatingPrivateMessage:private-message', 'composeState', 'content.loading', 'content.editTitle', 'postMade', 'content.creatingTopic:topic', 'content.showPreview', 'content.hidePreview'], composeState: function() { var state = this.get('content.composeState'); if (state) return state; return Discourse.Composer.CLOSED; }.property('content.composeState'), draftStatus: function() { this.$('.saving-draft').text(this.get('content.draftStatus') || ""); }.observes('content.draftStatus'), // Disable fields when we're loading loadingChanged: function() { if (this.get('loading')) { $('#wmd-input, #reply-title').prop('disabled', 'disabled'); } else { $('#wmd-input, #reply-title').prop('disabled', ''); } }.observes('loading'), postMade: function() { if (this.present('controller.createdPost')) return 'created-post'; return null; }.property('content.createdPost'), observeReplyChanges: function() { var _this = this; if (this.get('content.hidePreview')) return; Ember.run.next(null, function() { var $wmdPreview, caretPosition; if (_this.editor) { _this.editor.refreshPreview(); // if the caret is on the last line ensure preview scrolled to bottom caretPosition = Discourse.Utilities.caretPosition(_this.wmdInput[0]); if (!_this.wmdInput.val().substring(caretPosition).match(/\n/)) { $wmdPreview = $('#wmd-preview:visible'); if ($wmdPreview.length > 0) { return $wmdPreview.scrollTop($wmdPreview[0].scrollHeight); } } } }); }.observes('content.reply', 'content.hidePreview'), newUserEducationVisibilityChanged: function() { var $panel = $('#new-user-education'); if (this.get('controller.newUserEducationVisible')) { $panel.slideDown('fast'); } else { $panel.slideUp('fast'); } }.observes('controller.newUserEducationVisible'), similarVisibilityChanged: function() { var $panel = $('#similar-topics'); if (this.get('controller.similarVisible')) { $panel.slideDown('fast'); } else { $panel.slideUp('fast'); } }.observes('controller.similarVisible'), movePanels: function(sizePx) { $('.composer-popup').css('bottom', sizePx); }, focusIn: function() { var controller = this.get('controller'); if(controller) controller.resetDraftStatus(); }, resize: function() { // this still needs to wait on animations, need a clean way to do that return Em.run.next(null, function() { var replyControl = $('#reply-control'); var h = replyControl.height() || 0; var sizePx = "" + h + "px"; $('.topic-area').css('padding-bottom', sizePx); $('.composer-popup').css('bottom', sizePx); }); }.observes('content.composeState'), keyUp: function(e) { var controller = this.get('controller'); controller.checkReplyLength(); var lastKeyUp = new Date(); this.set('lastKeyUp', lastKeyUp); // One second from now, check to see if the last key was hit when // we recorded it. If it was, the user paused typing. var composerView = this; Em.run.later(function() { if (lastKeyUp !== composerView.get('lastKeyUp')) return; // Search for similar topics if the user pauses typing controller.findSimilarTopics(); }, 1000); // If the user hit ESC if (e.which === 27) controller.hitEsc(); }, didInsertElement: function() { var replyControl = $('#reply-control'); replyControl.DivResizer({ resize: this.resize, onDrag: this.movePanels }); Discourse.TransitionHelper.after(replyControl, this.resize); }, click: function() { this.get('controller').openIfDraft(); }, // Called after the preview renders. Debounced for performance afterRender: Discourse.debounce(function() { var $wmdPreview = $('#wmd-preview'); if ($wmdPreview.length === 0) return; Discourse.SyntaxHighlighting.apply($wmdPreview); var post = this.get('controller.content.post'); var refresh = false; // If we are editing a post, we'll refresh its contents once. This is a feature that // allows a user to refresh its contents once. if (post && post.blank('refreshedPost')) { refresh = true; post.set('refreshedPost', true); } // Load the post processing effects $('a.onebox', $wmdPreview).each(function(i, e) { Discourse.Onebox.load(e, refresh); }); $('span.mention', $wmdPreview).each(function(i, e) { Discourse.Mention.load(e, refresh); }); }, 100), cancelUpload: function() { // TODO }, initEditor: function() { // not quite right, need a callback to pass in, meaning this gets called once, // but if you start replying to another topic it will get the avatars wrong var $uploadTarget, $wmdInput, editor, saveDraft, selected, template, topic, transformTemplate, _this = this; this.wmdInput = $wmdInput = $('#wmd-input'); if ($wmdInput.length === 0 || $wmdInput.data('init') === true) return; $LAB.script(assetPath('defer/html-sanitizer-bundle')); Discourse.ComposerView.trigger("initWmdEditor"); template = Handlebars.compile("