UNPKG

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.

460 lines (396 loc) 13.2 kB
var GLOBALS = {} , RIPPLE = {}; // Avoid `console` errors in browsers that lack a console. ;(function() { var method; var noop = function () {}; var methods = [ 'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error', 'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log', 'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd', 'timeStamp', 'trace', 'warn' ]; var length = methods.length; var console = (window.console = window.console || {}); while (length--) { method = methods[length]; // Only stub undefined methods. if (!console[method]) { console[method] = noop; } } }()); // jQuery (function ($) { // Fire when document is ready. $(document).ready(function() { // Make iOS delay touchend FastClick.attach(document.body); // handle user logout // $('#btn-logout').click(function(e){ GLOBALS.attemptLogout(); e.preventDefault(); }); // Put Pathname into body class var pathArray = location.pathname.split('/') , pathClass = "page"; while ( pathArray.length > 0 ){ var pathElement = pathArray.shift(); // Find First Character var subPathFirstChar = parseInt( pathElement.substring(0,1) ); // Make sure that it is not a digit if( ! ( /^\d$/.test(subPathFirstChar) ) ) pathClass += "-" + pathElement; }; // Change class when js is loaded $('body').removeClass('no-js').addClass('js ' + pathClass); // Initialize Sliding Panel var slidebarWidth = 260 , adjSlideWidth = slidebarWidth + 20; GLOBALS.jPM = $.jPanelMenu({ openPosition: slidebarWidth + "px", keyboardShortcuts: [{ code: 27, /* Escape Key */ open: false, close: true }], before: clearChatCount, afterClose: jPanelStatic }); GLOBALS.jPM.on(); setTimeout(function(){ jPanelStatic(); }, 1000); // Add swipe to sidebar var isClientPage = $('#page').hasClass('client-page'); $('.admin-page #content').swipe({ allowPageScroll: "vertical", swipe:function(e,direction){ switch(direction){ case "left": if( GLOBALS.jPM.isOpen() && !isClientPage ) GLOBALS.jPM.close(); break; case "right": if( !GLOBALS.jPM.isOpen() && !isClientPage ) GLOBALS.jPM.open(); break; } } }) //Skip Link $('#skip-to-content').click(function(){ $('#content').focus(); }); // Stop Bubbling of click otherwise jPanelMenu is listening // and will close slidebar $('#jPanelMenu-menu').on('click touchend',function(e){ e.stopPropagation(); }) // Hide chat notify $('#chat-count').css('visibility','hidden'); // open slidebar $('#slidebar-btn, #chat-count, #chat-notify').on('click keydown', function(e) { if( !GLOBALS.isKeypressActivate(e) ) return; e.preventDefault(); // Open or Close Slidebar if( GLOBALS.jPM.isOpen() ) GLOBALS.jPM.close(); else GLOBALS.jPM.open(); // If keypress enter move focus if( GLOBALS.isOnlyKeypressActivate(e) && GLOBALS.jPM.isOpen() ) { $('#slidebar .subset a:first, #slidebar button:first').focus(); } // Clear the Chat Count clearChatCount(); // Move Focus if( $(this).attr('id') == 'chat-count' || $(this).attr('id') == 'chat-notify') { if( GLOBALS.jPM.isOpen() ) $('#message-txt').focus(); } }); // Tooltip $( GLOBALS.params.tooltipSelector ).tooltip(); // Overide Session Start to put in new window $('#nav-session').on('click keypress', function(e){ if( isKeypressEnter(e) ) GLOBALS.openSessionWindow( $(this).prop('href'), e ); }) // Move focus to overlay on shown $(document).on('shown', '.modal', function(e){ var modal = $(e.currentTarget) , firstInput = modal.find('input').first(); if( firstInput.length > 0 ) firstInput.focus(); else modal.focus(); }) // IE9 Bug Fix for menu not shutting all the way if( $('html.lt-ie10').length ) { $('#btn-logout').on('focusin', function(){ setTimeout(function(){ if( GLOBALS.jPM.isOpen) GLOBALS.jPM.close(); }, 100); }) } // Allow spacebar to follow links $('body').on("keypress", "a", function(e){ console.log(e); var target = e.target.href , jElem = $(e.target) , hasHref = target && target != "#"; if( keyCode(e) == 32 && hasHref && !jElem.hasClass("no-autolink") ) document.location = target; }) }); /** * Clear the chat count */ function clearChatCount(){ var chatCnt = $('#chat-count'); chatCnt.css('visibility', 'hidden'); chatCnt.text("0"); } function jPanelStatic(){ $('.jPanelMenu-panel').css('position','static'); } })(jQuery); GLOBALS.params = { tooltipSelector: "i[rel='tooltip'], button[rel='tooltip'], span[rel='tooltip'], a[rel='tooltip']" } GLOBALS.attemptLogout = function(){ // Post to clear connect session $.ajax({ url: "/logout", type: "POST", data: {logout : true}, success: function(data){ // Show Prompt GLOBALS.showLockedAlert('You are now logged out.<br>Redirecting you back to the homepage.'); }, error: function(jqXHR){ console.error(jqXHR.responseText+' :: '+jqXHR.statusText); } }); }; GLOBALS.showLockedAlert = function(msg){ $('.modal-alert').modal({ show : false, keyboard : false, backdrop : 'static' }); $('.modal-alert .modal-header h3').text('Success!'); $('.modal-alert .modal-body p').html(msg); $('.modal-alert').modal('show'); $('.modal-alert button').click(function(){window.location.href = '/';}) setTimeout(function(){window.location.href = '/';}, 3000); }; // Open Stand alone window for sessions GLOBALS.openSessionWindow = function(URL, e){ e.preventDefault(); var newWindowWidth = ',width=' + $(window).width() , newWindowHeight = ',height=' + $(window).height(); var newWindow = window.open( URL, 'Session', 'location=0,directories=0,status=0,menubar=0,copyhistory=0,titlebar=0' + newWindowWidth + newWindowHeight ); newWindow.moveTo(20,20); }; GLOBALS.dynamicPopoverDirection = function(element, tooltip) { var $element, $tooltip, above, actualHeight, actualWidth, below, boundBottom, boundLeft, boundRight, boundTop, elementAbove, elementBelow, elementLeft, elementRight, isWithinBounds, left, pos, right; isWithinBounds = function(elementPosition) { return 0 <= elementPosition.top && 0 <= elementPosition.left; }; $element = $(element); $tooltip = $(tooltip); pos = $.extend({}, $element.offset(), { width: $element.width(), height: $element.height(), tipWidth: $tooltip.width() + 20, tipHeight: $tooltip.height() + 40, windowHeight: $(window).height(), windowWidth: $(window).width() }); // Positive indicate that space is available elementAbove = { top: pos.top - pos.tipHeight, left: pos.left - pos.tipWidth }; elementBelow = { top: pos.windowHeight - (pos.top + pos.height + pos.tipHeight), left: pos.left - pos.tipWidth }; elementLeft = { top: pos.top - pos.tipHeight, left: pos.left - pos.tipWidth }; elementRight = { top: pos.windowHeight - ( pos.top + pos.height + pos.tipHeight/2), left: pos.windowWidth - (pos.left + pos.width + pos.tipWidth) }; // Determine if within bounds above = isWithinBounds(elementAbove); bottom = isWithinBounds(elementBelow); left = isWithinBounds(elementLeft); right = isWithinBounds(elementRight); // Prioritize Directions if (bottom) return "bottom"; else if (right) return "right"; else if (above) return "top"; else if (left) return "left"; else return "right"; }; GLOBALS.cloneObj = function(obj) { if (null == obj || "object" != typeof obj) return obj; var copy = obj.constructor(); for (var attr in obj) { if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr]; } return copy; } GLOBALS.isString = function(o) { return typeof o === "string" && o !== null && o !== "" && o !== false; } GLOBALS.genID = function(length){ var id = ""; var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; for( var i=0; i < length; i++ ) id += possible.charAt(Math.floor(Math.random() * possible.length)); return id; } GLOBALS.wysihtml5Options = { "font-styles": false //"link": false, //dom: { autoLink: false } } GLOBALS.createHint = function(hint){ return ' <i class="icon-info-sign" rel="tooltip" title="' + hint + '" tabindex="0"></i> '; } GLOBALS.isKeypressActivate = function(e){ if(e.type === "keypress" || e.type === "keyup" || e.type === "keydown"){ // Check that code was an enter if( keyCode(e) === 13 || keyCode(e) === 32 ) return true; else return false; } return true; } GLOBALS.isOnlyKeypressActivate = function(e) { return isOnlyKeypressEnter || isOnlyKeypressSpace } function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function isAplhaLower(x){ return x.match(/^[a-z0-9]{6}$/); } function isKeypressEnter(e){ if(e.type === "keypress" || e.type === "keyup" || e.type === "keydown"){ // Check that code was an enter if( keyCode(e) === 13 || keyCode(e) === 32) return true; else return false; } return true; } function isOnlyKeypressEnter(e){ if(e.type === "keypress" || e.type === "keyup" || e.type === "keydown"){ // Check that code was an enter if( keyCode(e) === 13) return true; else return false; } return false; } function isOnlyKeypressSpace(e){ if(e.type === "keypress" || e.type === "keyup" || e.type === "keydown"){ // Check that code was an enter if( keyCode(e) === 32) return true; else return false; } return false; } function isKeypressEsc(e){ if(e.type === "keypress" || e.type === "keyup" || e.type === "keydown"){ // Check that code was an enter if( keyCode(e) === 27) return true; } return false; } function keyCode(e){ return e.keyCode ? e.keyCode : e.which; } var EXTEND = { parseQueryString : function(qs){ var queryObj = {} , pairs = qs.split('&'); $.each(pairs, function(i, v){ var pair = v.split('='); value = decodeURIComponent( pair[1] ); value = value.replace("+", " "); queryObj[pair[0]] = value; }); return queryObj; } } // Make sure that Array has method indexOf if(!Array.prototype.indexOf) { Array.prototype.indexOf = function(needle) { for(var i = 0; i < this.length; i++) { if(this[i] === needle) { return i; } } return -1; }; } RIPPLE.namespace = function() { var a=arguments, o=null, i, j, d, that=this; for (i=0; i<a .length; i=i+1) { d=a[i].split("."); o=that; // RIPPLE is implied, so it is ignored if it is included for (j=(d[0] == "RIPPLE") ? 1 : 0; j<d.length; j=j+1) { o[d[j]]=o[d[j]] || {}; o=o[d[j]]; } } return o; }; // Create Name Spacing RIPPLE.namespace('questionType'); RIPPLE.checkClass = function(rippleClass, methods, params){ var err = [] , methods = methods || 0 , params = params || 0; // Check for Required Class, Methods and Parameters if( ! RIPPLE.questionType.hasOwnProperty(rippleClass) ) err.push( "Missing Class Declaration: RIPPLE.questionType." + rippleClass ); var qTypeClass = RIPPLE.questionType[rippleClass]; var checkMethod = function(method){ if( ! qTypeClass.hasOwnProperty(method) ) err.push( "Missing Function: RIPPLE.questionType." + rippleClass + "." + method ); } // Iterator over functions if array if( methods !== 0 ){ if( typeof methods === 'string' ) checkMethod(methods); else { for (var i = methods.length - 1; i >= 0; i--) { checkMethod( methods[i] ); }; } } var checkParam = function(param){ if( ! qTypeClass.hasOwnProperty(param) ) err.push("Missing Parameter: RIPPLE.questionType." + rippleClass + "." + param); } // Iterator over params if array if( params !== 0 ){ if( typeof params === 'string' ) checkParam( params ); else{ for (var i = params.length - 1; i >= 0; i--) { checkParam( params[i] ); }; } } err = err.length > 0 ? err : true; if( err !== true) { for (var i = err.length - 1; i >= 0; i--) { console.error("ERROR: ",err[i]); }; } return err; }; RIPPLE.questionTypeBootstrap = function(refObj){ var controller = RIPPLE.activeController; var hasFn = refObj.hasOwnProperty(controller) && (typeof refObj[controller] === 'function'); if( !hasFn ) return false // Add properties and methods to parent returnedObj = refObj[controller](); for (var attrname in returnedObj) { refObj[attrname] = returnedObj[attrname]; } };