diff --git a/arsnova.click/client/js/live_results.js b/arsnova.click/client/js/live_results.js index 45ac502deb1086646c3522e1d487b28351f9fa33..22b12e18842b3a821924f596516c3b5306f996e2 100644 --- a/arsnova.click/client/js/live_results.js +++ b/arsnova.click/client/js/live_results.js @@ -101,6 +101,8 @@ Template.live_results.onRendered(()=>{ Meteor.call("EventManager.showReadConfirmedForIndex", localData.getPrivateKey(), Session.get("hashtag"), 0); } } + Session.set("LearnerCountOverride", false); + calculateButtonCount(); }); Template.live_results.helpers({ @@ -262,17 +264,16 @@ Template.live_results.helpers({ return index <= EventManager.findOne().questionIndex; }, readingConfirmationListForQuestion: (index)=>{ - let result = []; + var result = []; let sortParamObj = Session.get('LearnerCountOverride') ? {lowerCaseNick: 1} : {insertDate: -1}; let ownNick = MemberList.findOne({nick:Session.get("nick")}, {limit: 1}); if ( !Session.get("isOwner") && ownNick.readConfirmed[index] ) { result.push(ownNick); } MemberList.find({nick: {$ne: Session.get("nick")}}, { - limit: (Session.get("LearnerCount") - 1), sort: sortParamObj }).forEach(function (doc) { - if(doc.readConfirmed[index]) { + if(result.length < Session.get("LearnerCount") && doc.readConfirmed[index]) { result.push(doc); } }); @@ -280,6 +281,24 @@ Template.live_results.helpers({ }, isOwnNick: (nick)=>{ return nick === Session.get("nick"); + }, + showMoreButton: function (index) { + var result = []; + MemberList.find().forEach(function (doc) { + if(doc.readConfirmed[index]) { + result.push(doc); + } + }); + return ((result.length - Session.get("LearnerCount")) > 1); + }, + invisibleLearnerCount: function (index) { + var result = []; + MemberList.find().forEach(function (doc) { + if(doc.readConfirmed[index]) { + result.push(doc); + } + }); + return result.length - Session.get("LearnerCount"); } }); @@ -384,6 +403,17 @@ Template.live_results.events({ 'click #showNextQuestionDialog': (event)=>{ event.stopPropagation(); Meteor.call("EventManager.showReadConfirmedForIndex",localData.getPrivateKey(), Session.get("hashtag"), EventManager.findOne().questionIndex + 1); + }, + "click .btn-more-learners": function () { + Session.set("LearnerCount", MemberList.find().count()); + Session.set("LearnerCountOverride", true); + }, + 'click .btn-less-learners': function () { + Session.set("LearnerCountOverride", false); + calculateButtonCount(); + }, + 'click .btn-learner': function (event) { + event.preventDefault(); } }); @@ -406,6 +436,16 @@ Template.result_button_mc.helpers({ getCSSClassForIsCorrect: checkIfIsCorrect }); +Template.readingConfirmedLearner.onRendered(function () { + calculateButtonCount(); +}); + +Template.readingConfirmedLearner.helpers({ + isOwnNick: function (nickname) { + return nickname === Session.get("nick"); + } +}); + /** * @source http://stackoverflow.com/a/17267684 */ @@ -504,4 +544,75 @@ function setMcCSSClasses () { bar.addClass("col-xs-10 col-sm-10 col-md-10"); } } +} + +/** + * TODO remove this function with the Meteor 1.3 update and replace with an import from the memberList! + */ +function calculateButtonCount () { + + /* + This session variable determines if the user has clicked on the show-more-button. The button count must not + be calculated then. It is set in the event handler of the button and is reset if the user reenters the page + */ + if (Session.get("LearnerCountOverride")) { + return; + } + + /* + To calculate the maximum output of attendee button rows we need to: + - get the contentPosition height (the content wrapper for all elements) + - subtract the confirmationCounter height (the progress bar) + - subtract the attendee-in-quiz-wrapper height (the session information for the attendees) + - subtract the margin to the top (the title or the show more button) + */ + var viewport = $(".contentPosition"), + learnerListMargin = $('.learner-list').length > 0 ? parseInt($('.learner-list').first().css('margin-top').replace("px", "")) : 0; + + var viewPortHeight = + viewport.outerHeight() - + $('.question-title').outerHeight(true) - + $('.readingConfirmationProgressRow').outerHeight(true) - + $('.btn-more-learners').outerHeight(true) - + learnerListMargin; + + /* The height of the learner button must be set manually if the html elements are not yet generated */ + var btnLearnerHeight = $('.btn-learner').first().parent().outerHeight() ? $('.btn-learner').first().parent().outerHeight() : 54; + + /* Calculate how much buttons we can place in the viewport until we need to scroll */ + var queryLimiter = Math.floor(viewPortHeight / btnLearnerHeight); + + /* + Multiply the displayed elements by 3 if on widescreen and reduce the max output of buttons by 1 row for the display + more button if necessary. Also make sure there is at least one row of buttons shown even if the user has to scroll + */ + var allMembers = []; + MemberList.find().forEach(function (doc) { + if(doc.readConfirmed[EventManager.findOne().readingConfirmationIndex]) { + allMembers.push(doc); + } + }); + var limitModifier = (viewport.outerWidth() >= 992) ? 3 : (viewport.outerWidth() >= 768 && viewport.outerWidth() < 992) ? 2 : 1; + + queryLimiter *= limitModifier; + if (queryLimiter <= 0){ + queryLimiter = limitModifier; + } else if(allMembers > queryLimiter) { + + /* + Use Math.ceil() as a session owner because the member buttons position may conflict with the back/forward buttons position. + As a session attendee we do not have these buttons, so we can use Math.floor() to display a extra row + */ + if($(".fixed-bottom").length > 0) { + queryLimiter -= Math.ceil($('.more-learners-row').first().outerHeight() / btnLearnerHeight) * limitModifier; + } else { + queryLimiter -= Math.floor($('.more-learners-row').first().outerHeight() / btnLearnerHeight) * limitModifier; + } + } + + /* + This session variable holds the amount of shown buttons and is used in the helper function + Template.memberlist.helpers.learners which gets the attendees from the mongo db + */ + Session.set("LearnerCount", queryLimiter); } \ No newline at end of file diff --git a/arsnova.click/client/js/voting_view.js b/arsnova.click/client/js/voting_view.js index 83a26629e606a125040e1980fd4a57353d705eca..daa943ada01bcd9bdc1ba8122b4eeadab7ab0fd3 100644 --- a/arsnova.click/client/js/voting_view.js +++ b/arsnova.click/client/js/voting_view.js @@ -23,8 +23,16 @@ Template.votingview.onCreated(function () { Session.set("sessionClosed", undefined); countdown = null; + this.subscribe("EventManager.join",Session.get("hashtag")); + this.subscribe('QuestionGroup.questionList', Session.get("hashtag"), function () { + Session.set("questionGroupSubscriptionReady", true); + if(!Session.get("sessionClosed")) { + countdownRunning = true; + startCountdown(EventManager.findOne().questionIndex); + } + }); + this.autorun(() => { - this.subscribe("EventManager.join",Session.get("hashtag")); this.subscribe('AnswerOptions.public', Session.get("hashtag"), function () { var answerOptionCount = AnswerOptions.find({questionIndex: EventManager.findOne().questionIndex}).count(); var responseArr = []; @@ -33,14 +41,6 @@ Template.votingview.onCreated(function () { } Session.set("responses", JSON.stringify(responseArr)); }); - - this.subscribe('QuestionGroup.questionList', Session.get("hashtag"), function () { - Session.set("questionGroupSubscriptionReady", true); - }); - if(Session.get("questionGroupSubscriptionReady") && !Session.get("sessionClosed") && !countdownRunning) { - countdownRunning = true; - startCountdown(EventManager.findOne().questionIndex); - } }); }); @@ -138,15 +138,8 @@ Template.votingview.events({ var responseArr = JSON.parse(Session.get("responses")); var currentId = event.currentTarget.id; responseArr[currentId] = responseArr[currentId] ? false : true; - var hasToggledResponse = false; - $.each(responseArr, function (index, item) { - if (item) { - hasToggledResponse = true; - return false; - } - }); - Session.set("hasToggledResponse", hasToggledResponse); Session.set("responses", JSON.stringify(responseArr)); + Session.set("hasToggledResponse", JSON.stringify(responseArr).indexOf("true") > -1); $(event.target).toggleClass("answer-selected"); } } diff --git a/arsnova.click/client/templates/live_results.html b/arsnova.click/client/templates/live_results.html index b7f09e666b3a3ff75536a26eb164d1ceb4635d92..ed6be47b592e29a773434d6c7772f2d9fd50538f 100644 --- a/arsnova.click/client/templates/live_results.html +++ b/arsnova.click/client/templates/live_results.html @@ -111,17 +111,22 @@ </div> </div> {{else}} - {{#each readingConfirmationListForQuestion displayIndex}} - <div class="row"> - <div class="col-xs-12 col-sm-6 col-md-4"> - <button class="btn btn-learner slide-top {{#if isOwnNick nick}}color-changing-own-nick{{/if}} " - id="{{_id}}" - style="background-color: {{backgroundColor}}; color:{{foregroundColor}}"> - {{nick}} + {{#if showMoreButton displayIndex}} + <div class="row more-learners-row"> + <div class="col-xs-12"> + <button class="btn btn-more-learners"> + <span class="glyphicon glyphicon-align-justify"></span> + (Zeige {{invisibleLearnerCount displayIndex}} weitere) </button> </div> </div> - {{/each}} + {{/if}} + <div class="row learner-list margin-title" + id="learner-list"> + {{#each readingConfirmationListForQuestion displayIndex}} + {{>readingConfirmedLearner}} + {{/each}} + </div> {{/if}} </div> </div> @@ -191,6 +196,16 @@ </div> </template> +<template name="readingConfirmedLearner"> + <div class="col-xs-12 col-sm-6 col-md-4"> + <button class="btn btn-learner slide-top {{#if isOwnNick nick}}color-changing-own-nick{{/if}} " + id="{{_id}}" + style="background-color: {{backgroundColor}}; color:{{foregroundColor}}"> + {{nick}} + </button> + </div> +</template> + <template name="questionT"> <div id="questionTText"></div> <br/>