From bb4c2ee85d9aff9ba6eb68934fcc4b8e9efc09ec Mon Sep 17 00:00:00 2001 From: zhitomirskiyi <ilya@joindiaspora.com> Date: Wed, 30 Mar 2011 18:59:30 -0700 Subject: [PATCH] added a character count to the publisher --- app/views/shared/_publisher.html.haml | 2 +- config/assets.yml | 1 + public/javascripts/publisher.js | 23 ++++++++-- public/javascripts/vendor/charCount.js | 58 ++++++++++++++++++++++++ public/stylesheets/sass/application.sass | 9 +++- spec/javascripts/publisher-spec.js | 31 ++++++++++--- spec/javascripts/support/jasmine.yml | 1 + 7 files changed, 113 insertions(+), 12 deletions(-) create mode 100644 public/javascripts/vendor/charCount.js diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index 3bab72762d..b16e7f3e17 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -53,7 +53,7 @@ = image_tag "icons/globe.png", :title => t('.public'), :class => 'public_icon dim', :width => 16, :height => 16 - if current_user.services - for service in current_user.services - = image_tag "social_media_logos/#{service.provider}-16x16.png", :title => service.provider.titleize, :class => "service_icon dim", :id =>"#{service.provider}" + = image_tag "social_media_logos/#{service.provider}-16x16.png", :title => service.provider.titleize, :class => "service_icon dim", :id =>"#{service.provider}", :maxchar => "#{service.class::MAX_CHARACTERS}" = link_to (image_tag "icons/monotone_wrench_settings.png"), "#question_mark_pane", :class => 'question_mark', :rel => 'facebox', :title => t('shared.public_explain.manage') = status.submit t('.share'), :disable_with => t('.posting'), :class => 'button', :tabindex => 2 diff --git a/config/assets.yml b/config/assets.yml index c8d4ee51d8..46d9893edb 100644 --- a/config/assets.yml +++ b/config/assets.yml @@ -20,6 +20,7 @@ javascripts: - public/javascripts/vendor/facebox.js - public/javascripts/vendor/timeago.js - public/javascripts/vendor/Mustache.js + - public/javascripts/vendor/charCount.js - public/javascripts/jquery.autocomplete-custom.js - public/javascripts/fileuploader-custom.js - public/javascripts/keycodes.js diff --git a/public/javascripts/publisher.js b/public/javascripts/publisher.js index e28cabde25..b13270d899 100644 --- a/public/javascripts/publisher.js +++ b/public/javascripts/publisher.js @@ -287,7 +287,7 @@ var Publisher = { bindServiceIcons: function(){ $(".service_icon").bind("click", function(evt){ $(this).toggleClass("dim"); - Publisher.toggleServiceField($(this).attr('id')); + Publisher.toggleServiceField($(this)); }); }, bindPublicIcon: function(){ @@ -299,12 +299,14 @@ var Publisher = { }); }, toggleServiceField: function(service){ - var hidden_field = $('#publisher [name="services[]"][value="'+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="'+service+'">'); + '<input id="services_" name="services[]" type="hidden" value="'+provider+'">'); }; }, toggleAspectIds: function(aspectId) { @@ -316,6 +318,21 @@ var Publisher = { '<input id="aspect_ids_" name="aspect_ids[]" type="hidden" value="'+aspectId+'">'); }; }, + createCounter: function(service){ + var counter = $("#publisher .counter"); + if (counter.length > 0) { 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 .aspect_badge').bind("click", function(){ var unremovedAspects = $(this).parent().children('.aspect_badge').length - $(this).parent().children(".aspect_badge.removed").length; diff --git a/public/javascripts/vendor/charCount.js b/public/javascripts/vendor/charCount.js new file mode 100644 index 0000000000..67d1442d4e --- /dev/null +++ b/public/javascripts/vendor/charCount.js @@ -0,0 +1,58 @@ +/* + * Character Count Plugin - jQuery plugin + * Dynamic character count for text areas and input fields + * written by Alen Grakalic + * http://cssglobe.com/post/7161/jquery-plugin-simplest-twitterlike-dynamic-character-count-for-textareas + * + * Copyright (c) 2009 Alen Grakalic (http://cssglobe.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * Built for jQuery library + * http://jquery.com + * + */ + +(function($) { + + $.fn.charCount = function(options){ + + // default configuration properties + var defaults = { + allowed: 140, + warning: 25, + css: 'counter', + counterElement: 'span', + cssWarning: 'warning', + cssExceeded: 'exceeded', + counterText: '' + }; + + var options = $.extend(defaults, options); + + function calculate(obj){ + var count = $(obj).val().length; + var available = options.allowed - count; + if(available <= options.warning && available >= 0){ + $(obj).next().addClass(options.cssWarning); + } else { + $(obj).next().removeClass(options.cssWarning); + } + if(available < 0){ + $(obj).next().addClass(options.cssExceeded); + } else { + $(obj).next().removeClass(options.cssExceeded); + } + $(obj).next().html(options.counterText + available); + }; + + this.each(function() { + $(this).after('<'+ options.counterElement +' class="' + options.css + '">'+ options.counterText +'</'+ options.counterElement +'>'); + calculate(this); + $(this).keyup(function(){calculate(this)}); + $(this).change(function(){calculate(this)}); + }); + + }; + +})(jQuery); diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 8acc42da53..ad1677acf7 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -839,7 +839,8 @@ label form textarea :height 18px !important - + .counter + :display none form :position relative :top 0 @@ -1021,6 +1022,12 @@ label .x :display block + .counter + :position absolute + .warning + :color orange + .exceeded + :color red .field_with_submit input[type='text'] :width 82% diff --git a/spec/javascripts/publisher-spec.js b/spec/javascripts/publisher-spec.js index 7197d4aa60..7eab22ce7c 100644 --- a/spec/javascripts/publisher-spec.js +++ b/spec/javascripts/publisher-spec.js @@ -21,6 +21,24 @@ describe("Publisher", function() { }); }); + 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(); + expect(Publisher.createCounter).toHaveBeenCalled(); + }); + + it("removes the .counter span", function(){ + spyOn($.fn, "remove"); + Publisher.createCounter(); + expect($.fn.remove).toHaveBeenCalled(); + }); + }); + describe("bindAspectToggles", function() { beforeEach( function(){ spec.loadFixture('status_message_new'); @@ -151,7 +169,7 @@ describe("Publisher", function() { Publisher.bindServiceIcons(); $(".service_icon#facebook").click(); - expect(Publisher.toggleServiceField).toHaveBeenCalledWith("facebook"); + expect(Publisher.toggleServiceField).toHaveBeenCalledWith($(".service_icon#facebook").first()); }); }); @@ -162,25 +180,24 @@ describe("Publisher", function() { it('adds a hidden field to the form if there is not one already', function(){ expect($('#publisher [name="services[]"]').length).toBe(0); - Publisher.toggleServiceField("facebook"); + Publisher.toggleServiceField($(".service_icon#facebook").first()); expect($('#publisher [name="services[]"]').length).toBe(1); expect($('#publisher [name="services[]"]').attr('value')).toBe("facebook"); - //<input id="aspect_ids_" name="aspect_ids[]" type="hidden" value="1"> }); it('removes the hidden field if its already there', function() { - Publisher.toggleServiceField("facebook"); + Publisher.toggleServiceField($(".service_icon#facebook").first()); expect($('#publisher [name="services[]"]').length).toBe(1); - Publisher.toggleServiceField("facebook"); + 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("facebook"); + Publisher.toggleServiceField($(".service_icon#facebook").first()); expect($('#publisher [name="services[]"]').length).toBe(1); - Publisher.toggleServiceField("twitter"); + Publisher.toggleServiceField(($(".service_icon#twitter").first()); expect($('#publisher [name="services[]"]').length).toBe(2); }); }); diff --git a/spec/javascripts/support/jasmine.yml b/spec/javascripts/support/jasmine.yml index 4f946da6bc..c7ddaeecb0 100644 --- a/spec/javascripts/support/jasmine.yml +++ b/spec/javascripts/support/jasmine.yml @@ -17,6 +17,7 @@ src_files: - public/javascripts/vendor/jquery.infieldlabel.js - public/javascripts/vendor/jquery.autoresize.min.js - public/javascripts/vendor/Mustache.js + - public/javascripts/vendor/charCount.js - public/javascripts/vendor/timeago.js - public/javascripts/vendor/facebox.js - public/javascripts/jquery.autocomplete-custom.js -- GitLab