From a58d8110d1444e54679fcb446a2e5da9766e3110 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 14 Jul 2009 09:36:16 -0600 Subject: [PATCH] minify all included javascript and add Hyphenator.js library --- jsmin.py | 218 +++ .../gui2/viewer/hyphenate/Hyphenator.js | 1605 +++++++++++++++++ .../gui2/viewer/hyphenate/patterns/bn.js | 13 + .../gui2/viewer/hyphenate/patterns/cs.js | 17 + .../gui2/viewer/hyphenate/patterns/da.js | 16 + .../gui2/viewer/hyphenate/patterns/de.js | 20 + .../gui2/viewer/hyphenate/patterns/en.js | 16 + .../gui2/viewer/hyphenate/patterns/es.js | 27 + .../gui2/viewer/hyphenate/patterns/fi.js | 17 + .../gui2/viewer/hyphenate/patterns/fr.js | 27 + .../gui2/viewer/hyphenate/patterns/gu.js | 12 + .../gui2/viewer/hyphenate/patterns/hi.js | 12 + .../gui2/viewer/hyphenate/patterns/hu.js | 23 + .../gui2/viewer/hyphenate/patterns/it.js | 20 + .../gui2/viewer/hyphenate/patterns/kn.js | 13 + .../gui2/viewer/hyphenate/patterns/ml.js | 14 + .../gui2/viewer/hyphenate/patterns/nl.js | 19 + .../gui2/viewer/hyphenate/patterns/or.js | 14 + .../gui2/viewer/hyphenate/patterns/pa.js | 12 + .../gui2/viewer/hyphenate/patterns/pl.js | 27 + .../gui2/viewer/hyphenate/patterns/pt.js | 16 + .../gui2/viewer/hyphenate/patterns/ru.js | 22 + .../gui2/viewer/hyphenate/patterns/sv.js | 19 + .../gui2/viewer/hyphenate/patterns/ta.js | 12 + .../gui2/viewer/hyphenate/patterns/te.js | 12 + .../gui2/viewer/hyphenate/patterns/uk.js | 25 + upload.py | 31 +- 27 files changed, 2275 insertions(+), 4 deletions(-) create mode 100644 jsmin.py create mode 100644 src/calibre/gui2/viewer/hyphenate/Hyphenator.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/bn.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/cs.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/da.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/de.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/en.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/es.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/fi.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/fr.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/gu.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/hi.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/hu.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/it.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/kn.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/ml.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/nl.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/or.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/pa.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/pl.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/pt.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/ru.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/sv.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/ta.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/te.js create mode 100644 src/calibre/gui2/viewer/hyphenate/patterns/uk.js diff --git a/jsmin.py b/jsmin.py new file mode 100644 index 0000000000..ae7581413a --- /dev/null +++ b/jsmin.py @@ -0,0 +1,218 @@ +#!/usr/bin/python + +# This code is original from jsmin by Douglas Crockford, it was translated to +# Python by Baruch Even. The original code had the following copyright and +# license. +# +# /* jsmin.c +# 2007-05-22 +# +# Copyright (c) 2002 Douglas Crockford (www.crockford.com) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of +# this software and associated documentation files (the "Software"), to deal in +# the Software without restriction, including without limitation the rights to +# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +# of the Software, and to permit persons to whom the Software is furnished to do +# so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# The Software shall be used for Good, not Evil. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# */ + +from StringIO import StringIO + +def jsmin(js): + ins = StringIO(js) + outs = StringIO() + JavascriptMinify().minify(ins, outs) + str = outs.getvalue() + if len(str) > 0 and str[0] == '\n': + str = str[1:] + return str + +def isAlphanum(c): + """return true if the character is a letter, digit, underscore, + dollar sign, or non-ASCII character. + """ + return ((c >= 'a' and c <= 'z') or (c >= '0' and c <= '9') or + (c >= 'A' and c <= 'Z') or c == '_' or c == '$' or c == '\\' or (c is not None and ord(c) > 126)); + +class UnterminatedComment(Exception): + pass + +class UnterminatedStringLiteral(Exception): + pass + +class UnterminatedRegularExpression(Exception): + pass + +class JavascriptMinify(object): + + def _outA(self): + self.outstream.write(self.theA) + def _outB(self): + self.outstream.write(self.theB) + + def _get(self): + """return the next character from stdin. Watch out for lookahead. If + the character is a control character, translate it to a space or + linefeed. + """ + c = self.theLookahead + self.theLookahead = None + if c == None: + c = self.instream.read(1) + if c >= ' ' or c == '\n': + return c + if c == '': # EOF + return '\000' + if c == '\r': + return '\n' + return ' ' + + def _peek(self): + self.theLookahead = self._get() + return self.theLookahead + + def _next(self): + """get the next character, excluding comments. peek() is used to see + if an unescaped '/' is followed by a '/' or '*'. + """ + c = self._get() + if c == '/' and self.theA != '\\': + p = self._peek() + if p == '/': + c = self._get() + while c > '\n': + c = self._get() + return c + if p == '*': + c = self._get() + while 1: + c = self._get() + if c == '*': + if self._peek() == '/': + self._get() + return ' ' + if c == '\000': + raise UnterminatedComment() + + return c + + def _action(self, action): + """do something! What you do is determined by the argument: + 1 Output A. Copy B to A. Get the next B. + 2 Copy B to A. Get the next B. (Delete A). + 3 Get the next B. (Delete B). + action treats a string as a single character. Wow! + action recognizes a regular expression if it is preceded by ( or , or =. + """ + if action <= 1: + self._outA() + + if action <= 2: + self.theA = self.theB + if self.theA == "'" or self.theA == '"': + while 1: + self._outA() + self.theA = self._get() + if self.theA == self.theB: + break + if self.theA <= '\n': + raise UnterminatedStringLiteral() + if self.theA == '\\': + self._outA() + self.theA = self._get() + + + if action <= 3: + self.theB = self._next() + if self.theB == '/' and (self.theA == '(' or self.theA == ',' or + self.theA == '=' or self.theA == ':' or + self.theA == '[' or self.theA == '?' or + self.theA == '!' or self.theA == '&' or + self.theA == '|' or self.theA == ';' or + self.theA == '{' or self.theA == '}' or + self.theA == '\n'): + self._outA() + self._outB() + while 1: + self.theA = self._get() + if self.theA == '/': + break + elif self.theA == '\\': + self._outA() + self.theA = self._get() + elif self.theA <= '\n': + raise UnterminatedRegularExpression() + self._outA() + self.theB = self._next() + + + def _jsmin(self): + """Copy the input to the output, deleting the characters which are + insignificant to JavaScript. Comments will be removed. Tabs will be + replaced with spaces. Carriage returns will be replaced with linefeeds. + Most spaces and linefeeds will be removed. + """ + self.theA = '\n' + self._action(3) + + while self.theA != '\000': + if self.theA == ' ': + if isAlphanum(self.theB): + self._action(1) + else: + self._action(2) + elif self.theA == '\n': + if self.theB in ['{', '[', '(', '+', '-']: + self._action(1) + elif self.theB == ' ': + self._action(3) + else: + if isAlphanum(self.theB): + self._action(1) + else: + self._action(2) + else: + if self.theB == ' ': + if isAlphanum(self.theA): + self._action(1) + else: + self._action(3) + elif self.theB == '\n': + if self.theA in ['}', ']', ')', '+', '-', '"', '\'']: + self._action(1) + else: + if isAlphanum(self.theA): + self._action(1) + else: + self._action(3) + else: + self._action(1) + + def minify(self, instream, outstream): + self.instream = instream + self.outstream = outstream + self.theA = '\n' + self.theB = None + self.theLookahead = None + + self._jsmin() + self.instream.close() + +if __name__ == '__main__': + import sys + jsm = JavascriptMinify() + jsm.minify(sys.stdin, sys.stdout) diff --git a/src/calibre/gui2/viewer/hyphenate/Hyphenator.js b/src/calibre/gui2/viewer/hyphenate/Hyphenator.js new file mode 100644 index 0000000000..4352487f36 --- /dev/null +++ b/src/calibre/gui2/viewer/hyphenate/Hyphenator.js @@ -0,0 +1,1605 @@ +/*! + * Hyphenator 2.3.0 - client side hyphenation for webbrowsers + * Copyright (C) 2009 Mathias Nater, Zürich (mathias at mnn dot ch) + * Project and Source hosted on http://code.google.com/p/hyphenator/ + * + * This JavaScript code is free software: you can redistribute + * it and/or modify it under the terms of the GNU Lesser + * General Public License (GNU LGPL) as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) + * any later version. The code is distributed WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. + * + * As additional permission under GNU GPL version 3 section 7, you + * may distribute non-source (e.g., minimized or compacted) forms of + * that code without the copy of the GNU GPL normally required by + * section 4, provided you include this license notice and a URL + * through which recipients can access the Corresponding Source. + */ + +/* + * Comments are jsdoctoolkit formatted. See jsdoctoolkit.org + */ + +/* The following comment is for JSLint: */ +/*global window, ActiveXObject, unescape */ +/*jslint browser: true, eqeqeq: true, immed: true, newcap: true, nomen: true, onevar: true, undef: true, white: true, indent: 4*/ + +/** + * @fileOverview + * A script that does hyphenation in (X)HTML files + * @author Mathias Nater, mathias@mnn.ch + * @version 2.3.0 + */ + +/** + * @constructor + * @description Provides all functionality to do hyphenation, except the patterns that are loaded + * externally. + * @namespace Holds all methods and properties + * @example + * <script src = "Hyphenator.js" type = "text/javascript"></script> + * <script type = "text/javascript"> + *   Hyphenator.run(); + * </script> + */ +var Hyphenator = (function () { + + + /** + * @name Hyphenator-languageHint + * @fieldOf Hyphenator + * @description + * A string to be displayed in a prompt if the language can't be guessed. + * If you add hyphenation patterns change this string. + * Internally, this string is used to define languages that are supported by Hyphenator. + * @see Hyphenator-supportedLang + * @type string + * @private + * @see Hyphenator-autoSetMainLanguage + */ + var languageHint = 'cs, da, bn, de, en, es, fi, fr, gu, hi, hu, it, kn, ml, nl, or, pa, pl, pt, ru, sv, ta, te, uk', + + /** + * @name Hyphenator-supportedLang + * @fieldOf Hyphenator + * @description + * A generated key-value object that stores supported languages. + * The languages are retrieved from {@link Hyphenator-languageHint}. + * @type object + * @private + * @example + * Check if language lang is supported: + * if (supportedLang[lang]) + */ + supportedLang = (function () { + var k, i = 0, a = languageHint.split(', '), r = {}; + while (!!(k = a[i++])) { + r[k] = true; + } + return r; + }()), + + /** + * @name Hyphenator-prompterStrings + * @fieldOf Hyphenator + * @description + * A key-value object holding the strings to be displayed if the language can't be guessed + * If you add hyphenation patterns change this string. + * @type object + * @private + * @see Hyphenator-autoSetMainLanguage + */ + prompterStrings = { + 'cs': 'Jazyk této internetové stránky nebyl automaticky rozpoznán. Určete prosím její jazyk:', + 'da': 'Denne websides sprog kunne ikke bestemmes. Angiv venligst sprog:', + 'de': 'Die Sprache dieser Webseite konnte nicht automatisch bestimmt werden. Bitte Sprache angeben:', + 'en': 'The language of this website could not be determined automatically. Please indicate the main language:', + 'es': 'El idioma del sitio no pudo determinarse autom%E1ticamente. Por favor, indique el idioma principal:', + 'fi': 'Sivun kielt%E4 ei tunnistettu automaattisesti. M%E4%E4rit%E4 sivun p%E4%E4kieli:', + 'fr': 'La langue de ce site n%u2019a pas pu %EAtre d%E9termin%E9e automatiquement. Veuillez indiquer une langue, s.v.p.%A0:', + 'hu': 'A weboldal nyelvét nem sikerült automatikusan megállapítani. Kérem adja meg a nyelvet:', + 'it': 'Lingua del sito sconosciuta. Indicare una lingua, per favore:', + 'ml': 'ഈ വെ%u0D2C%u0D4D%u200Cസൈറ്റിന്റെ ഭാഷ കണ്ടുപിടിയ്ക്കാ%u0D28%u0D4D%u200D കഴിഞ്ഞില്ല. ഭാഷ ഏതാണെന്നു തിരഞ്ഞെടുക്കുക:', + 'nl': 'De taal van deze website kan niet automatisch worden bepaald. Geef de hoofdtaal op:', + 'pt': 'A língua deste site não pôde ser determinada automaticamente. Por favor indique a língua principal:', + 'ru': 'Язык этого сайта не может быть определен автоматически. Пожалуйста укажите язык:', + 'sv': 'Spr%E5ket p%E5 den h%E4r webbplatsen kunde inte avg%F6ras automatiskt. V%E4nligen ange:', + 'uk': 'Мова цього веб-сайту не може бути визначена автоматично. Будь ласка, вкажіть головну мову:' + }, + + /** + * @name Hyphenator-basePath + * @fieldOf Hyphenator + * @description + * A string storing the basepath from where Hyphenator.js was loaded. + * This is used to load the patternfiles. + * The basepath is determined dynamically by searching all script-tags for Hyphenator.js + * If the path cannot be determined http://hyphenator.googlecode.com/svn/trunk/ is used as fallback. + * @type string + * @private + * @see Hyphenator-loadPatterns + */ + basePath = (function () { + var s = document.getElementsByTagName('script'), i = 0, p, src, t; + while (!!(t = s[i++])) { + if (!t.src) { + continue; + } + src = t.src; + p = src.indexOf('Hyphenator.js'); + if (p !== -1) { + return src.substring(0, p); + } + } + return 'http://hyphenator.googlecode.com/svn/trunk/'; + }()), + + /** + * @name Hyphenator-isLocal + * @fieldOf Hyphenator + * @description + * isLocal is true, if Hyphenator is loaded from the same domain, as the webpage, but false, if + * it's loaded from an external source (i.e. directly from google.code) + */ + isLocal = (function () { + var re = false; + if (basePath.indexOf(window.location.hostname) !== -1) { + re = true; + } + return re; + }()), + + /** + * @name Hyphenator-documentLoaded + * @fieldOf Hyphenator + * @description + * documentLoaded is true, when the DOM has been loaded. This is set by runOnContentLoaded + */ + documentLoaded = false, + + /** + * @name Hyphenator-dontHyphenate + * @fieldOf Hyphenator + * @description + * A key-value object containing all html-tags whose content should not be hyphenated + * @type object + * @private + * @see Hyphenator-hyphenateElement + */ + 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}, + + /** + * @name Hyphenator-enableCache + * @fieldOf Hyphenator + * @description + * A variable to set if caching is enabled or not + * @type boolean + * @default true + * @private + * @see Hyphenator.config + * @see hyphenateWord + */ + enableCache = true, + + /** + * @name Hyphenator-enableRemoteLoading + * @fieldOf Hyphenator + * @description + * A variable to set if pattern files should be loaded remotely or not + * @type boolean + * @default true + * @private + * @see Hyphenator.config + * @see Hyphenator-loadPatterns + */ + enableRemoteLoading = true, + + /** + * @name Hyphenator-displayToggleBox + * @fieldOf Hyphenator + * @description + * A variable to set if the togglebox should be displayed or not + * @type boolean + * @default false + * @private + * @see Hyphenator.config + * @see Hyphenator-toggleBox + */ + displayToggleBox = false, + + /** + * @name Hyphenator-hyphenateClass + * @fieldOf Hyphenator + * @description + * A string containing the css-class-name for the hyphenate class + * @type string + * @default 'hyphenate' + * @private + * @example + * <p class = "hyphenate">Text</p> + * @see Hyphenator.config + */ + hyphenateClass = 'hyphenate', + + /** + * @name Hyphenator-dontHyphenateClass + * @fieldOf Hyphenator + * @description + * A string containing the css-class-name for elements that should not be hyphenated + * @type string + * @default 'donthyphenate' + * @private + * @example + * <p class = "donthyphenate">Text</p> + * @see Hyphenator.config + */ + dontHyphenateClass = 'donthyphenate', + + /** + * @name Hyphenator-min + * @fieldOf Hyphenator + * @description + * A number wich indicates the minimal length of words to hyphenate. + * @type number + * @default 6 + * @private + * @see Hyphenator.config + */ + min = 6, + + /** + * @name Hyphenator-isBookmarklet + * @fieldOf Hyphenator + * @description + * Indicates if Hyphanetor runs as bookmarklet or not. + * @type boolean + * @default false + * @private + */ + isBookmarklet = (function () { + var loc = null, re = false, jsArray = document.getElementsByTagName('script'), i, l; + for (i = 0, l = jsArray.length; i < l; i++) { + if (!!jsArray[i].getAttribute('src')) { + loc = jsArray[i].getAttribute('src'); + } + if (!loc) { + continue; + } else if (loc.indexOf('Hyphenator.js?bm=true') !== -1) { + re = true; + } + } + return re; + }()), + + /** + * @name Hyphenator-mainLanguage + * @fieldOf Hyphenator + * @description + * The general language of the document + * @type number + * @private + * @see Hyphenator-autoSetMainLanguage + */ + mainLanguage = null, + + /** + * @name Hyphenator-elements + * @fieldOf Hyphenator + * @description + * An array holding all elements that have to be hyphenated. This var is filled by + * {@link Hyphenator-gatherDocumentInfos} + * @type array + * @private + */ + elements = [], + + /** + * @name Hyphenator-exceptions + * @fieldOf Hyphenator + * @description + * An object containing exceptions as comma separated strings for each language. + * When the language-objects are loaded, their exceptions are processed, copied here and then deleted. + * @see Hyphenator-prepareLanguagesObj + * @type object + * @private + */ + exceptions = {}, + + /** + * @name Hyphenator-docLanguages + * @fieldOf Hyphenator + * @description + * An object holding all languages used in the document. This is filled by + * {@link Hyphenator-gatherDocumentInfos} + * @type object + * @private + */ + docLanguages = {}, + + + /** + * @name Hyphenator-state + * @fieldOf Hyphenator + * @description + * A number that inidcates the current state of the script + * 0: not initialized + * 1: loading patterns + * 2: ready + * 3: hyphenation done + * 4: hyphenation removed + * @type number + * @private + */ + state = 0, + + /** + * @name Hyphenator-url + * @fieldOf Hyphenator + * @description + * A string containing a RegularExpression to match URL's + * @type string + * @private + */ + url = '(\\w*:\/\/)?((\\w*:)?(\\w*)@)?((([\\d]{1,3}\\.){3}([\\d]{1,3}))|(([\\w]*\\.)+([\\w]{2,4})))(:\\d*)?(\/[\\w#!:\\.?\\+=&%@!\\-]*)*', + + /** + * @name Hyphenator-mail + * @fieldOf Hyphenator + * @description + * A string containing a RegularExpression to match mail-adresses + * @type string + * @private + */ + mail = '[\\w-\\.]+@[\\w\\.]+', + + /** + * @name Hyphenator-urlRE + * @fieldOf Hyphenator + * @description + * A RegularExpressions-Object for url- and mail adress matching + * @type object + * @private + */ + urlOrMailRE = new RegExp('(' + url + ')|(' + mail + ')', 'i'), + + /** + * @name Hyphenator-zeroWidthSpace + * @fieldOf Hyphenator + * @description + * A string that holds a char. + * Depending on the browser, this is the zero with space or an empty string. + * The zeroWidthSpace is inserted after a '-' in compound words, so even FF and IE + * will break after a '-' if necessary. + * zeroWidthSpace is also used to break URLs + * @type string + * @private + */ + zeroWidthSpace = (function () { + var zws, ua = navigator.userAgent.toLowerCase(); + if (ua.indexOf('msie 6') === -1) { + zws = String.fromCharCode(8203); //Unicode zero width space + } else { + zws = ''; //IE6 doesn't support zws + } + return zws; + }()), + + /** + * @name Hyphenator-onHyphenationDone + * @fieldOf Hyphenator + * @description + * A method to be called, when the last element has been hyphenated or the hyphenation has been + * removed from the last element. + * @see Hyphenator.config + * @type function + * @private + */ + onHyphenationDone = function () {}, + + /** + * @name Hyphenator-onError + * @fieldOf Hyphenator + * @description + * A function that can be called upon an error. + * @see Hyphenator.config + * @type function + * @private + */ + onError = function (e) { + alert("Hyphenator.js says:\n\nAn Error ocurred:\n" + e.message); + }, + + /** + * @name Hyphenator-selectorFunction + * @fieldOf Hyphenator + * @description + * A function that has to return a HTMLNodeList of Elements to be hyphenated. + * By default it uses the classname ('hyphenate') to select the elements. + * @see Hyphenator.config + * @type function + * @private + */ + selectorFunction = function () { + var tmp, el = [], i, l; + if (document.getElementsByClassName) { + el = document.getElementsByClassName(hyphenateClass); + } else { + tmp = document.getElementsByTagName('*'); + l = tmp.length; + for (i = 0; i < l; i++) + { + if (tmp[i].className.indexOf(hyphenateClass) !== -1 && tmp[i].className.indexOf(dontHyphenateClass) === -1) { + el.push(tmp[i]); + } + } + } + return el; + }, + + /** + * @name Hyphenator-intermediateState + * @fieldOf Hyphenator + * @description + * The value of style.visibility of the text while it is hyphenated. + * @see Hyphenator.config + * @type string + * @private + */ + intermediateState = 'hidden', + + /** + * @name Hyphenator-hyphen + * @fieldOf Hyphenator + * @description + * A string containing the character for in-word-hyphenation + * @type string + * @default the soft hyphen + * @private + * @see Hyphenator.config + */ + hyphen = String.fromCharCode(173), + + /** + * @name Hyphenator-urlhyphen + * @fieldOf Hyphenator + * @description + * A string containing the character for url/mail-hyphenation + * @type string + * @default the zero width space + * @private + * @see Hyphenator.config + * @see Hyphenator-zeroWidthSpace + */ + urlhyphen = zeroWidthSpace, + + /** + * @name Hyphenator-Expando + * @methodOf Hyphenator + * @description + * This custom object stores data for elements: storing data directly in elements + * (DomElement.customData = foobar;) isn't a good idea. It would lead to conflicts + * in form elements, when the form has a child with name="foobar". Therefore, this + * solution follows the approach of jQuery: the data is stored in an object and + * referenced by a unique attribute of the element. The attribute has a name that + * is built by the prefix "HyphenatorExpando_" and a random number, so if the very + * very rare case occurs, that there's already an attribute with the same name, a + * simple reload is enough to make it function. + * @private + */ + Expando = (function () { + var container = {}, + name = "HyphenatorExpando_" + Math.random(), + uuid = 0; + return { + getDataForElem : function (elem) { + return container[elem[name]]; + }, + setDataForElem : function (elem, data) { + var id; + if (elem[name] && elem[name] !== '') { + id = elem[name]; + } else { + id = uuid++; + elem[name] = id; + } + container[id] = data; + }, + appendDataForElem : function (elem, data) { + var k; + for (k in data) { + if (data.hasOwnProperty(k)) { + container[elem[name]][k] = data[k]; + } + } + }, + delDataOfElem : function (elem) { + delete container[elem[name]]; + } + }; + }()), + + /* + * ContentLoaded.js + * + * Author: Diego Perini (diego.perini at gmail.com) + * Summary: Cross-browser wrapper for DOMContentLoaded + * Updated: 17/05/2008 + * License: MIT + * Version: 1.1 + * + * URL: + * http://javascript.nwbox.com/ContentLoaded/ + * http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE + * + * Notes: + * based on code by Dean Edwards and John Resig + * http://dean.edwards.name/weblog/2006/06/again/ + */ + // @w window reference + // @f function reference + //function ContentLoaded(w, f) { + /** + * @name Hyphenator-runOnContentLoaded + * @methodOf Hyphenator + * @description + * A crossbrowser solution for the DOMContentLoaded-Event + * @author Diego Perini (diego.perini at gmail.com) + * http://javascript.nwbox.com/ContentLoaded/ + * @param object the window-object + * @param function-object the function to call onDOMContentLoaded + * @private + */ + runOnContentLoaded = function (w, f) { + var d = w.document, + D = 'DOMContentLoaded', + // user agent, version + u = w.navigator.userAgent.toLowerCase(), + v = parseFloat(u.match(/.+(?:rv|it|ml|ra|ie)[\/: ]([\d.]+)/)[1]), + oldonload = w.onload; + + function init(e) { + if (!documentLoaded) { + documentLoaded = true; + // pass a fake event if needed + f((e.type && e.type === D) ? e : { + type: D, + target: d, + eventPhase: 0, + currentTarget: d, + timeStamp: new Date().getTime(), + eventType: e.type || e + }); + } + } + + // safari < 525.13 + if (/webkit\//.test(u) && v < 525.13) { + + (function () { + if (/complete|loaded/.test(d.readyState)) { + init('khtml-poll'); + } else { + setTimeout(arguments.callee, 10); + } + }()); + + // internet explorer all versions + } else if (/msie/.test(u) && !w.opera) { + + d.attachEvent('onreadystatechange', + function (e) { + if (d.readyState === 'complete') { + d.detachEvent('on' + e.type, arguments.callee); + init(e); + } + } + ); + if (w.self === top) { + (function () { + try { + d.documentElement.doScroll('left'); + } catch (e) { + setTimeout(arguments.callee, 10); + return; + } + init('msie-poll'); + }()); + } + + // browsers having native DOMContentLoaded + } else if (d.addEventListener && + (/opera\//.test(u) && v > 9) || + (/gecko\//.test(u) && v >= 1.8) || + (/khtml\//.test(u) && v >= 4.0) || + (/webkit\//.test(u) && v >= 525.13)) { + + d.addEventListener(D, + function (e) { + d.removeEventListener(D, arguments.callee, false); + init(e); + }, false + ); + + // fallback to last resort for older browsers + } else { + + // from Simon Willison + /** + * @ignore + */ + w.onload = function (e) { + init(e || w.event); + if (typeof oldonload === 'function') { + oldonload(e || w.event); + } + }; + + } + }, + /* end ContentLoaded.js */ + + /** + * @name Hyphenator-getLang + * @methodOf Hyphenator + * @description + * Gets the language of an element. If no language is set, it may use the {@link Hyphenator-mainLanguage}. + * @param object The first parameter is an DOM-Element-Object + * @param boolean The second parameter is a boolean to tell if the function should return the {@link Hyphenator-mainLanguage} + * if there's no language found for the element. + * @private + */ + getLang = function (el, fallback) { + if (!!el.getAttribute('lang')) { + return el.getAttribute('lang').substring(0, 2).toLowerCase(); + } + // The following doesn't work in IE due to a bug when getAttribute('xml:lang') in a table + /*if (!!el.getAttribute('xml:lang')) { + return el.getAttribute('xml:lang').substring(0, 2); + }*/ + //instead, we have to do this (thanks to borgzor): + try { + if (!!el.getAttribute('xml:lang')) { + return el.getAttribute('xml:lang').substring(0, 2).toLowerCase(); + } + } catch (ex) {} + if (el.tagName !== 'HTML') { + return getLang(el.parentNode, true); + } + if (fallback) { + return mainLanguage; + } + return null; + }, + + /** + * @name Hyphenator-autoSetMainLanguage + * @methodOf Hyphenator + * @description + * Retrieves the language of the document from the DOM. + * The function looks in the following places: + *