1var _____WB$wombat$assign$function_____=function(name){return (self._wb_wombat && self._wb_wombat.local_init && self._wb_wombat.local_init(name))||self[name];};if(!self.__WB_pmw){self.__WB_pmw=function(obj){this.__WB_source=obj;return this;}}{ 2let window = _____WB$wombat$assign$function_____("window"); 3let self = _____WB$wombat$assign$function_____("self"); 4let document = _____WB$wombat$assign$function_____("document"); 5let location = _____WB$wombat$assign$function_____("location"); 6let top = _____WB$wombat$assign$function_____("top"); 7let parent = _____WB$wombat$assign$function_____("parent"); 8let frames = _____WB$wombat$assign$function_____("frames"); 9let opens = _____WB$wombat$assign$function_____("opens"); 10/** @license Hyphenator 4.0.0 - client side hyphenation for webbrowsers 11 * Copyright (C) 2011 Mathias Nater, Zürich (mathias at mnn dot ch) 12 * Project and Source hosted on http://code.google.com/p/hyphenator/ 13 * 14 * This JavaScript code is free software: you can redistribute 15 * it and/or modify it under the terms of the GNU Lesser 16 * General Public License (GNU LGPL) as published by the Free Software 17 * Foundation, either version 3 of the License, or (at your option) 18 * any later version. The code is distributed WITHOUT ANY WARRANTY; 19 * without even the implied warranty of MERCHANTABILITY or FITNESS 20 * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. 21 * 22 * As additional permission under GNU GPL version 3 section 7, you 23 * may distribute non-source (e.g., minimized or compacted) forms of 24 * that code without the copy of the GNU GPL normally required by 25 * section 4, provided you include this license notice and a URL 26 * through which recipients can access the Corresponding Source. 27 * 28 * 29 * Hyphenator.js contains code from Bram Steins hypher.js-Project: 30 * https://github.com/bramstein/Hypher 31 * 32 * Code from this project is marked in the source and belongs 33 * to the following license: 34 * 35 * Copyright (c) 2011, Bram Stein 36 * All rights reserved. 37 * 38 * Redistribution and use in source and binary forms, with or without 39 * modification, are permitted provided that the following conditions 40 * are met: 41 * 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. The name of the author may not be used to endorse or promote products 48 * derived from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 51 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 52 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 53 * EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 54 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 55 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 56 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 57 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 58 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 59 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 60 * 61 */ 62 63/* 64 * Comments are jsdoctoolkit formatted. See http://code.google.com/p/jsdoc-toolkit/ 65 */ 66 67/* The following comment is for JSLint: */ 68/*global window, ActiveXObject, unescape */ 69/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, regexp: true, sub: true, newcap: true, immed: true, evil: true, eqeqeq: false */ 70 71 72/** 73 * @constructor 74 * @description Provides all functionality to do hyphenation, except the patterns that are loaded 75 * externally. 76 * @author Mathias Nater, <a href = "mailto:[email protected]">[email protected]</a> 77 * @version X.Y.Z 78 * @namespace Holds all methods and properties 79 * @example 80 * <script src = "Hyphenator.js" type = "text/javascript"></script> 81 * <script type = "text/javascript"> 82 * Hyphenator.run(); 83 * </script> 84 */ 85var Hyphenator = (function (window) { 86 87 var 88 /** 89 * @name Hyphenator-supportedLang 90 * @description 91 * A key-value object that stores supported languages. 92 * The key is the bcp47 code of the language and the value 93 * is the (abbreviated) filename of the pattern file. 94 * @type {Object.<string, string>} 95 * @private 96 * @example 97 * Check if language lang is supported: 98 * if (supportedLang.hasOwnProperty(lang)) 99 */ 100 supportedLang = { 101 'be': 'be.js', 102 'ca': 'ca.js', 103 'cs': 'cs.js', 104 'da': 'da.js', 105 'bn': 'bn.js', 106 'de': 'de.js', 107 'el': 'el-monoton.js', 108 'el-monoton': 'el-monoton.js', 109 'el-polyton': 'el-polyton.js', 110 'en': 'en-us.js', 111 'en-gb': 'en-gb.js', 112 'en-us': 'en-us.js', 113 'es': 'es.js', 114 'fi': 'fi.js', 115 'fr': 'fr.js', 116 'grc': 'grc.js', 117 'gu': 'gu.js', 118 'hi': 'hi.js', 119 'hu': 'hu.js', 120 'hy': 'hy.js', 121 'it': 'it.js', 122 'kn': 'kn.js', 123 'la': 'la.js', 124 'lt': 'lt.js', 125 'lv': 'lv.js', 126 'ml': 'ml.js', 127 'nb': 'nb-no.js', 128 'no': 'nb-no.js', 129 'nb-no': 'nb-no.js', 130 'nl': 'nl.js', 131 'or': 'or.js', 132 'pa': 'pa.js', 133 'pl': 'pl.js', 134 'pt': 'pt.js', 135 'ru': 'ru.js', 136 'sk': 'sk.js', 137 'sl': 'sl.js', 138 'sv': 'sv.js', 139 'ta': 'ta.js', 140 'te': 'te.js',
141 'tr': 'tr.js', 142 'uk': 'uk.js' 143 }, 144 145 /** 146 * @name Hyphenator-languageHint 147 * @description 148 * An automatically generated string to be displayed in a prompt if the language can't be guessed. 149 * The string is generated using the supportedLang-object. 150 * @see Hyphenator-supportedLang 151 * @type {string} 152 * @private 153 * @see Hyphenator-autoSetMainLanguage 154 */ 155 156 languageHint = (function () { 157 var k, r = ''; 158 for (k in supportedLang) { 159 if (supportedLang.hasOwnProperty(k)) { 160 r += k + ', '; 161 } 162 } 163 r = r.substring(0, r.length - 2); 164 return r; 165 }()), 166 167 /** 168 * @name Hyphenator-prompterStrings 169 * @description 170 * A key-value object holding the strings to be displayed if the language can't be guessed 171 * If you add hyphenation patterns change this string. 172 * @type {Object.<string,string>} 173 * @private 174 * @see Hyphenator-autoSetMainLanguage 175 */ 176 prompterStrings = { 177 'be': 'Ðова гÑÑага ÑайÑа не можа бÑÑÑ Ð²ÑзнаÑÐ°Ð½Ñ Ð°ÑÑамаÑÑÑна. ÐÐ°Ð»Ñ Ð»Ð°Ñка пакажÑÑе мовÑ:', 178 'cs': 'Jazyk této internetové stránky nebyl automaticky rozpoznán. UrÄete prosÃm jejà jazyk:', 179 'da': 'Denne websides sprog kunne ikke bestemmes. Angiv venligst sprog:', 180 'de': 'Die Sprache dieser Webseite konnte nicht automatisch bestimmt werden. Bitte Sprache angeben:', 181 'en': 'The language of this website could not be determined automatically. Please indicate the main language:', 182 'es': 'El idioma del sitio no pudo determinarse autom%E1ticamente. Por favor, indique el idioma principal:', 183 'fi': 'Sivun kielt%E4 ei tunnistettu automaattisesti. M%E4%E4rit%E4 sivun p%E4%E4kieli:', 184 'fr': 'La langue de ce site n%u2019a pas pu %EAtre d%E9termin%E9e automatiquement. Veuillez indiquer une langue, s.v.p.%A0:', 185 'hu': 'A weboldal nyelvét nem sikerült automatikusan megállapÃtani. Kérem adja meg a nyelvet:', 186 'hy': 'ÕÕ°Õ¡Õ»Õ¸Õ²Õ¾Õ¥Ö Õ°Õ¡ÕµÕ¿Õ¶Õ¡Õ¢Õ¥ÖÕ¥Õ¬ Õ¡ÕµÕ½ Õ¯Õ¡ÕµÖÕ« Õ¬Õ¥Õ¦Õ¸ÖÕ¶Ö Ô½Õ¶Õ¤ÖÕ¸ÖÕ´ Õ¥Õ¶Ö Õ¶Õ·Õ¥Ö Õ°Õ«Õ´Õ¶Õ¡Õ¯Õ¡Õ¶ Õ¬Õ¥Õ¦Õ¸ÖÕ¶Õ', 187 'it': 'Lingua del sito sconosciuta. Indicare una lingua, per favore:', 188 'kn': 'à²à²¾à²² ತಾಣದ à²à²¾à²·à³à²¯à²¨à³à²¨à³ ನಿರà³à²§à²°à²¿à²¸à²²à³ ಸಾಧà³à²¯à²µà²¾à²à³à²¤à³à²¤à²¿à²²à³à²². ದಯವಿà²à³à²à³ ಮà³à²à³à²¯ à²à²¾à²·à³à²¯à²¨à³à²¨à³ ಸà³à²à²¿à²¸à²¿:', 189 'lt': 'Nepavyko automatiÅ¡kai nustatyti Å¡ios svetainÄs kalbos. PraÅ¡ome įvesti kalbÄ :', 190 'lv': 'Å Ä«s lapas valodu nevarÄja noteikt automÄtiski. LÅ«dzu norÄdiet pamata valodu:', 191 'ml': 'à´ à´µàµ%u0D2C%u0D4D%u200Cà´¸àµà´±àµà´±à´¿à´¨àµà´±àµ à´à´¾à´· à´à´£àµà´àµà´ªà´¿à´à´¿à´¯àµà´àµà´à´¾%u0D28%u0D4D%u200D à´à´´à´¿à´àµà´à´¿à´²àµà´². à´à´¾à´· à´à´¤à´¾à´£àµà´¨àµà´¨àµ തിരà´àµà´àµà´àµà´àµà´àµà´:', 192 'nl': 'De taal van deze website kan niet automatisch worden bepaald. Geef de hoofdtaal op:', 193 'no': 'Nettstedets sprÃ¥k kunne ikke finnes automatisk. Vennligst oppgi sprÃ¥k:', 194 'pt': 'A lÃngua deste site não pôde ser determinada automaticamente. Por favor indique a lÃngua principal:', 195 'ru': 'ЯзÑк ÑÑого ÑайÑа не Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¾Ð¿Ñеделен авÑомаÑиÑеÑки. ÐожалÑйÑÑа ÑкажиÑе ÑзÑк:', 196 'sl': 'Jezika te spletne strani ni bilo mogoÄe samodejno doloÄiti. Prosim navedite jezik:', 197 'sv': 'Spr%E5ket p%E5 den h%E4r webbplatsen kunde inte avg%F6ras automatiskt. V%E4nligen ange:', 198 'tr': 'Bu web sitesinin dili otomatik olarak tespit edilememiÅtir. Lütfen dökümanın dilini seçiniz%A0:', 199 'uk': 'Ðова ÑÑого веб-ÑайÑÑ Ð½Ðµ може бÑÑи визнаÑена авÑомаÑиÑно. ÐÑÐ´Ñ Ð»Ð°Ñка, вкажÑÑÑ Ð³Ð¾Ð»Ð¾Ð²Ð½Ñ Ð¼Ð¾Ð²Ñ:' 200 }, 201 202 /** 203 * @name Hyphenator-basePath 204 * @description 205 * A string storing the basepath from where Hyphenator.js was loaded. 206 * This is used to load the patternfiles. 207 * The basepath is determined dynamically by searching all script-tags for Hyphenator.js 208 * If the path cannot be determined http://hyphenator.googlecode.com/svn/trunk/ is used as fallback. 209 * @type {string} 210 * @private 211 * @see Hyphenator-loadPatterns 212 */ 213 basePath = (function () { 214 var s = document.getElementsByTagName('script'), i = 0, p, src, t; 215 while (!!(t = s[i++])) { 216 if (!t.src) { 217 continue; 218 } 219 src = t.src; 220 p = src.indexOf('Hyphenator.js'); 221 if (p !== -1) { 222 return src.substring(0, p); 223 } 224 } 225 return 'http://hyphenator.googlecode.com/svn/trunk/'; 226 }()), 227 228 /** 229 * @name Hyphenator-isLocal 230 * @description 231 * isLocal is true, if Hyphenator is loaded from the same domain, as the webpage, but false, if 232 * it's loaded from an external source (i.e. directly from google.code) 233 */ 234 isLocal = (function () { 235 var re = false;
236 if (window.location.href.indexOf(basePath) !== -1) { 237 re = true; 238 } 239 return re; 240 }()), 241 242 /** 243 * @name Hyphenator-documentLoaded 244 * @description 245 * documentLoaded is true, when the DOM has been loaded. This is set by runOnContentLoaded 246 */ 247 documentLoaded = false, 248 documentCount = 0, 249 250 /** 251 * @name Hyphenator-persistentConfig 252 * @description 253 * if persistentConfig is set to true (defaults to false), config options and the state of the 254 * toggleBox are stored in DOM-storage (according to the storage-setting). So they haven't to be 255 * set for each page. 256 */ 257 persistentConfig = false, 258 259 /** 260 * @name Hyphenator-contextWindow 261 * @description 262 * contextWindow stores the window for the document to be hyphenated. 263 * If there are frames this will change. 264 * So use contextWindow instead of window! 265 */ 266 contextWindow = window, 267 268 /** 269 * @name Hyphenator-doFrames 270 * @description 271 * switch to control if frames/iframes should be hyphenated, too 272 * defaults to false (frames are a bag of hurt!) 273 */ 274 doFrames = false, 275 276 /** 277 * @name Hyphenator-dontHyphenate 278 * @description 279 * A key-value object containing all html-tags whose content should not be hyphenated 280 * @type {Object.<string,boolean>} 281 * @private 282 * @see Hyphenator-hyphenateElement 283 */ 284 dontHyphenate = {'script': true, 'code': true, 'pre': true, 'img': true, 'br': true, 'samp': true, 'kbd': true, 'var': true, 'abbr': true, 'acronym': true, 'sub': true, 'sup': true, 'button': true, 'option': true, 'label': true, 'textarea': true, 'input': true, 'math': true, 'svg': true}, 285 286 /** 287 * @name Hyphenator-enableCache 288 * @description 289 * A variable to set if caching is enabled or not 290 * @type boolean 291 * @default true 292 * @private 293 * @see Hyphenator.config 294 * @see hyphenateWord 295 */ 296 enableCache = true, 297 298 /** 299 * @name Hyphenator-storageType 300 * @description 301 * A variable to define what html5-DOM-Storage-Method is used ('none', 'local' or 'session') 302 * @type {string} 303 * @default 'none' 304 * @private 305 * @see Hyphenator.config 306 */ 307 storageType = 'local', 308 309 /** 310 * @name Hyphenator-storage 311 * @description 312 * An alias to the storage-Method defined in storageType. 313 * Set by Hyphenator.run() 314 * @type {Object|undefined} 315 * @default null 316 * @private 317 * @see Hyphenator.run 318 */ 319 storage, 320 321 /** 322 * @name Hyphenator-enableReducedPatternSet 323 * @description 324 * A variable to set if storing the used patterns is set 325 * @type boolean 326 * @default false 327 * @private 328 * @see Hyphenator.config 329 * @see hyphenateWord 330 * @see Hyphenator.getRedPatternSet 331 */ 332 enableReducedPatternSet = false, 333 334 /** 335 * @name Hyphenator-enableRemoteLoading 336 * @description 337 * A variable to set if pattern files should be loaded remotely or not 338 * @type boolean 339 * @default true 340 * @private 341 * @see Hyphenator.config 342 * @see Hyphenator-loadPatterns 343 */ 344 enableRemoteLoading = true, 345 346 /** 347 * @name Hyphenator-displayToggleBox 348 * @description 349 * A variable to set if the togglebox should be displayed or not 350 * @type boolean 351 * @default false 352 * @private 353 * @see Hyphenator.config 354 * @see Hyphenator-toggleBox 355 */ 356 displayToggleBox = false, 357 358 /** 359 * @name Hyphenator-css3 360 * @description 361 * A variable to set if css3 hyphenation should be used 362 * @type boolean 363 * @default false 364 * @private 365 * @see Hyphenator.config 366 */ 367 css3 = false, 368 /** 369 * @name Hyphenator-css3_hsupport 370 * @description 371 * A generated object containing information for CSS3-hyphenation support 372 * { 373 * support: boolean, 374 * property: <the property name to access hyphen-settings>, 375 * languages: <an object containing supported languages> 376 * } 377 * @type object 378 * @default undefined 379 * @private 380 * @see Hyphenator-css3_gethsupport 381 */ 382 css3_h9n, 383 /** 384 * @name Hyphenator-css3_gethsupport 385 * @description 386 * This function sets Hyphenator-css3_h9n for the current UA 387 * @type function 388 * @private 389 * @see Hyphenator-css3_h9n 390 */ 391 css3_gethsupport = function () { 392 var s, 393 ua = navigator.userAgent, 394 r = { 395 support: false, 396 property: '', 397 languages: {} 398 }; 399 if (window.getComputedStyle) { 400 s = window.getComputedStyle(window.document.getElementsByTagName('body')[0]); 401 } else { 402 //ancient Browser don't support CSS3 anyway 403 css3_h9n = r; 404 return; 405 } 406 if (ua.indexOf('Chrome') !== -1) { 407 //Chrome actually knows -webkit-hyphens but does no hyphenation 408 r.support = false;
409 } else if ((ua.indexOf('Safari') !== -1) && (s['-webkit-hyphens'] !== undefined)) { 410 r.support = true; 411 r.property = '-webkit-hyphens'; 412 if (ua.indexOf('Mobile') !== -1) { 413 //iOS only hyphenates in systemlanguage 414 r.languages[navigator.language.split('-')[0]] = true; 415 } else { 416 //Desktop Safari only hyphenates some languages: 417 r.languages = { 418 de: true, 419 en: true, 420 es: true, 421 fr: true, 422 it: true, 423 nl: true, 424 ru: true, 425 zh: true 426 }; 427 } 428 } else if ((ua.indexOf('Firefox') !== -1) && (s['MozHyphens'] !== undefined)) { 429 r.support = true; 430 r.property = 'MozHyphens'; 431 r.languages = { 432 en: true 433 }; 434 } 435 css3_h9n = r; 436 }, 437 438 /** 439 * @name Hyphenator-hyphenateClass 440 * @description 441 * A string containing the css-class-name for the hyphenate class 442 * @type {string} 443 * @default 'hyphenate' 444 * @private 445 * @example 446 * <p class = "hyphenate">Text</p> 447 * @see Hyphenator.config 448 */ 449 hyphenateClass = 'hyphenate', 450 451 /** 452 * @name Hyphenator-dontHyphenateClass 453 * @description 454 * A string containing the css-class-name for elements that should not be hyphenated 455 * @type {string} 456 * @default 'donthyphenate' 457 * @private 458 * @example 459 * <p class = "donthyphenate">Text</p> 460 * @see Hyphenator.config 461 */ 462 dontHyphenateClass = 'donthyphenate', 463 464 /** 465 * @name Hyphenator-min 466 * @description 467 * A number wich indicates the minimal length of words to hyphenate. 468 * @type {number} 469 * @default 6 470 * @private 471 * @see Hyphenator.config 472 */ 473 min = 6, 474 475 /** 476 * @name Hyphenator-orphanControl 477 * @description 478 * Control how the last words of a line are handled: 479 * level 1 (default): last word is hyphenated 480 * level 2: last word is not hyphenated 481 * level 3: last word is not hyphenated and last space is non breaking 482 * @type {number} 483 * @default 1 484 * @private 485 */ 486 orphanControl = 1, 487 488 /** 489 * @name Hyphenator-isBookmarklet 490 * @description 491 * Indicates if Hyphanetor runs as bookmarklet or not. 492 * @type boolean 493 * @default false 494 * @private 495 */ 496 isBookmarklet = (function () { 497 var loc = null, re = false, jsArray = document.getElementsByTagName('script'), i, l; 498 for (i = 0, l = jsArray.length; i < l; i++) { 499 if (!!jsArray[i].getAttribute('src')) { 500 loc = jsArray[i].getAttribute('src'); 501 } 502 if (!loc) { 503 continue; 504 } else if (loc.indexOf('Hyphenator.js?bm=true') !== -1) { 505 re = true; 506 } 507 } 508 return re; 509 }()), 510 511 /** 512 * @name Hyphenator-mainLanguage 513 * @description 514 * The general language of the document. In contrast to {@link Hyphenator-defaultLanguage}, 515 * mainLanguage is defined by the client (i.e. by the html or by a prompt). 516 * @type {string|null} 517 * @private 518 * @see Hyphenator-autoSetMainLanguage 519 */ 520 mainLanguage = null, 521 522 /** 523 * @name Hyphenator-defaultLanguage 524 * @description 525 * The language defined by the developper. This language setting is defined by a config option. 526 * It is overwritten by any html-lang-attribute and only taken in count, when no such attribute can 527 * be found (i.e. just before the prompt). 528 * @type {string|null} 529 * @private 530 * @see Hyphenator-autoSetMainLanguage 531 */ 532 defaultLanguage = '', 533 534 535 /** 536 * @name Hyphenator-elements 537 * @description 538 * An array holding all elements that have to be hyphenated. This var is filled by 539 * {@link Hyphenator-gatherDocumentInfos} 540 * @type {Array} 541 * @private 542 */ 543 elements = (function () { 544 var Element = function (element, data) { 545 this.element = element; 546 this.hyphenated = false; 547 this.treated = false; //collected but not hyphenated (dohyphenation is off) 548 this.data = data; 549 }, 550 ElementCollection = function () { 551 this.count = 0; 552 this.hyCount = 0; 553 this.list = {}; 554 }; 555 ElementCollection.prototype = { 556 add: function (el, lang, data) { 557 if (!this.list.hasOwnProperty(lang)) { 558 this.list[lang] = []; 559 } 560 this.list[lang].push(new Element(el, data)); 561 this.count += 1; 562 }, 563 each: function (fn) { 564 var k; 565 for (k in this.list) { 566 if (this.list.hasOwnProperty(k)) { 567 fn(k, this.list[k]); 568 } 569 } 570 } 571 }; 572 return new ElementCollection(); 573 }()), 574 575 576 /** 577 * @name Hyphenator-exceptions 578 * @description
579 * An object containing exceptions as comma separated strings for each language. 580 * When the language-objects are loaded, their exceptions are processed, copied here and then deleted. 581 * @see Hyphenator-prepareLanguagesObj 582 * @type {Object} 583 * @private 584 */ 585 exceptions = {}, 586 587 /** 588 * @name Hyphenator-docLanguages 589 * @description 590 * An object holding all languages used in the document. This is filled by 591 * {@link Hyphenator-gatherDocumentInfos} 592 * @type {Object} 593 * @private 594 */ 595 docLanguages = {}, 596 597 /** 598 * @name Hyphenator-state 599 * @description 600 * A number that inidcates the current state of the script 601 * 0: not initialized 602 * 1: loading patterns 603 * 2: ready 604 * 3: hyphenation done 605 * 4: hyphenation removed 606 * @type {number} 607 * @private 608 */ 609 state = 0, 610 611 /** 612 * @name Hyphenator-url 613 * @description 614 * A string containing a RegularExpression to match URL's 615 * @type {string} 616 * @private 617 */ 618 url = '(\\w*:\/\/)?((\\w*:)?(\\w*)@)?((([\\d]{1,3}\\.){3}([\\d]{1,3}))|((www\\.|[a-zA-Z]\\.)?[a-zA-Z0-9\\-\\.]+\\.([a-z]{2,4})))(:\\d*)?(\/[\\w#!:\\.?\\+=&%@!\\-]*)*', 619 // protocoll usr pwd ip or host tld port path 620 /** 621 * @name Hyphenator-mail 622 * @description 623 * A string containing a RegularExpression to match mail-adresses 624 * @type {string} 625 * @private 626 */ 627 mail = '[\\w-\\.]+@[\\w\\.]+', 628 629 /** 630 * @name Hyphenator-urlRE 631 * @description 632 * A RegularExpressions-Object for url- and mail adress matching 633 * @type {RegExp} 634 * @private 635 */ 636 urlOrMailRE = new RegExp('(' + url + ')|(' + mail + ')', 'i'), 637 638 /** 639 * @name Hyphenator-zeroWidthSpace 640 * @description 641 * A string that holds a char. 642 * Depending on the browser, this is the zero with space or an empty string. 643 * zeroWidthSpace is used to break URLs 644 * @type {string} 645 * @private 646 */ 647 zeroWidthSpace = (function () { 648 var zws, ua = navigator.userAgent.toLowerCase(); 649 zws = String.fromCharCode(8203); //Unicode zero width space 650 if (ua.indexOf('msie 6') !== -1) { 651 zws = ''; //IE6 doesn't support zws 652 } 653 if (ua.indexOf('opera') !== -1 && ua.indexOf('version/10.00') !== -1) { 654 zws = ''; //opera 10 on XP doesn't support zws 655 } 656 return zws; 657 }()), 658 659 /** 660 * @name Hyphenator-createElem 661 * @description 662 * A function alias to document.createElementNS or document.createElement 663 * @type {function(string, Object)} 664 * @private 665 */ 666 createElem = function (tagname, context) { 667 context = context || contextWindow; 668 if (document.createElementNS) { 669 return context.document.createElementNS('http://www.w3.org/1999/xhtml', tagname); 670 } else if (document.createElement) { 671 return context.document.createElement(tagname); 672 } 673 }, 674 675 /** 676 * @name Hyphenator-onHyphenationDone 677 * @description 678 * A method to be called, when the last element has been hyphenated or the hyphenation has been 679 * removed from the last element. 680 * @see Hyphenator.config 681 * @type {function()} 682 * @private 683 */ 684 onHyphenationDone = function () {}, 685 686 /** 687 * @name Hyphenator-onError 688 * @description 689 * A function that can be called upon an error. 690 * @see Hyphenator.config 691 * @type {function(Object)} 692 * @private 693 */ 694 onError = function (e) { 695 window.alert("Hyphenator.js says:\n\nAn Error ocurred:\n" + e.message); 696 }, 697 698 /** 699 * @name Hyphenator-selectorFunction 700 * @description 701 * A function that has to return a HTMLNodeList of Elements to be hyphenated. 702 * By default it uses the classname ('hyphenate') to select the elements. 703 * @see Hyphenator.config 704 * @type {function()} 705 * @private 706 */ 707 selectorFunction = function () { 708 var tmp, el = [], i, l; 709 if (document.getElementsByClassName) { 710 el = contextWindow.document.getElementsByClassName(hyphenateClass); 711 } else { 712 tmp = contextWindow.document.getElementsByTagName('*'); 713 l = tmp.length; 714 for (i = 0; i < l; i++) 715 {
716 if (tmp[i].className.indexOf(hyphenateClass) !== -1 && tmp[i].className.indexOf(dontHyphenateClass) === -1) { 717 el.push(tmp[i]); 718 } 719 } 720 } 721 return el; 722 }, 723 724 /** 725 * @name Hyphenator-intermediateState 726 * @description 727 * The value of style.visibility of the text while it is hyphenated. 728 * @see Hyphenator.config 729 * @type {string} 730 * @private 731 */ 732 intermediateState = 'hidden', 733 734 /** 735 * @name Hyphenator-unhide 736 * @description 737 * How hidden elements unhide: either simultaneous (default: 'wait') or progressively. 738 * 'wait' makes Hyphenator.js to wait until all elements are hyphenated (one redraw) 739 * With 'progressiv' Hyphenator.js unhides elements as soon as they are hyphenated. 740 * @see Hyphenator.config 741 * @type {string} 742 * @private 743 */ 744 unhide = 'wait', 745 746 /** 747 * @name Hyphenator-hyphen 748 * @description 749 * A string containing the character for in-word-hyphenation 750 * @type {string} 751 * @default the soft hyphen 752 * @private 753 * @see Hyphenator.config 754 */ 755 hyphen = String.fromCharCode(173), 756 757 /** 758 * @name Hyphenator-urlhyphen 759 * @description 760 * A string containing the character for url/mail-hyphenation 761 * @type {string} 762 * @default the zero width space 763 * @private 764 * @see Hyphenator.config 765 * @see Hyphenator-zeroWidthSpace 766 */ 767 urlhyphen = zeroWidthSpace, 768 769 /** 770 * @name Hyphenator-safeCopy 771 * @description 772 * Defines wether work-around for copy issues is active or not 773 * Not supported by Opera (no onCopy handler) 774 * @type boolean 775 * @default true 776 * @private 777 * @see Hyphenator.config 778 * @see Hyphenator-registerOnCopy 779 */ 780 safeCopy = true, 781 782 783 /* 784 * runOnContentLoaded is based od jQuery.bindReady() 785 * see 786 * jQuery JavaScript Library v1.3.2 787 * http://jquery.com/ 788 * 789 * Copyright (c) 2009 John Resig 790 * Dual licensed under the MIT and GPL licenses. 791 * http://docs.jquery.com/License 792 * 793 * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) 794 * Revision: 6246 795 */ 796 /** 797 * @name Hyphenator-runOnContentLoaded 798 * @description 799 * A crossbrowser solution for the DOMContentLoaded-Event based on jQuery 800 * <a href = "http://jquery.com/</a> 801 * I added some functionality: e.g. support for frames and iframes⦠802 * @param {Object} w the window-object 803 * @param {function()} f the function to call onDOMContentLoaded 804 * @private 805 */ 806 runOnContentLoaded = function (w, f) { 807 var DOMContentLoaded = function () {}, toplevel, hyphRunForThis = {}; 808 if (documentLoaded && !hyphRunForThis[w.location.href]) { 809 f(); 810 hyphRunForThis[w.location.href] = true; 811 return; 812 } 813 function init(context) { 814 contextWindow = context || window; 815 if (!hyphRunForThis[contextWindow.location.href] && (!documentLoaded || contextWindow != window.parent)) { 816 documentLoaded = true; 817 f(); 818 hyphRunForThis[contextWindow.location.href] = true; 819 } 820 } 821 822 function doScrollCheck() { 823 try { 824 // If IE is used, use the trick by Diego Perini 825 // http://javascript.nwbox.com/IEContentLoaded/ 826 document.documentElement.doScroll("left"); 827 } catch (error) { 828 setTimeout(doScrollCheck, 1); 829 return; 830 } 831 832 // and execute any waiting functions 833 init(window); 834 } 835 836 function doOnLoad() { 837 var i, haveAccess, fl = window.frames.length; 838 if (doFrames && fl > 0) { 839 for (i = 0; i < fl; i++) { 840 haveAccess = undefined; 841 //try catch isn't enough for webkit 842 try { 843 //opera throws only on document.toString-access 844 haveAccess = window.frames[i].document.toString(); 845 } catch (e) { 846 haveAccess = undefined; 847 } 848 if (!!haveAccess) { 849 init(window.frames[i]); 850 } 851 } 852 contextWindow = window; 853 f(); 854 hyphRunForThis[window.location.href] = true; 855 } else { 856 init(window); 857 } 858 } 859 860 // Cleanup functions for the document ready method 861 if (document.addEventListener) { 862 DOMContentLoaded = function () { 863 document.removeEventListener("DOMContentLoaded", DOMContentLoaded, false); 864 if (doFrames && window.frames.length > 0) { 865 //we are in a frameset, so do nothing but wait for onload to fire 866 return; 867 } else { 868 init(window); 869 } 870 }; 871 872 } else if (document.attachEvent) { 873 DOMContentLoaded = function () { 874 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). 875 if (document.readyState === "complete") { 876 document.detachEvent("onreadystatechange", DOMContentLoaded); 877 if (doFrames && window.frames.length > 0) { 878 //we are in a frameset, so do nothing but wait for onload to fire 879 return; 880 } else { 881 init(window); 882 } 883 } 884 }; 885 } 886 887 // Mozilla, Opera and webkit nightlies currently support this event 888 if (document.addEventListener) { 889 // Use the handy event callback 890 document.addEventListener("DOMContentLoaded", DOMContentLoaded, false); 891 892 // A fallback to window.onload, that will always work 893 window.addEventListener("load", doOnLoad, false); 894 895 // If IE event model is used 896 } else if (document.attachEvent) { 897 // ensure firing before onload, 898 // maybe late but safe also for iframes 899 document.attachEvent("onreadystatechange", DOMContentLoaded); 900 901 // A fallback to window.onload, that will always work 902 window.attachEvent("onload", doOnLoad); 903 904 // If IE and not a frame 905 // continually check to see if the document is ready 906 toplevel = false;
907 try { 908 toplevel = window.frameElement === null; 909 } catch (e) {} 910 911 if (document.documentElement.doScroll && toplevel) { 912 doScrollCheck(); 913 } 914 } 915 916 }, 917 918 919 920 /** 921 * @name Hyphenator-getLang 922 * @description 923 * Gets the language of an element. If no language is set, it may use the {@link Hyphenator-mainLanguage}. 924 * @param {Object} el The first parameter is an DOM-Element-Object 925 * @param {boolean} fallback The second parameter is a boolean to tell if the function should return the {@link Hyphenator-mainLanguage} 926 * if there's no language found for the element. 927 * @private 928 */ 929 getLang = function (el, fallback) { 930 if (!!el.getAttribute('lang')) { 931 return el.getAttribute('lang').toLowerCase(); 932 } 933 // The following doesn't work in IE due to a bug when getAttribute('xml:lang') in a table 934 /*if (!!el.getAttribute('xml:lang')) { 935 return el.getAttribute('xml:lang').substring(0, 2); 936 }*/ 937 //instead, we have to do this (thanks to borgzor): 938 try { 939 if (!!el.getAttribute('xml:lang')) { 940 return el.getAttribute('xml:lang').toLowerCase(); 941 } 942 } catch (ex) {} 943 if (el.tagName !== 'HTML') { 944 return getLang(el.parentNode, true); 945 } 946 if (fallback) { 947 return mainLanguage; 948 } 949 return null; 950 }, 951 952 /** 953 * @name Hyphenator-autoSetMainLanguage 954 * @description 955 * Retrieves the language of the document from the DOM. 956 * The function looks in the following places: 957 * <ul> 958 * <li>lang-attribute in the html-tag</li> 959 * <li><meta http-equiv = "content-language" content = "xy" /></li> 960 * <li><meta name = "DC.Language" content = "xy" /></li> 961 * <li><meta name = "language" content = "xy" /></li> 962 * </li> 963 * If nothing can be found a prompt using {@link Hyphenator-languageHint} and {@link Hyphenator-prompterStrings} is displayed. 964 * If the retrieved language is in the object {@link Hyphenator-supportedLang} it is copied to {@link Hyphenator-mainLanguage} 965 * @private 966 */ 967 autoSetMainLanguage = function (w) { 968 w = w || contextWindow; 969 var el = w.document.getElementsByTagName('html')[0], 970 m = w.document.getElementsByTagName('meta'), 971 i, text, e, ul; 972 mainLanguage = getLang(el, false); 973 if (!mainLanguage) { 974 for (i = 0; i < m.length; i++) { 975 //<meta http-equiv = "content-language" content="xy"> 976 if (!!m[i].getAttribute('http-equiv') && (m[i].getAttribute('http-equiv').toLowerCase() === 'content-language')) { 977 mainLanguage = m[i].getAttribute('content').toLowerCase(); 978 } 979 //<meta name = "DC.Language" content="xy"> 980 if (!!m[i].getAttribute('name') && (m[i].getAttribute('name').toLowerCase() === 'dc.language')) { 981 mainLanguage = m[i].getAttribute('content').toLowerCase(); 982 } 983 //<meta name = "language" content = "xy"> 984 if (!!m[i].getAttribute('name') && (m[i].getAttribute('name').toLowerCase() === 'language')) { 985 mainLanguage = m[i].getAttribute('content').toLowerCase(); 986 } 987 } 988 } 989 //get lang for frame from enclosing document 990 if (!mainLanguage && doFrames && contextWindow != window.parent) { 991 autoSetMainLanguage(window.parent); 992 } 993 //fallback to defaultLang if set 994 if (!mainLanguage && defaultLanguage !== '') { 995 mainLanguage = defaultLanguage; 996 } 997 //ask user for lang 998 if (!mainLanguage) { 999 text = ''; 1000 ul = navigator.language ? navigator.language : navigator.userLanguage; 1001 ul = ul.substring(0, 2); 1002 if (prompterStrings.hasOwnProperty(ul)) { 1003 text = prompterStrings[ul]; 1004 } else { 1005 text = prompterStrings.en; 1006 } 1007 text += ' (ISO 639-1)\n\n' + languageHint; 1008 mainLanguage = window.prompt(unescape(text), ul).toLowerCase(); 1009 } 1010 if (!supportedLang.hasOwnProperty(mainLanguage)) { 1011 if (supportedLang.hasOwnProperty(mainLanguage.split('-')[0])) { //try subtag 1012 mainLanguage = mainLanguage.split('-')[0]; 1013 } else { 1014 e = new Error('The language "' + mainLanguage + '" is not yet supported.'); 1015 throw e; 1016 } 1017 } 1018 }, 1019 1020 /** 1021 * @name Hyphenator-gatherDocumentInfos 1022 * @description 1023 * This method runs through the DOM and executes the process()-function on: 1024 * - every node returned by the {@link Hyphenator-selectorFunction}. 1025 * The process()-function copies the element to the elements-variable, sets its visibility 1026 * to intermediateState, retrieves its language and recursivly desce
1026nds the DOM-tree until 1027 * the child-Nodes aren't of type 1 1028 * @private 1029 */ 1030 gatherDocumentInfos = function () { 1031 var elToProcess, tmp, i = 0, 1032 process = function (el, hide, lang) { 1033 var n, i = 0, hyphenatorSettings = {}; 1034 1035 if (el.lang && typeof(el.lang) === 'string') { 1036 lang = el.lang.toLowerCase(); //copy attribute-lang to internal lang 1037 } else if (lang) { 1038 lang = lang.toLowerCase(); 1039 } else { 1040 lang = getLang(el, true); 1041 } 1042 1043 //if css3-hyphenation is supported: use it! 1044 if (css3 && css3_h9n.support && !!css3_h9n.languages[lang]) { 1045 el.style[css3_h9n.property] = "auto"; 1046 el.style['-webkit-locale'] = "'" + lang + "'"; 1047 } else { 1048 if (intermediateState === 'hidden') { 1049 if (!!el.getAttribute('style')) { 1050 hyphenatorSettings.hasOwnStyle = true; 1051 } else { 1052 hyphenatorSettings.hasOwnStyle = false; 1053 } 1054 hyphenatorSettings.isHidden = true; 1055 el.style.visibility = 'hidden'; 1056 } 1057 if (supportedLang[lang]) { 1058 docLanguages[lang] = true; 1059 } else { 1060 if (supportedLang.hasOwnProperty(lang.split('-')[0])) { //try subtag 1061 lang = lang.split('-')[0]; 1062 hyphenatorSettings.language = lang; 1063 } else if (!isBookmarklet) { 1064 onError(new Error('Language ' + lang + ' is not yet supported.')); 1065 } 1066 } 1067 elements.add(el, lang, hyphenatorSettings); 1068 } 1069 while (!!(n = el.childNodes[i++])) { 1070 if (n.nodeType === 1 && !dontHyphenate[n.nodeName.toLowerCase()] && 1071 n.className.indexOf(dontHyphenateClass) === -1 && !(n in elToProcess)) { 1072 process(n, false, lang); 1073 } 1074 } 1075 }; 1076 if (css3) { 1077 css3_gethsupport(); 1078 } 1079 if (isBookmarklet) { 1080 elToProcess = contextWindow.document.getElementsByTagName('body')[0]; 1081 process(elToProcess, false, mainLanguage); 1082 } else { 1083 elToProcess = selectorFunction(); 1084 while (!!(tmp = elToProcess[i++])) 1085 { 1086 process(tmp, true, ''); 1087 } 1088 } 1089 if (elements.count === 0) { 1090 //nothing to hyphenate or all hyphenated b css3 1091 state = 3; 1092 onHyphenationDone(); 1093 } 1094 }, 1095 1096 1097 /** 1098 * @name Hyphenator-createTrie 1099 * @description 1100 * converts patterns of the given language in a trie 1101 * @private 1102 * @param {string} lang the language whose patterns shall be converted 1103 */ 1104 convertPatterns = function (lang) { 1105 /** @license BSD licenced code 1106 * The following code is based on code from hypher.js and adapted for Hyphenator.js 1107 * Copyright (c) 2011, Bram Stein 1108 */ 1109 var size = 0, 1110 tree = { 1111 tpoints: [] 1112 }, 1113 patterns, pattern, i, j, k, 1114 patternObject = Hyphenator.languages[lang].patterns, 1115 c, chars, points, t, p, codePoint, 1116 getPoints = (function () { 1117 //IE<9 doesn't act like other browsers 1118 if ('in3se'.split(/\D/).length === 1) { 1119 return function (pattern) { 1120 var chars = pattern.split(''), c, i, r = [], 1121 numb3rs = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}, lastWasNum = false; 1122 i = 0; 1123 while (!!(c = chars[i])) { 1124 if (numb3rs.hasOwnProperty(c)) { 1125 r.push(c); 1126 i += 2; 1127 lastWasNum = true; 1128 } else { 1129 r.push(''); 1130 i += 1; 1131 lastWasNum = false; 1132 } 1133 } 1134 if (!lastWasNum) { 1135 r.push(''); 1136 } 1137 return r; 1138 }; 1139 } else { 1140 return function (pattern) { 1141 return pattern.split(/\D/); 1142 }; 1143 } 1144 }()); 1145 1146 for (size in patternObject) { 1147 if (patternObject.hasOwnProperty(size)) { 1148 patterns = patternObject[size].match(new RegExp('.{1,' + (+size) + '}', 'g')); 1149 i = 0; 1150 while (!!(pattern = patterns[i++])) { 1151 chars = pattern.replace(/[\d]/g, '').split(''); 1152 points = getPoints(pattern); 1153 t = tree; 1154 1155 j = 0; 1156 while (!!(c = chars[j++])) { 1157 codePoint = c.charCodeAt(0); 1158 1159 if (!t[codePoint]) { 1160 t[codePoint] = {}; 1161 } 1162 t = t[codePoint]; 1163 } 1164 1165 t.tpoints = []; 1166 for (k = 0; k < points.length; k++) { 1167 p = points[k]; 1168 t.tpoints.push((p == "") ? 0 : p); 1169 } 1170 } 1171 } 1172 } 1173 Hyphenator.languages[lang].patterns = tree; 1174 /** 1175 * end of BSD licenced code from hypher.js 1176 */ 1177 }, 1178 1179 recreatePattern = function (pattern, nodePoints) { 1180 var r = [], c = pattern.split(''), i; 1181 for (i = 0; i < nodePoints.length; i++) { 1182 if (nodePoints[i] !== 0) { 1183 r.push(nodePoints[i]); 1184 } 1185 if (c[i]) { 1186 r.push(c[i]); 1187 } 1188 } 1189 return r.join(''); 1190 }, 1191 1192 /** 1193 * @name Hyphenator-convertExceptionsToObject 1194 * @description 1195 * Converts a list of comma seprated exceptions to an object: 1196 * 'Fortran,Hy-phen-a-tion' -> {'Fortran':'Fortran','Hyphenation':'Hy-phen-a-tion'} 1197 * @private 1198 * @param {string} exc a comma separated string of exceptions (without spaces) 1199 */ 1200 convertExceptionsToObject = function (exc) { 1201 var w = exc.split(', '), 1202 r = {}, 1203 i, l, key; 1204 for (i = 0, l = w.length; i < l; i++) { 1205 key = w[i].replace(/-/g, ''); 1206 if (!r.hasOwnProperty(key)) { 1207 r[key] = w[i]; 1208 } 1209 } 1210 return r; 1211 }, 1212 1213 /** 1214 * @name Hyphenator-loadPatterns 1215 * @description 1216 * Adds a <script>-Tag to the DOM to load an externeal .js-file containing patterns and settings for the given language. 1217 * If the given language is not in the {@link Hyphenator-supportedLang}-Object it returns. 1218 * One may ask why we are not using AJAX to load the patterns. The XMLHttpRequest-Object 1219 * has a same-origin-policy. This makes the isBookmarklet-functionality impossible. 1220 * @param {string} lang The language to load the patterns for 1221 * @private 1222 * @see Hyphenator-basePath 1223 */ 1224 loadPatterns = function (lang) { 1225 var url, xhr, head, script; 1226 if (supportedLang[lang] && !Hyphenator.languages[lang]) { 1227 url = basePath + 'patterns/' + supportedLang[lang]; 1228 } else { 1229 return; 1230 } 1231 if (isLocal && !isBookmarklet) { 1232 //check if 'url' is available: 1233 xhr = null; 1234 if (typeof XMLHttpRequest !== 'undefined') { 1235 xhr = new XMLHttpRequest(); 1236 } 1237 if (!xhr) { 1238 try { 1239 xhr = new ActiveXObject("Msxml2.XMLHTTP"); 1240 } catch (e) { 1241 xhr = null; 1242 } 1243 } 1244 if (xhr) { 1245 xhr.open('HEAD', url, false); 1246 xhr.setRequestHeader('Cache-Control', 'no-cache'); 1247 xhr.send(null); 1248 if (xhr.status === 404) { 1249 onError(new Error('Could not load\n' + url)); 1250 delete docLanguages[lang]; 1251 return; 1252 } 1253 } 1254 } 1255 if (createElem) { 1256 head = window.document.getElementsByTagName('head').item(0); 1257 script = createElem('script', window); 1258 script.src = url; 1259 script.type = 'text/javascript'; 1260 head.appendChild(script); 1261 } 1262 }, 1263 1264 /** 1265 * @name Hyphenator-prepareLanguagesObj 1266 * @description 1267 * Adds a cache to each language and converts the exceptions-list to an object. 1268 * If storage is active the object is stored there. 1269 * @private 1270 * @param {string} lang the language ob the lang-obj 1271 */ 1272 prepareLanguagesObj = function (lang) { 1273 var lo = Hyphenator.languages[lang], wrd; 1274 if (!lo.prepared) { 1275 if (enableCache) { 1276 lo.cache = {}; 1277 //Export 1278 lo['cache'] = lo.cache; 1279 } 1280 if (enableReducedPatternSet) { 1281 lo.redPatSet = {}; 1282 } 1283 //add exceptions from the pattern file to the local 'exceptions'-obj 1284 if (lo.hasOwnProperty('exceptions')) { 1285 Hyphenator.addExceptions(lang, lo.exceptions); 1286 delete lo.exceptions; 1287 } 1288 //copy global exceptions to the language specific exceptions 1289 if (exceptions.hasOwnProperty('global')) { 1290 if (exceptions.hasOwnProperty(lang)) { 1291 exceptions[lang] += ', ' + exceptions.global; 1292 } else { 1293 exceptions[lang] = exceptions.global; 1294 } 1295 } 1296 //move exceptions from the the local 'exceptions'-obj to the 'language'-object 1297 if (exceptions.hasOwnProperty(lang)) { 1298 lo.exceptions = convertExceptionsToObject(exceptions[lang]); 1299 delete exceptions[lang]; 1300 } else { 1301 lo.exceptions = {}; 1302 } 1303 convertPatterns(lang); 1304 wrd = '[\\w' + lo.specialChars + '@' + String.fromCharCode(173) + String.fromCharCode(8204) + '-]{' + min + ',}'; 1305 lo.genRegExp = new RegExp('(' + url + ')|(' + mail + ')|(' + wrd + ')', 'gi'); 1306 lo.prepared = true; 1307 } 1308 if (!!storage) { 1309 try { 1310 storage.setItem('Hyphenator_' + lang, window.JSON.stringify(lo)); 1311 } catch (e) { 1312 //onError(e); 1313 } 1314 } 1315 1316 }, 1317 1318 /** 1319 * @name Hyphenator-prepare 1320 * @description 1321 * This funtion prepares the Hyphenator-Object: If RemoteLoading is turned off, it assumes
1322 * that the patternfiles are loaded, all conversions are made and the callback is called. 1323 * If storage is active the object is retrieved there. 1324 * If RemoteLoading is on (default), it loads the pattern files and waits until they are loaded, 1325 * by repeatedly checking Hyphenator.languages. If a patterfile is loaded the patterns are 1326 * converted to their object style and the lang-object extended. 1327 * Finally the callback is called. 1328 * @private 1329 */ 1330 prepare = function (callback) { 1331 var lang, interval, tmp1, tmp2; 1332 if (!enableRemoteLoading) { 1333 for (lang in Hyphenator.languages) { 1334 if (Hyphenator.languages.hasOwnProperty(lang)) { 1335 prepareLanguagesObj(lang); 1336 } 1337 } 1338 state = 2; 1339 callback('*'); 1340 return; 1341 } 1342 // get all languages that are used and preload the patterns 1343 state = 1; 1344 for (lang in docLanguages) { 1345 if (docLanguages.hasOwnProperty(lang)) { 1346 if (!!storage && storage.getItem('Hyphenator_' + lang)) { 1347 Hyphenator.languages[lang] = window.JSON.parse(storage.getItem('Hyphenator_' + lang)); 1348 if (exceptions.hasOwnProperty('global')) { 1349 tmp1 = convertExceptionsToObject(exceptions.global); 1350 for (tmp2 in tmp1) { 1351 if (tmp1.hasOwnProperty(tmp2)) { 1352 Hyphenator.languages[lang].exceptions[tmp2] = tmp1[tmp2]; 1353 } 1354 } 1355 } 1356 //Replace exceptions since they may have been changed: 1357 if (exceptions.hasOwnProperty(lang)) { 1358 tmp1 = convertExceptionsToObject(exceptions[lang]); 1359 for (tmp2 in tmp1) { 1360 if (tmp1.hasOwnProperty(tmp2)) { 1361 Hyphenator.languages[lang].exceptions[tmp2] = tmp1[tmp2]; 1362 } 1363 } 1364 delete exceptions[lang]; 1365 } 1366 //Replace genRegExp since it may have been changed: 1367 tmp1 = '[\\w' + Hyphenator.languages[lang].specialChars + '@' + String.fromCharCode(173) + String.fromCharCode(8204) + '-]{' + min + ',}'; 1368 Hyphenator.languages[lang].genRegExp = new RegExp('(' + url + ')|(' + mail + ')|(' + tmp1 + ')', 'gi'); 1369 1370 delete docLanguages[lang]; 1371 callback(lang); 1372 continue; 1373 } else { 1374 loadPatterns(lang); 1375 } 1376 } 1377 } 1378 // else async wait until patterns are loaded, then hyphenate 1379 interval = window.setInterval(function () { 1380 var finishedLoading = true, lang; 1381 for (lang in docLanguages) { 1382 if (docLanguages.hasOwnProperty(lang)) { 1383 finishedLoading = false; 1384 if (!!Hyphenator.languages[lang]) { 1385 delete docLanguages[lang]; 1386 //do conversion while other patterns are loading: 1387 prepareLanguagesObj(lang); 1388 callback(lang); 1389 } 1390 } 1391 } 1392 if (finishedLoading) { 1393 //console.log('callig callback for ' + contextWindow.location.href); 1394 window.clearInterval(interval); 1395 state = 2; 1396 } 1397 }, 100); 1398 }, 1399 1400 /** 1401 * @name Hyphenator-switchToggleBox 1402 * @description 1403 * Creates or hides the toggleBox: a small button to turn off/on hyphenation on a page. 1404 * @see Hyphenator.config 1405 * @private 1406 */ 1407 toggleBox = function () { 1408 var myBox, bdy, myIdAttribute, myTextNode, myClassAttribute, 1409 text = (Hyphenator.doHyphenation ? 'Hy-phen-a-tion' : 'Hyphenation'); 1410 if (!!(myBox = contextWindow.document.getElementById('HyphenatorToggleBox'))) { 1411 myBox.firstChild.data = text; 1412 } else { 1413 bdy = contextWindow.document.getElementsByTagName('body')[0]; 1414 myBox = createElem('div', contextWindow); 1415 myIdAttribute = contextWindow.document.createAttribute('id'); 1416 myIdAttribute.nodeValue = 'HyphenatorToggleBox'; 1417 myClassAttribute = contextWindow.document.createAttribute('class'); 1418 myClassAttribute.nodeValue = dontHyphenateClass; 1419 myTextNode = contextWindow.document.createTextNode(text); 1420 myBox.appendChild(myTextNode); 1421 myBox.setAttributeNode(myIdAttribute); 1422 myBox.setAttributeNode(myClassAttribute); 1423 myBox.onclick = Hyphenator.toggleHyphenation; 1424 myBox.style.position = 'absolute'; 1425 myBox.style.top = '0px'; 1426 myBox.style.right = '0px'; 1427 myBox.style.margin = '0'; 1428 myBox.style.backgroundColor = '#AAAAAA'; 1429 myBox.style.color = '#FFFFFF'; 1430 myBox.style.font = '6pt Arial'; 1431 myBox.style.letterSpacing = '0.2em'; 1432 myBox.style.padding = '3px'; 1433 myBox.style.cursor = 'pointer'; 1434 myBox.style.WebkitBorderBottomLeftRadius = '4px'; 1435 myBox.style.MozBorderRadiusBottomleft = '4px'; 1436 bdy.appendChild(myBox); 1437 } 1438 }, 1439 1440 1441 /** 1442 * @name Hyphenator-hyphenateWord 1443 * @description 1444 * This function is the heart of Hyphenator.js. It returns a hyphenated word. 1445 * 1446 * If there's already a {@link Hyphenator-hypen} in the word, the word is returned as it is. 1447 * If the word is in the exceptions list or in the cache, it is retrieved from it. 1448 * If there's a '-' put a zeroWidthSpace after the '-' and hyphenate the parts. 1449 * @param {string} lang The language of the word 1450 * @param {string} word The word 1451 * @returns string The hyphenated word 1452 * @public 1453 */ 1454 hyphenateWord = function (lang, word) { 1455 var lo = Hyphenator.languages[lang], parts, l, subst, 1456 w, characters, originalCharacters, wordLength, i, j, k, node, points = [], 1457 characterPoints = [], nodePoints, nodePointsLength, m = Math.max, trie, 1458 result = [''], pattern; 1459 if (word === '') { 1460 return ''; 1461 } 1462 if (word.indexOf(hyphen) !== -1) { 1463 //word already contains shy; -> leave at it is! 1464 return word; 1465 } 1466 if (enableCache && lo.cache.hasOwnProperty(word)) { //the word is in the cache 1467 return lo.cache[word]; 1468 } 1469 if (lo.exceptions.hasOwnProperty(word)) { //the word is in the exceptions list 1470 return lo.exceptions[word].replace(/-/g, hyphen); 1471 } 1472 if (word.indexOf('-') !== -1) { 1473 //word contains '-' -> hyphenate the parts separated with '-' 1474 parts = word.split('-'); 1475 for (i = 0, l = parts.length; i < l; i++) { 1476 parts[i] = hyphenateWord(lang, parts[i]); 1477 } 1478 return parts.join('-'); 1479 } 1480 w = word = '_' + word + '_'; 1481 if (!!lo.charSubstitution) { 1482 for (subst in lo.charSubstitution) { 1483 if (lo.charSubstitution.hasOwnProperty(subst)) { 1484 w = w.replace(new RegExp(subst, 'g'), lo.charSubstitution[subst]); 1485 } 1486 } 1487 } 1488 if (word.indexOf("'") !== -1) { 1489 w = w.replace("'", "â");
1489 //replace APOSTROPHE with RIGHT SINGLE QUOTATION MARK (since the latter is used in the patterns) 1490 } 1491 /** @license BSD licenced code 1492 * The following code is based on code from hypher.js 1493 * Copyright (c) 2011, Bram Stein 1494 */ 1495 characters = w.toLowerCase().split(''); 1496 originalCharacters = word.split(''); 1497 wordLength = characters.length; 1498 trie = lo.patterns; 1499 for (i = 0; i < wordLength; i += 1) { 1500 points[i] = 0; 1501 characterPoints[i] = characters[i].charCodeAt(0); 1502 } 1503 for (i = 0; i < wordLength; i += 1) { 1504 pattern = ''; 1505 node = trie; 1506 for (j = i; j < wordLength; j += 1) { 1507 node = node[characterPoints[j]]; 1508 if (node) { 1509 if (enableReducedPatternSet) { 1510 pattern += String.fromCharCode(characterPoints[j]); 1511 } 1512 nodePoints = node.tpoints; 1513 if (nodePoints) { 1514 if (enableReducedPatternSet) { 1515 if (!lo.redPatSet) { 1516 lo.redPatSet = {}; 1517 } 1518 lo.redPatSet[pattern] = recreatePattern(pattern, nodePoints); 1519 } 1520 for (k = 0, nodePointsLength = nodePoints.length; k < nodePointsLength; k += 1) { 1521 points[i + k] = m(points[i + k], nodePoints[k]); 1522 } 1523 } 1524 } else { 1525 break; 1526 } 1527 } 1528 } 1529 for (i = 1; i < wordLength - 1; i += 1) { 1530 if (i > lo.leftmin && i < (wordLength - lo.rightmin) && points[i] % 2) { 1531 result.push(originalCharacters[i]); 1532 } else { 1533 result[result.length - 1] += originalCharacters[i]; 1534 } 1535 } 1536 return result.join(hyphen); 1537 /** 1538 * end of BSD licenced code from hypher.js 1539 */ 1540 }, 1541 1542 /** 1543 * @name Hyphenator-hyphenateURL 1544 * @description 1545 * Puts {@link Hyphenator-urlhyphen} after each no-alphanumeric char that my be in a URL. 1546 * @param {string} url to hyphenate 1547 * @returns string the hyphenated URL 1548 * @public 1549 */ 1550 hyphenateURL = function (url) { 1551 return url.replace(/([:\/\.\?#&_,;!@]+)/gi, '$&' + urlhyphen); 1552 }, 1553 1554 /** 1555 * @name Hyphenator-removeHyphenationFromElement 1556 * @description 1557 * Removes all hyphens from the element. If there are other elements, the function is 1558 * called recursively. 1559 * Removing hyphens is usefull if you like to copy text. Some browsers are buggy when the copy hyphenated texts. 1560 * @param {Object} el The element where to remove hyphenation. 1561 * @public 1562 */ 1563 removeHyphenationFromElement = function (el) { 1564 var h, i = 0, n; 1565 switch (hyphen) { 1566 case '|': 1567 h = '\\|'; 1568 break; 1569 case '+': 1570 h = '\\+'; 1571 break; 1572 case '*': 1573 h = '\\*'; 1574 break; 1575 default: 1576 h = hyphen; 1577 } 1578 while (!!(n = el.childNodes[i++])) { 1579 if (n.nodeType === 3) { 1580 n.data = n.data.replace(new RegExp(h, 'g'), ''); 1581 n.data = n.data.replace(new RegExp(zeroWidthSpace, 'g'), ''); 1582 } else if (n.nodeType === 1) { 1583 removeHyphenationFromElement(n); 1584 } 1585 } 1586 }, 1587 1588 1589 /** 1590 * @name Hyphenator-registerOnCopy 1591 * @description 1592 * Huge work-around for browser-inconsistency when it comes to 1593 * copying of hyphenated text. 1594 * The idea behind this code has been provided by http://github.com/aristus/sweet-justice 1595 * sweet-justice is under BSD-License 1596 * @private 1597 */ 1598 registerOnCopy = function (el) { 1599 var body = el.ownerDocument.getElementsByTagName('body')[0], 1600 shadow, 1601 selection, 1602 range, 1603 rangeShadow, 1604 restore, 1605 oncopyHandler = function (e) { 1606 e = e || window.event; 1607 var target = e.target || e.srcElement, 1608 currDoc = target.ownerDocument, 1609 body = currDoc.getElementsByTagName('body')[0], 1610 targetWindow = 'defaultView' in currDoc ? currDoc.defaultView : currDoc.parentWindow; 1611 if (target.tagName && dontHyphenate[target.tagName.toLowerCase()]) { 1612 //Safari needs this 1613 return; 1614 } 1615 //create a hidden shadow element 1616 shadow = currDoc.createElement('div'); 1617 //Moving the element out of the screen doesn't work for IE9 (https://connect.microsoft.com/IE/feedback/details/663981/) 1618 //shadow.style.overflow = 'hidden'; 1619 //shadow.style.position = 'absolute'; 1620 //shadow.style.top = '-5000px'; 1621 //shadow.style.height = '1px'; 1622 //doing this instead: 1623 shadow.style.color = window.getComputedStyle ? targetWindow.getComputedStyle(body).backgroundColor : '#FFFFFF'; 1624 shadow.style.fontSize = '0px'; 1625 body.appendChild(shadow); 1626 if (!!window.getSelection) { 1627 //FF3, Webkit, IE9 1628 e.stopPropagation(); 1629 selection = targetWindow.getSelection(); 1630 range = selection.getRangeAt(0); 1631 shadow.appendChild(range.cloneContents()); 1632 removeHyphenationFromElement(shadow); 1633 selection.selectAllChildren(shadow); 1634 restore = function () { 1635 shadow.parentNode.removeChild(shadow); 1636 selection.removeAllRanges(); //IE9 needs that 1637 selection.addRange(range); 1638 }; 1639 } else { 1640 // IE<9 1641 e.cancelBubble = true; 1642 selection = targetWindow.document.selection; 1643 range = selection.createRange(); 1644 shadow.innerHTML = range.htmlText; 1645 removeHyphenationFromElement(shadow); 1646 rangeShadow = body.createTextRange(); 1647 rangeShadow.moveToElementText(shadow); 1648 rangeShadow.select(); 1649 restore = function () { 1650 shadow.parentNode.removeChild(shadow); 1651 if (range.text !== "") { 1652 range.select(); 1653 } 1654 }; 1655 } 1656 window.setTimeout(restore, 0); 1657 }; 1658 if (!body) { 1659 return; 1660 } 1661 el = el || body; 1662 if (window.addEventListener) { 1663 el.addEventListener("copy", oncopyHandler, true); 1664 } else { 1665 el.attachEvent("oncopy", oncopyHandler); 1666 } 1667 }, 1668 1669 /** 1670 * @name Hyphenator-unhideElement 1671 * @description 1672 * Unhides an element and removes the visibility attr if set by hyphenator 1673 * @param Object The Element object from ElementCollection 1674 * @private 1675 */ 1676 unhideElement = function (elo) { 1677 var el = elo.element, 1678 hyphenatorSettings = elo.data; 1679 el.style.visibility = 'visible'; 1680 elo.data.isHidden = false;
1681 if (!hyphenatorSettings.hasOwnStyle) { 1682 el.setAttribute('style', ''); // without this, removeAttribute doesn't work in Safari (thanks to molily) 1683 el.removeAttribute('style'); 1684 } else { 1685 if (el.style.removeProperty) { 1686 el.style.removeProperty('visibility'); 1687 } else if (el.style.removeAttribute) { // IE 1688 el.style.removeAttribute('visibility'); 1689 } 1690 } 1691 }, 1692 1693 /** 1694 * @name Hyphenator-checkIfAllDone 1695 * @description 1696 * Checks if all Elements are hyphenated, unhides them and fires onHyphenationDone() 1697 * @private 1698 */ 1699 checkIfAllDone = function () { 1700 var allDone = true; 1701 elements.each(function (lang, list) { 1702 var i, l = list.length; 1703 for (i = 0; i < l; i++) { 1704 allDone = allDone && list[i].hyphenated; 1705 if (intermediateState === 'hidden' && unhide === 'wait') { 1706 unhideElement(list[i]); 1707 } 1708 } 1709 }); 1710 if (allDone) { 1711 state = 3; 1712 onHyphenationDone(); 1713 } 1714 }, 1715 1716 1717 /** 1718 * @name Hyphenator-hyphenateElement 1719 * @description 1720 * Takes the content of the given element and - if there's text - replaces the words 1721 * by hyphenated words. If there's another element, the function is called recursively. 1722 * When all words are hyphenated, the visibility of the element is set to 'visible'. 1723 * @param {Object} el The element to hyphenate 1724 * @private 1725 */ 1726 hyphenateElement = function (lang, elo) { 1727 var hyphenatorSettings = elo.data, 1728 el = elo.element, 1729 hyphenate, n, i, 1730 controlOrphans = function (part) { 1731 var h, r; 1732 switch (hyphen) { 1733 case '|': 1734 h = '\\|'; 1735 break; 1736 case '+': 1737 h = '\\+'; 1738 break; 1739 case '*': 1740 h = '\\*'; 1741 break; 1742 default: 1743 h = hyphen; 1744 } 1745 if (orphanControl >= 2) { 1746 //remove hyphen points from last word 1747 r = part.split(' '); 1748 r[1] = r[1].replace(new RegExp(h, 'g'), ''); 1749 r[1] = r[1].replace(new RegExp(zeroWidthSpace, 'g'), ''); 1750 r = r.join(' '); 1751 } 1752 if (orphanControl === 3) { 1753 //replace spaces by non breaking spaces 1754 r = r.replace(/[ ]+/g, String.fromCharCode(160)); 1755 } 1756 return r; 1757 }; 1758 if (Hyphenator.languages.hasOwnProperty(lang)) { 1759 hyphenate = function (word) { 1760 if (!Hyphenator.doHyphenation) { 1761 return word; 1762 } else if (urlOrMailRE.test(word)) { 1763 return hyphenateURL(word); 1764 } else { 1765 return hyphenateWord(lang, word); 1766 } 1767 }; 1768 if (safeCopy && (el.tagName.toLowerCase() !== 'body')) { 1769 registerOnCopy(el); 1770 } 1771 i = 0; 1772 while (!!(n = el.childNodes[i++])) { 1773 if (n.nodeType === 3 && n.data.length >= min) { //type 3 = #text -> hyphenate! 1774 n.data = n.data.replace(Hyphenator.languages[lang].genRegExp, hyphenate); 1775 if (orphanControl !== 1) { 1776 n.data = n.data.replace(/[\S]+ [\S]+$/, controlOrphans); 1777 } 1778 } 1779 } 1780 } 1781 if (hyphenatorSettings.isHidden && intermediateState === 'hidden' && unhide === 'progressive') { 1782 unhideElement(elo); 1783 } 1784 elo.hyphenated = true; 1785 elements.hyCount += 1; 1786 if (elements.count <= elements.hyCount) { 1787 checkIfAllDone(); 1788 } 1789 }, 1790 1791 1792 /** 1793 * @name Hyphenator-hyphenateLanguageElements 1794 * @description 1795 * Calls hyphenateElement() for all elements of the specified language. 1796 * If the language is '*' then all elements are hyphenated. 1797 * This is done with a setTimout 1798 * to prevent a "long running Script"-alert when hyphenating large pages. 1799 * Therefore a tricky bind()-function was necessary. 1800 * @private 1801 */ 1802 hyphenateLanguageElements = function (lang) { 1803 function bind(fun, arg1, arg2) { 1804 return function () { 1805 return fun(arg1, arg2); 1806 }; 1807 } 1808 var el, i, l; 1809 if (lang === '*') { 1810 elements.each(function (lang, langels) { 1811 var i, l = langels.length; 1812 for (i = 0; i < l; i++) { 1813 window.setTimeout(bind(hyphenateElement, lang, langels[i]), 0); 1814 } 1815 }); 1816 } else { 1817 if (elements.list.hasOwnProperty(lang)) { 1818 l = elements.list[lang].length; 1819 for (i = 0; i < l; i++) { 1820 window.setTimeout(bind(hyphenateElement, lang, elements.list[lang][i]), 0); 1821 } 1822 } 1823 } 1824 }, 1825 1826 /** 1827 * @name Hyphenator-removeHyphenationFromDocument 1828 * @description 1829 * Does what it says ;-) 1830 * @private 1831 */ 1832 removeHyphenationFromDocument = function () { 1833 elements.each(function (lang, elo) { 1834 var i, l = elo.length, el; 1835 for (i = 0; i < l; i++) { 1836 removeHyphenationFromElement(elo[i].element); 1837 elo[i].hyphenated = false;
1838 } 1839 }); 1840 state = 4; 1841 }, 1842 1843 /** 1844 * @name Hyphenator-createStorage 1845 * @description 1846 * inits the private var storage depending of the setting in storageType 1847 * and the supported features of the system. 1848 * @private 1849 */ 1850 createStorage = function () { 1851 try { 1852 if (storageType !== 'none' && 1853 typeof(window.localStorage) !== 'undefined' && 1854 typeof(window.sessionStorage) !== 'undefined' && 1855 typeof(window.JSON.stringify) !== 'undefined' && 1856 typeof(window.JSON.parse) !== 'undefined') { 1857 switch (storageType) { 1858 case 'session': 1859 storage = window.sessionStorage; 1860 break; 1861 case 'local': 1862 storage = window.localStorage; 1863 break; 1864 default: 1865 storage = undefined; 1866 break; 1867 } 1868 } 1869 } catch (f) { 1870 //FF throws an error if DOM.storage.enabled is set to false 1871 } 1872 }, 1873 1874 /** 1875 * @name Hyphenator-storeConfiguration 1876 * @description 1877 * Stores the current config-options in DOM-Storage 1878 * @private 1879 */ 1880 storeConfiguration = function () { 1881 if (!storage) { 1882 return; 1883 } 1884 var settings = { 1885 'STORED': true, 1886 'classname': hyphenateClass, 1887 'donthyphenateclassname': dontHyphenateClass, 1888 'minwordlength': min, 1889 'hyphenchar': hyphen, 1890 'urlhyphenchar': urlhyphen, 1891 'togglebox': toggleBox, 1892 'displaytogglebox': displayToggleBox, 1893 'remoteloading': enableRemoteLoading, 1894 'enablecache': enableCache, 1895 'onhyphenationdonecallback': onHyphenationDone, 1896 'onerrorhandler': onError, 1897 'intermediatestate': intermediateState, 1898 'selectorfunction': selectorFunction, 1899 'safecopy': safeCopy, 1900 'doframes': doFrames, 1901 'storagetype': storageType, 1902 'orphancontrol': orphanControl, 1903 'dohyphenation': Hyphenator.doHyphenation, 1904 'persistentconfig': persistentConfig, 1905 'defaultlanguage': defaultLanguage 1906 }; 1907 storage.setItem('Hyphenator_config', window.JSON.stringify(settings)); 1908 }, 1909 1910 /** 1911 * @name Hyphenator-restoreConfiguration 1912 * @description 1913 * Retrieves config-options from DOM-Storage and does configuration accordingly 1914 * @private 1915 */ 1916 restoreConfiguration = function () { 1917 var settings; 1918 if (storage.getItem('Hyphenator_config')) { 1919 settings = window.JSON.parse(storage.getItem('Hyphenator_config')); 1920 Hyphenator.config(settings); 1921 } 1922 }; 1923 1924 return { 1925 1926 /** 1927 * @name Hyphenator.version 1928 * @memberOf Hyphenator 1929 * @description 1930 * String containing the actual version of Hyphenator.js 1931 * [major release].[minor releas].[bugfix release] 1932 * major release: new API, new Features, big changes 1933 * minor release: new languages, improvements 1934 * @public 1935 */ 1936 version: '4.0.0', 1937 1938 /** 1939 * @name Hyphenator.doHyphenation 1940 * @description 1941 * If doHyphenation is set to false (defaults to true), hyphenateDocument() isn't called. 1942 * All other actions are performed. 1943 */ 1944 doHyphenation: true, 1945 1946 /** 1947 * @name Hyphenator.languages 1948 * @memberOf Hyphenator 1949 * @description 1950 * Objects that holds key-value pairs, where key is the language and the value is the 1951 * language-object loaded from (and set by) the pattern file. 1952 * The language object holds the following members: 1953 * <table> 1954 * <tr><th>key</th><th>desc></th></tr> 1955 * <tr><td>leftmin</td><td>The minimum of chars to remain on the old line</td></tr> 1956 * <tr><td>rightmin</td><td>The minimum of chars to go on the new line</td></tr> 1957 * <tr><td>shortestPattern</td><td>The shortes pattern (numbers don't count!)</td></tr> 1958 * <tr><td>longestPattern</td><td>The longest pattern (numbers don't count!)</td></tr> 1959 * <tr><td>specialChars</td><td>Non-ASCII chars in the alphabet.</td></tr> 1960 * <tr><td>patterns</td><td>the patterns</td></tr> 1961 * </table> 1962 * And optionally (or after prepareLanguagesObj() has been called): 1963 * <table> 1964 * <tr><td>exceptions</td><td>Excpetions for the secified language</td></tr> 1965 * </table> 1966 * @public 1967 */ 1968 languages: {}, 1969 1970 1971 /** 1972 * @name Hyphenator.config 1973 * @description 1974 * Config function that takes an object as an argument. The object contains key-value-pairs 1975 * containig Hyphenator-settings. This is a shortcut for calling Hyphenator.set...-Methods. 1976 * @param {Object} obj <table> 1977 * <tr><th>key</th><th>values</th><th>default</th></tr> 1978 * <tr><td>classname</td><td>string</td><td>'hyphenate'</td></tr> 1979 * <tr><td>donthyphenateclassname</td><td>string</td><td>''</td></tr> 1980 * <tr><td>minwordlength</td><td>integer</td><td>6</td></tr> 1981 * <tr><td>
1981hyphenchar</td><td>string</td><td>'&shy;'</td></tr> 1982 * <tr><td>urlhyphenchar</td><td>string</td><td>'zero with space'</td></tr> 1983 * <tr><td>togglebox</td><td>function</td><td>see code</td></tr> 1984 * <tr><td>displaytogglebox</td><td>boolean</td><td>false</td></tr> 1985 * <tr><td>remoteloading</td><td>boolean</td><td>true</td></tr> 1986 * <tr><td>enablecache</td><td>boolean</td><td>true</td></tr> 1987 * <tr><td>enablereducedpatternset</td><td>boolean</td><td>false</td></tr> 1988 * <tr><td>onhyphenationdonecallback</td><td>function</td><td>empty function</td></tr> 1989 * <tr><td>onerrorhandler</td><td>function</td><td>alert(onError)</td></tr> 1990 * <tr><td>intermediatestate</td><td>string</td><td>'hidden'</td></tr> 1991 * <tr><td>selectorfunction</td><td>function</td><td>[â¦]</td></tr> 1992 * <tr><td>safecopy</td><td>boolean</td><td>true</td></tr> 1993 * <tr><td>doframes</td><td>boolean</td><td>false</td></tr> 1994 * <tr><td>storagetype</td><td>string</td><td>'none'</td></tr> 1995 * </table> 1996 * @public 1997 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 1998 * <script type = "text/javascript"> 1999 * Hyphenator.config({'minwordlength':4,'hyphenchar':'|'}); 2000 * Hyphenator.run(); 2001 * </script> 2002 */ 2003 config: function (obj) { 2004 var assert = function (name, type) { 2005 if (typeof obj[name] === type) { 2006 return true; 2007 } else { 2008 onError(new Error('Config onError: ' + name + ' must be of type ' + type)); 2009 return false; 2010 } 2011 }, 2012 key; 2013 2014 if (obj.hasOwnProperty('storagetype')) { 2015 if (assert('storagetype', 'string')) { 2016 storageType = obj.storagetype; 2017 } 2018 if (!storage) { 2019 createStorage(); 2020 } 2021 } 2022 if (!obj.hasOwnProperty('STORED') && storage && obj.hasOwnProperty('persistentconfig') && obj.persistentconfig === true) { 2023 restoreConfiguration(); 2024 } 2025 2026 for (key in obj) { 2027 if (obj.hasOwnProperty(key)) { 2028 switch (key) { 2029 case 'STORED': 2030 break; 2031 case 'classname': 2032 if (assert('classname', 'string')) { 2033 hyphenateClass = obj[key]; 2034 } 2035 break; 2036 case 'donthyphenateclassname': 2037 if (assert('donthyphenateclassname', 'string')) { 2038 dontHyphenateClass = obj[key]; 2039 } 2040 break; 2041 case 'minwordlength': 2042 if (assert('minwordlength', 'number')) { 2043 min = obj[key]; 2044 } 2045 break; 2046 case 'hyphenchar': 2047 if (assert('hyphenchar', 'string')) { 2048 if (obj.hyphenchar === '­') { 2049 obj.hyphenchar = String.fromCharCode(173); 2050 } 2051 hyphen = obj[key]; 2052 } 2053 break; 2054 case 'urlhyphenchar': 2055 if (obj.hasOwnProperty('urlhyphenchar')) { 2056 if (assert('urlhyphenchar', 'string')) { 2057 urlhyphen = obj[key]; 2058 } 2059 } 2060 break; 2061 case 'togglebox': 2062 if (assert('togglebox', 'function')) { 2063 toggleBox = obj[key]; 2064 } 2065 break; 2066 case 'displaytogglebox': 2067 if (assert('displaytogglebox', 'boolean')) { 2068 displayToggleBox = obj[key]; 2069 } 2070 break; 2071 case 'remoteloading': 2072 if (assert('remoteloading', 'boolean')) { 2073 enableRemoteLoading = obj[key]; 2074 } 2075 break; 2076 case 'enablecache': 2077 if (assert('enablecache', 'boolean')) { 2078 enableCache = obj[key]; 2079 } 2080 break; 2081 case 'enablereducedpatternset': 2082 if (assert('enablereducedpatternset', 'boolean')) { 2083 enableReducedPatternSet = obj[key]; 2084 } 2085 break; 2086 case 'onhyphenationdonecallback': 2087 if (assert('onhyphenationdonecallback', 'function')) { 2088 onHyphenationDone = obj[key]; 2089 } 2090 break; 2091 case 'onerrorhandler': 2092 if (assert('onerrorhandler', 'function')) { 2093 onError = obj[key]; 2094 } 2095 break; 2096 case 'intermediatestate': 2097 if (assert('intermediatestate', 'string')) { 2098 intermediateState = obj[key]; 2099 } 2100 break; 2101 case 'selectorfunction': 2102 if (assert('selectorfunction', 'function')) { 2103 selectorFunction = obj[key]; 2104 } 2105 break; 2106 case 'safecopy': 2107 if (assert('safecopy', 'boolean')) { 2108 safeCopy = obj[key]; 2109 } 2110 break; 2111 case 'doframes': 2112 if (assert('doframes', 'boolean')) { 2113 doFrames = obj[key]; 2114 } 2115 break; 2116 case 'storagetype': 2117 if (assert('storagetype', 'string')) { 2118 storageType = obj[key]; 2119 } 2120 break; 2121 case 'orphancontrol': 2122 if (assert('orphancontrol', 'number')) { 2123 orphanControl = obj[key]; 2124 } 2125 break; 2126 case 'dohyphenation': 2127 if (assert('dohyphenation', 'boolean')) { 2128 Hyphenator.doHyphenation = obj[key]; 2129 } 2130 break; 2131 case 'persistentconfig': 2132 if (assert('persistentconfig', 'boolean')) { 2133 persistentConfig = obj[key]; 2134 } 2135 break; 2136 case 'defaultlanguage': 2137 if (assert('defaultlanguage', 'string')) { 2138 defaultLanguage = obj[key]; 2139 } 2140 break; 2141 case 'useCSS3hyphenation': 2142 if (assert('useCSS3hyphenation', 'boolean')) { 2143 css3 = obj[key]; 2144 } 2145 break; 2146 case 'unhide': 2147 if (assert('unhide', 'string')) { 2148 unhide = obj[key]; 2149 } 2150 break; 2151 default: 2152 onError(new Error('Hyphenator.config: property ' + key + ' not known.')); 2153 } 2154 } 2155 } 2156 if (storage && persistentConfig) { 2157 storeConfiguration(); 2158 } 2159 }, 2160 2161 /** 2162 * @name Hyphenator.run
2163 * @description 2164 * Bootstrap function that starts all hyphenation processes when called. 2165 * @public 2166 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 2167 * <script type = "text/javascript"> 2168 * Hyphenator.run(); 2169 * </script> 2170 */ 2171 run: function () { 2172 documentCount = 0; 2173 var process = function () { 2174 try { 2175 if (contextWindow.document.getElementsByTagName('frameset').length > 0) { 2176 return; //we are in a frameset 2177 } 2178 documentCount++; 2179 autoSetMainLanguage(undefined); 2180 gatherDocumentInfos(); 2181 //console.log('preparing for ' + contextWindow.location.href); 2182 prepare(hyphenateLanguageElements); 2183 if (displayToggleBox) { 2184 toggleBox(); 2185 } 2186 } catch (e) { 2187 onError(e); 2188 } 2189 }, i, haveAccess, fl = window.frames.length; 2190 2191 if (!storage) { 2192 createStorage(); 2193 } 2194 if (!documentLoaded && !isBookmarklet) { 2195 runOnContentLoaded(window, process); 2196 } 2197 if (isBookmarklet || documentLoaded) { 2198 if (doFrames && fl > 0) { 2199 for (i = 0; i < fl; i++) { 2200 haveAccess = undefined; 2201 //try catch isn't enough for webkit 2202 try { 2203 //opera throws only on document.toString-access 2204 haveAccess = window.frames[i].document.toString(); 2205 } catch (e) { 2206 haveAccess = undefined; 2207 } 2208 if (!!haveAccess) { 2209 contextWindow = window.frames[i]; 2210 process(); 2211 } 2212 } 2213 } 2214 contextWindow = window; 2215 process(); 2216 } 2217 }, 2218 2219 /** 2220 * @name Hyphenator.addExceptions 2221 * @description 2222 * Adds the exceptions from the string to the appropriate language in the 2223 * {@link Hyphenator-languages}-object 2224 * @param {string} lang The language 2225 * @param {string} words A comma separated string of hyphenated words WITH spaces. 2226 * @public 2227 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 2228 * <script type = "text/javascript"> 2229 * Hyphenator.addExceptions('de','ziem-lich, Wach-stube'); 2230 * Hyphenator.run(); 2231 * </script> 2232 */ 2233 addExceptions: function (lang, words) { 2234 if (lang === '') { 2235 lang = 'global'; 2236 } 2237 if (exceptions.hasOwnProperty(lang)) { 2238 exceptions[lang] += ", " + words; 2239 } else { 2240 exceptions[lang] = words; 2241 } 2242 }, 2243 2244 /** 2245 * @name Hyphenator.hyphenate 2246 * @public 2247 * @description 2248 * Hyphenates the target. The language patterns must be loaded. 2249 * If the target is a string, the hyphenated string is returned, 2250 * if it's an object, the values are hyphenated directly. 2251 * @param {string|Object} target the target to be hyphenated 2252 * @param {string} lang the language of the target 2253 * @returns string 2254 * @example <script src = "Hyphenator.js" type = "text/javascript"></script> 2255 * <script src = "patterns/en.js" type = "text/javascript"></script> 2256 * <script type = "text/javascript"> 2257 * var t = Hyphenator.hyphenate('Hyphenation', 'en'); //Hy|phen|ation 2258 * </script> 2259 */ 2260 hyphenate: function (target, lang) { 2261 var hyphenate, n, i; 2262 if (Hyphenator.languages.hasOwnProperty(lang)) { 2263 if (!Hyphenator.languages[lang].prepared) { 2264 prepareLanguagesObj(lang); 2265 } 2266 hyphenate = function (word) { 2267 if (urlOrMailRE.test(word)) { 2268 return hyphenateURL(word); 2269 } else { 2270 return hyphenateWord(lang, word); 2271 } 2272 }; 2273 if (typeof target === 'string' || target.constructor === String) { 2274 return target.replace(Hyphenator.languages[lang].genRegExp, hyphenate); 2275 } else if (typeof target === 'object') { 2276 i = 0; 2277 while (!!(n = target.childNodes[i++])) { 2278 if (n.nodeType === 3 && n.data.length >= min) { //type 3 = #text -> hyphenate! 2279 n.data = n.data.replace(Hyphenator.languages[lang].genRegExp, hyphenate); 2280 } else if (n.nodeType === 1) { 2281 if (n.lang !== '') { 2282 Hyphenator.hyphenate(n, n.lang); 2283 } else { 2284 Hyphenator.hyphenate(n, lang); 2285 } 2286 } 2287 } 2288 } 2289 } else { 2290 onError(new Error('Language "' + lang + '" is not loaded.')); 2291 } 2292 }, 2293 2294 /** 2295 * @name Hyphenator.getRedPatternSet
2296 * @description 2297 * Returns {@link Hyphenator-isBookmarklet}. 2298 * @param {string} lang the language patterns are stored for 2299 * @returns object {'patk': pat} 2300 * @public 2301 */ 2302 getRedPatternSet: function (lang) { 2303 return Hyphenator.languages[lang].redPatSet; 2304 }, 2305 2306 /** 2307 * @name Hyphenator.isBookmarklet 2308 * @description 2309 * Returns {@link Hyphenator-isBookmarklet}. 2310 * @returns boolean 2311 * @public 2312 */ 2313 isBookmarklet: function () { 2314 return isBookmarklet; 2315 }, 2316 2317 getConfigFromURI: function () { 2318 var loc = null, re = {}, jsArray = document.getElementsByTagName('script'), i, j, l, s, gp, option; 2319 for (i = 0, l = jsArray.length; i < l; i++) { 2320 if (!!jsArray[i].getAttribute('src')) { 2321 loc = jsArray[i].getAttribute('src'); 2322 } 2323 if (!loc) { 2324 continue; 2325 } else { 2326 s = loc.indexOf('Hyphenator.js?'); 2327 if (s === -1) { 2328 continue; 2329 } 2330 gp = loc.substring(s + 14).split('&'); 2331 for (j = 0; j < gp.length; j++) { 2332 option = gp[j].split('='); 2333 if (option[0] === 'bm') { 2334 continue; 2335 } 2336 if (option[1] === 'true') { 2337 re[option[0]] = true; 2338 continue; 2339 } 2340 if (option[1] === 'false') { 2341 re[option[0]] = false; 2342 continue; 2343 } 2344 if (isFinite(option[1])) { 2345 re[option[0]] = parseInt(option[1], 10); 2346 continue; 2347 } 2348 if (option[0] === 'onhyphenationdonecallback') { 2349 re[option[0]] = new Function('', option[1]); 2350 continue; 2351 } 2352 re[option[0]] = option[1]; 2353 } 2354 break; 2355 } 2356 } 2357 return re; 2358 }, 2359 2360 /** 2361 * @name Hyphenator.toggleHyphenation 2362 * @description 2363 * Checks the current state of the ToggleBox and removes or does hyphenation. 2364 * @public 2365 */ 2366 toggleHyphenation: function () { 2367 if (Hyphenator.doHyphenation) { 2368 removeHyphenationFromDocument(); 2369 Hyphenator.doHyphenation = false; 2370 storeConfiguration(); 2371 toggleBox(); 2372 } else { 2373 hyphenateLanguageElements('*'); 2374 Hyphenator.doHyphenation = true; 2375 storeConfiguration(); 2376 toggleBox(); 2377 } 2378 } 2379 }; 2380}(window)); 2381 2382//Export properties/methods (for google closure compiler) 2383Hyphenator['languages'] = Hyphenator.languages; 2384Hyphenator['config'] = Hyphenator.config; 2385Hyphenator['run'] = Hyphenator.run; 2386Hyphenator['addExceptions'] = Hyphenator.addExceptions; 2387Hyphenator['hyphenate'] = Hyphenator.hyphenate; 2388Hyphenator['getRedPatternSet'] = Hyphenator.getRedPatternSet; 2389Hyphenator['isBookmarklet'] = Hyphenator.isBookmarklet; 2390Hyphenator['getConfigFromURI'] = Hyphenator.getConfigFromURI; 2391Hyphenator['toggleHyphenation'] = Hyphenator.toggleHyphenation; 2392window['Hyphenator'] = Hyphenator; 2393 2394if (Hyphenator.isBookmarklet()) { 2395 Hyphenator.config({displaytogglebox: true, intermediatestate: 'visible', doframes: true}); 2396 Hyphenator.config(Hyphenator.getConfigFromURI()); 2397 Hyphenator.run(); 2398} 2399}
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.