ripple-core
Version:
Ripple is an interactive audience response system that allows presenters to survey audience members in real time communication through their mobile devices.
229 lines (183 loc) • 6.33 kB
JavaScript
/**
* Client Plugin Session API Module.
*
* @author William Myers
* @class plugin-client.session
* @title session
* @space RIPPLE.questionType['<i>pluginName</i>'].session<br /> <span class="note"><i>pluginName</i> will be replaced by your plugin's name</span>
*/
RIPPLE.namespace('session');
// Set up session components
RIPPLE.session.displayController = new SessionDisplayController();
RIPPLE.session.mainController = new SessionMainController();
RIPPLE.activeController = "session";
function SessionMainController() {
var that = this
, DISPLAY = RIPPLE.session.displayController
console.log(RIPPLE);
var initialParams = {
"total":0,
"setPolling":false,
"firstSet":false,
"graph":{"instance":{}, "interval":0},
"timer":0,
"flashAnswers":true,
"initialQuestion":true
}
var params = GLOBALS.cloneObj( initialParams );
// Expose function to set and get params
this.params = function(param, value, option){
var that = this;
var get = function(){
return params[param];
}
var set = function(){
params[param] = value;
}
if(typeof value !== 'undefined') set()
else return get();
};
this.sendQuestion = function(nowDistributeQuestion){
var type = $('#type').val()
, question = []
, qOptionsArr = [];
// Serialize Answers
qOptionsArr = $('#qOptions :input').serializeArray();
question = {
"type":type,
"qTxt":$("#question textarea").val(),
"authorID":now.name,
"qOptions":qOptionsArr
};
// Distribute Question
nowDistributeQuestion(question);
// Notify of sent
$.jGrowl($("#question textarea").val(), { header: "QUESTION SENT" });
// Clear Params
params = GLOBALS.cloneObj( initialParams );
/**
* Hook fired when a question is sent to audience.
*
* @event sendQuestionFn
*/
var passCheck = RIPPLE.checkClass(type)
var hasClearFn = RIPPLE.questionType[type].hasOwnProperty('sendQuestionFn');
if( passCheck && hasClearFn ) RIPPLE.questionType[type].sendQuestionFn();
// Clear Responses
$('#qOptions .tally, #responses').html("");
that.clearTotal()
DISPLAY.total('0');
$('#question-sent').html( "Q?: " + $("#question textarea").val() );
};
this.recieveAnswer = function(clientID, name, answer){
var that = this
, type = now.question.type;
// Check for Class, Methods, & Params
var passCheck = RIPPLE.checkClass(type, 'recieveAnswerFn');
if( !passCheck ) return false;
RIPPLE.questionType[type].recieveAnswerFn(clientID, name, answer);
// Display Total number of responses
$('#total').text( that.params("total") );
};
this.graphUpdate = function(ansObj){
var that = this
, graph = params.graph;
// Increment the clock in seconds
ansObj.clock++;
// Determine the current index and length
var dataLen = ansObj.data.length;
var dataIndex = dataLen - 1;
// Copy the last data child array
var preVals = ansObj.data[dataLen - 1].slice(0);
var newVals = preVals;
// Correct the time elements in the array - always the first indice
newVals[0] = ansObj.clock;
// Add the new values
ansObj.data.push(newVals);
// Update the graph with the new array
graph.instance.updateOptions( { 'file': ansObj.data } );
};
this.startGraphing = function(ansObj){
var that = this
, graph = params.graph;
graph.interval = setInterval(function() {
that.graphUpdate(ansObj);
}, 1000);
// Set Clear Interval for 5 minutes due to amount of data
var graphTime = 5 * 60 * 1000;
params.timer = setTimeout(function(){
clearInterval(graph.interval);
}, graphTime);
};
this.graphPolling = function(action){
if( action === "start"){
var type = $('#type').val()
, passCheck = RIPPLE.checkClass(type, "getAnswerObjectFn");
if( passCheck ) that.startGraphing( RIPPLE.questionType[type].getAnswerObjectFn() );
} else if( action === "stop" ){
that.clearTimers();
}
};
this.clearTimers = function(){
var graph = params.graph;
if( graph.interval !== 0 ) clearInterval( graph.interval );
if( params.timer > 0 ) clearInterval( params.timer );
};
this.incrementTotal = function(){
var that = this
, newTotal = DISPLAY.incrementVal("total", that.params("total") );
that.params("total", newTotal);
return newTotal;
};
this.clearTotal = function(){
that.params('total', 0)
}
this.setOpenFlash = function(status){
that.params('flashAnswers',status);
};
this.clearGraphInterval = function(){
var currInterval = that.params('graph').interval;
clearInterval( currInterval );
currInterval = 0;
};
this.clearAnsVals = function(){
var type = $('#type').val();
// Clear an outstanding timers
that.clearTimers();
// Check for Class, Methods, & Params
var passCheck = RIPPLE.checkClass(type);
var hasClearFn = RIPPLE.questionType[type].hasOwnProperty('clearAnsValsFn');
if( passCheck && hasClearFn ) RIPPLE.questionType[type].clearAnsValsFn();
};
this.setPolling = function(state){
var that = this
that.params["setPolling"] = state;
}
this.barChartPlotter = function(e) {
var ctx = e.drawingContext;
var points = e.points;
var y_bottom = e.dygraph.toDomYCoord(0); // see http://dygraphs.com/jsdoc/symbols/Dygraph.html#toDomYCoord
var min = parseFloat($("input#min").val())
, max = parseFloat($("input#max").val())
, step = parseFloat($("#step").val() );
// This should really be based on the minimum gap
var intervals = (max - min) / step
, graphWidth = parseInt( e.dygraph.getArea()["w"] )
, spacing = graphWidth / intervals
, bar_width = 2/3 * spacing;
ctx.fillStyle = e.color;
// Do the actual plotting.
for (var i = 0; i < points.length; i++) {
var p = points[i]
, center_x = p.canvasx; // center of the bar
ctx.fillRect(center_x - bar_width / 2, p.canvasy,
bar_width, y_bottom - p.canvasy);
ctx.strokeRect(center_x - bar_width / 2, p.canvasy,
bar_width, y_bottom - p.canvasy);
}
};
}
// Should be in GLOBALS
function sortNumber(a,b){
return a[0] - b[0];
}