From 2d3933ccd8498e4d1cd320062fdf2c206fa5eba7 Mon Sep 17 00:00:00 2001 From: Hincu Petru Date: Sat, 5 Apr 2014 20:42:10 +0000 Subject: [PATCH] Rewrite poll creation inputs --- .../app/views/publisher/poll_creator_view.js | 59 +++++++++++++ .../javascripts/app/views/publisher_view.js | 48 +++------- .../stylesheets/publisher_blueprint.css.scss | 87 ++++++++++--------- app/assets/templates/poll_creator_tpl.jst.hbs | 18 ++++ .../publisher/_publisher_blueprint.html.haml | 12 +-- config/locales/javascript/javascript.en.yml | 7 +- features/desktop/post_preview.feature | 1 + features/desktop/post_with_a_poll.feature | 20 +++-- .../step_definitions/post_with_poll_steps.rb | 10 +-- .../views/publisher_poll_creator_view_spec.js | 54 ++++++++++++ .../app/views/publisher_view_spec.js | 34 -------- 11 files changed, 213 insertions(+), 137 deletions(-) create mode 100644 app/assets/javascripts/app/views/publisher/poll_creator_view.js create mode 100644 app/assets/templates/poll_creator_tpl.jst.hbs create mode 100644 spec/javascripts/app/views/publisher_poll_creator_view_spec.js diff --git a/app/assets/javascripts/app/views/publisher/poll_creator_view.js b/app/assets/javascripts/app/views/publisher/poll_creator_view.js new file mode 100644 index 000000000..e7078c2ad --- /dev/null +++ b/app/assets/javascripts/app/views/publisher/poll_creator_view.js @@ -0,0 +1,59 @@ +app.views.PublisherPollCreator = app.views.Base.extend({ + templateName: "poll_creator", + + events: { + 'click .add-answer .button': 'clickAddAnswer', + 'click .remove-answer': 'removeAnswer', + }, + + postRenderTemplate: function(){ + this.$pollAnswers = this.$('.poll-answers'); + this.inputCount = 1; + }, + + clickAddAnswer: function(evt){ + evt.preventDefault(); + + this.addAnswerInput(); + }, + + addAnswerInput: function(){ + this.inputCount++; + var input_wrapper = this.$('.poll-answer:first').clone(); + var input = input_wrapper.find('input'); + + var text = Diaspora.I18n.t('publisher.option', { + nr: this.inputCount + }); + + input.attr('placeholder', text); + input.val(''); + this.$pollAnswers.append(input_wrapper); + this.toggleRemoveAnswer(); + }, + + removeAnswer: function(evt){ + evt.stopPropagation(); + this.removeAnswerInput(this.$(evt.target)); + }, + + removeAnswerInput: function(input){ + input.parents('.poll-answer').remove(); + this.toggleRemoveAnswer(); + }, + + toggleRemoveAnswer: function(){ + var inputs = this.$pollAnswers.find('input'); + if(inputs.length < 2){ + this.$('.remove-answer').removeClass('active'); + } + else { + this.$('.remove-answer').addClass('active'); + } + }, + + clearInputs: function(){ + this.$('input').val(''); + } + +}); diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index ff1fb37d5..be4037d82 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -23,16 +23,13 @@ app.views.Publisher = Backbone.View.extend({ "click .post_preview_button" : "createPostPreview", "textchange #status_message_fake_text": "handleTextchange", "click #locator" : "showLocation", - "click #poll_creator" : "showPollCreator", - "click #add_poll_answer" : "addPollAnswer", - "click .remove_poll_answer" : "removePollAnswer", + "click #poll_creator" : "togglePollCreator", "click #hide_location" : "destroyLocation", "keypress #location_address" : "avoidEnter" }, initialize : function(opts){ this.standalone = opts ? opts.standalone : false; - this.option_counter = 1; // init shortcut references to the various elements this.el_input = this.$('#status_message_fake_text'); @@ -41,8 +38,6 @@ app.views.Publisher = Backbone.View.extend({ this.el_submit = this.$('input[type=submit], button#submit'); this.el_preview = this.$('button.post_preview_button'); this.el_photozone = this.$('#photodropzone'); - this.el_poll_creator = this.$('#poll_creator_wrapper'); - this.el_poll_answer = this.$('#poll_creator_wrapper .poll_answer'); // init mentions plugin Mentions.initialize(this.el_input); @@ -75,7 +70,6 @@ app.views.Publisher = Backbone.View.extend({ }); this.initSubviews(); - this.addPollAnswer(); return this; }, @@ -109,6 +103,11 @@ app.views.Publisher = Backbone.View.extend({ publisher: this }); this.view_uploader.on('change', this.checkSubmitAvailability, this); + + this.view_poll_creator = new app.views.PublisherPollCreator({ + el: this.$('#publisher-poll-creator') + }); + this.view_poll_creator.render(); }, @@ -179,36 +178,11 @@ app.views.Publisher = Backbone.View.extend({ } }, - showPollCreator: function(){ - this.el_poll_creator.toggle(); + togglePollCreator: function(){ + this.view_poll_creator.$el.toggleClass('active'); + this.el_input.focus(); }, - addPollAnswer: function(){ - if($(".poll_answer").size() == 1) { - $(".remove_poll_answer").css("visibility","visible"); - } - - this.option_counter++; - var clone = this.el_poll_answer.clone(); - - var answer = clone.find('.poll_answer_input'); - answer.val(""); - - var placeholder = answer.attr("placeholder"); - var expression = /[^0-9]+/; - answer.attr("placeholder", expression.exec(placeholder) + this.option_counter); - - $('#poll_creator_wrapper .poll_answer').last().after(clone); - }, - - removePollAnswer: function(evt){ - $(evt.currentTarget).parent().remove(); - if($(".poll_answer").size() == 1) { - $(".remove_poll_answer").css("visibility","hidden");; - } - - return false; - }, // avoid submitting form when pressing Enter key avoidEnter: function(evt){ if(evt.keyCode == 13) @@ -351,7 +325,7 @@ app.views.Publisher = Backbone.View.extend({ this.destroyLocation(); // clear poll form - this.clearPollForm(); + this.view_poll_creator.clearInputs(); // force textchange plugin to update lastValue this.el_input.data('lastValue', ''); @@ -386,7 +360,7 @@ app.views.Publisher = Backbone.View.extend({ $(this.el).addClass("closed"); this.el_wrapper.removeClass("active"); this.el_input.css('height', ''); - this.el_poll_creator.hide(); + this.view_poll_creator.$el.removeClass('active'); return this; }, diff --git a/app/assets/stylesheets/publisher_blueprint.css.scss b/app/assets/stylesheets/publisher_blueprint.css.scss index 9865e7997..f038fe875 100644 --- a/app/assets/stylesheets/publisher_blueprint.css.scss +++ b/app/assets/stylesheets/publisher_blueprint.css.scss @@ -334,50 +334,55 @@ } } -#poll_creator_wrapper { - display:none; +#publisher-poll-creator { border: 1px solid $border-dark-grey; - padding:5px; - margin-top:1em; + padding: 5px; + margin-top: 5px; @include border-radius(2px); -} + display: none; -.remove_poll_answer { - visibility:hidden; - float:right; - display: table-cell; + &.active { + display: block; + } + input { + -moz-box-sizing: border-box; + box-sizing: border-box; + margin-bottom: 0px; + } + .poll-question input { + width: 100%; + } + .controls { + float: none; + z-index: none; + } + .poll-answer { + input { + width: 96%; + display: inline-block; + vertical-align: bottom; + } + .remove-answer { + width: 14px; + height: 14px; + @include opacity(0.4); + cursor: pointer; + vertical-align: top; + margin-top: 7px; + display: none; - .icons-deletelabel { - height: 14px; - width: 14px; - margin-top:5px; + &:hover { + @include opacity(1); + } + &.active { + display: inline-block; + } + } + } + .control-group { + margin-bottom: 5px; + } + .add-answer { + padding-top: 5px; } } - -.poll_answer_input { - width:100%; -} - -#add_poll_answer_wrapper { - padding:5px 0 5px 0; - display:block; -} - -#poll_question_wrapper { -} - -#poll_question { - width: 100%; - box-sizing: border-box; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; -} - -.poll_answer { - display: table; - width: 100%; -} - -.poll_answer_input_wrapper { - display: table-cell; -} \ No newline at end of file diff --git a/app/assets/templates/poll_creator_tpl.jst.hbs b/app/assets/templates/poll_creator_tpl.jst.hbs new file mode 100644 index 000000000..ec33719fd --- /dev/null +++ b/app/assets/templates/poll_creator_tpl.jst.hbs @@ -0,0 +1,18 @@ +
+
+ +
+
+
+
+
+ +
+
+
+
+
+
+ {{t 'publisher.add_option' }} +
+
diff --git a/app/views/publisher/_publisher_blueprint.html.haml b/app/views/publisher/_publisher_blueprint.html.haml index 75918f3fe..68ea93d6f 100644 --- a/app/views/publisher/_publisher_blueprint.html.haml +++ b/app/views/publisher/_publisher_blueprint.html.haml @@ -37,17 +37,7 @@ = image_tag 'icons/camera.png', :alt => t('shared.publisher.upload_photos').titleize, :class => 'publisher_image' = hidden_field :location, :coords #location_container - #poll_creator_wrapper - #poll_question_wrapper - %input{:id => 'poll_question', :placeholder => t('shared.publisher.poll.question'), :name => 'poll_question'} - .poll_answer - %span{:class => 'poll_answer_input_wrapper'} - %input{:class => 'poll_answer_input', :placeholder => t('shared.publisher.poll.option'), :name => 'poll_answers[]'} - %a{:class => 'remove_poll_answer', :title => t('shared.publisher.poll.remove_poll_answer')} - .icons-deletelabel - #add_poll_answer_wrapper - #add_poll_answer{:class => 'button creation'} - = t('shared.publisher.poll.add_poll_answer') + #publisher-poll-creator - if publisher_public = hidden_field_tag 'aspect_ids[]', "public" diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 91527ffc1..437a5848e 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -102,6 +102,11 @@ en: mark_read: "Mark read" mark_unread: "Mark unread" + publisher: + option: "Option <%= nr %>" + add_option: "Add option" + question: "Question" + stream: hide: "Hide" public: "Public" @@ -180,4 +185,4 @@ en: one: "1 vote so far" other: "<%=count%> votes so far" show_result: "Show result" - close_result: "Hide result" \ No newline at end of file + close_result: "Hide result" diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature index 7f537758a..97d97d877 100644 --- a/features/desktop/post_preview.feature +++ b/features/desktop/post_preview.feature @@ -76,6 +76,7 @@ Feature: preview posts in the stream When I fill in the following: | status_message_fake_text | I am eating yogurt | And I press the element "#poll_creator" + And I press the element ".add-answer .button.creation" When I fill in the following: | status_message_fake_text | I am eating yogurt | | poll_question | What kind of yogurt do you like? | diff --git a/features/desktop/post_with_a_poll.feature b/features/desktop/post_with_a_poll.feature index faed7efdd..c725bcead 100644 --- a/features/desktop/post_with_a_poll.feature +++ b/features/desktop/post_with_a_poll.feature @@ -9,28 +9,29 @@ Feature: posting with a poll And I am on the home page Scenario: expanding the publisher - Given "#poll_creator_wrapper" is hidden + Given "#publisher-poll-creator" is hidden When I expand the publisher Then I should see an element "#poll_creator" Scenario: expanding the poll creator - Given "#poll_creator_wrapper" is hidden + Given "#publisher-poll-creator" is hidden When I expand the publisher And I press the element "#poll_creator" - Then I should see an element "#poll_creator_wrapper" + Then I should see an element "#publisher-poll-creator" Scenario: adding option to poll - Given "#poll_creator_wrapper" is hidden + Given "#publisher-poll-creator" is hidden When I expand the publisher And I press the element "#poll_creator" - And I press the element "#add_poll_answer" - Then I should see 3 options + And I press the element ".add-answer .button.creation" + Then I should see 2 options Scenario: delete an option - Given "#poll_creator_wrapper" is hidden + Given "#publisher-poll-creator" is hidden When I expand the publisher And I press the element "#poll_creator" - And I delete the first option + And I press the element ".add-answer .button.creation" + And I delete the last option Then I should see 1 option And I should not see a remove icon @@ -40,6 +41,7 @@ Feature: posting with a poll When I fill in the following: | status_message_fake_text | I am eating yogurt | | poll_question | What kind of yogurt do you like? | + And I press the element ".add-answer .button.creation" And I fill in the following for the options: | normal | | not normal | @@ -50,6 +52,7 @@ Feature: posting with a poll Scenario: vote for an option Given I expand the publisher And I press the element "#poll_creator" + And I press the element ".add-answer .button.creation" When I fill in the following: | status_message_fake_text | I am eating yogurt | | poll_question | What kind of yogurt do you like? | @@ -67,6 +70,7 @@ Feature: posting with a poll Scenario: click to show result Given I expand the publisher And I press the element "#poll_creator" + And I press the element ".add-answer .button.creation" When I fill in the following: | status_message_fake_text | I am eating yogurt | | poll_question | What kind of yogurt do you like? | diff --git a/features/step_definitions/post_with_poll_steps.rb b/features/step_definitions/post_with_poll_steps.rb index e2ea6631a..60fb3eeb7 100644 --- a/features/step_definitions/post_with_poll_steps.rb +++ b/features/step_definitions/post_with_poll_steps.rb @@ -1,19 +1,19 @@ Then /^I should see ([1-9]+) options?$/ do |number| - find("#poll_creator_wrapper").all(".poll_answer").count.should eql(number.to_i) + find("#publisher-poll-creator").all(".poll-answer").count.should eql(number.to_i) end -And /^I delete the first option$/ do - find("#poll_creator_wrapper").all(".poll_answer .remove_poll_answer").first.click +And /^I delete the last option$/ do + find("#publisher-poll-creator").all(".poll-answer .remove-answer").first.click end And /^I should not see a remove icon$/ do - page.should_not have_css(".remove_poll_answer") + page.should_not have_css(".remove-answer") end When /^I fill in the following for the options:$/ do |table| i = 0 table.raw.flatten.each do |value| - all(".poll_answer_input")[i].set(value) + all(".poll-answer input")[i].set(value) i+=1 end end diff --git a/spec/javascripts/app/views/publisher_poll_creator_view_spec.js b/spec/javascripts/app/views/publisher_poll_creator_view_spec.js new file mode 100644 index 000000000..e11b8b35e --- /dev/null +++ b/spec/javascripts/app/views/publisher_poll_creator_view_spec.js @@ -0,0 +1,54 @@ +describe('app.views.PublisherPollCreator', function(){ + beforeEach(function(){ + this.view = new app.views.PublisherPollCreator(); + this.view.render(); + this.input_selector = '.poll-answer input'; + }); + describe('rendering', function(){ + it('should have question input', function(){ + expect(this.view.$('input[name=poll_question]')).toExist(); + }); + it('should have answerinput', function(){ + expect(this.view.$(this.input_selector)).toExist(); + }); + }); + describe('#addAnswerInput', function(){ + it('should add new answer input', function(){ + this.view.addAnswerInput(); + expect(this.view.$(this.input_selector).length).toBe(2); + }); + it('should change input count', function(){ + this.view.addAnswerInput(); + expect(this.view.inputCount).toBe(2); + }); + }); + describe('#removeAnswerInput', function(){ + it('remove answer input', function(){ + var input = this.view.$('input:first'); + this.view.removeAnswerInput(input); + expect(this.view.$(this.input_selector).length).toBe(1); + }); + }); + describe('#clearInputs', function(){ + it('clear input', function(){ + this.view.$('input').val('Hello word'); + this.view.clearInputs(); + expect(this.view.$(this.input_selector).val()).toBe(''); + }); + }); + describe('#toggleRemoveAnswer', function(){ + var remove_btn = '.poll-answer .remove-answer'; + it('show remove button when answer input is greater 1', function(){ + this.view.addAnswerInput(); + expect(this.view.$(remove_btn).hasClass('active')).toBe(true); + }); + it('hide remove button when is only one answer input', function(){ + var input = this.view.$(this.input_selector); + + this.view.addAnswerInput(); + this.view.removeAnswerInput(input); + + expect(this.view.$(remove_btn).hasClass('active')).toBe(false); + }); + }); +}); diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index 4d7a809ad..fb753f01f 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -277,40 +277,6 @@ describe("app.views.Publisher", function() { }); - context("poll", function(){ - beforeEach(function() { - loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}}); - spec.loadFixture("aspects_index"); - $("#poll_creator_wrapper").hide(); //css not loaded? :-/ - this.view = new app.views.Publisher(); - }); - - describe('#showPollCreator', function(){ - it("Shows the poll creator", function(){ - expect($("#poll_creator_wrapper").is(":visible")).toBe(false); - this.view.showPollCreator(); - expect($("#poll_creator_wrapper").is(":visible")).toBe(true); - }) - }); - - describe("#addPollAnswer", function(){ - it("should add a poll answer if clicked", function(){ - expect($("#poll_creator_wrapper .poll_answer").length).toBe(2); - this.view.addPollAnswer(); - expect($("#poll_creator_wrapper .poll_answer").length).toBe(3); - }) - }); - - describe("#removePollAnswer", function(){ - it("should remove a poll answer if clicked", function(){ - var answer_count = $('.poll_answer').length; - var evt = {'currentTarget' : $("#poll_creator_wrapper .poll_answer:first .remove_poll_answer")}; - this.view.removePollAnswer(evt); - expect($("#poll_creator_wrapper .poll_answer").length).toBe(answer_count-1); - }) - }); - }); - context("locator", function() { beforeEach(function() { // should be jasmine helper