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( "