Last active
August 29, 2015 14:02
-
-
Save jdaly13/b2367b0b231a16611280 to your computer and use it in GitHub Desktop.
wordgame
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Word Game jQuery plugin | |
* | |
* @param {object} options | |
* @returns {settings object that override default} | |
* jQuery plugin | |
* current dependencies are jQuery ... duh | |
*/ | |
(function ($) { | |
$.fn.WordGame = function (options) { | |
var $container = $(this), | |
defaults = { | |
index: 0, // this should get incremented after each correct answer ; | |
data: null, | |
dataLength: null, | |
testPattern: /^[a-z0-9]+$/i, | |
currentScore: 0, | |
continueOn: 'continue', | |
reveal: 'reveal', | |
view: 'view', | |
killBillSetTimeout: null, | |
socialSharing: false, | |
analytics: false, | |
userID: null, | |
timer: 1500, | |
nextLetterTimer: 1, | |
//Jquery DOM Objects | |
$wordup: $container.find('.word'), //word up | |
$takeActionBro: $container.find('.takeAction') || null, | |
$rightOrWrongDiv: $container.find('.rightOrWrong') || null, | |
$currentScoreDiv: $container.find('.currentScore') || null, | |
$sharingIsCaring: $container.find('.shaingIsCaring') || null, | |
$img: $container.find('.row-item-image-url img') || null, | |
$span: $('<span class="editable" contenteditable="true"></span>'), | |
$spannoneditable: $('<span contenteditable="false"></span>'), | |
$differentSpan: $('<span class="what"> </span>'), // !!!!!!! that space is vewy vewy impowtant !!!!!!!!! | |
$secondDifferentspan: $('<span class="dash">-</span>'), //don't even think of making that dash an html entity sucka! | |
$periodSpan: $('<span class="period">.</span>') // not sure this name is appropriate reminds me of at least one week per month with wife JD | |
}, | |
i = 0, | |
isInitializeGameRunning = null, | |
flag = null, //this is used for when users keep continusosly type in the last correct letter | |
// google analytics | |
userHasStartedGame = null, | |
//sniff sniff | |
ieNineOrBelow = $('html').hasClass('lt-ie10'), | |
ieNineAndAbove = window.clipboardData, | |
iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent), | |
//overide defaults with any new data passed in | |
settings = $.extend({}, defaults, options), | |
//event callbacks | |
focusCallBack = function () { | |
preAnalyticsFiltering(settings.analytics, userHasStartedGame, 'initial'); | |
var $this = $(this); | |
$this.data('before', $this.text()); | |
$this.addClass('active'); | |
return $this; | |
}, | |
keyDownCallBack = function (event) { | |
if (event.keyCode === 13 || event.keyCode === 32) { | |
event.preventDefault(); | |
//for those morons who don't know how to play the game and want to break stuff by pressing enter //also, spacebar -dan | |
} else if (event.keyCode === 8) { | |
var length = $.trim($(this).text()).length; | |
if (length > 0) { | |
return; | |
} | |
var $this = $(this); | |
skiptoNextOrPrevAvailablePosition($this, true, 'previous'); | |
} | |
}, | |
keyupCallBack = function (event) { // a lot of stuff happens here | |
var $this = $(this); | |
if ($this.data('before') !== $this.text()) { | |
$this.data('before', $this.text()); | |
var text = $.trim($this.text()); | |
var length = text.length; | |
(length > 1) ? showOnlyFirstLetter($this, text) : ''; | |
if (flag) return false; // set only when yougotitrightson function is executing then set to null after it's finished | |
skiptoNextOrPrevAvailablePosition($this, length, 'next'); | |
var areTheyFilled = areAllLettersFilledIn($(event.delegateTarget)); // returns array or false; | |
var onToTheNext = makeComparison(areTheyFilled); | |
(onToTheNext === 'got it right') ? youGotItRightSon() : (onToTheNext === 'got it wrong') ? youGotItWrongSon() : ''; | |
} | |
return $this; | |
}, | |
blurCallBack = function () { | |
var $this = $(this); | |
$this.removeClass('active'); | |
}, | |
showMeTheBaby = function (e) { //translated show me something bro ! | |
if ($(e.target).hasClass(settings.view)) { | |
goToCharacterPage(); | |
} else { | |
var $this = $(this); | |
// we do this for those click crazy people who want to reveal answer before word is spelled out what up with that yo! | |
if (isInitializeGameRunning) return false; | |
var reveal = settings.reveal; | |
if ($this.hasClass(reveal)) { | |
iGiveUpShowMeTheWord($this); | |
return false; | |
} | |
if ($this.hasClass(settings.continueOn)) { | |
clearTimeout(settings.killBillSetTimeout); | |
wouldntItBeGoodToShowNextCharacter($this, reveal); | |
} | |
} | |
}, | |
goToCharacterPage = function () { | |
preAnalyticsFiltering(settings.analytics, null, 'goToCharacter'); | |
var link = settings.data[settings.index].page; | |
window.location.href = link; | |
}, | |
socialSharing = function (e) { | |
e.preventDefault(); | |
var message; | |
var img; | |
var url = window.location.href; | |
if (settings.dataLength != settings.index) { | |
message = "I scored " + settings.currentScore + " points on the Who Am I game on marvel.com"; | |
img = settings.data[settings.index].img; | |
} else { | |
message = "I scored " + settings.currentScore + " points and completed the Who Am I game on marvel.com"; | |
img = settings.data[settings.dataLength - 1].img; | |
} | |
var shareType = this.getAttribute('data-game-sharebtn'); | |
janrain.engage.share.setTitle('Marvel Character Guessing Game'); | |
janrain.engage.share.setImage(img); | |
janrain.engage.share.setDescription($("meta[name='og:description']").attr('content') || ''); | |
janrain.engage.share.setUrl(url); | |
janrain.engage.share.setMessage(message); | |
janrain.engage.share.reset(); | |
janrain.engage.share.showProvider(shareType); | |
janrain.engage.share.show(); | |
preAnalyticsFiltering(settings.analytics, shareType, 'sharing'); | |
}; | |
/* Help I really need some helper functions Help! */ | |
function preAnalyticsFiltering(analytics, gameStarted, type) { | |
if (!analytics || gameStarted === 'initialized') return false; | |
var obj = {}; | |
var index = parseInt(settings.index) + 1; | |
switch (type) { | |
case "initial": | |
//first focus of game only done once | |
obj.type = 'event'; | |
obj.cat = 'wordgame initialized'; | |
obj.action = 'focus'; | |
obj.label = 'attempting to play'; | |
obj.value = settings.userID; | |
runAnalytics('event', obj); | |
userHasStartedGame = 'initialized'; | |
break; | |
case "reveal": | |
// when user reveals character with click | |
obj.type = "event"; | |
obj.cat = "wordgame reveal character"; | |
obj.action = "click"; | |
obj.label = "character name " + settings.data[settings.index].name; | |
obj.value = index; | |
runAnalytics('event', obj); | |
break; | |
case "correct": | |
// when user gets correct answer | |
obj.type = "event"; | |
obj.cat = "wordgame points scored"; | |
obj.action = "character guessed correctly " + settings.data[settings.index].name; | |
obj.label = settings.currentScore + ' points'; | |
obj.value = index; | |
runAnalytics('event', obj); | |
break; | |
case "sharing": | |
//when user socially shares his score | |
obj.type = "social"; | |
obj.socialNetwork = gameStarted; //facebook twitter or email | |
obj.socialAction = "sharing score " + settings.currentScore + ' points'; | |
obj.socialTarget = "character index " + index; | |
runAnalytics('social', obj); | |
break; | |
case "goToCharacter": | |
//when user clicks on view character page | |
obj.type = "event"; | |
obj.cat = "going to external character page"; | |
obj.action = "click"; | |
obj.label = "character name " + settings.data[settings.index].name; | |
obj.value = index; | |
runAnalytics('event', obj); | |
break; | |
default: | |
return false; | |
} | |
function runAnalytics(event, obj) { | |
if (event === 'event') { | |
ga('send', obj.type, obj.cat, obj.action, obj.label, obj.value); | |
} | |
if (event === 'social') { | |
ga('send', obj.type, obj.socialNetwork, obj.socialAction, obj.socialTarget); | |
} | |
} | |
} | |
function showOnlyFirstLetter($span, text) { | |
$span.text(text[0]); | |
} | |
//It was annoying me so I threw this in quickly. Could probably be simplified with skip to next but I didn't want to break -dan | |
function skiptoNextOrPrevAvailablePosition($that, length, nextOrPrev) { | |
if (length === 0 || iOS) return; //IOS go Tab yourself! | |
var areNextorPrevLettersInWordNotEditable = function ($elements) { | |
var whatToReturn = true; | |
$elements.each(function (i, ele) { | |
if ($(ele).hasClass('editable')) { | |
whatToReturn = false; | |
return false; | |
} | |
}); | |
return whatToReturn; | |
}; | |
if (nextOrPrev === 'next') { | |
goNext(); | |
} else { // it's previous | |
goPrev(); | |
} | |
function goNext() { | |
if ($that.next().is("[contenteditable='true']")) { | |
setTimeout(function () { | |
$that.next().focus(); | |
}, settings.nextLetterTimer); | |
} else if (areNextorPrevLettersInWordNotEditable($that.nextAll())) { //go to/focus on next word | |
setTimeout(function () { | |
$that.parent('div.new').next().children("[contenteditable='true']").first().focus(); | |
}, settings.nextLetterTimer); | |
} else { | |
setTimeout(function () { | |
$that.nextAll("[contenteditable='true']").first().focus(); | |
}, settings.nextLetterTimer); | |
} | |
} | |
function goPrev() { | |
if ($that.prev().is("[contenteditable='true']")) { | |
setTimeout(function () { | |
$that.prev().focus().text(''); | |
}, settings.nextLetterTimer); | |
} else if (areNextorPrevLettersInWordNotEditable($that.prevAll())) { //go to/focus on prev word | |
setTimeout(function () { | |
$that.parent('div.new').prev().children("[contenteditable='true']").last().focus().text(''); | |
}, settings.nextLetterTimer); | |
} else { | |
setTimeout(function () { | |
$that.prevAll("[contenteditable='true']").first().focus().text(''); | |
}, settings.nextLetterTimer); | |
} | |
} | |
} | |
function areAllLettersFilledIn($word) { | |
var $childs = $word.find('span'); | |
var allFilled = true; | |
var array = []; | |
//specifically for IE when QA tries type a million characters per second | |
var doublecheckforIE = function (arr) { | |
var moreThanOne = false; | |
for (var i = 0; i < arr.length; i++) { | |
if (arr[i].length > 1) { | |
arr[i] = arr[i][0]; | |
moreThanOne = true; | |
} | |
} | |
if (moreThanOne) { | |
$childs.each(function (i, ele) { | |
$(ele).text(arr[i]); | |
}); | |
} | |
return arr; | |
}; | |
$childs.each(function (i, ele) { | |
if ($(ele).text().length === 0) { | |
allFilled = false; | |
return false; | |
} | |
array[i] = $(this).text().toLowerCase(); | |
}); | |
if (allFilled) { | |
if (ieNineAndAbove) { | |
return doublecheckforIE(array); | |
} else { | |
return array; | |
} | |
} else { | |
showOrHideWrongButton('hide'); | |
return false; | |
} | |
} | |
function makeComparison(fillCheckArr) { | |
if (!fillCheckArr) return false; | |
var doesitMatch = compareArrays(fillCheckArr, settings.data[settings.index].name); | |
if ( !! doesitMatch) { | |
return 'got it right'; | |
} else { | |
return 'got it wrong'; | |
} | |
} | |
function compareArrays(arr, string) { | |
var j = 0; | |
for (j; j < arr.length; j++) { | |
if (arr[j] !== string[j]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
function youGotItRightSon() { | |
flag = true; // this is set so users don't continuosly his last letter in correct answer | |
showOrHideWrongButton('hide'); | |
settings.$rightOrWrongDiv.find('span.icon-checkmark').removeClass('hide'); | |
settings.currentScore = settings.currentScore + 10; | |
var $currentScoreElement = settings.$currentScoreDiv; | |
$currentScoreElement.addClass('turnWhite').one('transitionend webkitTransitionEnd ie9holla', function () { | |
$(this).removeClass('turnWhite').find('b').text(settings.currentScore); | |
}); | |
if (ieNineOrBelow) { //pure politics no browser left behind | |
setTimeout(function () { | |
$currentScoreElement.trigger('ie9holla'); | |
}, 400); | |
} | |
shortLivedContinue(settings.$takeActionBro.find('span.reveal')); | |
createSpecialTimeout(settings.$takeActionBro.find('span.continue')); | |
preAnalyticsFiltering(settings.analytics, 'null', 'correct'); | |
} | |
function youGotItWrongSon() { | |
showOrHideWrongButton('show'); | |
} | |
function showOrHideWrongButton(showOrHide) { | |
(showOrHide === 'hide') ? settings.$rightOrWrongDiv.find('span.icon-close').addClass('hide') : ''; | |
(showOrHide === 'show') ? settings.$rightOrWrongDiv.find('span.icon-close').removeClass('hide') : ''; | |
} | |
function iGiveUpShowMeTheWord($this) { | |
preAnalyticsFiltering(settings.analytics, null, 'reveal'); | |
var $lilBreezy = settings.$wordup.find('span'); // 3/5/14 named after Fabrizio's newborn | |
settings.$rightOrWrongDiv.find('span.icon-close').addClass('hide'); | |
$lilBreezy.each(function (i, ele) { | |
$(ele).text(settings.data[settings.index].name[i]); | |
}); | |
shortLivedContinue($this); | |
createSpecialTimeout($this); | |
} | |
function wouldntItBeGoodToShowNextCharacter($this, text) { | |
settings.index++; | |
var endOfGame = isItendOfGame(settings.dataLength, settings.index, false); | |
if (endOfGame) return true; | |
initializeGame(true); | |
if (text === settings.reveal) { | |
$this.addClass(settings.reveal).removeClass(settings.continueOn).text('reveal character'); | |
} | |
settings.$rightOrWrongDiv.find('span.icon-checkmark').addClass('hide'); | |
//move this somewhere else | |
// console.log(settings.imgArray[settings.index]); | |
replaceImage(); | |
flag = null; | |
} | |
function isItendOfGame(dataLength, index, easterEgg) { | |
if (dataLength != index) return false; | |
var $social = $container.find('.social'); | |
var $easterEggHtml; | |
var $aleksey; | |
$social.addClass('absolute'); | |
if (easterEgg) { | |
$aleksey = $('<div id="aleksey"><img src="http://i.annihil.us/u/prod/marvel/i/mg/4/03/537a3584440c4.png"/></div>'); | |
$easterEggHtml = $('<div id="easter_egg"><h1 class="fadeIn one">Congratulations!</h1><h1 class="fadeIn two">You Have Completed the who am I game, Your Reward is...</h1><h1 class="fadeIn three"> our QA Manager floating in space, feel free to share your accomplishment!</h1></div>'); | |
} else { | |
$easterEggHtml = $('<div id="easter_egg"><h1 class="fadeIn one">Congratulations!</h1><h1 class="fadeIn two">You Have Completed the who am I game</h1><h1 class="fadeIn three"> Please Share your score</h1></div>'); | |
$aleksey = $('<div></div>'); | |
} | |
$container.css('min-height', '380px').html($easterEggHtml).find('h1.three').one("animationend webkitAnimationEnd", function () { | |
$social.prependTo($container); | |
setTimeout(function () { | |
$container.find($easterEggHtml).fadeOut('slow', function () { | |
$aleksey.appendTo($container); | |
$social.prependTo($container); | |
}); | |
}, 3000); | |
}); | |
if (ieNineOrBelow) { | |
$social.prependTo($container); | |
} | |
return true; | |
} | |
function shortLivedContinue($ele) { | |
$ele.addClass(settings.continueOn).removeClass(settings.reveal).text(settings.continueOn); | |
} | |
function createSpecialTimeout($ele) { | |
settings.killBillSetTimeout = setTimeout(function () { | |
wouldntItBeGoodToShowNextCharacter($ele, settings.reveal); | |
}, settings.timer); | |
} | |
function positionElementBasedOnTextLength(iterator, arrLength) { | |
if (iterator > 0) return false; | |
//length = arrLength; | |
if (arrLength > 14) { // we love magic numbers because they are magical! | |
settings.$wordup.addClass('removeMarginTop'); | |
} else { | |
settings.$wordup.removeClass('removeMarginTop'); | |
} | |
} | |
function initializeGame(remove) { | |
isInitializeGameRunning = true; | |
if (remove) { | |
settings.$wordup.html(''); | |
i = 0; | |
} | |
positionElementBasedOnTextLength(i, settings.data[settings.index].name.length); | |
setTimeout(function () { | |
var letter = settings.data[settings.index].name[i]; | |
var ele = settings.$wordup; | |
if (settings.testPattern.test(letter) && (i % 3 !== 0)) { | |
settings.$span.clone().appendTo(ele); | |
} else if (settings.testPattern.test(letter) && (i % 3 === 0)) { | |
settings.$spannoneditable.clone().text(letter).appendTo(ele); //.hide().fadeIn(); | |
} else if (letter === '-') { | |
settings.$secondDifferentspan.clone().appendTo(ele); | |
} else if (letter === '.') { | |
settings.$periodSpan.clone().appendTo(ele); | |
} else { | |
settings.$differentSpan.clone().appendTo(ele); | |
settings.$wordup.children('span:last-child').prevAll('span').andSelf().wrapAll("<div class='new' />"); | |
} | |
i++; | |
if (i < settings.data[settings.index].name.length) { | |
initializeGame(false); | |
} else { | |
settings.$wordup.children('span:last-child').prevAll('span').andSelf().wrapAll("<div class='new' />"); | |
settings.index >= 1 ? setTimeout(function () { | |
settings.$wordup.find('div.new').children("[contenteditable='true']").first().focus(); | |
}, 300) : ''; | |
isInitializeGameRunning = false; | |
} | |
}, 100); | |
} | |
function createEvents(sharing) { | |
settings.$wordup.on('focus', 'span', focusCallBack).on('keydown', 'span', keyDownCallBack).on('keyup paste input', 'span', keyupCallBack).on('blur', 'span', blurCallBack); | |
//chainingsaw massacre! | |
settings.$takeActionBro.on('click', 'span', showMeTheBaby); | |
//click event for reveal character or goto character page | |
if (sharing) $container.on('click', '[data-game-sharebtn]', socialSharing); | |
//sharing is caring good ole facebook and twitter sharing ur scrore lovely! | |
} | |
function ie8Madness(arr) { | |
for (var j = 0; j < arr.length; j++) { | |
arr[j].name = arr[j].name.replace(/\s+/g, '?'); | |
} | |
settings.$differentSpan = $('<span class="what">?</span>'); | |
//this is done becasue IE 8 doesn't like spaces so I replaced each space with a ? mark to keep IE 8 happy | |
} | |
function replaceImage() { | |
settings.$img.attr('src', settings.data[settings.index].img); | |
} | |
function hideLoader() { | |
$container.find('.loader').addClass('hide').next().removeClass('hide'); | |
} | |
function init() { | |
hideLoader(); | |
if ($('html').hasClass('lt-ie9')) ie8Madness(settings.data); | |
createEvents(settings.socialSharing, settings.analytics); | |
initializeGame(); | |
replaceImage(); | |
} | |
init(); | |
return settings; | |
}; | |
}(jQuery)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment