pticlic.js (14561B)
1 // ==== Code métier général 2 function init(fn) { 3 $(window).queue('init', function(next) {fn(); next();}); 4 } 5 6 $.ajaj = function(url, data, dfd, retryCheck, callback) { 7 dfd = dfd || $.Deferred(); 8 var user = '' + UI().getPreference("user"); 9 var passwd = '' + UI().getPreference("passwd"); 10 user = runstate.user || user; 11 passwd = runstate.passwd || passwd; 12 if (user && passwd) { 13 if (!data.user) data.user = user; 14 if (!data.passwd) data.passwd = passwd; 15 } 16 var fromScreen = state.screen; 17 if (callback) return $.getJSON(url, data, callback); 18 return $.getJSON(url, data, function(data) { 19 if (data.isError) { 20 isConnected(false); 21 dfd.reject(data); 22 message("Erreur", data.msg); 23 if ((data.error == 10 || data.error == 3) && state.screen == fromScreen && (!retryCheck || retryCheck())) { 24 $.screen('connection').trigger('goto'); 25 } else if (runstate.screen == fromScreen) { 26 $.screen('frontpage').trigger('goto'); 27 } 28 } else { 29 isConnected(true); 30 dfd.resolve(data); 31 } 32 }).fail(function(data) { 33 isConnected(false); 34 dfd.reject(data); 35 $("#frontpage").trigger('goto'); 36 message("Erreur", "Une erreur est survenue, veuillez nous en excuser."); 37 }); 38 }; 39 40 $(function() { 41 var lastWinSize = $(window).wh(); 42 $(window).dequeue('init'); 43 $(window).resize($.debounce(function resizeJSS() { 44 if (lastWinSize.width != $(window).width() || lastWinSize.height != $(window).height()) { 45 lastWinSize = $(window).wh(); 46 hashchange(); 47 } 48 })); 49 $(window).hashchange(hashchange); 50 hashchange(); 51 runstate.loaded = true; 52 }); 53 54 // ==== URL persistantes et passage d'un écran à l'autre 55 var runstate = { screen: 'none' }; 56 var state = decodeHash(""); 57 var oldstate = decodeHash(""); 58 59 init(function() { 60 $('.screen').live('goto', function() { 61 var screen = this.id; 62 if (screen == '') return; 63 // Afficher "Chargement…" 64 /* location.hash = "#" + screen; */ 65 $.screen(runstate.screen).trigger('leave').hide(); 66 runstate.screen = screen; 67 UI().setScreen(screen); 68 $(this).trigger('pre-enter'); 69 }); 70 71 $('.screen').live('pre-enter', function() { 72 $(this).trigger('enter'); 73 }); 74 75 $('.screen').live('enter', function() { 76 $(this).show(); 77 $(this).trigger('update'); 78 }); 79 80 $('.screen').live('update', function() { 81 jss(); 82 }); 83 84 $('.screen').live('leave', function() { 85 $(this).hide(); 86 }); 87 }); 88 89 $.screen = function (name) { 90 return $(document.getElementById(name)).filter('.screen'); 91 } 92 93 function hashchange() { 94 oldstate = state; 95 state = decodeHash(location.hash); 96 $.screen(state.screen).trigger(state.screen != runstate.screen ? "goto" : "update"); 97 } 98 99 // ==== Interface Android™ 100 function UI () { 101 if (typeof(PtiClicAndroid) != "undefined") { 102 return PtiClicAndroid; 103 } else { 104 return { 105 isAndroid: function() { return false; }, 106 setPreference: function() {}, 107 getPreference: function() {return "";}, 108 setScreen: function() {} 109 }; 110 } 111 } 112 113 // ==== Nouveau jss 114 function jss() { 115 var iconSize = 0; 116 if (jss.running) return; 117 jss.running = true; 118 $('body').removeClass().addClass(runstate.prefs.theme); 119 if ($("#splash img").is(':visible')) { 120 var ratio = Math.min($('#splash').width() / 320, $('#splash').height() / 480); 121 $('#splash.screen img') 122 .wh(320 * ratio, 480 * ratio); 123 } 124 if ($('#game.screen').is(':visible')) { 125 var rb = $('#game.screen .relationBox'); 126 var screenHeight = $('#game.screen').height(); 127 var nbRb = rb.size(); 128 129 var calcFreeSpace = function (iconSize) { 130 var rbHeight = (iconSize || 20) + 2*({72:3,48:2,36:1,0:1})[iconSize] + Math.ceil(2*10/72*iconSize); // = iconSize + border + padding 131 return screenHeight - rbHeight*nbRb; 132 }; 133 $.each([72,48,36,0], function(i,is) { 134 iconSize = is; 135 return (calcFreeSpace(is) - (nbRb+1)*5 < Math.max(/*Hauteur min du header :*/70, screenHeight*0.2)); 136 }); 137 var freeSpace = calcFreeSpace(iconSize); 138 var headerHeight = Math.min(screenHeight * 0.35, freeSpace - (nbRb+1)*5); 139 var interRbSpace = (freeSpace - headerHeight) / (nbRb+1); 140 141 $('#game .header').height(headerHeight); 142 $('#game .relations').height(screenHeight - headerHeight).css('top', headerHeight); 143 (rb) 144 .css({ 145 borderWidth: ({72:3,48:2,36:1,0:1})[iconSize], 146 padding: 10/72*iconSize, 147 borderRadius: 20/72*iconSize, 148 marginTop: interRbSpace 149 }) 150 .height(iconSize) 151 .find('img.icon').wh(iconSize).css({paddingRight: 10/72*iconSize}); 152 } 153 $('#frontpage:visible a.fpButton').$each(function(i,e) { 154 var img = e.find('img'); 155 var size = Math.min($('#frontpage').width() * 0.3, $('#frontpage').height() * 0.32 * 0.5); 156 if (size >= 36) iconSize = 36; 157 if (size >= 48) iconSize = 48; 158 if (size >= 72) iconSize = 72; 159 e.find('.icon-label').height($('#frontpage').height() * 0.32 * 0.3); 160 img.css('padding-top', $('#frontpage').height() * 0.32 * 0.06); 161 }); 162 $('.fitFont:visible').$each(function(i,e) { e.fitFont(); }); 163 $('.fitFontGroup:visible').each(function(i,e) { $(e).find('.subFitFont').fitFont(); }); 164 $('.center:visible').$each(function(i,e) { e.center(e.parent().center()); }); 165 $('img.icon:visible').$each(function(i,e){ if(e.data('image') && iconSize) e.attr('src', 'ressources/img/'+iconSize+'/'+e.data('image')+'.png'); e.wh(iconSize); }); 166 if ($('#game.screen').is(':visible')) { 167 $('#game.screen').trigger('update'); 168 } 169 jss.running = false; 170 } 171 172 // ==== Bulle pour les messages 173 init(function() { 174 $('#message').hide(); 175 }); 176 177 function message(title, msg) { 178 $('#message') 179 .qCss('opacity',0).qShow() 180 .queue(function(next){ $('#message .text').text(msg || 'Une erreur est survenue, veuillez nous en excuser.'); jss(); next(); }) 181 .fadeTo(700, 0.9).delay(5000).fadeOut(700); 182 } 183 184 // ==== Écran splash 185 init(function() { 186 $('#splash.screen').click(function(){ $('#frontpage').trigger('goto'); return false; }); 187 window.setTimeout(function() { 188 if (runstate.screen == 'splash') $('#frontpage').trigger('goto'); 189 }, 5000); 190 $('#splash.screen').bind('goto', function(e){ 191 if (runstate.loaded) { 192 $('#frontpage').trigger('goto'); 193 return false; 194 } 195 }); 196 197 }); 198 199 // ==== Écran d'accueil 200 init(function() { 201 $.screen('frontpage').bind('enter', function() { 202 window.document.title = "PtiClic pre-alpha 0.2"; 203 if (runstate.pendingSetPrefs) runstate.pendingSetPrefs(); 204 }); 205 $.screen('frontpage').bind('update', function() { 206 $('.dis-connect').text(isConnected() ? "Déconnexion" : "Connexion"); 207 }); 208 if (UI().isAndroid()) $('#back2site').hide(); 209 $('#frontpage a.fpButton').$each(function(i,e) { 210 e.find('img.icon').data('image', e.attr('href').substring(1)); 211 }); 212 }); 213 214 // ==== Écran connexion 215 function isConnected(arg) { 216 if (typeof arg == 'undefined') { 217 return !!runstate.connected; 218 } else { 219 runstate.connected = !!arg; 220 if (runstate.screen == 'frontpage') $.screen('frontpage').trigger('update'); 221 } 222 } 223 224 init(function() { 225 $('#connection.screen form').submit(function() { 226 runstate.user = $('#user').val(); 227 runstate.passwd = $('#passwd').val(); 228 UI().setPreference('user', runstate.user); 229 UI().setPreference('passwd', runstate.passwd); 230 if (!runstate.pendingSetPrefs) { 231 runstate.pendingGetPrefs(); 232 } 233 if (state.screen == 'game') { 234 $('#game').trigger('goto'); 235 } else if (state.screen == 'score') { 236 $('#score').trigger('goto'); 237 } else if (state.screen == "frontpage") { 238 $.screen('frontpage').trigger('goto'); // Ne devrait jamais être appellé. 239 } else { 240 location.hash = "#frontpage"; 241 } 242 return false; 243 }); 244 245 $('#connection.screen .back').click(function() { 246 if (runstate.pendingSetPrefs) 247 runstate.cancelPendingSetPrefs(); 248 if (state.screen == 'frontpage') $.screen('frontpage').trigger('goto'); 249 }); 250 251 $('a[href="#connection"]').click(function() { 252 if (isConnected()) { 253 UI().setPreference("user", ''); 254 UI().setPreference("passwd", ''); 255 runstate.user = ''; 256 runstate.passwd = ''; 257 $.ajaj("server.php?callback=?", { action: 9 }, null, null, function(data) { 258 isConnected(false); 259 message("Succès", "Vous êtes déconnecté."); 260 loadPrefs({theme:"green"}); 261 }); 262 return false; 263 } 264 }); 265 }); 266 267 // ==== Écran game 268 runstate.gameCache = new Cache(function getGame(k, dfd) { 269 $.ajaj("getGame.php?callback=?", {pgid:k}, dfd, function() { return state.pgid == k; }); 270 }); 271 272 init(function() { 273 var game = $('#game.screen'); 274 $('a[href="#game"]').click(function() { 275 location.hash = '#game/' + $.now(); 276 return false; 277 }); 278 279 game.bind('pre-enter', function() { 280 runstate.gameCache.get(state.pgid).done(function(data) { 281 runstate.game = data; 282 game.trigger('enter'); 283 }); 284 return false; 285 }); 286 287 game.bind('enter', function() { 288 $("#game .relations").empty(); 289 var game = runstate.game; 290 runstate.relationBox = []; 291 $.each(game.relations, function(i, relation) { 292 runstate.relationBox[relation.id] = $('#templates .relationBox') 293 .clone() 294 .find(".text").html(relation.name.replace(/%(m[cn])/g, '<span class="$1"/>')).end() 295 .find(".icon").data("image",relation.id).end() 296 .click(function(e) { 297 var h = appendAnswer(state, relation.id); 298 if (state.answers.length + 1 >= runstate.game.cloud.length) { 299 location.hash = encodeHash($.extend(h, {screen:'score'})); 300 } else { 301 location.hash = encodeHash(h); 302 $(this).addClass("hot"); 303 } 304 return false; 305 }) 306 .appendTo("#game .relations"); 307 }); 308 $("#game .mc").text(game.center.name); 309 }); 310 311 var updating = false; 312 game.bind('update', function() { 313 if (updating) return false; 314 updating = true; 315 if (!runstate.game || state.pgid != runstate.game.pgid) { 316 updating = false; 317 $('#game').trigger('goto'); 318 return; 319 } 320 321 window.document.title = "PtiClic "+(state.answers.length + 1)+' / '+runstate.game.cloud.length; 322 $('.mn').text(runstate.game.cloud[state.answers.length].name); 323 jss(); 324 325 var isForward = (state.answers.length - oldstate.answers.length) >= 0; 326 var rb = runstate.relationBox[(isForward ? state : oldstate).answers[(isForward ? state : oldstate).answers.length - 1]]; 327 328 if (runstate.currentMNCaption && oldstate.screen != 'game') 329 runstate.currentMNCaption.remove(); 330 if (!runstate.currentMNCaption) 331 runstate.currentMNCaption = $('<span class="mn-caption"/>').attr('id', Math.random()); 332 var tmp = runstate.game.cloud[oldstate.answers.length]; 333 var a = runstate.currentMNCaption.text(tmp ? tmp.name : '…'); 334 var b = $('<span class="mn-caption"/>').attr('id', Math.random()).text(runstate.game.cloud[state.answers.length].name); 335 if (!rb || (isForward && (oldstate.screen != 'game' || state.answers.length == oldstate.answers.length))) { 336 isForward = true; 337 a.remove(); 338 a = $(); 339 } 340 if (!isForward) { var c = b; b = a; a = c; } 341 runstate.currentMNCaption = isForward ? b : a; 342 343 a.zoom(rb, '#mn-caption-box', isForward); // De ou vers la relationBox 344 b.zoom('#mn-caption-box', '#mn-caption-box', !isForward); // De ou vers le #mn-caption 345 346 window.setTimeout(function() { 347 $('.relationBox.hot').addClass('transition-bg').removeClass('hot').delay(700).qRemoveClass('transition-bg'); 348 }, 0); 349 350 updating = false; 351 return false; 352 }); 353 354 game.bind('leave', function() { 355 if (runstate.currentMNCaption) runstate.currentMNCaption.remove(); 356 }); 357 }); 358 359 // ==== Écran score 360 runstate.scoreCache = new Cache(function getScore(k, dfd, arg) { 361 $.ajaj("server.php?callback=?", { 362 action: 1, 363 pgid: k, 364 answers: arg, 365 }, dfd, function() { return state.pgid == k; }); 366 }); 367 368 function jAime(aime) { 369 $.ajaj('server.php?callback=?', { 370 pgid: state.pgid, 371 action: 10, 372 value: (aime ? 1 : -1) 373 }); 374 } 375 376 init(function() { 377 var score = $.screen('score'); 378 score.bind('pre-enter', function() { 379 runstate.scoreCache.get(state.pgid, state.answers).done(function(data) { 380 runstate.score = data; 381 score.trigger('enter'); 382 }); 383 return false; 384 }); 385 score.bind('enter', function() { 386 var s = runstate.score; 387 $("#score .scores").empty(); 388 $("#score .scoreTotal") 389 .text(s.scoreTotal) 390 .goodBad(s.minScore*s.scores.length, s.maxScore*s.scores.length, {r:255,g:0,b:0}, {r:0,g:192,b:0}); 391 $.each(s.scores, function(i,e) { 392 $("#templates .scoreLine") 393 .clone() 394 .find(".word").text(e.name).end() 395 .find(".score").text(e.score).goodBad(s.minScore, s.maxScore, {r:255,g:0,b:0}, {r:0,g:192,b:0}).end() 396 .appendTo("#score .scores"); 397 }); 398 }); 399 $('#jaime').click(function() { jAime(true); }); 400 $('#jaimepas').click(function() { jAime(false); }); 401 }); 402 403 // ==== Écran Préférences 404 runstate.prefs = { theme: "green" }; 405 runstate.serverPrefs = $.extend({}, runstate.prefs); 406 407 function loadPrefs(prefs) { 408 var previousTheme = runstate.prefs ? runstate.prefs.theme : 'green'; 409 if (prefs && prefs.theme) { 410 isConnected(prefs.connected); 411 runstate.prefs = prefs; 412 runstate.serverPrefs = $.extend({}, runstate.prefs); 413 if (runstate.loaded && previousTheme != runstate.prefs.theme) jss(); 414 } 415 } 416 417 function setPrefs(prefs, callback) { 418 var dfd = $.Deferred(); 419 $.ajaj("server.php?callback=?", { 420 action: 8, 421 key: 'theme', 422 value: prefs.theme 423 }, dfd); 424 return dfd; 425 } 426 427 runstate.pendingGetPrefs = function() { 428 $.ajaj("server.php?callback=?", { action: 7 }, null, null, function(data) { 429 if (data.theme) { isConnected(true); message("Succès", "Vous êtes connecté."); loadPrefs(data); } 430 if (data.isError) { isConnected(false); message("Erreur", data.msg); } 431 }); 432 }; 433 434 runstate.cancelPendingSetPrefs = function() { 435 runstate.pendingSetPrefs = false; 436 message("Préférences", "Les préférences n'ont pas pu être enregistrées."); 437 }; 438 439 init(function() { 440 $("#prefs").bind('enter', function() { 441 $("#prefs-form input:radio[name=theme]").attr('checked', function(i,val) { 442 return $(this).val() == runstate.prefs.theme; 443 }); 444 }); 445 446 var readPrefs = function() { 447 var newtheme = $("#prefs form input:radio[name=theme]:checked").eq(0).val(); 448 if (runstate.prefs.theme != newtheme) { 449 runstate.prefs.theme = newtheme; 450 jss(); 451 } 452 }; 453 454 $("#prefs form").submit(function() { 455 readPrefs(); 456 var p = $.extend({}, runstate.prefs); 457 runstate.pendingSetPrefs = function() { 458 setPrefs(p) 459 .fail(function(data) { 460 if (!data || (data.error != 10 && data.error != 3)) { 461 message("Erreur", data.msg); 462 runstate.cancelPendingSetPrefs(); 463 } 464 }) 465 .done(function(data) { 466 runstate.pendingSetPrefs = false; 467 loadPrefs(data); 468 message("Préférences", "Les préférences ont été enregistrées."); 469 }); 470 }; 471 location.href = "#frontpage"; 472 return false; 473 }); 474 $("#prefs form").bind('reset', function() { 475 runstate.prefs = $.extend({}, runstate.serverPrefs); 476 location.hash = "#frontpage"; 477 }); 478 $("#prefs form input:radio[name=theme]").bind('change click', readPrefs); 479 });