From 948b84eca17c9c7b002e9449aa5dd5a5e3c2f3af Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Sat, 15 Sep 2012 00:49:03 +0200 Subject: [PATCH 1/6] WIP backbone-ify publisher, get rid of weird old POJsO --- .../javascripts/app/views/publisher_view.js | 236 ++++++++++++++++-- app/assets/javascripts/aspects-dropdown.js | 2 +- app/assets/javascripts/home.js | 2 +- app/assets/javascripts/publisher.js | 221 ---------------- app/views/photos/_new_photo.haml | 6 +- app/views/shared/_publisher.html.haml | 2 +- .../status_messages/bookmarklet.html.haml | 5 +- app/views/status_messages/new.html.haml | 1 - 8 files changed, 231 insertions(+), 244 deletions(-) delete mode 100644 app/assets/javascripts/publisher.js diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 24b61ff7f..cfc5cc51a 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -1,19 +1,51 @@ -//this file is the scary no-no-zone bad-touch of our backbone code. -//after re-writing/eliminating the existing Publisher let's re-write -//this with PANACHE! <333 Dennis +/* Copyright (c) 2010-2012, Diaspora Inc. This file is + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ +// TODO: split this up in modules: +// - base +// - services +// - aspect selector +// - getting started app.views.Publisher = Backbone.View.extend({ - + el : "#publisher", events : { "focus textarea" : "open", "click #hide_publisher" : "clear", - "submit form" : "createStatusMessage" + "submit form" : "createStatusMessage", + "click .service_icon": "toggleService", + "textchange #status_message_fake_text": "handleTextchange", + "click .dropdown .dropdown_list li": "toggleAspect" }, initialize : function(){ - this.collection = this.collection //takes a Posts collection + // init shortcut references to the various elements + this.el_input = this.$('#status_message_fake_text'); + this.el_hiddenInput = this.$('#status_message_text'); + this.el_wrapper = this.$('#publisher_textarea_wrapper'); + this.el_submit = this.$('input[type=submit]'); + this.el_photozone = this.$('#photodropzone'); + + // init mentions plugin + Mentions.initialize(this.el_input); + + // init autoresize plugin + this.el_input.autoResize({ 'extraSpace' : 10, 'maxHeight' : Infinity }); + + // sync textarea content + if( this.el_hiddenInput.val() == "" ) { + this.el_hiddenInput.val( this.el_input.val() ); + } + + // this has to be here, otherwise for some reason the callback for the + // textchange event won't be called in Backbone... + this.el_input.bind('textchange', function(ev){ + //console.log(ev); + }); + return this; }, @@ -49,34 +81,210 @@ app.views.Publisher = Backbone.View.extend({ }, clear : function() { - this.$('textarea').val(""); - this.$('#publisher_textarea_wrapper').removeClass("with_attachments"); + // clear text(s) + this.el_input.val(''); + this.el_hiddenInput.val(''); + + // remove mentions + this.el_input.mentionsInput('reset'); // remove photos - this.$("#photodropzone").find('li').remove(); + this.el_photozone.find('li').remove(); this.$("input[name='photos[]']").remove(); + this.el_wrapper.removeClass("with_attachments"); // close publishing area (CSS) this.close(); - Publisher.clear() + // disable submitting + this.checkSubmitAvailability(); return this; }, open : function() { - $(this.el).removeClass('closed'); - this.$("#publisher_textarea_wrapper").addClass('active'); + // visually 'open' the publisher + this.$el.removeClass('closed'); + this.el_wrapper.addClass('active'); + + // fetch contacts for mentioning + Mentions.fetchContacts(); return this; }, close : function() { $(this.el).addClass("closed"); - this.$("#publisher_textarea_wrapper").removeClass("active"); - this.$("textarea").css('height', ''); + this.el_wrapper.removeClass("active"); + this.el_input.css('height', ''); return this; + }, + + checkSubmitAvailability: function() { + if( this._submittable() ) { + this.el_submit.removeAttr('disabled'); + } else { + this.el_submit.attr('disabled','disabled'); + } + }, + + // determine submit availability + _submittable: function() { + var onlyWhitespaces = ($.trim(this.el_input.val()) === ''), + isPhotoAttached = (this.el_photozone.children().length > 0); + + return (!onlyWhitespaces || isPhotoAttached); + }, + + toggleService: function(evt) { + var el = $(evt.target); + var provider = el.attr('id'); + + el.toggleClass("dim"); + + this._createCounter(); + this._toggleServiceField(provider); + }, + + // keep track of character count + _createCounter: function() { + // remove obsolete counter + this.$('.counter').remove(); + + // create new counter + var min = 40000; + var a = this.$('.service_icon:not(.dim)'); + if(a.length > 0){ + $.each(a, function(index, value){ + var num = parseInt($(value).attr('maxchar')); + if (min > num) { min = num; } + }); + this.el_input.charCount({allowed: min, warning: min/10 }); + } + }, + + // add or remove the input containing the selected service + _toggleServiceField: function(provider) { + var hidden_field = this.$('input[name="services[]"][value="'+provider+'"]'); + if(hidden_field.length > 0){ + hidden_field.remove(); + } else { + var uid = _.uniqueId('services_'); + this.$(".content_creation form").append( + ''); + } + }, + + handleTextchange: function() { + var self = this; + + this.checkSubmitAvailability(); + this.el_input.mentionsInput("val", function(value){ + self.el_hiddenInput.val(value); + }); + }, + + triggerGettingStarted: function() { + this._addPopover(this.el_input, { + trigger: 'manual', + offset: 30, + id: 'first_message_explain', + placement: 'right', + html: true + }, 600); + this._addPopover(this.$('.dropdown'), { + trigger: 'manual', + offset: 10, + id: 'message_visibility_explain', + placement: 'bottom', + html: true + }, 1000); + this._addPopover($('#gs-shim'), { + trigger: 'manual', + offset: -5, + id: 'stream_explain', + placement: 'left', + html: true + }, 1400); + + // hide some popovers when a post is created + this.$('.button.creation').click(function() { + this.$('.dropdown').popover('hide'); + this.el_input.popover('hide'); + }); + }, + + _addPopover: function(el, opts, timeout) { + el.popover(opts); + el.click(function() { + el.popover('hide'); + }); + + // show the popover after the given timeout + setTimeout(function() { + el.popover('show'); + + // disable 'getting started' when the last popover is closed + var popup = el.data('popover').$tip[0]; + var close = $(popup).find('.close'); + + close.click(function() { + if( $('.popover').length==1 ) { + $.get('/getting_started_completed'); + } + el.popover('hide'); + }); + }, timeout); + }, + + toggleAspect: function(evt) { + var el = $(evt.target); + var btn = el.parent('.dropdown').find('.button'); + + // visually toggle the aspect selection + if( el.is('.radio') ) { + AspectsDropdown.toggleRadio(el); + } else { + AspectsDropdown.toggleCheckbox(el); + } + + // update the selection summary + AspectsDropdown.updateNumber( + el.closest(".dropdown_list"), + null, + el.parent().find('li.selected').length, + '' + ); + + this._updateSelectedAspectIds(); + }, + + _updateSelectedAspectIds: function() { + var self = this; + + // remove previous selection + this.$('input[name="aspect_ids[]"]').remove(); + + // create fields for current selection + this.$('.dropdown .dropdown_list li.selected').each(function() { + var el = $(this); + var aspectId = el.data('aspect_id'); + + self._addHiddenAspectInput(aspectId); + + // close the dropdown when a radio item was selected + if( el.is('.radio') ) { + el.closest('.dropdown').removeClass('active'); + } + }); + }, + + _addHiddenAspectInput: function(id) { + var uid = _.uniqueId('aspect_ids_'); + this.$('.content_creation form').append( + '' + ); } }); diff --git a/app/assets/javascripts/aspects-dropdown.js b/app/assets/javascripts/aspects-dropdown.js index 61f035d17..50ee48fab 100644 --- a/app/assets/javascripts/aspects-dropdown.js +++ b/app/assets/javascripts/aspects-dropdown.js @@ -1,4 +1,4 @@ -// Copyright (c) 2010-2011, Diaspora Inc. This file is +// Copyright (c) 2010-2012, Diaspora Inc. This file is // licensed under the Affero General Public License version 3 or later. See // the COPYRIGHT file. diff --git a/app/assets/javascripts/home.js b/app/assets/javascripts/home.js index 7eb2db874..e53601da1 100644 --- a/app/assets/javascripts/home.js +++ b/app/assets/javascripts/home.js @@ -2,7 +2,7 @@ * licensed under the Affero General Public License version 3 or later. See * the COPYRIGHT file. */ -//= require publisher + //= require jquery.textchange //= require aspect-edit-pane //= require fileuploader-custom \ No newline at end of file diff --git a/app/assets/javascripts/publisher.js b/app/assets/javascripts/publisher.js deleted file mode 100644 index 40eeb4580..000000000 --- a/app/assets/javascripts/publisher.js +++ /dev/null @@ -1,221 +0,0 @@ -/* Copyright (c) 2010-2011, Diaspora Inc. This file is - * licensed under the Affero General Public License version 3 or later. See - * the COPYRIGHT file. - */ - -//TODO: make this a widget -var Publisher = { - bookmarklet : false, - - form: function(){ - return Publisher.cachedForm = Publisher.cachedForm || $('#publisher'); - }, - - input: function(){ - return Publisher.cachedInput = Publisher.cachedInput || Publisher.form().find('#status_message_fake_text'); - }, - - wrapper: function(){ - return Publisher.cachedWrapper = Publisher.cachedWrapper || Publisher.form().find('#publisher_textarea_wrapper'); - }, - - hiddenInput: function(){ - return Publisher.cachedHiddenInput= Publisher.cachedHiddenInput || Publisher.form().find('#status_message_text'); - }, - - submit: function(){ - return Publisher.cachedSubmit = Publisher.cachedSubmit || Publisher.form().find("input[type='submit']"); - }, - - determineSubmitAvailability: function(){ - var onlyWhitespaces = ($.trim(Publisher.input().val()) === ''), - isSubmitDisabled = Publisher.submit().attr('disabled'), - isPhotoAttached = ($("#photodropzone").children().length > 0); - - if ((onlyWhitespaces && !isPhotoAttached) && !isSubmitDisabled) { - Publisher.submit().attr('disabled', 'disabled'); - } else if ((!onlyWhitespaces || isPhotoAttached) && isSubmitDisabled) { - Publisher.submit().removeAttr('disabled'); - } - }, - - clear: function(){ - $("#photodropzone").find('li').remove(); - Publisher.input().mentionsInput("reset"); - Publisher.wrapper().removeClass("with_attachments"); - Publisher.hiddenInput().val(''); - Publisher.determineSubmitAvailability() - }, - - bindServiceIcons: function(){ - $(".service_icon").bind("click", function(evt){ - $(this).toggleClass("dim"); - Publisher.toggleServiceField($(this)); - }); - }, - - toggleServiceField: function(service){ - Publisher.createCounter(service); - - var provider = service.attr('id'); - var hidden_field = $('#publisher [name="services[]"][value="'+provider+'"]'); - if(hidden_field.length > 0){ - hidden_field.remove(); - } else { - $("#publisher .content_creation form").append( - ''); - } - }, - - isPublicPost: function(){ - return $('#publisher [name="aspect_ids[]"]').first().val() == "public"; - }, - - isToAllAspects: function(){ - return $('#publisher [name="aspect_ids[]"]').first().val() == "all_aspects"; - }, - - selectedAspectIds: function() { - var aspects = $('#publisher [name="aspect_ids[]"]'); - var aspectIds = []; - aspects.each(function() { aspectIds.push( parseInt($(this).attr('value'))); }); - return aspectIds; - }, - - removeRadioSelection: function(hiddenFields){ - $.each(hiddenFields, function(index, value){ - var el = $(value); - - if(el.val() == "all_aspects" || el.val() == "public") { - el.remove(); - } - }); - }, - - toggleAspectIds: function(li) { - var aspectId = li.attr('data-aspect_id'), - hiddenFields = $('#publisher [name="aspect_ids[]"]'), - appendId = function(){ - $("#publisher .content_creation form").append( - ''); - }; - - if(li.hasClass('radio')){ - $.each(hiddenFields, function(index, value){ - $(value).remove(); - }); - appendId(); - - // close dropdown after selecting a binary option - li.closest('.dropdown').removeClass('active'); - - } else { - var hiddenField = $('#publisher [name="aspect_ids[]"][value="'+aspectId+'"]'); - - // remove all radio selections - Publisher.removeRadioSelection(hiddenFields); - - if(hiddenField.length > 0){ - hiddenField.remove(); - } else { - appendId(); - } - } - }, - - createCounter: function(service){ - var counter = $("#publisher .counter"); - counter.remove(); - - var min = 40000; - var a = $('.service_icon:not(.dim)'); - if(a.length > 0){ - $.each(a, function(index, value){ - var num = parseInt($(value).attr('maxchar')); - if (min > num) { min = num; } - }); - $('#status_message_fake_text').charCount({allowed: min, warning: min/10 }); - } - }, - - bindAspectToggles: function() { - $('#publisher .dropdown .dropdown_list li').bind("click", function(evt){ - var li = $(this), - button = li.parent('.dropdown').find('.button'); - - if(li.hasClass('radio')){ - AspectsDropdown.toggleRadio(li); - } else { - AspectsDropdown.toggleCheckbox(li); - } - - AspectsDropdown.updateNumber(li.closest(".dropdown_list"), null, li.parent().find('li.selected').length, ''); - - Publisher.toggleAspectIds(li); - }); - }, - - textChange : function(){ - Publisher.determineSubmitAvailability(); - Publisher.input().mentionsInput("val", function(value) { - Publisher.hiddenInput().val(value); - }); - }, - - triggerGettingStarted: function(){ - Publisher.setUpPopovers("#publisher .dropdown", {trigger: 'manual', offset: 10, id: "message_visibility_explain", placement:'bottom', html:true}, 1000); - Publisher.setUpPopovers("#publisher #status_message_fake_text", {trigger: 'manual', placement: 'right', offset: 30, id: "first_message_explain", html:true}, 600); - Publisher.setUpPopovers("#gs-shim", {trigger: 'manual', placement: 'left', id:"stream_explain", offset: -5, html:true}, 1400); - - $("#publisher .button.creation").bind("click", function(){ - $("#publisher .dropdown").popover("hide"); - $("#publisher #status_message_fake_text").popover("hide"); - }); - }, - - setUpPopovers: function(selector, options, timeout){ - var selection = $(selector); - selection.popover(options); - selection.bind("click", function(){$(this).popover("hide")}); - - setTimeout(function(){ - selection.popover("show"); - - var popup = selection.data('popover').$tip[0], - closeIcon = $(popup).find(".close"); - - closeIcon.bind("click",function(){ - if($(".popover").length == 1){ - $.get("/getting_started_completed"); - }; - selection.popover("hide"); - }); - }, timeout); - }, - - initialize: function() { - Publisher.cachedForm = Publisher.cachedSubmit = - Publisher.cachedInput = Publisher.cachedHiddenInput = false; - - Publisher.bindServiceIcons(); - Publisher.bindAspectToggles(); - - Mentions.initialize(Publisher.input()); - - Publisher.input().bind("focus", function(){ - Mentions.fetchContacts(); - }) - - if(Publisher.hiddenInput().val() === "") { - Publisher.hiddenInput().val(Publisher.input().val()); - } - - Publisher.input().autoResize({ 'extraSpace' : 10, 'maxHeight' : Infinity }); - Publisher.input().bind('textchange', Publisher.textChange); - } -}; - -$(document).ready(function() { - Publisher.initialize(); - Diaspora.page.subscribe("stream/reloaded", Publisher.initialize); -}); diff --git a/app/views/photos/_new_photo.haml b/app/views/photos/_new_photo.haml index b5f418f2f..b4aec04b3 100644 --- a/app/views/photos/_new_photo.haml +++ b/app/views/photos/_new_photo.haml @@ -29,7 +29,7 @@ $('#file-upload').addClass("loading"); $('#publisher').find("input[type='submit']").attr('disabled','disabled'); - Publisher.wrapper().addClass("with_attachments"); + app.publisher.el_wrapper.addClass("with_attachments"); $('#photodropzone').append( "
  • " + "#{escape_javascript(image_tag('ajax-loader2.gif'))}" + @@ -43,7 +43,7 @@ url = responseJSON.data.photo.unprocessed_image.url, currentPlaceholder = $('li.loading').first(); - Publisher.wrapper().addClass("with_attachments"); + app.publisher.el_wrapper.addClass("with_attachments"); $('#new_status_message').append(""); // replace image placeholders @@ -70,7 +70,7 @@ photo.fadeOut(400, function(){ photo.remove(); if ( $('.publisher_photo').length == 0){ - Publisher.wrapper().removeClass("with_attachments"); + app.publisher.el_wrapper.removeClass("with_attachments"); } }); } diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index 4c8d86094..2de6bcdb5 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -5,7 +5,7 @@ -if publisher_explain :javascript $(document).ready(function() { - Publisher.triggerGettingStarted(); + if( app.publisher ) app.publisher.triggerGettingStarted(); }); #publisher{:class => ((aspect == :profile || publisher_open) ? "mention_popup" : "closed")} diff --git a/app/views/status_messages/bookmarklet.html.haml b/app/views/status_messages/bookmarklet.html.haml index b1e7e2c36..1c5aa4010 100644 --- a/app/views/status_messages/bookmarklet.html.haml +++ b/app/views/status_messages/bookmarklet.html.haml @@ -9,8 +9,9 @@ = render :partial => 'shared/publisher', :locals => { :aspect => :profile, :selected_aspects => @aspects, :aspect_ids => @aspect_ids } :javascript - Publisher.bookmarklet = true; - app.publisher = new app.views.Publisher(); + app.publisher = new app.views.Publisher({ + bookmarklet: true + }); var contents = "#{escape_javascript params[:title]} - #{escape_javascript params[:url]}"; var notes = "#{escape_javascript params[:notes]}"; diff --git a/app/views/status_messages/new.html.haml b/app/views/status_messages/new.html.haml index 53185ce11..d2d38ad81 100644 --- a/app/views/status_messages/new.html.haml +++ b/app/views/status_messages/new.html.haml @@ -6,7 +6,6 @@ :javascript $(function() { $("#publisher").bind('ajax:success', function(){ location.reload(); }); - Publisher.bookmarklet = true; }); #new_status_message_pane From 1002fe088d4337719b7bcbdbf101e10fd3352588 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Sun, 16 Sep 2012 16:45:14 +0200 Subject: [PATCH 2/6] split up the various parts of the publisher, should probably rather be backbone-subviews ... ? --- .../app/views/publisher/aspects_selector.js | 62 +++++++ .../app/views/publisher/getting_started.js | 65 +++++++ .../app/views/publisher/services.js | 51 ++++++ .../javascripts/app/views/publisher_view.js | 162 ++---------------- 4 files changed, 189 insertions(+), 151 deletions(-) create mode 100644 app/assets/javascripts/app/views/publisher/aspects_selector.js create mode 100644 app/assets/javascripts/app/views/publisher/getting_started.js create mode 100644 app/assets/javascripts/app/views/publisher/services.js diff --git a/app/assets/javascripts/app/views/publisher/aspects_selector.js b/app/assets/javascripts/app/views/publisher/aspects_selector.js new file mode 100644 index 000000000..ecb2c5764 --- /dev/null +++ b/app/assets/javascripts/app/views/publisher/aspects_selector.js @@ -0,0 +1,62 @@ +/* Copyright (c) 2010-2012, Diaspora Inc. This file is + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ + +(function(){ + // mixin-object, used in conjunction with the publisher to provide the + // functionality for selecting aspects + app.views.PublisherAspectsSelector = { + + // event handler for aspect selection + toggleAspect: function(evt) { + var el = $(evt.target); + var btn = el.parent('.dropdown').find('.button'); + + // visually toggle the aspect selection + if( el.is('.radio') ) { + AspectsDropdown.toggleRadio(el); + } else { + AspectsDropdown.toggleCheckbox(el); + } + + // update the selection summary + AspectsDropdown.updateNumber( + el.closest(".dropdown_list"), + null, + el.parent().find('li.selected').length, + '' + ); + + this._updateSelectedAspectIds(); + }, + + // take care of the form fields that will indicate the selected aspects + _updateSelectedAspectIds: function() { + var self = this; + + // remove previous selection + this.$('input[name="aspect_ids[]"]').remove(); + + // create fields for current selection + this.$('.dropdown .dropdown_list li.selected').each(function() { + var el = $(this); + var aspectId = el.data('aspect_id'); + + self._addHiddenAspectInput(aspectId); + + // close the dropdown when a radio item was selected + if( el.is('.radio') ) { + el.closest('.dropdown').removeClass('active'); + } + }); + }, + + _addHiddenAspectInput: function(id) { + var uid = _.uniqueId('aspect_ids_'); + this.$('.content_creation form').append( + '' + ); + } + }; +})(); \ No newline at end of file diff --git a/app/assets/javascripts/app/views/publisher/getting_started.js b/app/assets/javascripts/app/views/publisher/getting_started.js new file mode 100644 index 000000000..815f05585 --- /dev/null +++ b/app/assets/javascripts/app/views/publisher/getting_started.js @@ -0,0 +1,65 @@ +/* Copyright (c) 2010-2012, Diaspora Inc. This file is + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ + +(function(){ + // mixin-object, used in conjunction with the publisher to provide the + // functionality for displaying 'getting-started' information + app.views.PublisherGettingStarted = { + + // initiate all the popover message boxes + triggerGettingStarted: function() { + this._addPopover(this.el_input, { + trigger: 'manual', + offset: 30, + id: 'first_message_explain', + placement: 'right', + html: true + }, 600); + this._addPopover(this.$('.dropdown'), { + trigger: 'manual', + offset: 10, + id: 'message_visibility_explain', + placement: 'bottom', + html: true + }, 1000); + this._addPopover($('#gs-shim'), { + trigger: 'manual', + offset: -5, + id: 'stream_explain', + placement: 'left', + html: true + }, 1400); + + // hide some popovers when a post is created + this.$('.button.creation').click(function() { + this.$('.dropdown').popover('hide'); + this.el_input.popover('hide'); + }); + }, + + _addPopover: function(el, opts, timeout) { + el.popover(opts); + el.click(function() { + el.popover('hide'); + }); + + // show the popover after the given timeout + setTimeout(function() { + el.popover('show'); + + // disable 'getting started' when the last popover is closed + var popup = el.data('popover').$tip[0]; + var close = $(popup).find('.close'); + + close.click(function() { + if( $('.popover').length==1 ) { + $.get('/getting_started_completed'); + } + el.popover('hide'); + }); + }, timeout); + } + }; +})(); \ No newline at end of file diff --git a/app/assets/javascripts/app/views/publisher/services.js b/app/assets/javascripts/app/views/publisher/services.js new file mode 100644 index 000000000..f8f250093 --- /dev/null +++ b/app/assets/javascripts/app/views/publisher/services.js @@ -0,0 +1,51 @@ +/* Copyright (c) 2010-2012, Diaspora Inc. This file is + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ + +(function(){ + // mixin-object, used in conjunction with the publisher to provide the + // functionality for selecting services for cross-posting + app.views.PublisherServices = { + + // visually toggle the icon and kick-off all other actions for cross-posting + toggleService: function(evt) { + var el = $(evt.target); + var provider = el.attr('id'); + + el.toggleClass("dim"); + + this._createCounter(); + this._toggleServiceField(provider); + }, + + // keep track of character count + _createCounter: function() { + // remove obsolete counter + this.$('.counter').remove(); + + // create new counter + var min = 40000; + var a = this.$('.service_icon:not(.dim)'); + if(a.length > 0){ + $.each(a, function(index, value){ + var num = parseInt($(value).attr('maxchar')); + if (min > num) { min = num; } + }); + this.el_input.charCount({allowed: min, warning: min/10 }); + } + }, + + // add or remove the input containing the selected service + _toggleServiceField: function(provider) { + var hidden_field = this.$('input[name="services[]"][value="'+provider+'"]'); + if(hidden_field.length > 0){ + hidden_field.remove(); + } else { + var uid = _.uniqueId('services_'); + this.$(".content_creation form").append( + ''); + } + } + }; +})(); \ No newline at end of file diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index cfc5cc51a..e6c5ac336 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -3,12 +3,14 @@ * the COPYRIGHT file. */ -// TODO: split this up in modules: -// - base -// - services -// - aspect selector -// - getting started -app.views.Publisher = Backbone.View.extend({ +//= require ./publisher/services +//= require ./publisher/aspects_selector +//= require ./publisher/getting_started + +app.views.Publisher = Backbone.View.extend(_.extend( + app.views.PublisherServices, + app.views.PublisherAspectsSelector, + app.views.PublisherGettingStarted, { el : "#publisher", @@ -42,9 +44,7 @@ app.views.Publisher = Backbone.View.extend({ // this has to be here, otherwise for some reason the callback for the // textchange event won't be called in Backbone... - this.el_input.bind('textchange', function(ev){ - //console.log(ev); - }); + this.el_input.bind('textchange', $.noop); return this; }, @@ -137,45 +137,6 @@ app.views.Publisher = Backbone.View.extend({ return (!onlyWhitespaces || isPhotoAttached); }, - toggleService: function(evt) { - var el = $(evt.target); - var provider = el.attr('id'); - - el.toggleClass("dim"); - - this._createCounter(); - this._toggleServiceField(provider); - }, - - // keep track of character count - _createCounter: function() { - // remove obsolete counter - this.$('.counter').remove(); - - // create new counter - var min = 40000; - var a = this.$('.service_icon:not(.dim)'); - if(a.length > 0){ - $.each(a, function(index, value){ - var num = parseInt($(value).attr('maxchar')); - if (min > num) { min = num; } - }); - this.el_input.charCount({allowed: min, warning: min/10 }); - } - }, - - // add or remove the input containing the selected service - _toggleServiceField: function(provider) { - var hidden_field = this.$('input[name="services[]"][value="'+provider+'"]'); - if(hidden_field.length > 0){ - hidden_field.remove(); - } else { - var uid = _.uniqueId('services_'); - this.$(".content_creation form").append( - ''); - } - }, - handleTextchange: function() { var self = this; @@ -183,110 +144,9 @@ app.views.Publisher = Backbone.View.extend({ this.el_input.mentionsInput("val", function(value){ self.el_hiddenInput.val(value); }); - }, - - triggerGettingStarted: function() { - this._addPopover(this.el_input, { - trigger: 'manual', - offset: 30, - id: 'first_message_explain', - placement: 'right', - html: true - }, 600); - this._addPopover(this.$('.dropdown'), { - trigger: 'manual', - offset: 10, - id: 'message_visibility_explain', - placement: 'bottom', - html: true - }, 1000); - this._addPopover($('#gs-shim'), { - trigger: 'manual', - offset: -5, - id: 'stream_explain', - placement: 'left', - html: true - }, 1400); - - // hide some popovers when a post is created - this.$('.button.creation').click(function() { - this.$('.dropdown').popover('hide'); - this.el_input.popover('hide'); - }); - }, - - _addPopover: function(el, opts, timeout) { - el.popover(opts); - el.click(function() { - el.popover('hide'); - }); - - // show the popover after the given timeout - setTimeout(function() { - el.popover('show'); - - // disable 'getting started' when the last popover is closed - var popup = el.data('popover').$tip[0]; - var close = $(popup).find('.close'); - - close.click(function() { - if( $('.popover').length==1 ) { - $.get('/getting_started_completed'); - } - el.popover('hide'); - }); - }, timeout); - }, - - toggleAspect: function(evt) { - var el = $(evt.target); - var btn = el.parent('.dropdown').find('.button'); - - // visually toggle the aspect selection - if( el.is('.radio') ) { - AspectsDropdown.toggleRadio(el); - } else { - AspectsDropdown.toggleCheckbox(el); - } - - // update the selection summary - AspectsDropdown.updateNumber( - el.closest(".dropdown_list"), - null, - el.parent().find('li.selected').length, - '' - ); - - this._updateSelectedAspectIds(); - }, - - _updateSelectedAspectIds: function() { - var self = this; - - // remove previous selection - this.$('input[name="aspect_ids[]"]').remove(); - - // create fields for current selection - this.$('.dropdown .dropdown_list li.selected').each(function() { - var el = $(this); - var aspectId = el.data('aspect_id'); - - self._addHiddenAspectInput(aspectId); - - // close the dropdown when a radio item was selected - if( el.is('.radio') ) { - el.closest('.dropdown').removeClass('active'); - } - }); - }, - - _addHiddenAspectInput: function(id) { - var uid = _.uniqueId('aspect_ids_'); - this.$('.content_creation form').append( - '' - ); } -}); + +})); // jQuery helper for serializing a
    into JSON $.fn.serializeObject = function() From a3477b76915c07a6f321b2c3f7480524ffe16741 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 17 Sep 2012 12:38:16 +0200 Subject: [PATCH 3/6] move modified (non-upstream) js lib to lib/assets --- {vendor => lib}/assets/javascripts/jquery.autoresize.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {vendor => lib}/assets/javascripts/jquery.autoresize.js (100%) diff --git a/vendor/assets/javascripts/jquery.autoresize.js b/lib/assets/javascripts/jquery.autoresize.js similarity index 100% rename from vendor/assets/javascripts/jquery.autoresize.js rename to lib/assets/javascripts/jquery.autoresize.js From 200887ca450e009dd98d95983398e0dbb60d3748 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 17 Sep 2012 15:33:52 +0200 Subject: [PATCH 4/6] adapt jasmine specs to the new structure --- .../app/views/publisher_view_spec.js | 288 ++++++++++++++---- spec/javascripts/bookmarklet-spec.js | 4 +- spec/javascripts/publisher-spec.js | 177 ----------- 3 files changed, 234 insertions(+), 235 deletions(-) delete mode 100644 spec/javascripts/publisher-spec.js diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index c18408a9f..d5be5c852 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -1,76 +1,252 @@ +/* Copyright (c) 2010-2012, Diaspora Inc. This file is +* licensed under the Affero General Public License version 3 or later. See +* the COPYRIGHT file. +*/ + describe("app.views.Publisher", function() { - beforeEach(function() { - // should be jasmine helper - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - - spec.loadFixture("aspects_index"); - this.view = new app.views.Publisher(); - }); - - describe("#open", function() { - it("removes the 'closed' class from the publisher element", function() { - expect($(this.view.el)).toHaveClass("closed"); - this.view.open($.Event()); - expect($(this.view.el)).not.toHaveClass("closed"); - }); - }); - - describe("#close", function() { + context("plain publisher", function() { beforeEach(function() { - this.view.open($.Event()); + // should be jasmine helper + loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + + spec.loadFixture("aspects_index"); + this.view = new app.views.Publisher(); }); - it("removes the 'active' class from the publisher element", function(){ - this.view.close($.Event()); - expect($(this.view.el)).toHaveClass("closed"); - }) + describe("#open", function() { + it("removes the 'closed' class from the publisher element", function() { + expect($(this.view.el)).toHaveClass("closed"); + this.view.open($.Event()); + expect($(this.view.el)).not.toHaveClass("closed"); + }); + }); - it("resets the element's height", function() { - $(this.view.el).find("#status_message_fake_text").height(100); - this.view.close($.Event()); - expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height"); + describe("#close", function() { + beforeEach(function() { + this.view.open($.Event()); + }); + + it("removes the 'active' class from the publisher element", function(){ + this.view.close($.Event()); + expect($(this.view.el)).toHaveClass("closed"); + }) + + it("resets the element's height", function() { + $(this.view.el).find("#status_message_fake_text").height(100); + this.view.close($.Event()); + expect($(this.view.el).find("#status_message_fake_text").attr("style")).not.toContain("height"); + }); + }); + + describe("#clear", function() { + it("calls close", function(){ + spyOn(this.view, "close"); + + this.view.clear($.Event()); + expect(this.view.close).toHaveBeenCalled(); + }) + + it("clears all textareas", function(){ + _.each(this.view.$("textarea"), function(element){ + $(element).val('this is some stuff'); + expect($(element).val()).not.toBe(""); + }); + + this.view.clear($.Event()); + + _.each(this.view.$("textarea"), function(element){ + expect($(element).val()).toBe(""); + }); + }) + + it("removes all photos from the dropzone area", function(){ + var self = this; + _.times(3, function(){ + self.view.el_photozone.append($("
  • ")) + }); + + expect(this.view.el_photozone.html()).not.toBe(""); + this.view.clear($.Event()); + expect(this.view.el_photozone.html()).toBe(""); + }) + + it("removes all photo values appended by the photo uploader", function(){ + $(this.view.el).prepend("") + var photoValuesInput = this.view.$("input[name='photos[]']"); + + photoValuesInput.val("3") + this.view.clear($.Event()); + expect(this.view.$("input[name='photos[]']").length).toBe(0); + }) }); }); - describe("#clear", function() { - it("calls close", function(){ - spyOn(this.view, "close"); + context("#toggleService", function(){ + beforeEach( function(){ + spec.loadFixture('aspects_index_services'); + this.view = new app.views.Publisher(); + }); - this.view.clear($.Event()); - expect(this.view.close); - }) + it("toggles the 'dim' class on a clicked item", function() { + var first = $(".service_icon").eq(0); + var second = $(".service_icon").eq(1); - it("clears all textareas", function(){ - _.each(this.view.$("textarea"), function(element){ - $(element).val('this is some stuff'); - expect($(element).val()).not.toBe(""); + expect(first.hasClass('dim')).toBeTruthy(); + expect(second.hasClass('dim')).toBeTruthy(); + + first.trigger('click'); + + expect(first.hasClass('dim')).toBeFalsy(); + expect(second.hasClass('dim')).toBeTruthy(); + + first.trigger('click'); + + expect(first.hasClass('dim')).toBeTruthy(); + expect(second.hasClass('dim')).toBeTruthy(); + }); + + describe("#_createCounter", function() { + it("gets called in when you toggle service icons", function(){ + spyOn(this.view, '_createCounter'); + $(".service_icon").first().trigger('click'); + expect(this.view._createCounter).toHaveBeenCalled(); }); - this.view.clear($.Event()); - - _.each(this.view.$("textarea"), function(element){ - expect($(element).val()).toBe(""); + it("removes the 'old' .counter span", function(){ + spyOn($.fn, "remove"); + $(".service_icon").first().trigger('click'); + expect($.fn.remove).toHaveBeenCalled(); }); - }) + }); - it("removes all photos from the dropzone area", function(){ - var self = this; - _.times(3, function(){ - self.view.$("#photodropzone").append($("
  • ")) + describe("#_toggleServiceField", function() { + it("gets called when you toggle service icons", function(){ + spyOn(this.view, '_toggleServiceField'); + $(".service_icon").first().trigger('click'); + expect(this.view._toggleServiceField).toHaveBeenCalled(); }); - expect(this.view.$("#photodropzone").html()).not.toBe(""); - this.view.clear($.Event()); - expect(this.view.$("#photodropzone").html()).toBe(""); - }) + it("toggles the hidden input field", function(){ + expect($('input[name="services[]"]').length).toBe(0); + $(".service_icon").first().trigger('click'); + expect($('input[name="services[]"]').length).toBe(1); + $(".service_icon").first().trigger('click'); + expect($('input[name="services[]"]').length).toBe(0); + }); - it("removes all photo values appended by the photo uploader", function(){ - $(this.view.el).prepend("") - var photoValuesInput = this.view.$("input[name='photos[]']"); + it("toggles the correct input", function() { + var first = $(".service_icon").eq(0); + var second = $(".service_icon").eq(1); - photoValuesInput.val("3") - this.view.clear($.Event()); - expect(this.view.$("input[name='photos[]']").length).toBe(0); - }) + first.trigger('click'); + second.trigger('click'); + + expect($('input[name="services[]"]').length).toBe(2); + + first.trigger('click'); + + var prov1 = first.attr('id'); + var prov2 = second.attr('id'); + + expect($('input[name="services[]"][value="'+prov1+'"]').length).toBe(0); + expect($('input[name="services[]"][value="'+prov2+'"]').length).toBe(1); + }); + }); + }); + + context("aspect selection", function(){ + beforeEach( function(){ + spec.loadFixture('status_message_new'); + + this.radio_els = $('#publisher .dropdown li.radio'); + this.check_els = $('#publisher .dropdown li.aspect_selector'); + + this.view = new app.views.Publisher(); + this.view.open(); + }); + + it("initializes with 'all_aspects'", function(){ + expect(this.radio_els.first().hasClass('selected')).toBeFalsy(); + expect(this.radio_els.last().hasClass('selected')).toBeTruthy(); + + _.each(this.check_els, function(el){ + expect($(el).hasClass('selected')).toBeFalsy(); + }); + }); + + it("toggles the selected entry visually", function(){ + this.check_els.last().trigger('click'); + + _.each(this.radio_els, function(el){ + expect($(el).hasClass('selected')).toBeFalsy(); + }); + + expect(this.check_els.first().hasClass('selected')).toBeFalsy(); + expect(this.check_els.last().hasClass('selected')).toBeTruthy(); + }); + + describe("#_updateSelectedAspectIds", function(){ + beforeEach(function(){ + this.li = $('
  • '); + this.view.$('.dropdown_list').append(this.li); + }); + + it("gets called when aspects are selected", function(){ + spyOn(this.view, "_updateSelectedAspectIds"); + this.check_els.last().trigger('click'); + expect(this.view._updateSelectedAspectIds).toHaveBeenCalled(); + }); + + it("removes a previous selection and inserts the current one", function() { + var selected = this.view.$('input[name="aspect_ids[]"]'); + expect(selected.length).toBe(1); + expect(selected.first().val()).toBe('all_aspects'); + + this.li.trigger('click'); + + selected = this.view.$('input[name="aspect_ids[]"]'); + expect(selected.length).toBe(1); + expect(selected.first().val()).toBe('42'); + }); + + it("toggles the same item", function() { + expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1); + + this.li.trigger('click'); + expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1); + + this.li.trigger('click'); + expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(0); + }); + + it("keeps other fields with different values", function() { + var li2 = $("
  • "); + this.view.$('.dropdown_list').append(li2); + + this.li.trigger('click'); + expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(1); + + li2.trigger('click'); + expect(this.view.$('input[name="aspect_ids[]"]').length).toBe(2); + }); + }); + + describe("#_addHiddenAspectInput", function(){ + it("gets called when aspects are selected", function(){ + spyOn(this.view, "_addHiddenAspectInput"); + this.check_els.last().trigger('click'); + expect(this.view._addHiddenAspectInput).toHaveBeenCalled(); + }); + + it("adds a hidden input to the form", function(){ + var id = 42; + + this.view._addHiddenAspectInput(id); + var input = this.view.$('input[name="aspect_ids[]"][value="'+id+'"]'); + + expect(input.length).toBe(1); + expect(input.val()).toBe('42'); + }); + }); }); }); diff --git a/spec/javascripts/bookmarklet-spec.js b/spec/javascripts/bookmarklet-spec.js index c776b9e1a..9a73cb51c 100644 --- a/spec/javascripts/bookmarklet-spec.js +++ b/spec/javascripts/bookmarklet-spec.js @@ -11,11 +11,11 @@ describe("bookmarklet", function() { }); it('verifies the publisher is loaded', function(){ - expect(typeof Publisher === "object").toBeTruthy(); + expect(typeof app.publisher === "object").toBeTruthy(); }); it('verifies we are using the bookmarklet', function(){ - expect(Publisher.bookmarklet).toBeTruthy(); + expect(app.publisher.options.bookmarklet).toBeTruthy(); }); }); diff --git a/spec/javascripts/publisher-spec.js b/spec/javascripts/publisher-spec.js deleted file mode 100644 index af84eeb39..000000000 --- a/spec/javascripts/publisher-spec.js +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright (c) 2010-2011, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ - -describe("Publisher", function() { - - Publisher.open = function(){ this.form().removeClass("closed"); } - - describe("toggleCounter", function(){ - beforeEach( function(){ - spec.loadFixture('aspects_index_services'); - }); - - it("gets called in when you toggle service icons", function(){ - spyOn(Publisher, 'createCounter'); - Publisher.toggleServiceField($(".service_icon").first()); - expect(Publisher.createCounter).toHaveBeenCalled(); - }); - - it("removes the .counter span", function(){ - spyOn($.fn, "remove"); - Publisher.createCounter($(".service_icon").first()); - expect($.fn.remove).toHaveBeenCalled(); - }); - }); - - describe("bindAspectToggles", function() { - beforeEach( function(){ - spec.loadFixture('status_message_new'); - Publisher.open(); - }); - - it('gets called on initialize', function(){ - spyOn(Publisher, 'bindAspectToggles'); - Publisher.initialize(); - expect(Publisher.bindAspectToggles).toHaveBeenCalled(); - }); - - it('correctly initializes an all_aspects state', function(){ - Publisher.initialize(); - - expect($("#publisher .dropdown .dropdown_list li.radio").first().hasClass("selected")).toBeFalsy(); - expect($("#publisher .dropdown .dropdown_list li.radio").last().hasClass("selected")).toBeTruthy(); - - $.each($("#publihser .dropdown .dropdown_list li.aspect_selector"), function(index, element){ - expect($(element).hasClass("selected")).toBeFalsy(); - }); - }); - - it('toggles selected only on the clicked icon', function(){ - Publisher.initialize(); - - $("#publisher .dropdown .dropdown_list li.aspect_selector").last().click(); - - $.each($("#publisher .dropdown .dropdown_list li.radio"), function(index, element){ - expect($(element).hasClass("selected")).toBeFalsy(); - }); - - expect($("#publisher .dropdown .dropdown_list li.aspect_selector").first().hasClass("selected")).toBeFalsy(); - expect($("#publisher .dropdown .dropdown_list li.aspect_selector").last().hasClass("selected")).toBeTruthy(); - }); - - it('calls toggleAspectIds with the clicked element', function(){ - spyOn(Publisher, 'toggleAspectIds'); - Publisher.bindAspectToggles(); - var aspectBadge = $("#publisher .dropdown .dropdown_list li").last(); - aspectBadge.click(); - expect(Publisher.toggleAspectIds.mostRecentCall.args[0].get(0)).toEqual(aspectBadge.get(0)); - }); - }); - - describe('toggleAspectIds', function(){ - beforeEach( function(){ - spec.loadFixture('status_message_new'); - li = $("
  • "); - }); - - it('adds a hidden field to the form if there is not one already', function(){ - expect($('#publisher [name="aspect_ids[]"]').length).toBe(1); - expect($('#publisher [name="aspect_ids[]"]').last().attr('value')).toBe('all_aspects'); - Publisher.toggleAspectIds(li); - expect($('#publisher [name="aspect_ids[]"]').length).toBe(1); - expect($('#publisher [name="aspect_ids[]"]').last().attr('value')).toBe('42'); - }); - - it('removes the hidden field if its already there', function() { - expect($('#publisher [name="aspect_ids[]"]').length).toBe(1); - - Publisher.toggleAspectIds(li); - expect($('#publisher [name="aspect_ids[]"]').length).toBe(1); - - Publisher.toggleAspectIds(li); - expect($('#publisher [name="aspect_ids[]"]').length).toBe(0); - }); - - it('does not remove a hidden field with a different value', function() { - var li2 = $("
  • "); - - Publisher.toggleAspectIds(li); - expect($('#publisher [name="aspect_ids[]"]').length).toBe(1); - - Publisher.toggleAspectIds(li2); - expect($('#publisher [name="aspect_ids[]"]').length).toBe(2); - }); - }); - - describe("bindServiceIcons", function() { - beforeEach( function(){ - spec.loadFixture('aspects_index_services'); - }); - - it('gets called on initialize', function(){ - spyOn(Publisher, 'bindServiceIcons'); - Publisher.initialize(); - expect(Publisher.bindServiceIcons).toHaveBeenCalled(); - }); - - it('toggles dim only on the clicked icon', function(){ - expect($(".service_icon#facebook").hasClass("dim")).toBeTruthy(); - expect($(".service_icon#twitter").hasClass("dim")).toBeTruthy(); - - Publisher.bindServiceIcons(); - $(".service_icon#facebook").click(); - - expect($(".service_icon#facebook").hasClass("dim")).toBeFalsy(); - expect($(".service_icon#twitter").hasClass("dim")).toBeTruthy(); - }); - - it('binds to the services icons and toggles the hidden field', function(){ - spyOn(Publisher, 'toggleServiceField'); - Publisher.bindServiceIcons(); - $(".service_icon#facebook").click(); - - expect(Publisher.toggleServiceField).toHaveBeenCalled(); - }); - }); - - describe('toggleServiceField', function(){ - beforeEach( function(){ - spec.loadFixture('aspects_index_services'); - }); - - it('adds a hidden field to the form if there is not one already', function(){ - expect($('#publisher [name="services[]"]').length).toBe(0); - Publisher.toggleServiceField($(".service_icon#facebook").first()); - expect($('#publisher [name="services[]"]').length).toBe(1); - expect($('#publisher [name="services[]"]').attr('value')).toBe("facebook"); - }); - - it('removes the hidden field if its already there', function() { - Publisher.toggleServiceField($(".service_icon#facebook").first()); - expect($('#publisher [name="services[]"]').length).toBe(1); - - Publisher.toggleServiceField($(".service_icon#facebook").first()); - expect($('#publisher [name="services[]"]').length).toBe(0); - }); - - it('does not remove a hidden field with a different value', function() { - Publisher.toggleServiceField($(".service_icon#facebook").first()); - expect($('#publisher [name="services[]"]').length).toBe(1); - - Publisher.toggleServiceField($(".service_icon#twitter").first()); - expect($('#publisher [name="services[]"]').length).toBe(2); - }); - }); - - describe("input", function(){ - beforeEach(function(){ - spec.loadFixture('aspects_index_prefill'); - }); - it("returns the status_message_fake_text textarea", function(){ - expect(Publisher.input()[0].id).toBe('status_message_fake_text'); - expect(Publisher.input().length).toBe(1); - }); - }); -}); From 452de1b8668f678bd2d9fb4a24d0962f6f2956f0 Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 17 Sep 2012 20:35:38 +0200 Subject: [PATCH 5/6] fix remaining cukes and some cleanup --- app/views/status_messages/bookmarklet.html.haml | 2 +- app/views/status_messages/new.html.haml | 13 ++++++++----- features/mentions_from_profile_page.feature | 7 ++----- features/step_definitions/custom_web_steps.rb | 12 ++++++++++-- features/support/publishing_cuke_helpers.rb | 4 ++-- spec/javascripts/app/views/publisher_view_spec.js | 6 +++--- spec/javascripts/bookmarklet-spec.js | 2 +- 7 files changed, 27 insertions(+), 19 deletions(-) diff --git a/app/views/status_messages/bookmarklet.html.haml b/app/views/status_messages/bookmarklet.html.haml index 1c5aa4010..992da8686 100644 --- a/app/views/status_messages/bookmarklet.html.haml +++ b/app/views/status_messages/bookmarklet.html.haml @@ -10,7 +10,7 @@ :javascript app.publisher = new app.views.Publisher({ - bookmarklet: true + standalone: true }); var contents = "#{escape_javascript params[:title]} - #{escape_javascript params[:url]}"; diff --git a/app/views/status_messages/new.html.haml b/app/views/status_messages/new.html.haml index d2d38ad81..fb87afa89 100644 --- a/app/views/status_messages/new.html.haml +++ b/app/views/status_messages/new.html.haml @@ -1,12 +1,8 @@ -# Copyright (c) 2010-2011, Diaspora Inc. This file is -# licensed under the Affero General Public License version 3 or later. See -# the COPYRIGHT file. -= javascript_include_tag 'jquery.textchange.js', "publisher.js" -:javascript - $(function() { - $("#publisher").bind('ajax:success', function(){ location.reload(); }); - }); += javascript_include_tag :home #new_status_message_pane .span-15.last @@ -16,3 +12,10 @@ = render :partial => 'shared/publisher', :locals => { :aspect => @aspect, :aspect_ids => @aspect_ids, :selected_aspects => @aspects_with_person, :person => @person} +:javascript + $(function() { + app.publisher = new app.views.Publisher({ + standalone: true + }); + $("#publisher").bind('ajax:success', function(){ location.reload(); }); + }); \ No newline at end of file diff --git a/features/mentions_from_profile_page.feature b/features/mentions_from_profile_page.feature index a3b86c3d7..be8e5d113 100644 --- a/features/mentions_from_profile_page.feature +++ b/features/mentions_from_profile_page.feature @@ -24,8 +24,7 @@ Feature: mentioning a contact from their profile page Scenario: mentioning while posting to all aspects Given I am on "alice@alice.alice"'s page And I have turned off jQuery effects - And I click "Mention" button - And I expand the publisher in the modal window + And I want to mention her from the profile And I append "I am eating a yogurt" to the publisher And I press "Share" in the modal window And I wait for the ajax to finish @@ -42,9 +41,7 @@ Feature: mentioning a contact from their profile page Scenario: mentioning while posting to just one aspect Given I am on "alice@alice.alice"'s page And I have turned off jQuery effects - And I click "Mention" button - And I wait for the ajax to finish - And I expand the publisher in the modal window + And I want to mention her from the profile And I append "I am eating a yogurt" to the publisher And I press the aspect dropdown in the modal window And I toggle the aspect "NotPostingThingsHere" in the modal window diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb index 67b95e7eb..6942655d0 100644 --- a/features/step_definitions/custom_web_steps.rb +++ b/features/step_definitions/custom_web_steps.rb @@ -46,10 +46,18 @@ end When /^I append "([^"]*)" to the publisher$/ do |stuff| elem = find('#status_message_fake_text') - elem.native.send_keys ' ' + stuff + elem.native.send_keys(' ' + stuff) wait_until do - page.find("#status_message_text").value.match(/#{stuff}/) + find('#status_message_text').value.include?(stuff) + end +end + +And /^I want to mention (?:him|her) from the profile$/ do + click_link("Mention") + wait_for_ajax_to_finish + within('#facebox') do + click_publisher end end diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index 6bfa7a290..de447cc7a 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -13,7 +13,7 @@ module PublishingCukeHelpers def click_publisher page.execute_script(' $("#publisher").removeClass("closed"); - $("#publisher").find("textarea").focus(); + $("#publisher").find("#status_message_fake_text").focus(); ') end @@ -79,7 +79,7 @@ module PublishingCukeHelpers end def comment_on_show_page(comment_text) - within("#post-interactions") do + within("#post-interactions") do focus_comment_box(".label.comment") make_comment(comment_text, "new-comment-text") end diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index d5be5c852..b1c55e64a 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -1,7 +1,7 @@ /* Copyright (c) 2010-2012, Diaspora Inc. This file is -* licensed under the Affero General Public License version 3 or later. See -* the COPYRIGHT file. -*/ + * licensed under the Affero General Public License version 3 or later. See + * the COPYRIGHT file. + */ describe("app.views.Publisher", function() { context("plain publisher", function() { diff --git a/spec/javascripts/bookmarklet-spec.js b/spec/javascripts/bookmarklet-spec.js index 9a73cb51c..57ac4925a 100644 --- a/spec/javascripts/bookmarklet-spec.js +++ b/spec/javascripts/bookmarklet-spec.js @@ -15,7 +15,7 @@ describe("bookmarklet", function() { }); it('verifies we are using the bookmarklet', function(){ - expect(app.publisher.options.bookmarklet).toBeTruthy(); + expect(app.publisher.options.standalone).toBeTruthy(); }); }); From 8193978fd2a7e93a4208941cff2b51dc55182e4f Mon Sep 17 00:00:00 2001 From: Florian Staudacher Date: Mon, 17 Sep 2012 20:46:33 +0200 Subject: [PATCH 6/6] in 'standalone' mode, the close button is hidden ... publisher is embedded into something, that has its own close button --- .../javascripts/app/views/publisher_view.js | 6 ++++++ .../javascripts/app/views/publisher_view_spec.js | 16 ++++++++++++++++ spec/javascripts/bookmarklet-spec.js | 1 + 3 files changed, 23 insertions(+) diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index e6c5ac336..c8c952f24 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -42,6 +42,12 @@ app.views.Publisher = Backbone.View.extend(_.extend( this.el_hiddenInput.val( this.el_input.val() ); } + // hide close button, in case publisher is standalone + // (e.g. bookmarklet, mentions popup) + if( this.options.standalone ) { + this.$('#hide_publisher').hide(); + } + // this has to be here, otherwise for some reason the callback for the // textchange event won't be called in Backbone... this.el_input.bind('textchange', $.noop); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index b1c55e64a..0e301847c 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -4,6 +4,22 @@ */ describe("app.views.Publisher", function() { + describe("standalone", function() { + beforeEach(function() { + // should be jasmine helper + loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); + + spec.loadFixture("aspects_index"); + this.view = new app.views.Publisher({ + standalone: true + }); + }); + + it("hides the close button in standalone mode", function() { + expect(this.view.$('#hide_publisher').is(':visible')).toBeFalsy(); + }); + }); + context("plain publisher", function() { beforeEach(function() { // should be jasmine helper diff --git a/spec/javascripts/bookmarklet-spec.js b/spec/javascripts/bookmarklet-spec.js index 57ac4925a..fee57d0e7 100644 --- a/spec/javascripts/bookmarklet-spec.js +++ b/spec/javascripts/bookmarklet-spec.js @@ -16,6 +16,7 @@ describe("bookmarklet", function() { it('verifies we are using the bookmarklet', function(){ expect(app.publisher.options.standalone).toBeTruthy(); + expect(app.publisher.$('#hide_publisher').is(':visible')).toBeFalsy(); }); });