script.js (10141B)
1 /* http://chrissilich.com/blog/convert-em-size-to-pixels-with-jquery/ */ 2 function em2px(n) { 3 var emSize = parseFloat($("body").css("font-size")); 4 return (emSize * n); 5 } 6 7 function htmlentities(x) { 8 return $('<div/>').text(x).html(); 9 } 10 11 function onlydigits(x) { 12 return String(x).replace(/[^0-9]/, ''); 13 } 14 15 function showCustom(a) { 16 if (a) { 17 document.getElementById("custom_template").style.display = "block"; 18 } else { 19 document.getElementById("custom_template").style.display = "none"; 20 } 21 } 22 23 function reportError(msg) { 24 if (lang == "fr") { 25 var message = ("Impossible de vérifier le poème faute de pouvoir " 26 + "communiquer avec le serveur p;: "); 27 } else { 28 var message = ("Could not check poem due to error when " 29 + "communicating with server: "); 30 } 31 $( "#status" ).html("<span class=\"error\">" + message + msg + "</span>"); 32 } 33 34 var setForCustom = false; 35 36 function setUnload() { 37 window.onbeforeunload = function() { 38 if (lang == "fr") { 39 return ("Votre poème sera perdu en fermant cette page."); 40 } else { 41 return ("Your poem will be lost when closing this page."); 42 } 43 }; 44 } 45 46 function toggleUnload() { 47 if ($('#poem').val().length > 10) { 48 setUnload(); 49 } else { 50 if (!setForCustom) { 51 window.onbeforeunload = null; 52 } 53 } 54 } 55 56 function setCustom() { 57 setForCustom = true; 58 setUnload(); 59 } 60 61 function getAvail() { 62 var avail = $( window ).height() - $( '#lcontainer' ).offset().top - em2px(4) - $( '#tools' ).height() - $( '#predef' ).height(); 63 if ($( '#user_template' ).is(":visible")) { 64 avail -= em2px(.5); 65 } 66 if ($( window ).width() <= 650) { 67 avail -= em2px(1); 68 } 69 return avail; 70 } 71 72 function sanitize(e) { 73 var avail = getAvail(); 74 var h1 = $( '#poem' ).height(); 75 var h2 = $( '#user_template' ).height(); 76 var h3 = $( '#cerrors' ).height(); 77 if (h1 > avail) { 78 $( '#poem' ).height(avail); 79 h1 = avail; 80 } 81 if (h2 > avail) { 82 $( '#user_template' ).height(avail); 83 h2 = avail; 84 } 85 if (h3 > avail) { 86 $( '#cerrors' ).height(avail); 87 h3 = avail; 88 } 89 } 90 91 var poem_h, poem_w, user_template_h, user_template_w; 92 93 function resizeCErrors(e) { 94 // resize in width 95 var twidth = $( window ).width() - $( '#poem' ).width() - em2px(2); 96 if (twidth > 50) { 97 $( '#cerrors' ).width(twidth); 98 } 99 100 if ($( window ).width() > 650) { 101 /* stretch cerrors */ 102 $( '#cerrors' ).height($( window ).height() - $( '#cerrors' ).offset().top - em2px(1)); 103 } 104 if ($( window ).width() <= 650) { 105 // everyone takes full width 106 $( '#cerrors' ).width($( window ).width() - em2px(2)); 107 $( '#user_template' ).width($( window ).width() - em2px(2)); 108 $( '#poem' ).width($( window ).width() - em2px(2)); 109 $( '#lcontainer' ).width($( window ).width() - em2px(2)); 110 } 111 // store the sizes (see resizeAllLast function) 112 // following http://stackoverflow.com/a/7055197 113 poem_h = $( '#poem' ).height(); 114 poem_w = $( '#poem' ).width(); 115 user_template_h = $( '#user_template' ).height(); 116 user_template_w = $( '#user_template' ).width(); 117 } 118 119 function resizeAllPoem(e) { 120 if ($( '#poem' ).height() == poem_h && $( '#poem' ).width() == poem_w) { 121 // nothing changed 122 return; 123 } 124 sanitize(e); 125 var avail = getAvail(); 126 var h1 = $( '#poem' ).height(); 127 avail -= h1; 128 var h2 = $( '#user_template' ).height(); 129 var h3 = $( '#cerrors' ).height(); 130 if (!($( '#user_template' ).is(":visible")) && ($( window ).width() > 650)) { 131 /* silly, just take the entire height */ 132 $( '#poem' ).height(avail + h1); 133 } else { 134 if ($( window ).width() <= 650) { 135 /* fix user_template, use the rest for cerrors*/ 136 if ($( '#user_template' ).is(":visible")) { 137 avail -= h2; 138 } 139 $( '#cerrors' ).height(0.1 + avail); 140 } else { 141 /* use the rest for user_template */ 142 $( '#user_template' ).height(0.1 + avail); 143 } 144 } 145 // resize in width 146 $( '#user_template' ).width($( '#poem' ).width()); 147 $( '#lcontainer' ).width($( '#poem' ).width()); 148 resizeCErrors(e); 149 } 150 151 function resizeAllUserTemplate(e) { 152 if ($( '#user_template' ).height() == user_template_h && $( '#user_template' ).width() == user_template_w) { 153 // nothing changed 154 return; 155 } 156 sanitize(e); 157 var avail = getAvail(); 158 var h1 = $( '#poem' ).height(); 159 var h2 = $( '#user_template' ).height(); 160 var h3 = $( '#cerrors' ).height(); 161 avail -= h2; 162 /* share what remains among other elements */ 163 var used = h1 + 0.01; 164 if ($( window ).width() <= 650) { 165 used += h3; 166 } 167 $( '#poem' ).height(h1 * avail/used); 168 if ($( window ).width() <= 650) { 169 $( '#cerrors' ).height(0.1 + h3 * avail/used); 170 } 171 // resize in width 172 $( '#poem' ).width($( '#user_template' ).width()); 173 $( '#lcontainer' ).width($( '#user_template' ).width()); 174 resizeCErrors(e); 175 } 176 177 function resizeAll(e) { 178 sanitize(e); 179 var avail = getAvail(); 180 var h1 = $( '#poem' ).height(); 181 var h2 = $( '#user_template' ).height(); 182 var h3 = $( '#cerrors' ).height(); 183 /* just scale existing proportions */ 184 var used = h1 + 0.01; 185 if ($( '#user_template' ).is(":visible")) { 186 used += h2; 187 } 188 if ($( window ).width() <= 650) { 189 used += h3; 190 } 191 $( '#poem' ).height(h1 * avail/used); 192 if ($( '#user_template' ).is(":visible")) { 193 $( '#user_template' ).height(0.1 + h2 * avail/used); 194 } 195 if ($( window ).width() <= 650) { 196 $( '#cerrors' ).height(0.1 + h3 * avail/used); 197 } 198 resizeCErrors(e); 199 } 200 201 function resizeAllLast(e) { 202 // chrome does not fire mouseup when it happens outside of the element 203 // and does not fire mousedown when resizing 204 // https://code.google.com/p/chromium/issues/detail?id=453023 205 // so we have to detect mouseups globally 206 // and figure out who was resized 207 // by comparing against stored sizes... 208 if ($( '#poem' ).height() != poem_h || $( '#poem' ).width() != poem_w) { 209 resizeAllPoem(); 210 } else if ($( '#user_template' ).height() != user_template_h || $( '#user_template' ).width() != user_template_w) { 211 resizeAllUserTemplate(); 212 } else { 213 // we can't figure it out (or the mouseup is irrelevant) 214 // run resizeAll 215 resizeAll(); 216 } 217 } 218 219 window.onresize = resizeAll; 220 window.onload = resizeAll; 221 222 function check() { 223 $( "#status" ).html("Checking..."); 224 $('#check').prop( "disabled", true); 225 var poem = $( '#poem' ).val(); 226 var mydata = { 227 'poem': poem, 228 'template': $( '#predef' ).val() 229 }; 230 if (mydata['template'] == 'custom') { 231 mydata['custom_template'] = $( "#user_template" ).val(); 232 } 233 $.ajax({ 234 url: "checkjs", 235 type: "post", 236 data: mydata, 237 error: function (jqxhr, stat, error) { 238 reportError(htmlentities(stat) + 239 (error.length > 0 ? ": " + htmlentities(error) : "")); 240 $('#check').prop( "disabled", false); 241 // do not keep old errors around lest the user may miss the problem 242 $( "#errors" ).empty(); 243 }, 244 success: function (data) { 245 if ("error" in data) { 246 $( "#status" ).html("<span class=\"error\">" + htmlentities(data.error) + "</span>"); 247 $( "#errors" ).empty(); 248 } else { 249 $( "#errors" ).empty(); 250 for (var i = 0; i < data.result.length; i++) { 251 var err = data.result[i]; 252 for (var j = 0; j < err.errors.length; j++) { 253 err.errors[j] = htmlentities(err.errors[j]); 254 } 255 $( "#errors" ).append("<li onclick=\"gotoLine(" + onlydigits(err.num) + ")\">" + 256 "<p>" + (lang == "fr" 257 ? "Erreurs pour la ligne " 258 : "Errors for line ") 259 + onlydigits(err.num) + ":</p>" + 260 "<blockquote>" + htmlentities(err.line) + "</blockquote>" + 261 "<pre>" + err.errors.join("<br />") + "</pre></li>"); 262 } 263 if (data.result.length > 0) { 264 var agreement = (data.result.length == 1 ? "" : "s"); 265 var msg = data.result.length; 266 if (lang == "fr") { 267 msg += (" erreur" + agreement + " trouvée" + agreement 268 + " en validant le poème !"); 269 } else { 270 msg += (" error" + agreement 271 + " found when validating poem" + "!"); 272 } 273 $( "#status" ).html("<span class=\"error\">" + msg + "</span>"); 274 } else { 275 if (lang == "fr") { 276 var msg = "Poème conforme au modèle !"; 277 } else { 278 var msg = "Poem validated against template!"; 279 } 280 $( "#status" ).html("<span class=\"success\">" + msg + "</span>"); 281 } 282 } 283 $('#check').prop( "disabled", false); 284 } 285 }); 286 } 287 288 function loadPredef() { 289 var predef = $( '#predef' ).val(); 290 if (predef == "custom") 291 return; 292 $('#predef option[value="custom"]').prop('selected', true) 293 $.ajax({ 294 url: "static/tpl/" + predef + ".tpl", 295 type: "get", 296 error: function (jqxhr, stat, error) { 297 reportError(htmlentities(stat) + 298 (error.length > 0 ? ": " + htmlentities(error) : "")); 299 }, 300 success: function (data) { 301 $( '#user_template' ).val(htmlentities(data)); 302 $('#user_template').show(); 303 $('#customize').prop("disabled", true); 304 resizeAll(); 305 } 306 }); 307 } 308 309 function toggleCustom() { 310 if ($( '#predef' ).val() == 'custom') { 311 $('#user_template').show(); 312 $('#customize').prop( "disabled", true); 313 } else { 314 $('#user_template').hide(); 315 $('#customize').prop("disabled", false); 316 } 317 resizeAll(); 318 } 319 320 function gotoLine(l) { 321 var pos = 0; 322 var lines = $( '#poem' ).val().split('\n'); 323 for (var i = 0; i < l - 1; i++) 324 pos += lines[i].length + "\n".length; 325 $( '#poem' ).caretTo(pos); 326 } 327 328 /* http://stackoverflow.com/a/7055239 */ 329 jQuery(document).ready(function(){ 330 $( '#user_template' ).mouseup(function(){ 331 resizeAllUserTemplate(); 332 }); 333 $( '#user_template' ).dblclick(function(){ 334 resizeAllUserTemplate(); 335 }); 336 $( '#poem' ).mouseup(function(){ 337 resizeAllPoem(); 338 }); 339 $( '#poem' ).dblclick(function(){ 340 resizeAllPoem(); 341 }); 342 $(document).mouseup(function() { 343 resizeAllLast(); 344 }); 345 resizeAll(); 346 }); 347 348 $(document).load(function(e) { 349 setTimeout(function () { 350 $(window).resize(); 351 }, 100); 352 }); 353