// ==== URL persistante var nullFunction = function(){}; function State(init) { try { $.extend(this, init || {}); if (!this.screen) this.screen = 'splash'; } catch(e) {alert("Error State");alert(e);} }; var futureHashChange = null; State.prototype.commit = function() { try { futureHashChange = "#"+encodeURI('"'+$.JSON.encode(this)); location.hash = futureHashChange; return this; } catch(e) {alert("Error State.prototype.commit");alert(e);} }; State.prototype.get = function(key) { try { return this[key]; } catch(e) {alert("Error State.prototype.get");alert(e);} }; State.prototype.set = function(key, value) { try { this[key] = value; return this; } catch(e) {alert("Error State.prototype.set");alert(e);} }; State.prototype.validate = function () { try { state = this; UI().setScreen(this.screen); if (oldScreen != this.screen) { if (window[oldScreen] && window[oldScreen].leave) window[oldScreen].leave(); oldScreen = this.screen; } if (window[this.screen] && window[this.screen].enter) window[this.screen].enter(); return this; } catch(e) {alert("Error State.prototype.validate");alert(e);} }; var runstate = {}; var state; var oldScreen = ''; var ui = {}; function hashchange() { try { if (futureHashChange === location.hash) { futureHashChange = null; } else { var stateJSON = location.hash.substring(location.hash.indexOf("#") + 1); if (stateJSON.charAt(0) != '"') { stateJSON = decodeURI(stateJSON); } stateJSON = stateJSON.substring(1); state = new State($.parseJSON(stateJSON || '{}')).validate(); } } catch(e) {alert("Error hashchange");alert(e);} } // ==== JavaScript Style général function jss() { try { var w = $(window).width(); var h = $(window).height(); var iconSize; if (h > 600) iconSize = 72; else if(h > 500) iconSize = 48; else iconSize = 36; $('#nojs').hide(); $('#message:visible') .css({ position: 'absolute', borderWidth: 'thin', borderStyle: 'solid', MozBorderRadius: 10, WebkitBorderRadius: 10, textAlign: 'center' }) .width(w*0.5) .fitFont(w/2, h*0.1) .center({left: w/2, top:h*0.1}); $("#"+state.screen+".screen") .wh(w, h) .northWest({top:0,left:0}); $("body, html") .css({ padding: 0, margin: 0, overflow: "hidden", textAlign: "left" }); $(".clearboth").css('clear', 'both'); $(".screen").hide(); $("#"+state.screen+".screen").show(); if (window[state.screen] && window[state.screen].jss) window[state.screen].jss(w, h, iconSize); $("img.icon").each(function(i,e) { try { e=$(e); if (typeof(e.data('image')) != 'undefined') e.attr("src", "ressources/img/"+iconSize+"/"+e.data('image')+".png"); } catch(e) {alert("Error anonymous in jss");alert(e);} }); } catch(e) {alert("Error jss");alert(e);} } // ==== Interface Android function UI () { try { if (typeof(PtiClicAndroid) != "undefined") { return PtiClicAndroid; } else { return { isAndroid: function() { return false; }, setPreference: function() {}, getPreference: function() {return "";}, show: function(title, text) {}, dismiss: function() {}, exit: function() {}, log: function(msg) { try { window.console && console.log(msg); } catch(e) {alert("Error UI().log");alert(e);} }, info: function(title, msg) { try { $('#message') .qCss('opacity',0) .qShow() .queue(function(next){ $('#message') .text(msg); jss(); next(); }) .animate({opacity:0.9}, 700) .delay(5000) .animate({opacity:0}, 700); } catch(e) {alert("Error UI().info");alert(e);} }, setScreen: function() {} }; } } catch(e) {alert("Error UI");alert(e);} } // ==== Code métier général $(function() { try { $(window).resize(jss); $(window).hashchange(hashchange); hashchange(); } catch(e) {alert("Error main function");alert(e);} }); // ==== Asynchronous Javascript And Json. ajaj = {}; ajaj.request = function(url, data, okFunction, smallErrorFunction, bigErrorFunction) { smallErrorFunction = smallErrorFunction || ajaj.smallError; bigErrorFunction = bigErrorFunction || ajaj.bigError; var user = UI().getPreference("user"); var passwd = UI().getPreference("passwd"); if (user != '' && passwd != '') { // TODO : on transfère le user/passwd à chaque fois ici… c'est pas très bon. data = $.extend({user:user, passwd:passwd}, data); } try { return $.getJSON(url, data, function(data) { if (data && data.isError) { smallErrorFunction(data); } else { okFunction(data); } }).error(bigErrorFunction); } catch(e) {alert("Error ajaj.request");alert(e);} } ajaj.smallError = function(x) { try { if (x.error == 10) { state.set('screen', 'connection').commit().validate(); } else { ajaj.error( "Erreur fatale. Merci de nous envoyer ce message : \n" + "Erreur signalée par le serveur\n" + "Code:"+x.error+"\n" + "Message:"+x.msg+"\n" ); } } catch(e) {alert("Error ajaj.smallError");alert(e);} } ajaj.bigError = function(x) { try { ajaj.error( "Erreur fatale. Merci de nous envoyer ce message : \n" + "Erreur de transmission\n" + "Code:"+x.status+"\n" + "État:"+x.statusText+"\n" + "Message:"+x.responseText.substring(0,20)+" ("+x.responseText.length+")" ); } catch(e) {alert("Error ajaj.bigError");alert(e);} } ajaj.error = function(msg) { try { UI().dismiss(); UI().info("Erreur !", msg); UI().exit(); } catch(e) {alert("Error ajaj.error");alert(e);} } // ==== Code métier pour le splash splash = {}; splash.jss = function(w,h,iconSize) { try { var splashW = 320; var splashH = 480; var ratio = Math.min(w / splashW, h / splashH); $('#splash.screen img') .wh(splashW * ratio, splashH * ratio) .center($('#splash.screen').center()); } catch(e) {alert("Error splash.jss");alert(e);} } splash.enter = function() { try { // Si l'application est déjà chargée, on zappe directement jusqu'à la frontpage. if (runstate.skipSplash) { splash.click.goFrontpage(); } else { runstate.skipSplash = true; jss(); $('#splash.screen').clickOnce(splash.click.goFrontpage); } } catch(e) {alert("Error splash.enter");alert(e);} } splash.click = {}; splash.click.goFrontpage = function() { try { UI().show("PtiClic", "Chargement…"); state.set('screen', 'frontpage').validate(); } catch(e) {alert("Error splash.click.goFrontpage");alert(e);} }; // ==== Code métier pour la frontpage frontpage = {}; frontpage.jss = function(w, h, iconSize) { try { var fp = $("#frontpage.screen"); var $fp = function() { try { return fp.find.apply(fp,arguments); } catch(e) {alert("Error anonymous 1 in frontpage.jss");alert(e);} }; var nbIcons = $fp(".icon").size(); var nbRows = Math.ceil(nbIcons / 2) var ww = w - 2 * iconSize; var hh = h - nbRows * iconSize; var titleHeight = hh*0.4; var labelHeight = hh*0.4 / nbRows; var buttonPadding = hh*0.05/nbRows; var buttonHeight = labelHeight + iconSize + buttonPadding; var buttonWidth = Math.max(w*0.25,iconSize); var freeSpace = h - titleHeight; $fp("#title-block") .wh(w*0.5, titleHeight) .north($("#frontpage.screen").north()); $fp("#title") .fitIn("#title-block", 0.2); $fp(".text") .fitFont(buttonWidth, labelHeight, 10); $fp(".icon") .wh(iconSize); $fp(".game .icon").data('image', 'mode_normal'); $fp(".prefs .icon").data('image', 'config'); $fp(".connection .icon").data('image', 'config'); $fp(".info .icon").data('image', 'aide'); $fp(".frontpage-button") .css({ textAlign: 'center', paddingTop: buttonPadding }) .width(buttonWidth); $fp(".frontpage-button > div").css('display', 'block'); var interIconSpace = (freeSpace - nbRows * buttonHeight) / (nbRows + 1); $fp(".frontpage-button").each(function(i,e){ try { e=$(e); var currentRow = Math.floor(i/2); var currentColumn = i % 2; var iconOffset = titleHeight + ((currentRow+1) * interIconSpace) + (currentRow * buttonHeight); if (currentColumn == 0) { e.northEast({left:w/2-ww*0.05,top:iconOffset}); } else { e.northWest({left:w/2+ww*0.05,top:iconOffset}); } } catch(e) {alert("Error anonymous 2 in frontpage.jss");alert(e);} }); } catch(e) {alert("Error frontpage.jss");alert(e);} }; frontpage.enter = function () { try { if (location.hash != '') state.commit(); $("#frontpage .frontpage-button.game").clickOnce(frontpage.click.goGame); $("#frontpage .frontpage-button.connection").clickOnce(frontpage.click.goConnection); $("#frontpage .frontpage-button.info").clickOnce(frontpage.click.goInfo); $("#frontpage .frontpage-button.prefs").clickOnce(frontpage.click.goPrefs); jss(); UI().dismiss(); } catch(e) {alert("Error frontpage.enter");alert(e);} }; frontpage.click = {}; frontpage.click.goGame = function(){ try { state.set('screen', 'game').validate(); } catch(e) {alert("Error frontpage.click.goGame");alert(e);} }; frontpage.click.goConnection = function() { try { UI().show("PtiClic", "Chargement…"); state.set('screen', 'connection').commit().validate(); } catch(e) {alert("Error frontpage.click.goConnection");alert(e);} }; frontpage.click.goInfo = function() { try { UI().show("PtiClic", "Chargement…"); state.set('screen', 'info').commit().validate(); } catch(e) {alert("Error frontpage.click.goInfo");alert(e);} }; frontpage.click.goPrefs = function() { try { UI().show("PtiClic", "Chargement…"); state.set('screen', 'prefs').commit().validate(); } catch(e) {alert("Error frontpage.click.goPrefs");alert(e);} }; // ==== Code métier pour le jeu game = {}; game.jss = function(w, h, iconSize) { try { var g = $("#game.screen"); var $g = function() { try { return g.find.apply(g,arguments); } catch(e) {alert("Error anonymous in game.jss");alert(e);} }; var mch = h/8, mnh = h*0.075; $g("#mc-caption-block") .wh(w, mch) .north(g.north()); $g("#mc-caption") .fitIn("#mc-caption-block", 0.1); $g("#mn-caption-block") .css({ borderWidth: h/100, borderStyle: 'solid none' }) .wh(w, mnh) .north($g("#mc-caption-block").south()); $g("#mn-caption") .css({zIndex: 10}) .fitIn("#mn-caption-block"); $g(".relationBox:visible") .css({ margin: 10, padding: 10, MozBorderRadius: 10, WebkitBorderRadius: 10, borderWidth: 'thin', borderStyle: 'solid', }); $g(".relationBox:visible .icon") .wh(iconSize,iconSize) .css({ float: "left", marginRight: $g(".relationBox").css("padding-left") }); $g(".relations") .width(w); $g(".relation:visible").fitFont($g(".relationBox:visible").width(), iconSize, 10); $g(".relations") .south(g.south()); } catch(e) {alert("Error game.jss");alert(e);} }; game.enter = function () { try { if (!state.game) { var notAlreadyFetching = !runstate.gameFetched || runstate.gameFetched == nullFunction; runstate.gameFetched = function(data) { try { state.game = data; state.currentWordNb = 0; state.game.answers = []; state.commit(); game.buildUi(); } catch(e) {alert("Error anonymous 1 in game.enter");alert(e);} }; if (notAlreadyFetching) { UI().show("PtiClic", "Récupération de la partie"); ajaj.request("getGame.php?callback=?", { nonce:Math.random() }, function(data) { try { var fn = runstate.gameFetched; runstate.gameFetched = false; fn(data); } catch(e) {alert("Error anonymous 2 in game.enter");alert(e);} }); } } else { game.buildUi(); } } catch(e) {alert("Error game.enter");alert(e);} }; game.leave = function () { try { $("#game .relations").empty(); $('#game #mn-caption').stop().clearQueue(); if (runstate.gameFetched) runstate.gameFetched = nullFunction; } catch(e) {alert("Error game.leave");alert(e);} }; game.buildUi = function () { try { $("#game .relations").empty(); $.each(state.game.relations, function(i, relation) { try { $('#templates .relationBox') .clone() .data("rid", relation.id) .find(".text") .html(relation.name.replace(/%(m[cn])/g, '')) .end() .find(".icon") .data("image",relation.id) .end() .click(function(e) { try { game.nextWord({left:e.pageX, top:e.pageY}, this); } catch(e) {alert("Error anonymous 2 click in game.buildUi");alert(e);} }) .appendTo("#game .relations"); } catch(e) {alert("Error anonymous 1 in game.buildUi");alert(e);} }); game.updateText(); } catch(e) {alert("Error game.buildUi");alert(e);} } game.updateText = function() { try { $("#game .mn").text(state.game.cloud[state.currentWordNb].name); $("#game .mc").text(state.game.center.name); jss(); UI().dismiss(); } catch(e) {alert("Error game.updateText");alert(e);} } game.animateNext = function (click, button) { try { var duration = 700; var mn = $("#game #mn-caption"); $(button).addClass("hot").removeClass("hot", duration); (mn) .stop() // Attention : stop() et clearQueue() ont aussi un effet .clearQueue() // sur la 2e utilisation de mn (ci-dessous). .clone() .removeClass("mn") // Pour que le texte animé ne soit pas modifié. .appendTo("body") // Append to body so we can animate the offset (instead of top/left). .offset(mn.offset()) .animate({left:click.left, top:click.top, fontSize: 0}, duration) .queue(function() { try { $(this).remove(); } catch(e) {alert("Error anonymous 1 in game.animateNext");alert(e);} }); game.updateText(); var fs = mn.css("fontSize"); var mncbCenter = $("#game #mn-caption-block").center(); (mn) .css("fontSize", 0) .animate({fontSize: fs}, {duration:duration, step:function(){ try { mn.center(mncbCenter); } catch(e) {alert("Error anonymous 2 in game.animateNext");alert(e);} }}); } catch(e) {alert("Error game.animateNext");alert(e);} } game.nextWord = function(click, button) { try { state.game.answers[state.currentWordNb++] = $(button).data("rid"); if (state.currentWordNb < state.game.cloud.length) { game.animateNext(click, button); state.commit(); } else { state.set('screen','score').validate(); } } catch(e) {alert("Error game.nextWord");alert(e);} } // ==== Code métier pour les scores score = {}; score.jss = function(w, h, iconSize) { try { $("#score.screen") .css('text-align', 'center'); } catch(e) {alert("Error score.jss");alert(e);} }; score.enter = function () { try { if (!state.hasScore) { var notAlreadyFetching = !runstate.scoreFetched || runstate.scoreFetched == nullFunction; runstate.scoreFetched = function(data) { try { for (var i = 0; i < data.scores.length; ++i) { state.game.cloud[i].score = data.scores[i]; } delete data.score; $.extend(state.game, data); state.hasScore = true; state.commit(); score.ui(); } catch(e) {alert("Error anonymous 1 in score.enter");alert(e);} }; if (notAlreadyFetching) { UI().show("PtiClic", "Calcul de votre score"); ajaj.request("server.php?callback=?", { action: 1, pgid: state.game.pgid, gid: state.game.gid, answers: state.game.answers, nonce: Math.random() }, function(data){ try { var fn = runstate.scoreFetched; runstate.scoreFetched = false; fn(data); } catch(e) {alert("Error anonymous 2 in score.enter");alert(e);} }); } } else { score.ui(); } jss(); } catch(e) {alert("Error score.enter");alert(e);} } score.leave = function () { try { if (runstate.scoreFetched) runstate.scoreFetched = nullFunction; $("#score .scores").empty(); $("#templates .scoreTotal").empty(); } catch(e) {alert("Error score.leave");alert(e);} }; score.ui = function () { try { $("#score .scores").empty(); $("#score .scoreTotal") .text(state.game.scoreTotal) .goodBad(state.game.minScore*state.game.cloud.length,state.game.maxScore*state.game.cloud.length,{r:255,g:0,b:0},{r:0,g:192,b:0}); $.each(state.game.cloud, function(i,e) { try { $("#templates .scoreLine") .clone() .find(".word") .text(e.name) .end() .find(".score") .text(e.score) .goodBad(state.game.minScore,state.game.maxScore,{r:255,g:0,b:0},{r:0,g:192,b:0}) .end() .appendTo("#score .scores"); } catch(e) {alert("Error anonymous 1 in score.ui");alert(e);} }); $("#score #jaivu").clickOnce(score.click.jaivu); jss(); UI().dismiss(); } catch(e) {alert("Error score.ui");alert(e);} } score.click = {}; score.click.jaivu = function() { try { state = new State().validate(); } catch(e) {alert("Error score.click.jaivu");alert(e);} }; // ==== Code métier pour la page d'info info = {}; info.jss = function(w,h,iconSize) { $("#info-back-p").css('text-align', 'center'); $("#info.screen .container input").css('font-size', 'inherit'); $("#info.screen .container") .fitFont(w*0.9, h*0.9, null, null, true) .center($("#info.screen")); } info.enter = function() { try { $("#info-back").clickOnce(info.click.goBack); jss(); UI().dismiss(); } catch(e) {alert("Error info.enter");alert(e);} }; info.click = {}; info.click.goBack = function(){ try { state.set('screen', 'frontpage').validate(); } catch(e) {alert("Error anonymous in info.enter");alert(e);} }; // ==== Code métier pour la connexion connection = {}; connection.jss = function(w, h, iconSize) { try { var c = $("#connection.screen"); var $c = function() { try { return c.find.apply(c,arguments); } catch(e) {alert("Error anonymous 1 in connection.jss");alert(e);} }; $c("input, label") .css("white-space", "nowrap") .css('position', 'absolute') .fitFont(w*0.45, h*0.06, null, null, true, true); $c("#user-label").east({left:w*0.475,top:h*0.25}); $c("#user").west({left:w*0.525,top:h*0.25}); $c("#passwd-label").east({left:w*0.475,top:h*0.5}); $c("#passwd").west({left:w*0.525,top:h*0.5}); $c("#connect").center({left:w/2,top:h*0.75}); } catch(e) {alert("Error connection.jss");alert(e);} }; connection.enter = function() { try { $("#connect-form").unbind("submit", connection.connect).submit(connection.connect); jss(); UI().dismiss(); } catch(e) {alert("Error connection.enter");alert(e);} }; connection.connect = function() { try { UI().setPreference("user", $("#user").val()); UI().setPreference("passwd", $("#passwd").val()); ajaj.request("server.php?callback=?", { action: 3, user: $("#user").val(), passwd: $("#passwd").val(), }, connection.connectFetched, connection.connectFetched); return false; } catch(e) {alert("Error connection.connect");alert(e);} } connection.connectFetched = function(data) { try { if (data && data.loginOk) { UI().info("Connexion", "Vous êtes connecté !"); } else if (data && data.isError && data.error == 3) { UI().info("Connexion", data.msg); } else { ajaj.smallError(data); } state.set('screen', 'frontpage').validate(); } catch(e) {alert("Error connection.connectFetched");alert(e);} } // ==== Code métier pour la page de configuration prefs = {}; prefs.jss = function(w,h,iconSize) { try { var p = $("#prefs.screen"); var $p = function() { try { return p.find.apply(p,arguments); } catch(e) {alert("Error anonymous 1 in prefs.jss");alert(e);} }; $("input, label, select") .css('position', 'absolute') .fitFont(w*0.45, h*0.06, null, null, true, true); $p("#theme-label").east({left:w*0.475,top:h*0.25}); $p("#theme").west({left:w*0.525,top:h*0.25}); $p("#prefs-cancel").east({left:w*0.475,top:h*0.5}); $p("#prefs-apply").west({left:w*0.525,top:h*0.5}); } catch(e) {alert("Error prefs.jss");alert(e);} } prefs.enter = function() { try { $("#prefs-form").unbind('submit', prefs.apply).submit(prefs.apply); $("#prefs-cancel").clickOnce(prefs.cancel); jss(); UI().dismiss(); } catch(e) {alert("Error prefs.enter");alert(e);} }; prefs.apply = function(){ try { var newtheme = $("#theme").val(); ajaj.request("server.php?callback=?", { action: 8, key: 'theme', value: newtheme }, function(data) { if (data) UI().info("Préférences", "Les préférences ont été enregistrées."); else UI().info("Préférences", "Les préférences n'ont pas pu être enregistrées."); }); $("link[@rel*=stylesheet][title]").each(function(i,e){ // Il semblerait que pour qu'un "aleternate stylesheet" puisse être activé, il faut d'abord qu'il ait été désactivé… e.disabled = true; e.disabled = (e.getAttribute('title') != newtheme); }); state.set('screen', 'frontpage').validate(); return false; } catch(e) {alert("Error anonymous in prefs.apply");alert(e);} }; function switchStylestyle(styleName) { } prefs.cancel = function(){ try { state.set('screen', 'frontpage').validate(); } catch(e) {alert("Error anonymous in prefs.cancel");alert(e);} };