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