WIP backbone-ify publisher, get rid of weird old POJsO
This commit is contained in:
parent
6c1a1ec6d2
commit
948b84eca1
8 changed files with 231 additions and 244 deletions
|
|
@ -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(
|
||||
'<input id="'+uid+'" name="services[]" type="hidden" value="'+provider+'">');
|
||||
}
|
||||
},
|
||||
|
||||
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(
|
||||
'<input id="'+uid+'" name="aspect_ids[]" type="hidden" value="'+id+'">'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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(
|
||||
'<input id="services_" name="services[]" type="hidden" value="'+provider+'">');
|
||||
}
|
||||
},
|
||||
|
||||
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(
|
||||
'<input id="aspect_ids_" name="aspect_ids[]" type="hidden" value="'+aspectId+'">');
|
||||
};
|
||||
|
||||
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);
|
||||
});
|
||||
|
|
@ -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(
|
||||
"<li class='publisher_photo loading' style='position:relative;'>" +
|
||||
"#{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("<input type='hidden' value='" + id + "' name='photos[]' />");
|
||||
|
||||
// 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");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")}
|
||||
|
|
|
|||
|
|
@ -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]}";
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
:javascript
|
||||
$(function() {
|
||||
$("#publisher").bind('ajax:success', function(){ location.reload(); });
|
||||
Publisher.bookmarklet = true;
|
||||
});
|
||||
|
||||
#new_status_message_pane
|
||||
|
|
|
|||
Loading…
Reference in a new issue