/ *
Copyright ( C ) 2012 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
var core = { } ;
var gui = { } ;
var xmldom = { } ;
var odf = { } ;
var ops = { } ;
function Runtime ( ) {
}
Runtime . ByteArray = function ( size ) {
} ;
Runtime . prototype . getVariable = function ( name ) {
} ;
Runtime . prototype . toJson = function ( anything ) {
} ;
Runtime . prototype . fromJson = function ( jsonstr ) {
} ;
Runtime . ByteArray . prototype . slice = function ( start , end ) {
} ;
Runtime . ByteArray . prototype . length = 0 ;
Runtime . prototype . byteArrayFromArray = function ( array ) {
} ;
Runtime . prototype . byteArrayFromString = function ( string , encoding ) {
} ;
Runtime . prototype . byteArrayToString = function ( bytearray , encoding ) {
} ;
Runtime . prototype . concatByteArrays = function ( bytearray1 , bytearray2 ) {
} ;
Runtime . prototype . read = function ( path , offset , length , callback ) {
} ;
Runtime . prototype . readFile = function ( path , encoding , callback ) {
} ;
Runtime . prototype . readFileSync = function ( path , encoding ) {
} ;
Runtime . prototype . loadXML = function ( path , callback ) {
} ;
Runtime . prototype . writeFile = function ( path , data , callback ) {
} ;
Runtime . prototype . isFile = function ( path , callback ) {
} ;
Runtime . prototype . getFileSize = function ( path , callback ) {
} ;
Runtime . prototype . deleteFile = function ( path , callback ) {
} ;
Runtime . prototype . log = function ( msgOrCategory , msg ) {
} ;
Runtime . prototype . setTimeout = function ( callback , milliseconds ) {
} ;
Runtime . prototype . clearTimeout = function ( timeoutID ) {
} ;
Runtime . prototype . libraryPaths = function ( ) {
} ;
Runtime . prototype . type = function ( ) {
} ;
Runtime . prototype . getDOMImplementation = function ( ) {
} ;
Runtime . prototype . parseXML = function ( xml ) {
} ;
Runtime . prototype . getWindow = function ( ) {
} ;
Runtime . prototype . assert = function ( condition , message , callback ) {
} ;
var IS _COMPILED _CODE = false ;
Runtime . byteArrayToString = function ( bytearray , encoding ) {
function byteArrayToString ( bytearray ) {
var s = "" , i , l = bytearray . length ;
for ( i = 0 ; i < l ; i += 1 ) {
s += String . fromCharCode ( bytearray [ i ] & 255 )
}
return s
}
function utf8ByteArrayToString ( bytearray ) {
var s = "" , i , l = bytearray . length , c0 , c1 , c2 , c3 , codepoint ;
for ( i = 0 ; i < l ; i += 1 ) {
c0 = bytearray [ i ] ;
if ( c0 < 128 ) {
s += String . fromCharCode ( c0 )
} else {
i += 1 ;
c1 = bytearray [ i ] ;
if ( c0 >= 194 && c0 < 224 ) {
s += String . fromCharCode ( ( c0 & 31 ) << 6 | c1 & 63 )
} else {
i += 1 ;
c2 = bytearray [ i ] ;
if ( c0 >= 224 && c0 < 240 ) {
s += String . fromCharCode ( ( c0 & 15 ) << 12 | ( c1 & 63 ) << 6 | c2 & 63 )
} else {
i += 1 ;
c3 = bytearray [ i ] ;
if ( c0 >= 240 && c0 < 245 ) {
codepoint = ( c0 & 7 ) << 18 | ( c1 & 63 ) << 12 | ( c2 & 63 ) << 6 | c3 & 63 ;
codepoint -= 65536 ;
s += String . fromCharCode ( ( codepoint >> 10 ) + 55296 , ( codepoint & 1023 ) + 56320 )
}
}
}
}
}
return s
}
var result ;
if ( encoding === "utf8" ) {
result = utf8ByteArrayToString ( bytearray )
} else {
if ( encoding !== "binary" ) {
this . log ( "Unsupported encoding: " + encoding )
}
result = byteArrayToString ( bytearray )
}
return result
} ;
Runtime . getVariable = function ( name ) {
try {
return eval ( name )
} catch ( e ) {
return undefined
}
} ;
Runtime . toJson = function ( anything ) {
return JSON . stringify ( anything )
} ;
Runtime . fromJson = function ( jsonstr ) {
return JSON . parse ( jsonstr )
} ;
Runtime . getFunctionName = function getFunctionName ( f ) {
var m ;
if ( f . name === undefined ) {
m = ( new RegExp ( "function\\s+(\\w+)" ) ) . exec ( f ) ;
return m && m [ 1 ]
}
return f . name
} ;
function BrowserRuntime ( logoutput ) {
var self = this , cache = { } , useNativeArray = window . ArrayBuffer && window . Uint8Array ;
if ( useNativeArray ) {
Uint8Array . prototype . slice = function ( begin , end ) {
if ( end === undefined ) {
if ( begin === undefined ) {
begin = 0
}
end = this . length
}
var view = this . subarray ( begin , end ) , array , i ;
end -= begin ;
array = new Uint8Array ( new ArrayBuffer ( end ) ) ;
for ( i = 0 ; i < end ; i += 1 ) {
array [ i ] = view [ i ]
}
return array
}
}
this . ByteArray = useNativeArray ? function ByteArray ( size ) {
return new Uint8Array ( new ArrayBuffer ( size ) )
} : function ByteArray ( size ) {
var a = [ ] ;
a . length = size ;
return a
} ;
this . concatByteArrays = useNativeArray ? function ( bytearray1 , bytearray2 ) {
var i , l1 = bytearray1 . length , l2 = bytearray2 . length , a = new this . ByteArray ( l1 + l2 ) ;
for ( i = 0 ; i < l1 ; i += 1 ) {
a [ i ] = bytearray1 [ i ]
}
for ( i = 0 ; i < l2 ; i += 1 ) {
a [ i + l1 ] = bytearray2 [ i ]
}
return a
} : function ( bytearray1 , bytearray2 ) {
return bytearray1 . concat ( bytearray2 )
} ;
function utf8ByteArrayFromString ( string ) {
var l = string . length , bytearray , i , n , j = 0 ;
for ( i = 0 ; i < l ; i += 1 ) {
n = string . charCodeAt ( i ) ;
j += 1 + ( n > 128 ) + ( n > 2048 )
}
bytearray = new self . ByteArray ( j ) ;
j = 0 ;
for ( i = 0 ; i < l ; i += 1 ) {
n = string . charCodeAt ( i ) ;
if ( n < 128 ) {
bytearray [ j ] = n ;
j += 1
} else {
if ( n < 2048 ) {
bytearray [ j ] = 192 | n >>> 6 ;
bytearray [ j + 1 ] = 128 | n & 63 ;
j += 2
} else {
bytearray [ j ] = 224 | n >>> 12 & 15 ;
bytearray [ j + 1 ] = 128 | n >>> 6 & 63 ;
bytearray [ j + 2 ] = 128 | n & 63 ;
j += 3
}
}
}
return bytearray
}
function byteArrayFromString ( string ) {
var l = string . length , a = new self . ByteArray ( l ) , i ;
for ( i = 0 ; i < l ; i += 1 ) {
a [ i ] = string . charCodeAt ( i ) & 255
}
return a
}
this . byteArrayFromArray = function ( array ) {
return array . slice ( )
} ;
this . byteArrayFromString = function ( string , encoding ) {
var result ;
if ( encoding === "utf8" ) {
result = utf8ByteArrayFromString ( string )
} else {
if ( encoding !== "binary" ) {
self . log ( "unknown encoding: " + encoding )
}
result = byteArrayFromString ( string )
}
return result
} ;
this . byteArrayToString = Runtime . byteArrayToString ;
this . getVariable = Runtime . getVariable ;
this . fromJson = Runtime . fromJson ;
this . toJson = Runtime . toJson ;
function log ( msgOrCategory , msg ) {
var node , doc , category ;
if ( msg !== undefined ) {
category = msgOrCategory
} else {
msg = msgOrCategory
}
if ( logoutput ) {
doc = logoutput . ownerDocument ;
if ( category ) {
node = doc . createElement ( "span" ) ;
node . className = category ;
node . appendChild ( doc . createTextNode ( category ) ) ;
logoutput . appendChild ( node ) ;
logoutput . appendChild ( doc . createTextNode ( " " ) )
}
node = doc . createElement ( "span" ) ;
if ( msg . length > 0 && msg [ 0 ] === "<" ) {
node . innerHTML = msg
} else {
node . appendChild ( doc . createTextNode ( msg ) )
}
logoutput . appendChild ( node ) ;
logoutput . appendChild ( doc . createElement ( "br" ) )
} else {
if ( console ) {
console . log ( msg )
}
}
if ( category === "alert" ) {
alert ( msg )
}
}
function assert ( condition , message , callback ) {
if ( ! condition ) {
log ( "alert" , "ASSERTION FAILED:\n" + message ) ;
if ( callback ) {
callback ( )
}
throw message ;
}
}
function readFile ( path , encoding , callback ) {
if ( cache . hasOwnProperty ( path ) ) {
callback ( null , cache [ path ] ) ;
return
}
var xhr = new XMLHttpRequest ;
function handleResult ( ) {
var data ;
if ( xhr . readyState === 4 ) {
if ( xhr . status === 0 && ! xhr . responseText ) {
callback ( "File " + path + " is empty." )
} else {
if ( xhr . status === 200 || xhr . status === 0 ) {
if ( encoding === "binary" ) {
if ( xhr . responseBody !== null && String ( typeof VBArray ) !== "undefined" ) {
data = ( new VBArray ( xhr . responseBody ) ) . toArray ( )
} else {
data = self . byteArrayFromString ( xhr . responseText , "binary" )
}
} else {
data = xhr . responseText
}
cache [ path ] = data ;
callback ( null , data )
} else {
callback ( xhr . responseText || xhr . statusText )
}
}
}
}
xhr . open ( "GET" , path , true ) ;
xhr . onreadystatechange = handleResult ;
if ( xhr . overrideMimeType ) {
if ( encoding !== "binary" ) {
xhr . overrideMimeType ( "text/plain; charset=" + encoding )
} else {
xhr . overrideMimeType ( "text/plain; charset=x-user-defined" )
}
}
try {
xhr . send ( null )
} catch ( e ) {
callback ( e . message )
}
}
function read ( path , offset , length , callback ) {
if ( cache . hasOwnProperty ( path ) ) {
callback ( null , cache [ path ] . slice ( offset , offset + length ) ) ;
return
}
var xhr = new XMLHttpRequest ;
function handleResult ( ) {
var data ;
if ( xhr . readyState === 4 ) {
if ( xhr . status === 0 && ! xhr . responseText ) {
callback ( "File " + path + " is empty." )
} else {
if ( xhr . status === 200 || xhr . status === 0 ) {
if ( xhr . response ) {
data = ( xhr . response ) ;
data = new Uint8Array ( data )
} else {
if ( xhr . responseBody !== null && String ( typeof VBArray ) !== "undefined" ) {
data = ( new VBArray ( xhr . responseBody ) ) . toArray ( )
} else {
data = self . byteArrayFromString ( xhr . responseText , "binary" )
}
}
cache [ path ] = data ;
callback ( null , data . slice ( offset , offset + length ) )
} else {
callback ( xhr . responseText || xhr . statusText )
}
}
}
}
xhr . open ( "GET" , path , true ) ;
xhr . onreadystatechange = handleResult ;
if ( xhr . overrideMimeType ) {
xhr . overrideMimeType ( "text/plain; charset=x-user-defined" )
}
xhr . responseType = "arraybuffer" ;
try {
xhr . send ( null )
} catch ( e ) {
callback ( e . message )
}
}
function readFileSync ( path , encoding ) {
var xhr = new XMLHttpRequest , result ;
xhr . open ( "GET" , path , false ) ;
if ( xhr . overrideMimeType ) {
if ( encoding !== "binary" ) {
xhr . overrideMimeType ( "text/plain; charset=" + encoding )
} else {
xhr . overrideMimeType ( "text/plain; charset=x-user-defined" )
}
}
try {
xhr . send ( null ) ;
if ( xhr . status === 200 || xhr . status === 0 ) {
result = xhr . responseText
}
} catch ( ignore ) {
}
return result
}
function writeFile ( path , data , callback ) {
cache [ path ] = data ;
var xhr = new XMLHttpRequest ;
function handleResult ( ) {
if ( xhr . readyState === 4 ) {
if ( xhr . status === 0 && ! xhr . responseText ) {
callback ( "File " + path + " is empty." )
} else {
if ( xhr . status >= 200 && xhr . status < 300 || xhr . status === 0 ) {
callback ( null )
} else {
callback ( "Status " + String ( xhr . status ) + ": " + xhr . responseText || xhr . statusText )
}
}
}
}
xhr . open ( "PUT" , path , true ) ;
xhr . onreadystatechange = handleResult ;
if ( data . buffer && ! xhr . sendAsBinary ) {
data = data . buffer
} else {
data = self . byteArrayToString ( data , "binary" )
}
try {
if ( xhr . sendAsBinary ) {
xhr . sendAsBinary ( data )
} else {
xhr . send ( data )
}
} catch ( e ) {
self . log ( "HUH? " + e + " " + data ) ;
callback ( e . message )
}
}
function deleteFile ( path , callback ) {
delete cache [ path ] ;
var xhr = new XMLHttpRequest ;
xhr . open ( "DELETE" , path , true ) ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState === 4 ) {
if ( xhr . status < 200 && xhr . status >= 300 ) {
callback ( xhr . responseText )
} else {
callback ( null )
}
}
} ;
xhr . send ( null )
}
function loadXML ( path , callback ) {
var xhr = new XMLHttpRequest ;
function handleResult ( ) {
if ( xhr . readyState === 4 ) {
if ( xhr . status === 0 && ! xhr . responseText ) {
callback ( "File " + path + " is empty." )
} else {
if ( xhr . status === 200 || xhr . status === 0 ) {
callback ( null , xhr . responseXML )
} else {
callback ( xhr . responseText )
}
}
}
}
xhr . open ( "GET" , path , true ) ;
if ( xhr . overrideMimeType ) {
xhr . overrideMimeType ( "text/xml" )
}
xhr . onreadystatechange = handleResult ;
try {
xhr . send ( null )
} catch ( e ) {
callback ( e . message )
}
}
function isFile ( path , callback ) {
self . getFileSize ( path , function ( size ) {
callback ( size !== - 1 )
} )
}
function getFileSize ( path , callback ) {
var xhr = new XMLHttpRequest ;
xhr . open ( "HEAD" , path , true ) ;
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState !== 4 ) {
return
}
var cl = xhr . getResponseHeader ( "Content-Length" ) ;
if ( cl ) {
callback ( parseInt ( cl , 10 ) )
} else {
readFile ( path , "binary" , function ( err , data ) {
if ( ! err ) {
callback ( data . length )
} else {
callback ( - 1 )
}
} )
}
} ;
xhr . send ( null )
}
this . readFile = readFile ;
this . read = read ;
this . readFileSync = readFileSync ;
this . writeFile = writeFile ;
this . deleteFile = deleteFile ;
this . loadXML = loadXML ;
this . isFile = isFile ;
this . getFileSize = getFileSize ;
this . log = log ;
this . assert = assert ;
this . setTimeout = function ( f , msec ) {
return setTimeout ( function ( ) {
f ( )
} , msec )
} ;
this . clearTimeout = function ( timeoutID ) {
clearTimeout ( timeoutID )
} ;
this . libraryPaths = function ( ) {
return [ "lib" ]
} ;
this . setCurrentDirectory = function ( ) {
} ;
this . type = function ( ) {
return "BrowserRuntime"
} ;
this . getDOMImplementation = function ( ) {
return window . document . implementation
} ;
this . parseXML = function ( xml ) {
var parser = new DOMParser ;
return parser . parseFromString ( xml , "text/xml" )
} ;
this . exit = function ( exitCode ) {
log ( "Calling exit with code " + String ( exitCode ) + ", but exit() is not implemented." )
} ;
this . getWindow = function ( ) {
return window
}
}
function NodeJSRuntime ( ) {
var self = this , fs = require ( "fs" ) , pathmod = require ( "path" ) , currentDirectory = "" , parser , domImplementation ;
this . ByteArray = function ( size ) {
return new Buffer ( size )
} ;
this . byteArrayFromArray = function ( array ) {
var ba = new Buffer ( array . length ) , i , l = array . length ;
for ( i = 0 ; i < l ; i += 1 ) {
ba [ i ] = array [ i ]
}
return ba
} ;
this . concatByteArrays = function ( a , b ) {
var ba = new Buffer ( a . length + b . length ) ;
a . copy ( ba , 0 , 0 ) ;
b . copy ( ba , a . length , 0 ) ;
return ba
} ;
this . byteArrayFromString = function ( string , encoding ) {
return new Buffer ( string , encoding )
} ;
this . byteArrayToString = function ( bytearray , encoding ) {
return bytearray . toString ( encoding )
} ;
this . getVariable = Runtime . getVariable ;
this . fromJson = Runtime . fromJson ;
this . toJson = Runtime . toJson ;
function isFile ( path , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
fs . stat ( path , function ( err , stats ) {
callback ( ! err && stats . isFile ( ) )
} )
}
function readFile ( path , encoding , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
if ( encoding !== "binary" ) {
fs . readFile ( path , encoding , callback )
} else {
fs . readFile ( path , null , callback )
}
}
this . readFile = readFile ;
function loadXML ( path , callback ) {
readFile ( path , "utf-8" , function ( err , data ) {
if ( err ) {
return callback ( err )
}
callback ( null , self . parseXML ( data ) )
} )
}
this . loadXML = loadXML ;
this . writeFile = function ( path , data , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
fs . writeFile ( path , data , "binary" , function ( err ) {
callback ( err || null )
} )
} ;
this . deleteFile = function ( path , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
fs . unlink ( path , callback )
} ;
this . read = function ( path , offset , length , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
fs . open ( path , "r+" , 666 , function ( err , fd ) {
if ( err ) {
callback ( err ) ;
return
}
var buffer = new Buffer ( length ) ;
fs . read ( fd , buffer , 0 , length , offset , function ( err ) {
fs . close ( fd ) ;
callback ( err , buffer )
} )
} )
} ;
this . readFileSync = function ( path , encoding ) {
if ( ! encoding ) {
return ""
}
if ( encoding === "binary" ) {
return fs . readFileSync ( path , null )
}
return fs . readFileSync ( path , encoding )
} ;
this . isFile = isFile ;
this . getFileSize = function ( path , callback ) {
path = pathmod . resolve ( currentDirectory , path ) ;
fs . stat ( path , function ( err , stats ) {
if ( err ) {
callback ( - 1 )
} else {
callback ( stats . size )
}
} )
} ;
function log ( msgOrCategory , msg ) {
var category ;
if ( msg !== undefined ) {
category = msgOrCategory
} else {
msg = msgOrCategory
}
if ( category === "alert" ) {
process . stderr . write ( "\n!!!!! ALERT !!!!!" + "\n" )
}
process . stderr . write ( msg + "\n" ) ;
if ( category === "alert" ) {
process . stderr . write ( "!!!!! ALERT !!!!!" + "\n" )
}
}
this . log = log ;
function assert ( condition , message , callback ) {
if ( ! condition ) {
process . stderr . write ( "ASSERTION FAILED: " + message ) ;
if ( callback ) {
callback ( )
}
}
}
this . assert = assert ;
this . setTimeout = function ( f , msec ) {
return setTimeout ( function ( ) {
f ( )
} , msec )
} ;
this . clearTimeout = function ( timeoutID ) {
clearTimeout ( timeoutID )
} ;
this . libraryPaths = function ( ) {
return [ _ _dirname ]
} ;
this . setCurrentDirectory = function ( dir ) {
currentDirectory = dir
} ;
this . currentDirectory = function ( ) {
return currentDirectory
} ;
this . type = function ( ) {
return "NodeJSRuntime"
} ;
this . getDOMImplementation = function ( ) {
return domImplementation
} ;
this . parseXML = function ( xml ) {
return parser . parseFromString ( xml , "text/xml" )
} ;
this . exit = process . exit ;
this . getWindow = function ( ) {
return null
} ;
function init ( ) {
var DOMParser = require ( "xmldom" ) . DOMParser ;
parser = new DOMParser ;
domImplementation = self . parseXML ( "<a/>" ) . implementation
}
init ( )
}
function RhinoRuntime ( ) {
var self = this , dom = Packages . javax . xml . parsers . DocumentBuilderFactory . newInstance ( ) , builder , entityresolver , currentDirectory = "" ;
dom . setValidating ( false ) ;
dom . setNamespaceAware ( true ) ;
dom . setExpandEntityReferences ( false ) ;
dom . setSchema ( null ) ;
entityresolver = Packages . org . xml . sax . EntityResolver ( { resolveEntity : function ( publicId , systemId ) {
var file , open = function ( path ) {
var reader = new Packages . java . io . FileReader ( path ) , source = new Packages . org . xml . sax . InputSource ( reader ) ;
return source
} ;
file = systemId ;
return open ( file )
} } ) ;
builder = dom . newDocumentBuilder ( ) ;
builder . setEntityResolver ( entityresolver ) ;
this . ByteArray = function ByteArray ( size ) {
return [ size ]
} ;
this . byteArrayFromArray = function ( array ) {
return array
} ;
this . byteArrayFromString = function ( string , encoding ) {
var a = [ ] , i , l = string . length ;
for ( i = 0 ; i < l ; i += 1 ) {
a [ i ] = string . charCodeAt ( i ) & 255
}
return a
} ;
this . byteArrayToString = Runtime . byteArrayToString ;
this . getVariable = Runtime . getVariable ;
this . fromJson = Runtime . fromJson ;
this . toJson = Runtime . toJson ;
this . concatByteArrays = function ( bytearray1 , bytearray2 ) {
return bytearray1 . concat ( bytearray2 )
} ;
function loadXML ( path , callback ) {
var file = new Packages . java . io . File ( path ) , xmlDocument ;
try {
xmlDocument = builder . parse ( file )
} catch ( err ) {
print ( err ) ;
callback ( err ) ;
return
}
callback ( null , xmlDocument )
}
function runtimeReadFile ( path , encoding , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var file = new Packages . java . io . File ( path ) , data , rhinoencoding = encoding === "binary" ? "latin1" : encoding ;
if ( ! file . isFile ( ) ) {
callback ( path + " is not a file." )
} else {
data = readFile ( path , rhinoencoding ) ;
if ( encoding === "binary" ) {
data = self . byteArrayFromString ( data , "binary" )
}
callback ( null , data )
}
}
function runtimeReadFileSync ( path , encoding ) {
var file = new Packages . java . io . File ( path ) ;
if ( ! file . isFile ( ) ) {
return null
}
if ( encoding === "binary" ) {
encoding = "latin1"
}
return readFile ( path , encoding )
}
function isFile ( path , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var file = new Packages . java . io . File ( path ) ;
callback ( file . isFile ( ) )
}
this . loadXML = loadXML ;
this . readFile = runtimeReadFile ;
this . writeFile = function ( path , data , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var out = new Packages . java . io . FileOutputStream ( path ) , i , l = data . length ;
for ( i = 0 ; i < l ; i += 1 ) {
out . write ( data [ i ] )
}
out . close ( ) ;
callback ( null )
} ;
this . deleteFile = function ( path , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var file = new Packages . java . io . File ( path ) ;
if ( file [ "delete" ] ( ) ) {
callback ( null )
} else {
callback ( "Could not delete " + path )
}
} ;
this . read = function ( path , offset , length , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var data = runtimeReadFileSync ( path , "binary" ) ;
if ( data ) {
callback ( null , this . byteArrayFromString ( data . substring ( offset , offset + length ) , "binary" ) )
} else {
callback ( "Cannot read " + path )
}
} ;
this . readFileSync = function ( path , encoding ) {
if ( ! encoding ) {
return ""
}
return readFile ( path , encoding )
} ;
this . isFile = isFile ;
this . getFileSize = function ( path , callback ) {
if ( currentDirectory ) {
path = currentDirectory + "/" + path
}
var file = new Packages . java . io . File ( path ) ;
callback ( file . length ( ) )
} ;
function log ( msgOrCategory , msg ) {
var category ;
if ( msg !== undefined ) {
category = msgOrCategory
} else {
msg = msgOrCategory
}
if ( category === "alert" ) {
print ( "\n!!!!! ALERT !!!!!" )
}
print ( msg ) ;
if ( category === "alert" ) {
print ( "!!!!! ALERT !!!!!" )
}
}
this . log = log ;
function assert ( condition , message , callback ) {
if ( ! condition ) {
log ( "alert" , "ASSERTION FAILED: " + message ) ;
if ( callback ) {
callback ( )
}
}
}
this . assert = assert ;
this . setTimeout = function ( f ) {
f ( ) ;
return 0
} ;
this . clearTimeout = function ( ) {
} ;
this . libraryPaths = function ( ) {
return [ "lib" ]
} ;
this . setCurrentDirectory = function ( dir ) {
currentDirectory = dir
} ;
this . currentDirectory = function ( ) {
return currentDirectory
} ;
this . type = function ( ) {
return "RhinoRuntime"
} ;
this . getDOMImplementation = function ( ) {
return builder . getDOMImplementation ( )
} ;
this . parseXML = function ( xml ) {
return builder . parse ( xml )
} ;
this . exit = quit ;
this . getWindow = function ( ) {
return null
}
}
var runtime = function ( ) {
var result ;
if ( String ( typeof window ) !== "undefined" ) {
result = new BrowserRuntime ( window . document . getElementById ( "logoutput" ) )
} else {
if ( String ( typeof require ) !== "undefined" ) {
result = new NodeJSRuntime
} else {
result = new RhinoRuntime
}
}
return result
} ( ) ;
( function ( ) {
var cache = { } , dircontents = { } ;
function getOrDefinePackage ( packageNameComponents ) {
var topname = packageNameComponents [ 0 ] , i , pkg ;
pkg = eval ( "if (typeof " + topname + " === 'undefined') {" + "eval('" + topname + " = {};');}" + topname ) ;
for ( i = 1 ; i < packageNameComponents . length - 1 ; i += 1 ) {
if ( ! pkg . hasOwnProperty ( packageNameComponents [ i ] ) ) {
pkg = pkg [ packageNameComponents [ i ] ] = { }
} else {
pkg = pkg [ packageNameComponents [ i ] ]
}
}
return pkg [ packageNameComponents [ packageNameComponents . length - 1 ] ]
}
runtime . loadClass = function ( classpath ) {
if ( IS _COMPILED _CODE ) {
return
}
if ( cache . hasOwnProperty ( classpath ) ) {
return
}
var names = classpath . split ( "." ) , impl ;
impl = getOrDefinePackage ( names ) ;
if ( impl ) {
cache [ classpath ] = true ;
return
}
function getPathFromManifests ( classpath ) {
var path = classpath . replace ( /\./g , "/" ) + ".js" , dirs = runtime . libraryPaths ( ) , i , dir , code ;
if ( runtime . currentDirectory ) {
dirs . push ( runtime . currentDirectory ( ) )
}
for ( i = 0 ; i < dirs . length ; i += 1 ) {
dir = dirs [ i ] ;
if ( ! dircontents . hasOwnProperty ( dir ) ) {
try {
code = runtime . readFileSync ( dirs [ i ] + "/manifest.js" , "utf8" ) ;
if ( code && code . length ) {
dircontents [ dir ] = eval ( code )
} else {
dircontents [ dir ] = null
}
} catch ( e1 ) {
dircontents [ dir ] = null ;
runtime . log ( "Cannot load manifest for " + dir + "." )
}
}
code = null ;
dir = dircontents [ dir ] ;
if ( dir && dir . indexOf && dir . indexOf ( path ) !== - 1 ) {
return dirs [ i ] + "/" + path
}
}
return null
}
function load ( classpath ) {
var code , path ;
path = getPathFromManifests ( classpath ) ;
if ( ! path ) {
throw classpath + " is not listed in any manifest.js." ;
}
try {
code = runtime . readFileSync ( path , "utf8" )
} catch ( e2 ) {
runtime . log ( "Error loading " + classpath + " " + e2 ) ;
throw e2 ;
}
if ( code === undefined ) {
throw "Cannot load class " + classpath ;
}
code += "\n//# sourceURL=" + path ;
code += "\n//@ sourceURL=" + path ;
try {
code = eval ( classpath + " = eval(code);" )
} catch ( e4 ) {
runtime . log ( "Error loading " + classpath + " " + e4 ) ;
throw e4 ;
}
return code
}
impl = load ( classpath ) ;
if ( ! impl || Runtime . getFunctionName ( impl ) !== names [ names . length - 1 ] ) {
runtime . log ( "Loaded code is not for " + names [ names . length - 1 ] ) ;
throw "Loaded code is not for " + names [ names . length - 1 ] ;
}
cache [ classpath ] = true
}
} ) ( ) ;
( function ( args ) {
if ( args ) {
args = Array . prototype . slice . call ( ( args ) )
} else {
args = [ ]
}
function run ( argv ) {
if ( ! argv . length ) {
return
}
var script = argv [ 0 ] ;
runtime . readFile ( script , "utf8" , function ( err , code ) {
var path = "" , codestring = ( code ) ;
if ( script . indexOf ( "/" ) !== - 1 ) {
path = script . substring ( 0 , script . indexOf ( "/" ) )
}
runtime . setCurrentDirectory ( path ) ;
function inner _run ( ) {
var script , path , args , argv , result ;
result = eval ( codestring ) ;
if ( result ) {
runtime . exit ( result )
}
return
}
if ( err || codestring === null ) {
runtime . log ( err ) ;
runtime . exit ( 1 )
} else {
inner _run . apply ( null , argv )
}
} )
}
if ( runtime . type ( ) === "NodeJSRuntime" ) {
run ( process . argv . slice ( 2 ) )
} else {
if ( runtime . type ( ) === "RhinoRuntime" ) {
run ( args )
} else {
run ( args . slice ( 1 ) )
}
}
} ) ( String ( typeof arguments ) !== "undefined" && arguments ) ;
core . Base64 = function ( ) {
var b64chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" , b64tab = function ( bin ) {
var t = { } , i , l ;
for ( i = 0 , l = bin . length ; i < l ; i += 1 ) {
t [ bin . charAt ( i ) ] = i
}
return t
} ( b64chars ) , convertUTF16StringToBase64 , convertBase64ToUTF16String , window = runtime . getWindow ( ) , btoa , atob ;
function stringToArray ( s ) {
var a = [ ] , i , l = s . length ;
for ( i = 0 ; i < l ; i += 1 ) {
a [ i ] = s . charCodeAt ( i ) & 255
}
return a
}
function convertUTF8ArrayToBase64 ( bin ) {
var n , b64 = "" , i , l = bin . length - 2 ;
for ( i = 0 ; i < l ; i += 3 ) {
n = bin [ i ] << 16 | bin [ i + 1 ] << 8 | bin [ i + 2 ] ;
b64 += b64chars [ n >>> 18 ] ;
b64 += b64chars [ n >>> 12 & 63 ] ;
b64 += b64chars [ n >>> 6 & 63 ] ;
b64 += b64chars [ n & 63 ]
}
if ( i === l + 1 ) {
n = bin [ i ] << 4 ;
b64 += b64chars [ n >>> 6 ] ;
b64 += b64chars [ n & 63 ] ;
b64 += "=="
} else {
if ( i === l ) {
n = bin [ i ] << 10 | bin [ i + 1 ] << 2 ;
b64 += b64chars [ n >>> 12 ] ;
b64 += b64chars [ n >>> 6 & 63 ] ;
b64 += b64chars [ n & 63 ] ;
b64 += "="
}
}
return b64
}
function convertBase64ToUTF8Array ( b64 ) {
b64 = b64 . replace ( /[^A-Za-z0-9+\/]+/g , "" ) ;
var bin = [ ] , padlen = b64 . length % 4 , i , l = b64 . length , n ;
for ( i = 0 ; i < l ; i += 4 ) {
n = ( b64tab [ b64 . charAt ( i ) ] || 0 ) << 18 | ( b64tab [ b64 . charAt ( i + 1 ) ] || 0 ) << 12 | ( b64tab [ b64 . charAt ( i + 2 ) ] || 0 ) << 6 | ( b64tab [ b64 . charAt ( i + 3 ) ] || 0 ) ;
bin . push ( n >> 16 , n >> 8 & 255 , n & 255 )
}
bin . length -= [ 0 , 0 , 2 , 1 ] [ padlen ] ;
return bin
}
function convertUTF16ArrayToUTF8Array ( uni ) {
var bin = [ ] , i , l = uni . length , n ;
for ( i = 0 ; i < l ; i += 1 ) {
n = uni [ i ] ;
if ( n < 128 ) {
bin . push ( n )
} else {
if ( n < 2048 ) {
bin . push ( 192 | n >>> 6 , 128 | n & 63 )
} else {
bin . push ( 224 | n >>> 12 & 15 , 128 | n >>> 6 & 63 , 128 | n & 63 )
}
}
}
return bin
}
function convertUTF8ArrayToUTF16Array ( bin ) {
var uni = [ ] , i , l = bin . length , c0 , c1 , c2 ;
for ( i = 0 ; i < l ; i += 1 ) {
c0 = bin [ i ] ;
if ( c0 < 128 ) {
uni . push ( c0 )
} else {
i += 1 ;
c1 = bin [ i ] ;
if ( c0 < 224 ) {
uni . push ( ( c0 & 31 ) << 6 | c1 & 63 )
} else {
i += 1 ;
c2 = bin [ i ] ;
uni . push ( ( c0 & 15 ) << 12 | ( c1 & 63 ) << 6 | c2 & 63 )
}
}
}
return uni
}
function convertUTF8StringToBase64 ( bin ) {
return convertUTF8ArrayToBase64 ( stringToArray ( bin ) )
}
function convertBase64ToUTF8String ( b64 ) {
return String . fromCharCode . apply ( String , convertBase64ToUTF8Array ( b64 ) )
}
function convertUTF8StringToUTF16Array ( bin ) {
return convertUTF8ArrayToUTF16Array ( stringToArray ( bin ) )
}
function convertUTF8ArrayToUTF16String ( bin ) {
var b = convertUTF8ArrayToUTF16Array ( bin ) , r = "" , i = 0 , chunksize = 45E3 ;
while ( i < b . length ) {
r += String . fromCharCode . apply ( String , b . slice ( i , i + chunksize ) ) ;
i += chunksize
}
return r
}
function convertUTF8StringToUTF16String _internal ( bin , i , end ) {
var str = "" , c0 , c1 , c2 , j ;
for ( j = i ; j < end ; j += 1 ) {
c0 = bin . charCodeAt ( j ) & 255 ;
if ( c0 < 128 ) {
str += String . fromCharCode ( c0 )
} else {
j += 1 ;
c1 = bin . charCodeAt ( j ) & 255 ;
if ( c0 < 224 ) {
str += String . fromCharCode ( ( c0 & 31 ) << 6 | c1 & 63 )
} else {
j += 1 ;
c2 = bin . charCodeAt ( j ) & 255 ;
str += String . fromCharCode ( ( c0 & 15 ) << 12 | ( c1 & 63 ) << 6 | c2 & 63 )
}
}
}
return str
}
function convertUTF8StringToUTF16String ( bin , callback ) {
var partsize = 1E5 , str = "" , pos = 0 ;
if ( bin . length < partsize ) {
callback ( convertUTF8StringToUTF16String _internal ( bin , 0 , bin . length ) , true ) ;
return
}
if ( typeof bin !== "string" ) {
bin = bin . slice ( )
}
function f ( ) {
var end = pos + partsize ;
if ( end > bin . length ) {
end = bin . length
}
str += convertUTF8StringToUTF16String _internal ( bin , pos , end ) ;
pos = end ;
end = pos === bin . length ;
if ( callback ( str , end ) && ! end ) {
runtime . setTimeout ( f , 0 )
}
}
f ( )
}
function convertUTF16StringToUTF8Array ( uni ) {
return convertUTF16ArrayToUTF8Array ( stringToArray ( uni ) )
}
function convertUTF16ArrayToUTF8String ( uni ) {
return String . fromCharCode . apply ( String , convertUTF16ArrayToUTF8Array ( uni ) )
}
function convertUTF16StringToUTF8String ( uni ) {
return String . fromCharCode . apply ( String , convertUTF16ArrayToUTF8Array ( stringToArray ( uni ) ) )
}
if ( window && window . btoa ) {
btoa = function ( b ) {
return window . btoa ( b )
} ;
convertUTF16StringToBase64 = function ( uni ) {
return btoa ( convertUTF16StringToUTF8String ( uni ) )
}
} else {
btoa = convertUTF8StringToBase64 ;
convertUTF16StringToBase64 = function ( uni ) {
return convertUTF8ArrayToBase64 ( convertUTF16StringToUTF8Array ( uni ) )
}
}
if ( window && window . atob ) {
atob = function ( a ) {
return window . atob ( a )
} ;
convertBase64ToUTF16String = function ( b64 ) {
var b = atob ( b64 ) ;
return convertUTF8StringToUTF16String _internal ( b , 0 , b . length )
}
} else {
atob = convertBase64ToUTF8String ;
convertBase64ToUTF16String = function ( b64 ) {
return convertUTF8ArrayToUTF16String ( convertBase64ToUTF8Array ( b64 ) )
}
}
function Base64 ( ) {
this . convertUTF8ArrayToBase64 = convertUTF8ArrayToBase64 ;
this . convertByteArrayToBase64 = convertUTF8ArrayToBase64 ;
this . convertBase64ToUTF8Array = convertBase64ToUTF8Array ;
this . convertBase64ToByteArray = convertBase64ToUTF8Array ;
this . convertUTF16ArrayToUTF8Array = convertUTF16ArrayToUTF8Array ;
this . convertUTF16ArrayToByteArray = convertUTF16ArrayToUTF8Array ;
this . convertUTF8ArrayToUTF16Array = convertUTF8ArrayToUTF16Array ;
this . convertByteArrayToUTF16Array = convertUTF8ArrayToUTF16Array ;
this . convertUTF8StringToBase64 = convertUTF8StringToBase64 ;
this . convertBase64ToUTF8String = convertBase64ToUTF8String ;
this . convertUTF8StringToUTF16Array = convertUTF8StringToUTF16Array ;
this . convertUTF8ArrayToUTF16String = convertUTF8ArrayToUTF16String ;
this . convertByteArrayToUTF16String = convertUTF8ArrayToUTF16String ;
this . convertUTF8StringToUTF16String = convertUTF8StringToUTF16String ;
this . convertUTF16StringToUTF8Array = convertUTF16StringToUTF8Array ;
this . convertUTF16StringToByteArray = convertUTF16StringToUTF8Array ;
this . convertUTF16ArrayToUTF8String = convertUTF16ArrayToUTF8String ;
this . convertUTF16StringToUTF8String = convertUTF16StringToUTF8String ;
this . convertUTF16StringToBase64 = convertUTF16StringToBase64 ;
this . convertBase64ToUTF16String = convertBase64ToUTF16String ;
this . fromBase64 = convertBase64ToUTF8String ;
this . toBase64 = convertUTF8StringToBase64 ;
this . atob = atob ;
this . btoa = btoa ;
this . utob = convertUTF16StringToUTF8String ;
this . btou = convertUTF8StringToUTF16String ;
this . encode = convertUTF16StringToBase64 ;
this . encodeURI = function ( u ) {
return convertUTF16StringToBase64 ( u ) . replace ( /[+\/]/g , function ( m0 ) {
return m0 === "+" ? "-" : "_"
} ) . replace ( /\\=+$/ , "" )
} ;
this . decode = function ( a ) {
return convertBase64ToUTF16String ( a . replace ( /[\-_]/g , function ( m0 ) {
return m0 === "-" ? "+" : "/"
} ) )
}
}
return Base64
} ( ) ;
core . RawDeflate = function ( ) {
var zip _WSIZE = 32768 , zip _STORED _BLOCK = 0 , zip _STATIC _TREES = 1 , zip _DYN _TREES = 2 , zip _DEFAULT _LEVEL = 6 , zip _FULL _SEARCH = true , zip _INBUFSIZ = 32768 , zip _INBUF _EXTRA = 64 , zip _OUTBUFSIZ = 1024 * 8 , zip _window _size = 2 * zip _WSIZE , zip _MIN _MATCH = 3 , zip _MAX _MATCH = 258 , zip _BITS = 16 , zip _LIT _BUFSIZE = 8192 , zip _HASH _BITS = 13 , zip _DIST _BUFSIZE = zip _LIT _BUFSIZE , zip _HASH _SIZE = 1 << zip _HASH _BITS , zip _HASH _MASK = zip _HASH _SIZE - 1 , zip _WMASK = zip _WSIZE - 1 , zip _NIL = 0 , zip _TOO _FAR = 4096 ,
zip _MIN _LOOKAHEAD = zip _MAX _MATCH + zip _MIN _MATCH + 1 , zip _MAX _DIST = zip _WSIZE - zip _MIN _LOOKAHEAD , zip _SMALLEST = 1 , zip _MAX _BITS = 15 , zip _MAX _BL _BITS = 7 , zip _LENGTH _CODES = 29 , zip _LITERALS = 256 , zip _END _BLOCK = 256 , zip _L _CODES = zip _LITERALS + 1 + zip _LENGTH _CODES , zip _D _CODES = 30 , zip _BL _CODES = 19 , zip _REP _3 _6 = 16 , zip _REPZ _3 _10 = 17 , zip _REPZ _11 _138 = 18 , zip _HEAP _SIZE = 2 * zip _L _CODES + 1 , zip _H _SHIFT = parseInt ( ( zip _HASH _BITS + zip _MIN _MATCH - 1 ) / zip _MIN _MATCH , 10 ) , zip _free _queue ,
zip _qhead , zip _qtail , zip _initflag , zip _outbuf = null , zip _outcnt , zip _outoff , zip _complete , zip _window , zip _d _buf , zip _l _buf , zip _prev , zip _bi _buf , zip _bi _valid , zip _block _start , zip _ins _h , zip _hash _head , zip _prev _match , zip _match _available , zip _match _length , zip _prev _length , zip _strstart , zip _match _start , zip _eofile , zip _lookahead , zip _max _chain _length , zip _max _lazy _match , zip _compr _level , zip _good _match , zip _nice _match , zip _dyn _ltree , zip _dyn _dtree , zip _static _ltree , zip _static _dtree , zip _bl _tree ,
zip _l _desc , zip _d _desc , zip _bl _desc , zip _bl _count , zip _heap , zip _heap _len , zip _heap _max , zip _depth , zip _length _code , zip _dist _code , zip _base _length , zip _base _dist , zip _flag _buf , zip _last _lit , zip _last _dist , zip _last _flags , zip _flags , zip _flag _bit , zip _opt _len , zip _static _len , zip _deflate _data , zip _deflate _pos , zip _extra _lbits = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 0 ] , zip _extra _dbits = [ 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , 5 , 5 , 6 , 6 , 7 , 7 , 8 , 8 , 9 ,
9 , 10 , 10 , 11 , 11 , 12 , 12 , 13 , 13 ] , zip _extra _blbits = [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 2 , 3 , 7 ] , zip _bl _order = [ 16 , 17 , 18 , 0 , 8 , 7 , 9 , 6 , 10 , 5 , 11 , 4 , 12 , 3 , 13 , 2 , 14 , 1 , 15 ] , zip _configuration _table ;
if ( zip _LIT _BUFSIZE > zip _INBUFSIZ ) {
runtime . log ( "error: zip_INBUFSIZ is too small" )
}
if ( zip _WSIZE << 1 > 1 << zip _BITS ) {
runtime . log ( "error: zip_WSIZE is too large" )
}
if ( zip _HASH _BITS > zip _BITS - 1 ) {
runtime . log ( "error: zip_HASH_BITS is too large" )
}
if ( zip _HASH _BITS < 8 || zip _MAX _MATCH !== 258 ) {
runtime . log ( "error: Code too clever" )
}
function Zip _DeflateCT ( ) {
this . fc = 0 ;
this . dl = 0
}
function Zip _DeflateTreeDesc ( ) {
this . dyn _tree = null ;
this . static _tree = null ;
this . extra _bits = null ;
this . extra _base = 0 ;
this . elems = 0 ;
this . max _length = 0 ;
this . max _code = 0
}
function Zip _DeflateConfiguration ( a , b , c , d ) {
this . good _length = a ;
this . max _lazy = b ;
this . nice _length = c ;
this . max _chain = d
}
function Zip _DeflateBuffer ( ) {
this . next = null ;
this . len = 0 ;
this . ptr = [ ] ;
this . ptr . length = zip _OUTBUFSIZ ;
this . off = 0
}
zip _configuration _table = [ new Zip _DeflateConfiguration ( 0 , 0 , 0 , 0 ) , new Zip _DeflateConfiguration ( 4 , 4 , 8 , 4 ) , new Zip _DeflateConfiguration ( 4 , 5 , 16 , 8 ) , new Zip _DeflateConfiguration ( 4 , 6 , 32 , 32 ) , new Zip _DeflateConfiguration ( 4 , 4 , 16 , 16 ) , new Zip _DeflateConfiguration ( 8 , 16 , 32 , 32 ) , new Zip _DeflateConfiguration ( 8 , 16 , 128 , 128 ) , new Zip _DeflateConfiguration ( 8 , 32 , 128 , 256 ) , new Zip _DeflateConfiguration ( 32 , 128 , 258 , 1024 ) , new Zip _DeflateConfiguration ( 32 , 258 , 258 , 4096 ) ] ;
function zip _deflate _start ( level ) {
var i ;
if ( ! level ) {
level = zip _DEFAULT _LEVEL
} else {
if ( level < 1 ) {
level = 1
} else {
if ( level > 9 ) {
level = 9
}
}
}
zip _compr _level = level ;
zip _initflag = false ;
zip _eofile = false ;
if ( zip _outbuf !== null ) {
return
}
zip _free _queue = zip _qhead = zip _qtail = null ;
zip _outbuf = [ ] ;
zip _outbuf . length = zip _OUTBUFSIZ ;
zip _window = [ ] ;
zip _window . length = zip _window _size ;
zip _d _buf = [ ] ;
zip _d _buf . length = zip _DIST _BUFSIZE ;
zip _l _buf = [ ] ;
zip _l _buf . length = zip _INBUFSIZ + zip _INBUF _EXTRA ;
zip _prev = [ ] ;
zip _prev . length = 1 << zip _BITS ;
zip _dyn _ltree = [ ] ;
zip _dyn _ltree . length = zip _HEAP _SIZE ;
for ( i = 0 ; i < zip _HEAP _SIZE ; i ++ ) {
zip _dyn _ltree [ i ] = new Zip _DeflateCT
}
zip _dyn _dtree = [ ] ;
zip _dyn _dtree . length = 2 * zip _D _CODES + 1 ;
for ( i = 0 ; i < 2 * zip _D _CODES + 1 ; i ++ ) {
zip _dyn _dtree [ i ] = new Zip _DeflateCT
}
zip _static _ltree = [ ] ;
zip _static _ltree . length = zip _L _CODES + 2 ;
for ( i = 0 ; i < zip _L _CODES + 2 ; i ++ ) {
zip _static _ltree [ i ] = new Zip _DeflateCT
}
zip _static _dtree = [ ] ;
zip _static _dtree . length = zip _D _CODES ;
for ( i = 0 ; i < zip _D _CODES ; i ++ ) {
zip _static _dtree [ i ] = new Zip _DeflateCT
}
zip _bl _tree = [ ] ;
zip _bl _tree . length = 2 * zip _BL _CODES + 1 ;
for ( i = 0 ; i < 2 * zip _BL _CODES + 1 ; i ++ ) {
zip _bl _tree [ i ] = new Zip _DeflateCT
}
zip _l _desc = new Zip _DeflateTreeDesc ;
zip _d _desc = new Zip _DeflateTreeDesc ;
zip _bl _desc = new Zip _DeflateTreeDesc ;
zip _bl _count = [ ] ;
zip _bl _count . length = zip _MAX _BITS + 1 ;
zip _heap = [ ] ;
zip _heap . length = 2 * zip _L _CODES + 1 ;
zip _depth = [ ] ;
zip _depth . length = 2 * zip _L _CODES + 1 ;
zip _length _code = [ ] ;
zip _length _code . length = zip _MAX _MATCH - zip _MIN _MATCH + 1 ;
zip _dist _code = [ ] ;
zip _dist _code . length = 512 ;
zip _base _length = [ ] ;
zip _base _length . length = zip _LENGTH _CODES ;
zip _base _dist = [ ] ;
zip _base _dist . length = zip _D _CODES ;
zip _flag _buf = [ ] ;
zip _flag _buf . length = parseInt ( zip _LIT _BUFSIZE / 8 , 10 )
}
var zip _reuse _queue = function ( p ) {
p . next = zip _free _queue ;
zip _free _queue = p
} ;
var zip _new _queue = function ( ) {
var p ;
if ( zip _free _queue !== null ) {
p = zip _free _queue ;
zip _free _queue = zip _free _queue . next
} else {
p = new Zip _DeflateBuffer
}
p . next = null ;
p . len = p . off = 0 ;
return p
} ;
var zip _head1 = function ( i ) {
return zip _prev [ zip _WSIZE + i ]
} ;
var zip _head2 = function ( i , val ) {
zip _prev [ zip _WSIZE + i ] = val ;
return val
} ;
var zip _qoutbuf = function ( ) {
var q , i ;
if ( zip _outcnt !== 0 ) {
q = zip _new _queue ( ) ;
if ( zip _qhead === null ) {
zip _qhead = zip _qtail = q
} else {
zip _qtail = zip _qtail . next = q
}
q . len = zip _outcnt - zip _outoff ;
for ( i = 0 ; i < q . len ; i ++ ) {
q . ptr [ i ] = zip _outbuf [ zip _outoff + i ]
}
zip _outcnt = zip _outoff = 0
}
} ;
var zip _put _byte = function ( c ) {
zip _outbuf [ zip _outoff + zip _outcnt ++ ] = c ;
if ( zip _outoff + zip _outcnt === zip _OUTBUFSIZ ) {
zip _qoutbuf ( )
}
} ;
var zip _put _short = function ( w ) {
w &= 65535 ;
if ( zip _outoff + zip _outcnt < zip _OUTBUFSIZ - 2 ) {
zip _outbuf [ zip _outoff + zip _outcnt ++ ] = w & 255 ;
zip _outbuf [ zip _outoff + zip _outcnt ++ ] = w >>> 8
} else {
zip _put _byte ( w & 255 ) ;
zip _put _byte ( w >>> 8 )
}
} ;
var zip _INSERT _STRING = function ( ) {
zip _ins _h = ( zip _ins _h << zip _H _SHIFT ^ zip _window [ zip _strstart + zip _MIN _MATCH - 1 ] & 255 ) & zip _HASH _MASK ;
zip _hash _head = zip _head1 ( zip _ins _h ) ;
zip _prev [ zip _strstart & zip _WMASK ] = zip _hash _head ;
zip _head2 ( zip _ins _h , zip _strstart )
} ;
var zip _Buf _size = 16 ;
var zip _send _bits = function ( value , length ) {
if ( zip _bi _valid > zip _Buf _size - length ) {
zip _bi _buf |= value << zip _bi _valid ;
zip _put _short ( zip _bi _buf ) ;
zip _bi _buf = value >> zip _Buf _size - zip _bi _valid ;
zip _bi _valid += length - zip _Buf _size
} else {
zip _bi _buf |= value << zip _bi _valid ;
zip _bi _valid += length
}
} ;
var zip _SEND _CODE = function ( c , tree ) {
zip _send _bits ( tree [ c ] . fc , tree [ c ] . dl )
} ;
var zip _D _CODE = function ( dist ) {
return ( dist < 256 ? zip _dist _code [ dist ] : zip _dist _code [ 256 + ( dist >> 7 ) ] ) & 255
} ;
var zip _SMALLER = function ( tree , n , m ) {
return tree [ n ] . fc < tree [ m ] . fc || tree [ n ] . fc === tree [ m ] . fc && zip _depth [ n ] <= zip _depth [ m ]
} ;
var zip _read _buff = function ( buff , offset , n ) {
var i ;
for ( i = 0 ; i < n && zip _deflate _pos < zip _deflate _data . length ; i ++ ) {
buff [ offset + i ] = zip _deflate _data . charCodeAt ( zip _deflate _pos ++ ) & 255
}
return i
} ;
var zip _fill _window = function ( ) {
var n , m ;
var more = zip _window _size - zip _lookahead - zip _strstart ;
if ( more === - 1 ) {
more --
} else {
if ( zip _strstart >= zip _WSIZE + zip _MAX _DIST ) {
for ( n = 0 ; n < zip _WSIZE ; n ++ ) {
zip _window [ n ] = zip _window [ n + zip _WSIZE ]
}
zip _match _start -= zip _WSIZE ;
zip _strstart -= zip _WSIZE ;
zip _block _start -= zip _WSIZE ;
for ( n = 0 ; n < zip _HASH _SIZE ; n ++ ) {
m = zip _head1 ( n ) ;
zip _head2 ( n , m >= zip _WSIZE ? m - zip _WSIZE : zip _NIL )
}
for ( n = 0 ; n < zip _WSIZE ; n ++ ) {
m = zip _prev [ n ] ;
zip _prev [ n ] = m >= zip _WSIZE ? m - zip _WSIZE : zip _NIL
}
more += zip _WSIZE
}
}
if ( ! zip _eofile ) {
n = zip _read _buff ( zip _window , zip _strstart + zip _lookahead , more ) ;
if ( n <= 0 ) {
zip _eofile = true
} else {
zip _lookahead += n
}
}
} ;
var zip _lm _init = function ( ) {
var j ;
for ( j = 0 ; j < zip _HASH _SIZE ; j ++ ) {
zip _prev [ zip _WSIZE + j ] = 0
}
zip _max _lazy _match = zip _configuration _table [ zip _compr _level ] . max _lazy ;
zip _good _match = zip _configuration _table [ zip _compr _level ] . good _length ;
if ( ! zip _FULL _SEARCH ) {
zip _nice _match = zip _configuration _table [ zip _compr _level ] . nice _length
}
zip _max _chain _length = zip _configuration _table [ zip _compr _level ] . max _chain ;
zip _strstart = 0 ;
zip _block _start = 0 ;
zip _lookahead = zip _read _buff ( zip _window , 0 , 2 * zip _WSIZE ) ;
if ( zip _lookahead <= 0 ) {
zip _eofile = true ;
zip _lookahead = 0 ;
return
}
zip _eofile = false ;
while ( zip _lookahead < zip _MIN _LOOKAHEAD && ! zip _eofile ) {
zip _fill _window ( )
}
zip _ins _h = 0 ;
for ( j = 0 ; j < zip _MIN _MATCH - 1 ; j ++ ) {
zip _ins _h = ( zip _ins _h << zip _H _SHIFT ^ zip _window [ j ] & 255 ) & zip _HASH _MASK
}
} ;
var zip _longest _match = function ( cur _match ) {
var chain _length = zip _max _chain _length ;
var scanp = zip _strstart ;
var matchp ;
var len ;
var best _len = zip _prev _length ;
var limit = zip _strstart > zip _MAX _DIST ? zip _strstart - zip _MAX _DIST : zip _NIL ;
var strendp = zip _strstart + zip _MAX _MATCH ;
var scan _end1 = zip _window [ scanp + best _len - 1 ] ;
var scan _end = zip _window [ scanp + best _len ] ;
if ( zip _prev _length >= zip _good _match ) {
chain _length >>= 2
}
do {
matchp = cur _match ;
if ( zip _window [ matchp + best _len ] !== scan _end || zip _window [ matchp + best _len - 1 ] !== scan _end1 || zip _window [ matchp ] !== zip _window [ scanp ] || zip _window [ ++ matchp ] !== zip _window [ scanp + 1 ] ) {
continue
}
scanp += 2 ;
matchp ++ ;
do {
++ scanp
} while ( zip _window [ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && zip _window [ ++ scanp ] === zip _window [ ++ matchp ] && scanp < strendp ) ;
len = zip _MAX _MATCH - ( strendp - scanp ) ;
scanp = strendp - zip _MAX _MATCH ;
if ( len > best _len ) {
zip _match _start = cur _match ;
best _len = len ;
if ( zip _FULL _SEARCH ) {
if ( len >= zip _MAX _MATCH ) {
break
}
} else {
if ( len >= zip _nice _match ) {
break
}
}
scan _end1 = zip _window [ scanp + best _len - 1 ] ;
scan _end = zip _window [ scanp + best _len ]
}
cur _match = zip _prev [ cur _match & zip _WMASK ]
} while ( cur _match > limit && -- chain _length !== 0 ) ;
return best _len
} ;
var zip _ct _tally = function ( dist , lc ) {
zip _l _buf [ zip _last _lit ++ ] = lc ;
if ( dist === 0 ) {
zip _dyn _ltree [ lc ] . fc ++
} else {
dist -- ;
zip _dyn _ltree [ zip _length _code [ lc ] + zip _LITERALS + 1 ] . fc ++ ;
zip _dyn _dtree [ zip _D _CODE ( dist ) ] . fc ++ ;
zip _d _buf [ zip _last _dist ++ ] = dist ;
zip _flags |= zip _flag _bit
}
zip _flag _bit <<= 1 ;
if ( ( zip _last _lit & 7 ) === 0 ) {
zip _flag _buf [ zip _last _flags ++ ] = zip _flags ;
zip _flags = 0 ;
zip _flag _bit = 1
}
if ( zip _compr _level > 2 && ( zip _last _lit & 4095 ) === 0 ) {
var out _length = zip _last _lit * 8 ;
var in _length = zip _strstart - zip _block _start ;
var dcode ;
for ( dcode = 0 ; dcode < zip _D _CODES ; dcode ++ ) {
out _length += zip _dyn _dtree [ dcode ] . fc * ( 5 + zip _extra _dbits [ dcode ] )
}
out _length >>= 3 ;
if ( zip _last _dist < parseInt ( zip _last _lit / 2 , 10 ) && out _length < parseInt ( in _length / 2 , 10 ) ) {
return true
}
}
return zip _last _lit === zip _LIT _BUFSIZE - 1 || zip _last _dist === zip _DIST _BUFSIZE
} ;
var zip _pqdownheap = function ( tree , k ) {
var v = zip _heap [ k ] ;
var j = k << 1 ;
while ( j <= zip _heap _len ) {
if ( j < zip _heap _len && zip _SMALLER ( tree , zip _heap [ j + 1 ] , zip _heap [ j ] ) ) {
j ++
}
if ( zip _SMALLER ( tree , v , zip _heap [ j ] ) ) {
break
}
zip _heap [ k ] = zip _heap [ j ] ;
k = j ;
j <<= 1
}
zip _heap [ k ] = v
} ;
var zip _gen _bitlen = function ( desc ) {
var tree = desc . dyn _tree ;
var extra = desc . extra _bits ;
var base = desc . extra _base ;
var max _code = desc . max _code ;
var max _length = desc . max _length ;
var stree = desc . static _tree ;
var h ;
var n , m ;
var bits ;
var xbits ;
var f ;
var overflow = 0 ;
for ( bits = 0 ; bits <= zip _MAX _BITS ; bits ++ ) {
zip _bl _count [ bits ] = 0
}
tree [ zip _heap [ zip _heap _max ] ] . dl = 0 ;
for ( h = zip _heap _max + 1 ; h < zip _HEAP _SIZE ; h ++ ) {
n = zip _heap [ h ] ;
bits = tree [ tree [ n ] . dl ] . dl + 1 ;
if ( bits > max _length ) {
bits = max _length ;
overflow ++
}
tree [ n ] . dl = bits ;
if ( n > max _code ) {
continue
}
zip _bl _count [ bits ] ++ ;
xbits = 0 ;
if ( n >= base ) {
xbits = extra [ n - base ]
}
f = tree [ n ] . fc ;
zip _opt _len += f * ( bits + xbits ) ;
if ( stree !== null ) {
zip _static _len += f * ( stree [ n ] . dl + xbits )
}
}
if ( overflow === 0 ) {
return
}
do {
bits = max _length - 1 ;
while ( zip _bl _count [ bits ] === 0 ) {
bits --
}
zip _bl _count [ bits ] -- ;
zip _bl _count [ bits + 1 ] += 2 ;
zip _bl _count [ max _length ] -- ;
overflow -= 2
} while ( overflow > 0 ) ;
for ( bits = max _length ; bits !== 0 ; bits -- ) {
n = zip _bl _count [ bits ] ;
while ( n !== 0 ) {
m = zip _heap [ -- h ] ;
if ( m > max _code ) {
continue
}
if ( tree [ m ] . dl !== bits ) {
zip _opt _len += ( bits - tree [ m ] . dl ) * tree [ m ] . fc ;
tree [ m ] . fc = bits
}
n --
}
}
} ;
var zip _bi _reverse = function ( code , len ) {
var res = 0 ;
do {
res |= code & 1 ;
code >>= 1 ;
res <<= 1
} while ( -- len > 0 ) ;
return res >> 1
} ;
var zip _gen _codes = function ( tree , max _code ) {
var next _code = [ ] ;
next _code . length = zip _MAX _BITS + 1 ;
var code = 0 ;
var bits ;
var n ;
for ( bits = 1 ; bits <= zip _MAX _BITS ; bits ++ ) {
code = code + zip _bl _count [ bits - 1 ] << 1 ;
next _code [ bits ] = code
}
var len ;
for ( n = 0 ; n <= max _code ; n ++ ) {
len = tree [ n ] . dl ;
if ( len === 0 ) {
continue
}
tree [ n ] . fc = zip _bi _reverse ( next _code [ len ] ++ , len )
}
} ;
var zip _build _tree = function ( desc ) {
var tree = desc . dyn _tree ;
var stree = desc . static _tree ;
var elems = desc . elems ;
var n , m ;
var max _code = - 1 ;
var node = elems ;
zip _heap _len = 0 ;
zip _heap _max = zip _HEAP _SIZE ;
for ( n = 0 ; n < elems ; n ++ ) {
if ( tree [ n ] . fc !== 0 ) {
zip _heap [ ++ zip _heap _len ] = max _code = n ;
zip _depth [ n ] = 0
} else {
tree [ n ] . dl = 0
}
}
var xnew ;
while ( zip _heap _len < 2 ) {
xnew = zip _heap [ ++ zip _heap _len ] = max _code < 2 ? ++ max _code : 0 ;
tree [ xnew ] . fc = 1 ;
zip _depth [ xnew ] = 0 ;
zip _opt _len -- ;
if ( stree !== null ) {
zip _static _len -= stree [ xnew ] . dl
}
}
desc . max _code = max _code ;
for ( n = zip _heap _len >> 1 ; n >= 1 ; n -- ) {
zip _pqdownheap ( tree , n )
}
do {
n = zip _heap [ zip _SMALLEST ] ;
zip _heap [ zip _SMALLEST ] = zip _heap [ zip _heap _len -- ] ;
zip _pqdownheap ( tree , zip _SMALLEST ) ;
m = zip _heap [ zip _SMALLEST ] ;
zip _heap [ -- zip _heap _max ] = n ;
zip _heap [ -- zip _heap _max ] = m ;
tree [ node ] . fc = tree [ n ] . fc + tree [ m ] . fc ;
if ( zip _depth [ n ] > zip _depth [ m ] + 1 ) {
zip _depth [ node ] = zip _depth [ n ]
} else {
zip _depth [ node ] = zip _depth [ m ] + 1
}
tree [ n ] . dl = tree [ m ] . dl = node ;
zip _heap [ zip _SMALLEST ] = node ++ ;
zip _pqdownheap ( tree , zip _SMALLEST )
} while ( zip _heap _len >= 2 ) ;
zip _heap [ -- zip _heap _max ] = zip _heap [ zip _SMALLEST ] ;
zip _gen _bitlen ( desc ) ;
zip _gen _codes ( tree , max _code )
} ;
var zip _scan _tree = function ( tree , max _code ) {
var n ;
var prevlen = - 1 ;
var curlen ;
var nextlen = tree [ 0 ] . dl ;
var count = 0 ;
var max _count = 7 ;
var min _count = 4 ;
if ( nextlen === 0 ) {
max _count = 138 ;
min _count = 3
}
tree [ max _code + 1 ] . dl = 65535 ;
for ( n = 0 ; n <= max _code ; n ++ ) {
curlen = nextlen ;
nextlen = tree [ n + 1 ] . dl ;
if ( ++ count < max _count && curlen === nextlen ) {
continue
}
if ( count < min _count ) {
zip _bl _tree [ curlen ] . fc += count
} else {
if ( curlen !== 0 ) {
if ( curlen !== prevlen ) {
zip _bl _tree [ curlen ] . fc ++
}
zip _bl _tree [ zip _REP _3 _6 ] . fc ++
} else {
if ( count <= 10 ) {
zip _bl _tree [ zip _REPZ _3 _10 ] . fc ++
} else {
zip _bl _tree [ zip _REPZ _11 _138 ] . fc ++
}
}
}
count = 0 ;
prevlen = curlen ;
if ( nextlen === 0 ) {
max _count = 138 ;
min _count = 3
} else {
if ( curlen === nextlen ) {
max _count = 6 ;
min _count = 3
} else {
max _count = 7 ;
min _count = 4
}
}
}
} ;
var zip _build _bl _tree = function ( ) {
var max _blindex ;
zip _scan _tree ( zip _dyn _ltree , zip _l _desc . max _code ) ;
zip _scan _tree ( zip _dyn _dtree , zip _d _desc . max _code ) ;
zip _build _tree ( zip _bl _desc ) ;
for ( max _blindex = zip _BL _CODES - 1 ; max _blindex >= 3 ; max _blindex -- ) {
if ( zip _bl _tree [ zip _bl _order [ max _blindex ] ] . dl !== 0 ) {
break
}
}
zip _opt _len += 3 * ( max _blindex + 1 ) + 5 + 5 + 4 ;
return max _blindex
} ;
var zip _bi _windup = function ( ) {
if ( zip _bi _valid > 8 ) {
zip _put _short ( zip _bi _buf )
} else {
if ( zip _bi _valid > 0 ) {
zip _put _byte ( zip _bi _buf )
}
}
zip _bi _buf = 0 ;
zip _bi _valid = 0
} ;
var zip _compress _block = function ( ltree , dtree ) {
var dist ;
var lc ;
var lx = 0 ;
var dx = 0 ;
var fx = 0 ;
var flag = 0 ;
var code ;
var extra ;
if ( zip _last _lit !== 0 ) {
do {
if ( ( lx & 7 ) === 0 ) {
flag = zip _flag _buf [ fx ++ ]
}
lc = zip _l _buf [ lx ++ ] & 255 ;
if ( ( flag & 1 ) === 0 ) {
zip _SEND _CODE ( lc , ltree )
} else {
code = zip _length _code [ lc ] ;
zip _SEND _CODE ( code + zip _LITERALS + 1 , ltree ) ;
extra = zip _extra _lbits [ code ] ;
if ( extra !== 0 ) {
lc -= zip _base _length [ code ] ;
zip _send _bits ( lc , extra )
}
dist = zip _d _buf [ dx ++ ] ;
code = zip _D _CODE ( dist ) ;
zip _SEND _CODE ( code , dtree ) ;
extra = zip _extra _dbits [ code ] ;
if ( extra !== 0 ) {
dist -= zip _base _dist [ code ] ;
zip _send _bits ( dist , extra )
}
}
flag >>= 1
} while ( lx < zip _last _lit )
}
zip _SEND _CODE ( zip _END _BLOCK , ltree )
} ;
var zip _send _tree = function ( tree , max _code ) {
var n ;
var prevlen = - 1 ;
var curlen ;
var nextlen = tree [ 0 ] . dl ;
var count = 0 ;
var max _count = 7 ;
var min _count = 4 ;
if ( nextlen === 0 ) {
max _count = 138 ;
min _count = 3
}
for ( n = 0 ; n <= max _code ; n ++ ) {
curlen = nextlen ;
nextlen = tree [ n + 1 ] . dl ;
if ( ++ count < max _count && curlen === nextlen ) {
continue
}
if ( count < min _count ) {
do {
zip _SEND _CODE ( curlen , zip _bl _tree )
} while ( -- count !== 0 )
} else {
if ( curlen !== 0 ) {
if ( curlen !== prevlen ) {
zip _SEND _CODE ( curlen , zip _bl _tree ) ;
count --
}
zip _SEND _CODE ( zip _REP _3 _6 , zip _bl _tree ) ;
zip _send _bits ( count - 3 , 2 )
} else {
if ( count <= 10 ) {
zip _SEND _CODE ( zip _REPZ _3 _10 , zip _bl _tree ) ;
zip _send _bits ( count - 3 , 3 )
} else {
zip _SEND _CODE ( zip _REPZ _11 _138 , zip _bl _tree ) ;
zip _send _bits ( count - 11 , 7 )
}
}
}
count = 0 ;
prevlen = curlen ;
if ( nextlen === 0 ) {
max _count = 138 ;
min _count = 3
} else {
if ( curlen === nextlen ) {
max _count = 6 ;
min _count = 3
} else {
max _count = 7 ;
min _count = 4
}
}
}
} ;
var zip _send _all _trees = function ( lcodes , dcodes , blcodes ) {
var rank ;
zip _send _bits ( lcodes - 257 , 5 ) ;
zip _send _bits ( dcodes - 1 , 5 ) ;
zip _send _bits ( blcodes - 4 , 4 ) ;
for ( rank = 0 ; rank < blcodes ; rank ++ ) {
zip _send _bits ( zip _bl _tree [ zip _bl _order [ rank ] ] . dl , 3 )
}
zip _send _tree ( zip _dyn _ltree , lcodes - 1 ) ;
zip _send _tree ( zip _dyn _dtree , dcodes - 1 )
} ;
var zip _init _block = function ( ) {
var n ;
for ( n = 0 ; n < zip _L _CODES ; n ++ ) {
zip _dyn _ltree [ n ] . fc = 0
}
for ( n = 0 ; n < zip _D _CODES ; n ++ ) {
zip _dyn _dtree [ n ] . fc = 0
}
for ( n = 0 ; n < zip _BL _CODES ; n ++ ) {
zip _bl _tree [ n ] . fc = 0
}
zip _dyn _ltree [ zip _END _BLOCK ] . fc = 1 ;
zip _opt _len = zip _static _len = 0 ;
zip _last _lit = zip _last _dist = zip _last _flags = 0 ;
zip _flags = 0 ;
zip _flag _bit = 1
} ;
var zip _flush _block = function ( eof ) {
var opt _lenb , static _lenb ;
var max _blindex ;
var stored _len ;
stored _len = zip _strstart - zip _block _start ;
zip _flag _buf [ zip _last _flags ] = zip _flags ;
zip _build _tree ( zip _l _desc ) ;
zip _build _tree ( zip _d _desc ) ;
max _blindex = zip _build _bl _tree ( ) ;
opt _lenb = zip _opt _len + 3 + 7 >> 3 ;
static _lenb = zip _static _len + 3 + 7 >> 3 ;
if ( static _lenb <= opt _lenb ) {
opt _lenb = static _lenb
}
if ( stored _len + 4 <= opt _lenb && zip _block _start >= 0 ) {
var i ;
zip _send _bits ( ( zip _STORED _BLOCK << 1 ) + eof , 3 ) ;
zip _bi _windup ( ) ;
zip _put _short ( stored _len ) ;
zip _put _short ( ~ stored _len ) ;
for ( i = 0 ; i < stored _len ; i ++ ) {
zip _put _byte ( zip _window [ zip _block _start + i ] )
}
} else {
if ( static _lenb === opt _lenb ) {
zip _send _bits ( ( zip _STATIC _TREES << 1 ) + eof , 3 ) ;
zip _compress _block ( zip _static _ltree , zip _static _dtree )
} else {
zip _send _bits ( ( zip _DYN _TREES << 1 ) + eof , 3 ) ;
zip _send _all _trees ( zip _l _desc . max _code + 1 , zip _d _desc . max _code + 1 , max _blindex + 1 ) ;
zip _compress _block ( zip _dyn _ltree , zip _dyn _dtree )
}
}
zip _init _block ( ) ;
if ( eof !== 0 ) {
zip _bi _windup ( )
}
} ;
var zip _deflate _fast = function ( ) {
var flush ;
while ( zip _lookahead !== 0 && zip _qhead === null ) {
zip _INSERT _STRING ( ) ;
if ( zip _hash _head !== zip _NIL && zip _strstart - zip _hash _head <= zip _MAX _DIST ) {
zip _match _length = zip _longest _match ( zip _hash _head ) ;
if ( zip _match _length > zip _lookahead ) {
zip _match _length = zip _lookahead
}
}
if ( zip _match _length >= zip _MIN _MATCH ) {
flush = zip _ct _tally ( zip _strstart - zip _match _start , zip _match _length - zip _MIN _MATCH ) ;
zip _lookahead -= zip _match _length ;
if ( zip _match _length <= zip _max _lazy _match ) {
zip _match _length -- ;
do {
zip _strstart ++ ;
zip _INSERT _STRING ( )
} while ( -- zip _match _length !== 0 ) ;
zip _strstart ++
} else {
zip _strstart += zip _match _length ;
zip _match _length = 0 ;
zip _ins _h = zip _window [ zip _strstart ] & 255 ;
zip _ins _h = ( zip _ins _h << zip _H _SHIFT ^ zip _window [ zip _strstart + 1 ] & 255 ) & zip _HASH _MASK
}
} else {
flush = zip _ct _tally ( 0 , zip _window [ zip _strstart ] & 255 ) ;
zip _lookahead -- ;
zip _strstart ++
}
if ( flush ) {
zip _flush _block ( 0 ) ;
zip _block _start = zip _strstart
}
while ( zip _lookahead < zip _MIN _LOOKAHEAD && ! zip _eofile ) {
zip _fill _window ( )
}
}
} ;
var zip _deflate _better = function ( ) {
var flush ;
while ( zip _lookahead !== 0 && zip _qhead === null ) {
zip _INSERT _STRING ( ) ;
zip _prev _length = zip _match _length ;
zip _prev _match = zip _match _start ;
zip _match _length = zip _MIN _MATCH - 1 ;
if ( zip _hash _head !== zip _NIL && zip _prev _length < zip _max _lazy _match && zip _strstart - zip _hash _head <= zip _MAX _DIST ) {
zip _match _length = zip _longest _match ( zip _hash _head ) ;
if ( zip _match _length > zip _lookahead ) {
zip _match _length = zip _lookahead
}
if ( zip _match _length === zip _MIN _MATCH && zip _strstart - zip _match _start > zip _TOO _FAR ) {
zip _match _length --
}
}
if ( zip _prev _length >= zip _MIN _MATCH && zip _match _length <= zip _prev _length ) {
flush = zip _ct _tally ( zip _strstart - 1 - zip _prev _match , zip _prev _length - zip _MIN _MATCH ) ;
zip _lookahead -= zip _prev _length - 1 ;
zip _prev _length -= 2 ;
do {
zip _strstart ++ ;
zip _INSERT _STRING ( )
} while ( -- zip _prev _length !== 0 ) ;
zip _match _available = 0 ;
zip _match _length = zip _MIN _MATCH - 1 ;
zip _strstart ++ ;
if ( flush ) {
zip _flush _block ( 0 ) ;
zip _block _start = zip _strstart
}
} else {
if ( zip _match _available !== 0 ) {
if ( zip _ct _tally ( 0 , zip _window [ zip _strstart - 1 ] & 255 ) ) {
zip _flush _block ( 0 ) ;
zip _block _start = zip _strstart
}
zip _strstart ++ ;
zip _lookahead --
} else {
zip _match _available = 1 ;
zip _strstart ++ ;
zip _lookahead --
}
}
while ( zip _lookahead < zip _MIN _LOOKAHEAD && ! zip _eofile ) {
zip _fill _window ( )
}
}
} ;
var zip _ct _init = function ( ) {
var n ;
var bits ;
var length ;
var code ;
var dist ;
if ( zip _static _dtree [ 0 ] . dl !== 0 ) {
return
}
zip _l _desc . dyn _tree = zip _dyn _ltree ;
zip _l _desc . static _tree = zip _static _ltree ;
zip _l _desc . extra _bits = zip _extra _lbits ;
zip _l _desc . extra _base = zip _LITERALS + 1 ;
zip _l _desc . elems = zip _L _CODES ;
zip _l _desc . max _length = zip _MAX _BITS ;
zip _l _desc . max _code = 0 ;
zip _d _desc . dyn _tree = zip _dyn _dtree ;
zip _d _desc . static _tree = zip _static _dtree ;
zip _d _desc . extra _bits = zip _extra _dbits ;
zip _d _desc . extra _base = 0 ;
zip _d _desc . elems = zip _D _CODES ;
zip _d _desc . max _length = zip _MAX _BITS ;
zip _d _desc . max _code = 0 ;
zip _bl _desc . dyn _tree = zip _bl _tree ;
zip _bl _desc . static _tree = null ;
zip _bl _desc . extra _bits = zip _extra _blbits ;
zip _bl _desc . extra _base = 0 ;
zip _bl _desc . elems = zip _BL _CODES ;
zip _bl _desc . max _length = zip _MAX _BL _BITS ;
zip _bl _desc . max _code = 0 ;
length = 0 ;
for ( code = 0 ; code < zip _LENGTH _CODES - 1 ; code ++ ) {
zip _base _length [ code ] = length ;
for ( n = 0 ; n < 1 << zip _extra _lbits [ code ] ; n ++ ) {
zip _length _code [ length ++ ] = code
}
}
zip _length _code [ length - 1 ] = code ;
dist = 0 ;
for ( code = 0 ; code < 16 ; code ++ ) {
zip _base _dist [ code ] = dist ;
for ( n = 0 ; n < 1 << zip _extra _dbits [ code ] ; n ++ ) {
zip _dist _code [ dist ++ ] = code
}
}
dist >>= 7 ;
n = code ;
for ( code = n ; code < zip _D _CODES ; code ++ ) {
zip _base _dist [ code ] = dist << 7 ;
for ( n = 0 ; n < 1 << zip _extra _dbits [ code ] - 7 ; n ++ ) {
zip _dist _code [ 256 + dist ++ ] = code
}
}
for ( bits = 0 ; bits <= zip _MAX _BITS ; bits ++ ) {
zip _bl _count [ bits ] = 0
}
n = 0 ;
while ( n <= 143 ) {
zip _static _ltree [ n ++ ] . dl = 8 ;
zip _bl _count [ 8 ] ++
}
while ( n <= 255 ) {
zip _static _ltree [ n ++ ] . dl = 9 ;
zip _bl _count [ 9 ] ++
}
while ( n <= 279 ) {
zip _static _ltree [ n ++ ] . dl = 7 ;
zip _bl _count [ 7 ] ++
}
while ( n <= 287 ) {
zip _static _ltree [ n ++ ] . dl = 8 ;
zip _bl _count [ 8 ] ++
}
zip _gen _codes ( zip _static _ltree , zip _L _CODES + 1 ) ;
for ( n = 0 ; n < zip _D _CODES ; n ++ ) {
zip _static _dtree [ n ] . dl = 5 ;
zip _static _dtree [ n ] . fc = zip _bi _reverse ( n , 5 )
}
zip _init _block ( )
} ;
var zip _init _deflate = function ( ) {
if ( zip _eofile ) {
return
}
zip _bi _buf = 0 ;
zip _bi _valid = 0 ;
zip _ct _init ( ) ;
zip _lm _init ( ) ;
zip _qhead = null ;
zip _outcnt = 0 ;
zip _outoff = 0 ;
if ( zip _compr _level <= 3 ) {
zip _prev _length = zip _MIN _MATCH - 1 ;
zip _match _length = 0
} else {
zip _match _length = zip _MIN _MATCH - 1 ;
zip _match _available = 0
}
zip _complete = false
} ;
var zip _qcopy = function ( buff , off , buff _size ) {
var n , i , j , p ;
n = 0 ;
while ( zip _qhead !== null && n < buff _size ) {
i = buff _size - n ;
if ( i > zip _qhead . len ) {
i = zip _qhead . len
}
for ( j = 0 ; j < i ; j ++ ) {
buff [ off + n + j ] = zip _qhead . ptr [ zip _qhead . off + j ]
}
zip _qhead . off += i ;
zip _qhead . len -= i ;
n += i ;
if ( zip _qhead . len === 0 ) {
p = zip _qhead ;
zip _qhead = zip _qhead . next ;
zip _reuse _queue ( p )
}
}
if ( n === buff _size ) {
return n
}
if ( zip _outoff < zip _outcnt ) {
i = buff _size - n ;
if ( i > zip _outcnt - zip _outoff ) {
i = zip _outcnt - zip _outoff
}
for ( j = 0 ; j < i ; j ++ ) {
buff [ off + n + j ] = zip _outbuf [ zip _outoff + j ]
}
zip _outoff += i ;
n += i ;
if ( zip _outcnt === zip _outoff ) {
zip _outcnt = zip _outoff = 0
}
}
return n
} ;
var zip _deflate _internal = function ( buff , off , buff _size ) {
var n ;
if ( ! zip _initflag ) {
zip _init _deflate ( ) ;
zip _initflag = true ;
if ( zip _lookahead === 0 ) {
zip _complete = true ;
return 0
}
}
n = zip _qcopy ( buff , off , buff _size ) ;
if ( n === buff _size ) {
return buff _size
}
if ( zip _complete ) {
return n
}
if ( zip _compr _level <= 3 ) {
zip _deflate _fast ( )
} else {
zip _deflate _better ( )
}
if ( zip _lookahead === 0 ) {
if ( zip _match _available !== 0 ) {
zip _ct _tally ( 0 , zip _window [ zip _strstart - 1 ] & 255 )
}
zip _flush _block ( 1 ) ;
zip _complete = true
}
return n + zip _qcopy ( buff , n + off , buff _size - n )
} ;
var zip _deflate = function ( str , level ) {
var i , j ;
zip _deflate _data = str ;
zip _deflate _pos = 0 ;
if ( String ( typeof level ) === "undefined" ) {
level = zip _DEFAULT _LEVEL
}
zip _deflate _start ( level ) ;
var buff = new Array ( 1024 ) ;
var aout = [ ] , cbuf = [ ] ;
i = zip _deflate _internal ( buff , 0 , buff . length ) ;
while ( i > 0 ) {
cbuf . length = i ;
for ( j = 0 ; j < i ; j ++ ) {
cbuf [ j ] = String . fromCharCode ( buff [ j ] )
}
aout [ aout . length ] = cbuf . join ( "" ) ;
i = zip _deflate _internal ( buff , 0 , buff . length )
}
zip _deflate _data = null ;
return aout . join ( "" )
} ;
this . deflate = zip _deflate
} ;
core . ByteArray = function ByteArray ( data ) {
this . pos = 0 ;
this . data = data ;
this . readUInt32LE = function ( ) {
this . pos += 4 ;
var d = this . data , pos = this . pos ;
return d [ -- pos ] << 24 | d [ -- pos ] << 16 | d [ -- pos ] << 8 | d [ -- pos ]
} ;
this . readUInt16LE = function ( ) {
this . pos += 2 ;
var d = this . data , pos = this . pos ;
return d [ -- pos ] << 8 | d [ -- pos ]
}
} ;
core . ByteArrayWriter = function ByteArrayWriter ( encoding ) {
var self = this , data = new runtime . ByteArray ( 0 ) ;
this . appendByteArrayWriter = function ( writer ) {
data = runtime . concatByteArrays ( data , writer . getByteArray ( ) )
} ;
this . appendByteArray = function ( array ) {
data = runtime . concatByteArrays ( data , array )
} ;
this . appendArray = function ( array ) {
data = runtime . concatByteArrays ( data , runtime . byteArrayFromArray ( array ) )
} ;
this . appendUInt16LE = function ( value ) {
self . appendArray ( [ value & 255 , value >> 8 & 255 ] )
} ;
this . appendUInt32LE = function ( value ) {
self . appendArray ( [ value & 255 , value >> 8 & 255 , value >> 16 & 255 , value >> 24 & 255 ] )
} ;
this . appendString = function ( string ) {
data = runtime . concatByteArrays ( data , runtime . byteArrayFromString ( string , encoding ) )
} ;
this . getLength = function ( ) {
return data . length
} ;
this . getByteArray = function ( ) {
return data
}
} ;
core . RawInflate = function RawInflate ( ) {
var zip _WSIZE = 32768 ;
var zip _STORED _BLOCK = 0 ;
var zip _STATIC _TREES = 1 ;
var zip _DYN _TREES = 2 ;
var zip _lbits = 9 ;
var zip _dbits = 6 ;
var zip _INBUFSIZ = 32768 ;
var zip _INBUF _EXTRA = 64 ;
var zip _slide ;
var zip _wp ;
var zip _fixed _tl = null ;
var zip _fixed _td ;
var zip _fixed _bl , fixed _bd ;
var zip _bit _buf ;
var zip _bit _len ;
var zip _method ;
var zip _eof ;
var zip _copy _leng ;
var zip _copy _dist ;
var zip _tl , zip _td ;
var zip _bl , zip _bd ;
var zip _inflate _data ;
var zip _inflate _pos ;
var zip _MASK _BITS = new Array ( 0 , 1 , 3 , 7 , 15 , 31 , 63 , 127 , 255 , 511 , 1023 , 2047 , 4095 , 8191 , 16383 , 32767 , 65535 ) ;
var zip _cplens = new Array ( 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 13 , 15 , 17 , 19 , 23 , 27 , 31 , 35 , 43 , 51 , 59 , 67 , 83 , 99 , 115 , 131 , 163 , 195 , 227 , 258 , 0 , 0 ) ;
var zip _cplext = new Array ( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 2 , 3 , 3 , 3 , 3 , 4 , 4 , 4 , 4 , 5 , 5 , 5 , 5 , 0 , 99 , 99 ) ;
var zip _cpdist = new Array ( 1 , 2 , 3 , 4 , 5 , 7 , 9 , 13 , 17 , 25 , 33 , 49 , 65 , 97 , 129 , 193 , 257 , 385 , 513 , 769 , 1025 , 1537 , 2049 , 3073 , 4097 , 6145 , 8193 , 12289 , 16385 , 24577 ) ;
var zip _cpdext = new Array ( 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , 5 , 5 , 6 , 6 , 7 , 7 , 8 , 8 , 9 , 9 , 10 , 10 , 11 , 11 , 12 , 12 , 13 , 13 ) ;
var zip _border = new Array ( 16 , 17 , 18 , 0 , 8 , 7 , 9 , 6 , 10 , 5 , 11 , 4 , 12 , 3 , 13 , 2 , 14 , 1 , 15 ) ;
var zip _HuftList = function ( ) {
this . next = null ;
this . list = null
} ;
var zip _HuftNode = function ( ) {
this . e = 0 ;
this . b = 0 ;
this . n = 0 ;
this . t = null
} ;
var zip _HuftBuild = function ( b , n , s , d , e , mm ) {
this . BMAX = 16 ;
this . N _MAX = 288 ;
this . status = 0 ;
this . root = null ;
this . m = 0 ;
var a ;
var c = new Array ( this . BMAX + 1 ) ;
var el ;
var f ;
var g ;
var h ;
var i ;
var j ;
var k ;
var lx = new Array ( this . BMAX + 1 ) ;
var p ;
var pidx ;
var q ;
var r = new zip _HuftNode ;
var u = new Array ( this . BMAX ) ;
var v = new Array ( this . N _MAX ) ;
var w ;
var x = new Array ( this . BMAX + 1 ) ;
var xp ;
var y ;
var z ;
var o ;
var tail ;
tail = this . root = null ;
for ( i = 0 ; i < c . length ; i ++ ) {
c [ i ] = 0
}
for ( i = 0 ; i < lx . length ; i ++ ) {
lx [ i ] = 0
}
for ( i = 0 ; i < u . length ; i ++ ) {
u [ i ] = null
}
for ( i = 0 ; i < v . length ; i ++ ) {
v [ i ] = 0
}
for ( i = 0 ; i < x . length ; i ++ ) {
x [ i ] = 0
}
el = n > 256 ? b [ 256 ] : this . BMAX ;
p = b ;
pidx = 0 ;
i = n ;
do {
c [ p [ pidx ] ] ++ ;
pidx ++
} while ( -- i > 0 ) ;
if ( c [ 0 ] == n ) {
this . root = null ;
this . m = 0 ;
this . status = 0 ;
return
}
for ( j = 1 ; j <= this . BMAX ; j ++ ) {
if ( c [ j ] != 0 ) {
break
}
}
k = j ;
if ( mm < j ) {
mm = j
}
for ( i = this . BMAX ; i != 0 ; i -- ) {
if ( c [ i ] != 0 ) {
break
}
}
g = i ;
if ( mm > i ) {
mm = i
}
for ( y = 1 << j ; j < i ; j ++ , y <<= 1 ) {
if ( ( y -= c [ j ] ) < 0 ) {
this . status = 2 ;
this . m = mm ;
return
}
}
if ( ( y -= c [ i ] ) < 0 ) {
this . status = 2 ;
this . m = mm ;
return
}
c [ i ] += y ;
x [ 1 ] = j = 0 ;
p = c ;
pidx = 1 ;
xp = 2 ;
while ( -- i > 0 ) {
x [ xp ++ ] = j += p [ pidx ++ ]
}
p = b ;
pidx = 0 ;
i = 0 ;
do {
if ( ( j = p [ pidx ++ ] ) != 0 ) {
v [ x [ j ] ++ ] = i
}
} while ( ++ i < n ) ;
n = x [ g ] ;
x [ 0 ] = i = 0 ;
p = v ;
pidx = 0 ;
h = - 1 ;
w = lx [ 0 ] = 0 ;
q = null ;
z = 0 ;
for ( ; k <= g ; k ++ ) {
a = c [ k ] ;
while ( a -- > 0 ) {
while ( k > w + lx [ 1 + h ] ) {
w += lx [ 1 + h ] ;
h ++ ;
z = ( z = g - w ) > mm ? mm : z ;
if ( ( f = 1 << ( j = k - w ) ) > a + 1 ) {
f -= a + 1 ;
xp = k ;
while ( ++ j < z ) {
if ( ( f <<= 1 ) <= c [ ++ xp ] ) {
break
}
f -= c [ xp ]
}
}
if ( w + j > el && w < el ) {
j = el - w
}
z = 1 << j ;
lx [ 1 + h ] = j ;
q = new Array ( z ) ;
for ( o = 0 ; o < z ; o ++ ) {
q [ o ] = new zip _HuftNode
}
if ( tail == null ) {
tail = this . root = new zip _HuftList
} else {
tail = tail . next = new zip _HuftList
}
tail . next = null ;
tail . list = q ;
u [ h ] = q ;
if ( h > 0 ) {
x [ h ] = i ;
r . b = lx [ h ] ;
r . e = 16 + j ;
r . t = q ;
j = ( i & ( 1 << w ) - 1 ) >> w - lx [ h ] ;
u [ h - 1 ] [ j ] . e = r . e ;
u [ h - 1 ] [ j ] . b = r . b ;
u [ h - 1 ] [ j ] . n = r . n ;
u [ h - 1 ] [ j ] . t = r . t
}
}
r . b = k - w ;
if ( pidx >= n ) {
r . e = 99
} else {
if ( p [ pidx ] < s ) {
r . e = p [ pidx ] < 256 ? 16 : 15 ;
r . n = p [ pidx ++ ]
} else {
r . e = e [ p [ pidx ] - s ] ;
r . n = d [ p [ pidx ++ ] - s ]
}
}
f = 1 << k - w ;
for ( j = i >> w ; j < z ; j += f ) {
q [ j ] . e = r . e ;
q [ j ] . b = r . b ;
q [ j ] . n = r . n ;
q [ j ] . t = r . t
}
for ( j = 1 << k - 1 ; ( i & j ) != 0 ; j >>= 1 ) {
i ^= j
}
i ^= j ;
while ( ( i & ( 1 << w ) - 1 ) != x [ h ] ) {
w -= lx [ h ] ;
h --
}
}
}
this . m = lx [ 1 ] ;
this . status = y != 0 && g != 1 ? 1 : 0
} ;
var zip _GET _BYTE = function ( ) {
if ( zip _inflate _data . length == zip _inflate _pos ) {
return - 1
}
return zip _inflate _data [ zip _inflate _pos ++ ]
} ;
var zip _NEEDBITS = function ( n ) {
while ( zip _bit _len < n ) {
zip _bit _buf |= zip _GET _BYTE ( ) << zip _bit _len ;
zip _bit _len += 8
}
} ;
var zip _GETBITS = function ( n ) {
return zip _bit _buf & zip _MASK _BITS [ n ]
} ;
var zip _DUMPBITS = function ( n ) {
zip _bit _buf >>= n ;
zip _bit _len -= n
} ;
var zip _inflate _codes = function ( buff , off , size ) {
var e ;
var t ;
var n ;
if ( size == 0 ) {
return 0
}
n = 0 ;
for ( ; ; ) {
zip _NEEDBITS ( zip _bl ) ;
t = zip _tl . list [ zip _GETBITS ( zip _bl ) ] ;
e = t . e ;
while ( e > 16 ) {
if ( e == 99 ) {
return - 1
}
zip _DUMPBITS ( t . b ) ;
e -= 16 ;
zip _NEEDBITS ( e ) ;
t = t . t [ zip _GETBITS ( e ) ] ;
e = t . e
}
zip _DUMPBITS ( t . b ) ;
if ( e == 16 ) {
zip _wp &= zip _WSIZE - 1 ;
buff [ off + n ++ ] = zip _slide [ zip _wp ++ ] = t . n ;
if ( n == size ) {
return size
}
continue
}
if ( e == 15 ) {
break
}
zip _NEEDBITS ( e ) ;
zip _copy _leng = t . n + zip _GETBITS ( e ) ;
zip _DUMPBITS ( e ) ;
zip _NEEDBITS ( zip _bd ) ;
t = zip _td . list [ zip _GETBITS ( zip _bd ) ] ;
e = t . e ;
while ( e > 16 ) {
if ( e == 99 ) {
return - 1
}
zip _DUMPBITS ( t . b ) ;
e -= 16 ;
zip _NEEDBITS ( e ) ;
t = t . t [ zip _GETBITS ( e ) ] ;
e = t . e
}
zip _DUMPBITS ( t . b ) ;
zip _NEEDBITS ( e ) ;
zip _copy _dist = zip _wp - t . n - zip _GETBITS ( e ) ;
zip _DUMPBITS ( e ) ;
while ( zip _copy _leng > 0 && n < size ) {
zip _copy _leng -- ;
zip _copy _dist &= zip _WSIZE - 1 ;
zip _wp &= zip _WSIZE - 1 ;
buff [ off + n ++ ] = zip _slide [ zip _wp ++ ] = zip _slide [ zip _copy _dist ++ ]
}
if ( n == size ) {
return size
}
}
zip _method = - 1 ;
return n
} ;
var zip _inflate _stored = function ( buff , off , size ) {
var n ;
n = zip _bit _len & 7 ;
zip _DUMPBITS ( n ) ;
zip _NEEDBITS ( 16 ) ;
n = zip _GETBITS ( 16 ) ;
zip _DUMPBITS ( 16 ) ;
zip _NEEDBITS ( 16 ) ;
if ( n != ( ~ zip _bit _buf & 65535 ) ) {
return - 1
}
zip _DUMPBITS ( 16 ) ;
zip _copy _leng = n ;
n = 0 ;
while ( zip _copy _leng > 0 && n < size ) {
zip _copy _leng -- ;
zip _wp &= zip _WSIZE - 1 ;
zip _NEEDBITS ( 8 ) ;
buff [ off + n ++ ] = zip _slide [ zip _wp ++ ] = zip _GETBITS ( 8 ) ;
zip _DUMPBITS ( 8 )
}
if ( zip _copy _leng == 0 ) {
zip _method = - 1
}
return n
} ;
var zip _fixed _bd ;
var zip _inflate _fixed = function ( buff , off , size ) {
if ( zip _fixed _tl == null ) {
var i ;
var l = new Array ( 288 ) ;
var h ;
for ( i = 0 ; i < 144 ; i ++ ) {
l [ i ] = 8
}
for ( ; i < 256 ; i ++ ) {
l [ i ] = 9
}
for ( ; i < 280 ; i ++ ) {
l [ i ] = 7
}
for ( ; i < 288 ; i ++ ) {
l [ i ] = 8
}
zip _fixed _bl = 7 ;
h = new zip _HuftBuild ( l , 288 , 257 , zip _cplens , zip _cplext , zip _fixed _bl ) ;
if ( h . status != 0 ) {
alert ( "HufBuild error: " + h . status ) ;
return - 1
}
zip _fixed _tl = h . root ;
zip _fixed _bl = h . m ;
for ( i = 0 ; i < 30 ; i ++ ) {
l [ i ] = 5
}
zip _fixed _bd = 5 ;
h = new zip _HuftBuild ( l , 30 , 0 , zip _cpdist , zip _cpdext , zip _fixed _bd ) ;
if ( h . status > 1 ) {
zip _fixed _tl = null ;
alert ( "HufBuild error: " + h . status ) ;
return - 1
}
zip _fixed _td = h . root ;
zip _fixed _bd = h . m
}
zip _tl = zip _fixed _tl ;
zip _td = zip _fixed _td ;
zip _bl = zip _fixed _bl ;
zip _bd = zip _fixed _bd ;
return zip _inflate _codes ( buff , off , size )
} ;
var zip _inflate _dynamic = function ( buff , off , size ) {
var i ;
var j ;
var l ;
var n ;
var t ;
var nb ;
var nl ;
var nd ;
var ll = new Array ( 286 + 30 ) ;
var h ;
for ( i = 0 ; i < ll . length ; i ++ ) {
ll [ i ] = 0
}
zip _NEEDBITS ( 5 ) ;
nl = 257 + zip _GETBITS ( 5 ) ;
zip _DUMPBITS ( 5 ) ;
zip _NEEDBITS ( 5 ) ;
nd = 1 + zip _GETBITS ( 5 ) ;
zip _DUMPBITS ( 5 ) ;
zip _NEEDBITS ( 4 ) ;
nb = 4 + zip _GETBITS ( 4 ) ;
zip _DUMPBITS ( 4 ) ;
if ( nl > 286 || nd > 30 ) {
return - 1
}
for ( j = 0 ; j < nb ; j ++ ) {
zip _NEEDBITS ( 3 ) ;
ll [ zip _border [ j ] ] = zip _GETBITS ( 3 ) ;
zip _DUMPBITS ( 3 )
}
for ( ; j < 19 ; j ++ ) {
ll [ zip _border [ j ] ] = 0
}
zip _bl = 7 ;
h = new zip _HuftBuild ( ll , 19 , 19 , null , null , zip _bl ) ;
if ( h . status != 0 ) {
return - 1
}
zip _tl = h . root ;
zip _bl = h . m ;
n = nl + nd ;
i = l = 0 ;
while ( i < n ) {
zip _NEEDBITS ( zip _bl ) ;
t = zip _tl . list [ zip _GETBITS ( zip _bl ) ] ;
j = t . b ;
zip _DUMPBITS ( j ) ;
j = t . n ;
if ( j < 16 ) {
ll [ i ++ ] = l = j
} else {
if ( j == 16 ) {
zip _NEEDBITS ( 2 ) ;
j = 3 + zip _GETBITS ( 2 ) ;
zip _DUMPBITS ( 2 ) ;
if ( i + j > n ) {
return - 1
}
while ( j -- > 0 ) {
ll [ i ++ ] = l
}
} else {
if ( j == 17 ) {
zip _NEEDBITS ( 3 ) ;
j = 3 + zip _GETBITS ( 3 ) ;
zip _DUMPBITS ( 3 ) ;
if ( i + j > n ) {
return - 1
}
while ( j -- > 0 ) {
ll [ i ++ ] = 0
}
l = 0
} else {
zip _NEEDBITS ( 7 ) ;
j = 11 + zip _GETBITS ( 7 ) ;
zip _DUMPBITS ( 7 ) ;
if ( i + j > n ) {
return - 1
}
while ( j -- > 0 ) {
ll [ i ++ ] = 0
}
l = 0
}
}
}
}
zip _bl = zip _lbits ;
h = new zip _HuftBuild ( ll , nl , 257 , zip _cplens , zip _cplext , zip _bl ) ;
if ( zip _bl == 0 ) {
h . status = 1
}
if ( h . status != 0 ) {
return - 1
}
zip _tl = h . root ;
zip _bl = h . m ;
for ( i = 0 ; i < nd ; i ++ ) {
ll [ i ] = ll [ i + nl ]
}
zip _bd = zip _dbits ;
h = new zip _HuftBuild ( ll , nd , 0 , zip _cpdist , zip _cpdext , zip _bd ) ;
zip _td = h . root ;
zip _bd = h . m ;
if ( zip _bd == 0 && nl > 257 ) {
return - 1
}
if ( h . status != 0 ) {
return - 1
}
return zip _inflate _codes ( buff , off , size )
} ;
var zip _inflate _start = function ( ) {
var i ;
if ( zip _slide == null ) {
zip _slide = new Array ( 2 * zip _WSIZE )
}
zip _wp = 0 ;
zip _bit _buf = 0 ;
zip _bit _len = 0 ;
zip _method = - 1 ;
zip _eof = false ;
zip _copy _leng = zip _copy _dist = 0 ;
zip _tl = null
} ;
var zip _inflate _internal = function ( buff , off , size ) {
var n , i ;
n = 0 ;
while ( n < size ) {
if ( zip _eof && zip _method == - 1 ) {
return n
}
if ( zip _copy _leng > 0 ) {
if ( zip _method != zip _STORED _BLOCK ) {
while ( zip _copy _leng > 0 && n < size ) {
zip _copy _leng -- ;
zip _copy _dist &= zip _WSIZE - 1 ;
zip _wp &= zip _WSIZE - 1 ;
buff [ off + n ++ ] = zip _slide [ zip _wp ++ ] = zip _slide [ zip _copy _dist ++ ]
}
} else {
while ( zip _copy _leng > 0 && n < size ) {
zip _copy _leng -- ;
zip _wp &= zip _WSIZE - 1 ;
zip _NEEDBITS ( 8 ) ;
buff [ off + n ++ ] = zip _slide [ zip _wp ++ ] = zip _GETBITS ( 8 ) ;
zip _DUMPBITS ( 8 )
}
if ( zip _copy _leng == 0 ) {
zip _method = - 1
}
}
if ( n == size ) {
return n
}
}
if ( zip _method == - 1 ) {
if ( zip _eof ) {
break
}
zip _NEEDBITS ( 1 ) ;
if ( zip _GETBITS ( 1 ) != 0 ) {
zip _eof = true
}
zip _DUMPBITS ( 1 ) ;
zip _NEEDBITS ( 2 ) ;
zip _method = zip _GETBITS ( 2 ) ;
zip _DUMPBITS ( 2 ) ;
zip _tl = null ;
zip _copy _leng = 0
}
switch ( zip _method ) {
case 0 :
i = zip _inflate _stored ( buff , off + n , size - n ) ;
break ;
case 1 :
if ( zip _tl != null ) {
i = zip _inflate _codes ( buff , off + n , size - n )
} else {
i = zip _inflate _fixed ( buff , off + n , size - n )
}
break ;
case 2 :
if ( zip _tl != null ) {
i = zip _inflate _codes ( buff , off + n , size - n )
} else {
i = zip _inflate _dynamic ( buff , off + n , size - n )
}
break ;
default :
i = - 1 ;
break
}
if ( i == - 1 ) {
if ( zip _eof ) {
return 0
}
return - 1
}
n += i
}
return n
} ;
var zip _inflate = function ( data , size ) {
var i , j ;
zip _inflate _start ( ) ;
zip _inflate _data = data ;
zip _inflate _pos = 0 ;
var buff = new runtime . ByteArray ( size ) ;
zip _inflate _internal ( buff , 0 , size ) ;
zip _inflate _data = null ;
return buff
} ;
this . inflate = zip _inflate
} ;
/ *
Copyright ( C ) 2012 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
core . LoopWatchDog = function LoopWatchDog ( timeout , maxChecks ) {
var startTime = Date . now ( ) , checks = 0 ;
function check ( ) {
var t ;
if ( timeout ) {
t = Date . now ( ) ;
if ( t - startTime > timeout ) {
runtime . log ( "alert" , "watchdog timeout" ) ;
throw "timeout!" ;
}
}
if ( maxChecks > 0 ) {
checks += 1 ;
if ( checks > maxChecks ) {
runtime . log ( "alert" , "watchdog loop overflow" ) ;
throw "loop overflow" ;
}
}
}
this . check = check
} ;
core . Utils = function Utils ( ) {
function hashString ( value ) {
var hash = 0 , i , l ;
for ( i = 0 , l = value . length ; i < l ; i += 1 ) {
hash = ( hash << 5 ) - hash + value . charCodeAt ( i ) ;
hash |= 0
}
return hash
}
this . hashString = hashString
} ;
core . DomUtils = function DomUtils ( ) {
function findStablePoint ( container , offset ) {
if ( offset < container . childNodes . length ) {
container = container . childNodes [ offset ] ;
offset = 0 ;
while ( container . firstChild ) {
container = container . firstChild
}
} else {
while ( container . lastChild ) {
container = container . lastChild ;
offset = container . nodeType === Node . TEXT _NODE ? container . textContent . length : container . childNodes . length
}
}
return { container : container , offset : offset }
}
function splitBoundaries ( range ) {
var modifiedNodes = [ ] , end , splitStart ;
if ( range . startContainer . nodeType === Node . TEXT _NODE || range . endContainer . nodeType === Node . TEXT _NODE ) {
end = findStablePoint ( range . endContainer , range . endOffset ) ;
range . setEnd ( end . container , end . offset ) ;
if ( range . endOffset !== 0 && range . endContainer . nodeType === Node . TEXT _NODE && range . endOffset !== range . endContainer . length ) {
modifiedNodes . push ( range . endContainer . splitText ( range . endOffset ) ) ;
modifiedNodes . push ( range . endContainer )
}
if ( range . startOffset !== 0 && range . startContainer . nodeType === Node . TEXT _NODE && range . startOffset !== range . startContainer . length ) {
splitStart = range . startContainer . splitText ( range . startOffset ) ;
modifiedNodes . push ( range . startContainer ) ;
modifiedNodes . push ( splitStart ) ;
range . setStart ( splitStart , 0 )
}
}
return modifiedNodes
}
this . splitBoundaries = splitBoundaries ;
function containsRange ( container , insideRange ) {
return container . compareBoundaryPoints ( container . START _TO _START , insideRange ) <= 0 && container . compareBoundaryPoints ( container . END _TO _END , insideRange ) >= 0
}
this . containsRange = containsRange ;
function rangesIntersect ( range1 , range2 ) {
return range1 . compareBoundaryPoints ( range1 . END _TO _START , range2 ) <= 0 && range1 . compareBoundaryPoints ( range1 . START _TO _END , range2 ) >= 0
}
this . rangesIntersect = rangesIntersect ;
function getNodesInRange ( range , nodeFilter ) {
var document = range . startContainer . ownerDocument , elements = [ ] , root = ( range . commonAncestorContainer ) , n , treeWalker = document . createTreeWalker ( root , NodeFilter . SHOW _ALL , nodeFilter , false ) ;
treeWalker . currentNode = range . startContainer ;
n = range . startContainer ;
while ( n ) {
if ( nodeFilter ( n ) === NodeFilter . FILTER _ACCEPT ) {
elements . push ( n )
} else {
if ( nodeFilter ( n ) === NodeFilter . FILTER _REJECT ) {
break
}
}
n = n . parentNode
}
elements . reverse ( ) ;
n = treeWalker . nextNode ( ) ;
while ( n ) {
elements . push ( n ) ;
n = treeWalker . nextNode ( )
}
return elements
}
this . getNodesInRange = getNodesInRange ;
function mergeTextNodes ( node1 , node2 ) {
if ( node1 . nodeType === Node . TEXT _NODE ) {
if ( node1 . length === 0 ) {
node1 . parentNode . removeChild ( node1 )
} else {
if ( node2 . nodeType === Node . TEXT _NODE ) {
node2 . insertData ( 0 , node1 . data ) ;
node1 . parentNode . removeChild ( node1 ) ;
return node2
}
}
}
return node1
}
function normalizeTextNodes ( node ) {
if ( node && node . nextSibling ) {
node = mergeTextNodes ( node , node . nextSibling )
}
if ( node && node . previousSibling ) {
mergeTextNodes ( node . previousSibling , node )
}
}
this . normalizeTextNodes = normalizeTextNodes ;
function rangeContainsNode ( limits , node ) {
var range = node . ownerDocument . createRange ( ) , nodeLength = node . nodeType === Node . TEXT _NODE ? node . length : node . childNodes . length , result ;
range . setStart ( limits . startContainer , limits . startOffset ) ;
range . setEnd ( limits . endContainer , limits . endOffset ) ;
result = range . comparePoint ( node , 0 ) === 0 && range . comparePoint ( node , nodeLength ) === 0 ;
range . detach ( ) ;
return result
}
this . rangeContainsNode = rangeContainsNode ;
function mergeIntoParent ( targetNode ) {
var parent = targetNode . parentNode ;
while ( targetNode . firstChild ) {
parent . insertBefore ( targetNode . firstChild , targetNode )
}
parent . removeChild ( targetNode ) ;
return parent
}
this . mergeIntoParent = mergeIntoParent ;
function getElementsByTagNameNS ( node , namespace , tagName ) {
return Array . prototype . slice . call ( node . getElementsByTagNameNS ( namespace , tagName ) )
}
this . getElementsByTagNameNS = getElementsByTagNameNS ;
function rangeIntersectsNode ( range , node ) {
var nodeLength = node . nodeType === Node . TEXT _NODE ? node . length : node . childNodes . length ;
return range . comparePoint ( node , 0 ) <= 0 && range . comparePoint ( node , nodeLength ) >= 0
}
this . rangeIntersectsNode = rangeIntersectsNode ;
function containsNode ( parent , descendant ) {
return parent === descendant || parent . contains ( descendant )
}
this . containsNode = containsNode ;
function containsNodeForBrokenWebKit ( parent , descendant ) {
return parent === descendant || Boolean ( parent . compareDocumentPosition ( descendant ) & Node . DOCUMENT _POSITION _CONTAINED _BY )
}
function init ( self ) {
var window = runtime . getWindow ( ) , appVersion , webKitOrSafari ;
if ( window === null ) {
return
}
appVersion = window . navigator . appVersion . toLowerCase ( ) ;
webKitOrSafari = appVersion . indexOf ( "chrome" ) === - 1 && ( appVersion . indexOf ( "applewebkit" ) !== - 1 || appVersion . indexOf ( "safari" ) !== - 1 ) ;
if ( webKitOrSafari ) {
self . containsNode = containsNodeForBrokenWebKit
}
}
init ( this )
} ;
runtime . loadClass ( "core.DomUtils" ) ;
core . Cursor = function Cursor ( document , memberId ) {
var cursorns = "urn:webodf:names:cursor" , cursorNode = document . createElementNS ( cursorns , "cursor" ) , anchorNode = document . createElementNS ( cursorns , "anchor" ) , forwardSelection , recentlyModifiedNodes = [ ] , selectedRange , isCollapsed , domUtils = new core . DomUtils ;
function putIntoTextNode ( node , container , offset ) {
runtime . assert ( Boolean ( container ) , "putCursorIntoTextNode: invalid container" ) ;
var parent = container . parentNode ;
runtime . assert ( Boolean ( parent ) , "putCursorIntoTextNode: container without parent" ) ;
runtime . assert ( offset >= 0 && offset <= container . length , "putCursorIntoTextNode: offset is out of bounds" ) ;
if ( offset === 0 ) {
parent . insertBefore ( node , container )
} else {
if ( offset === container . length ) {
parent . insertBefore ( node , container . nextSibling )
} else {
container . splitText ( offset ) ;
parent . insertBefore ( node , container . nextSibling )
}
}
}
function putIntoContainer ( node , container , offset ) {
runtime . assert ( Boolean ( container ) , "putCursorIntoContainer: invalid container" ) ;
var n = container . firstChild ;
while ( n !== null && offset > 0 ) {
n = n . nextSibling ;
offset -= 1
}
container . insertBefore ( node , n )
}
function removeNode ( node ) {
if ( node . parentNode ) {
recentlyModifiedNodes . push ( node . previousSibling ) ;
recentlyModifiedNodes . push ( node . nextSibling ) ;
node . parentNode . removeChild ( node )
}
}
function putNode ( node , container , offset ) {
var text , element ;
if ( container . nodeType === Node . TEXT _NODE ) {
text = ( container ) ;
putIntoTextNode ( node , text , offset )
} else {
if ( container . nodeType === Node . ELEMENT _NODE ) {
element = ( container ) ;
putIntoContainer ( node , element , offset )
}
}
recentlyModifiedNodes . push ( node . previousSibling ) ;
recentlyModifiedNodes . push ( node . nextSibling )
}
function getStartNode ( ) {
return forwardSelection ? anchorNode : cursorNode
}
function getEndNode ( ) {
return forwardSelection ? cursorNode : anchorNode
}
this . getNode = function ( ) {
return cursorNode
} ;
this . getAnchorNode = function ( ) {
return anchorNode . parentNode ? anchorNode : cursorNode
} ;
this . getSelectedRange = function ( ) {
if ( isCollapsed ) {
selectedRange . setStartBefore ( cursorNode ) ;
selectedRange . collapse ( true )
} else {
selectedRange . setStartAfter ( getStartNode ( ) ) ;
selectedRange . setEndBefore ( getEndNode ( ) )
}
return selectedRange
} ;
this . setSelectedRange = function ( range , isForwardSelection ) {
if ( selectedRange && selectedRange !== range ) {
selectedRange . detach ( )
}
selectedRange = range ;
forwardSelection = isForwardSelection !== false ;
isCollapsed = range . collapsed ;
if ( range . collapsed ) {
removeNode ( anchorNode ) ;
removeNode ( cursorNode ) ;
putNode ( cursorNode , ( range . startContainer ) , range . startOffset )
} else {
removeNode ( anchorNode ) ;
removeNode ( cursorNode ) ;
putNode ( getEndNode ( ) , ( range . endContainer ) , range . endOffset ) ;
putNode ( getStartNode ( ) , ( range . startContainer ) , range . startOffset )
}
recentlyModifiedNodes . forEach ( domUtils . normalizeTextNodes ) ;
recentlyModifiedNodes . length = 0
} ;
this . remove = function ( ) {
removeNode ( cursorNode ) ;
recentlyModifiedNodes . forEach ( domUtils . normalizeTextNodes ) ;
recentlyModifiedNodes . length = 0
} ;
function init ( ) {
cursorNode . setAttributeNS ( cursorns , "memberId" , memberId ) ;
anchorNode . setAttributeNS ( cursorns , "memberId" , memberId )
}
init ( )
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
core . EventNotifier = function EventNotifier ( eventIds ) {
var eventListener = { } ;
this . emit = function ( eventId , args ) {
var i , subscribers ;
runtime . assert ( eventListener . hasOwnProperty ( eventId ) , 'unknown event fired "' + eventId + '"' ) ;
subscribers = eventListener [ eventId ] ;
for ( i = 0 ; i < subscribers . length ; i += 1 ) {
subscribers [ i ] ( args )
}
} ;
this . subscribe = function ( eventId , cb ) {
runtime . assert ( eventListener . hasOwnProperty ( eventId ) , 'tried to subscribe to unknown event "' + eventId + '"' ) ;
eventListener [ eventId ] . push ( cb ) ;
runtime . log ( 'event "' + eventId + '" subscribed.' )
} ;
this . unsubscribe = function ( eventId , cb ) {
var cbIndex ;
runtime . assert ( eventListener . hasOwnProperty ( eventId ) , 'tried to unsubscribe from unknown event "' + eventId + '"' ) ;
cbIndex = eventListener [ eventId ] . indexOf ( cb ) ;
runtime . assert ( cbIndex !== - 1 , 'tried to unsubscribe unknown callback from event "' + eventId + '"' ) ;
if ( cbIndex !== - 1 ) {
eventListener [ eventId ] . splice ( cbIndex , 1 )
}
runtime . log ( 'event "' + eventId + '" unsubscribed.' )
} ;
function init ( ) {
var i ;
for ( i = 0 ; i < eventIds . length ; i += 1 ) {
eventListener [ eventIds [ i ] ] = [ ]
}
}
init ( )
} ;
core . UnitTest = function UnitTest ( ) {
} ;
core . UnitTest . prototype . setUp = function ( ) {
} ;
core . UnitTest . prototype . tearDown = function ( ) {
} ;
core . UnitTest . prototype . description = function ( ) {
} ;
core . UnitTest . prototype . tests = function ( ) {
} ;
core . UnitTest . prototype . asyncTests = function ( ) {
} ;
core . UnitTest . provideTestAreaDiv = function ( ) {
var maindoc = runtime . getWindow ( ) . document , testarea = maindoc . getElementById ( "testarea" ) ;
runtime . assert ( ! testarea , 'Unclean test environment, found a div with id "testarea".' ) ;
testarea = maindoc . createElement ( "div" ) ;
testarea . setAttribute ( "id" , "testarea" ) ;
maindoc . body . appendChild ( testarea ) ;
return testarea
} ;
core . UnitTest . cleanupTestAreaDiv = function ( ) {
var maindoc = runtime . getWindow ( ) . document , testarea = maindoc . getElementById ( "testarea" ) ;
runtime . assert ( ! ! testarea && testarea . parentNode === maindoc . body , 'Test environment broken, found no div with id "testarea" below body.' ) ;
maindoc . body . removeChild ( testarea )
} ;
core . UnitTestRunner = function UnitTestRunner ( ) {
var failedTests = 0 , areObjectsEqual ;
function debug ( msg ) {
runtime . log ( msg )
}
function testFailed ( msg ) {
failedTests += 1 ;
runtime . log ( "fail" , msg )
}
function testPassed ( msg ) {
runtime . log ( "pass" , msg )
}
function areArraysEqual ( a , b ) {
var i ;
try {
if ( a . length !== b . length ) {
testFailed ( "array of length " + a . length + " should be " + b . length + " long" ) ;
return false
}
for ( i = 0 ; i < a . length ; i += 1 ) {
if ( a [ i ] !== b [ i ] ) {
testFailed ( a [ i ] + " should be " + b [ i ] + " at array index " + i ) ;
return false
}
}
} catch ( ex ) {
return false
}
return true
}
function areAttributesEqual ( a , b , skipReverseCheck ) {
var aatts = a . attributes , n = aatts . length , i , att , v ;
for ( i = 0 ; i < n ; i += 1 ) {
att = aatts . item ( i ) ;
if ( att . prefix !== "xmlns" ) {
v = b . getAttributeNS ( att . namespaceURI , att . localName ) ;
if ( ! b . hasAttributeNS ( att . namespaceURI , att . localName ) ) {
testFailed ( "Attribute " + att . localName + " with value " + att . value + " was not present" ) ;
return false
}
if ( v !== att . value ) {
testFailed ( "Attribute " + att . localName + " was " + v + " should be " + att . value ) ;
return false
}
}
}
return skipReverseCheck ? true : areAttributesEqual ( b , a , true )
}
function areNodesEqual ( a , b ) {
if ( a . nodeType !== b . nodeType ) {
testFailed ( a . nodeType + " should be " + b . nodeType ) ;
return false
}
if ( a . nodeType === Node . TEXT _NODE ) {
return a . data === b . data
}
runtime . assert ( a . nodeType === Node . ELEMENT _NODE , "Only textnodes and elements supported." ) ;
if ( a . namespaceURI !== b . namespaceURI || a . localName !== b . localName ) {
testFailed ( a . namespaceURI + " should be " + b . namespaceURI ) ;
return false
}
if ( ! areAttributesEqual ( a , b , false ) ) {
return false
}
var an = a . firstChild , bn = b . firstChild ;
while ( an ) {
if ( ! bn ) {
return false
}
if ( ! areNodesEqual ( an , bn ) ) {
return false
}
an = an . nextSibling ;
bn = bn . nextSibling
}
if ( bn ) {
return false
}
return true
}
function isResultCorrect ( actual , expected ) {
if ( expected === 0 ) {
return actual === expected && 1 / actual === 1 / expected
}
if ( actual === expected ) {
return true
}
if ( typeof expected === "number" && isNaN ( expected ) ) {
return typeof actual === "number" && isNaN ( actual )
}
if ( Object . prototype . toString . call ( expected ) === Object . prototype . toString . call ( [ ] ) ) {
return areArraysEqual ( actual , expected )
}
if ( typeof expected === "object" && typeof actual === "object" ) {
if ( expected . constructor === Element || expected . constructor === Node ) {
return areNodesEqual ( expected , actual )
}
return areObjectsEqual ( expected , actual )
}
return false
}
function stringify ( v ) {
if ( v === 0 && 1 / v < 0 ) {
return "-0"
}
return String ( v )
}
function shouldBe ( t , a , b ) {
if ( typeof a !== "string" || typeof b !== "string" ) {
debug ( "WARN: shouldBe() expects string arguments" )
}
var exception , av , bv ;
try {
av = eval ( a )
} catch ( e ) {
exception = e
}
bv = eval ( b ) ;
if ( exception ) {
testFailed ( a + " should be " + bv + ". Threw exception " + exception )
} else {
if ( isResultCorrect ( av , bv ) ) {
testPassed ( a + " is " + b )
} else {
if ( String ( typeof av ) === String ( typeof bv ) ) {
testFailed ( a + " should be " + bv + ". Was " + stringify ( av ) + "." )
} else {
testFailed ( a + " should be " + bv + " (of type " + typeof bv + "). Was " + av + " (of type " + typeof av + ")." )
}
}
}
}
function shouldBeNonNull ( t , a ) {
var exception , av ;
try {
av = eval ( a )
} catch ( e ) {
exception = e
}
if ( exception ) {
testFailed ( a + " should be non-null. Threw exception " + exception )
} else {
if ( av !== null ) {
testPassed ( a + " is non-null." )
} else {
testFailed ( a + " should be non-null. Was " + av )
}
}
}
function shouldBeNull ( t , a ) {
shouldBe ( t , a , "null" )
}
areObjectsEqual = function ( a , b ) {
var akeys = Object . keys ( a ) , bkeys = Object . keys ( b ) ;
akeys . sort ( ) ;
bkeys . sort ( ) ;
return areArraysEqual ( akeys , bkeys ) && Object . keys ( a ) . every ( function ( key ) {
var aval = a [ key ] , bval = b [ key ] ;
if ( ! isResultCorrect ( aval , bval ) ) {
testFailed ( aval + " should be " + bval + " for key " + key ) ;
return false
}
return true
} )
} ;
this . areNodesEqual = areNodesEqual ;
this . shouldBeNull = shouldBeNull ;
this . shouldBeNonNull = shouldBeNonNull ;
this . shouldBe = shouldBe ;
this . countFailedTests = function ( ) {
return failedTests
}
} ;
core . UnitTester = function UnitTester ( ) {
var failedTests = 0 , results = { } ;
function link ( text , code ) {
return "<span style='color:blue;cursor:pointer' onclick='" + code + "'>" + text + "</span>"
}
this . runTests = function ( TestClass , callback , testNames ) {
var testName = Runtime . getFunctionName ( TestClass ) , tname , runner = new core . UnitTestRunner , test = new TestClass ( runner ) , testResults = { } , i , t , tests , lastFailCount , testNameString = "testName" , inBrowser = runtime . type ( ) === "BrowserRuntime" ;
if ( results . hasOwnProperty ( testName ) ) {
runtime . log ( "Test " + testName + " has already run." ) ;
return
}
if ( inBrowser ) {
runtime . log ( "<span>Running " + link ( testName , 'runSuite("' + testName + '");' ) + ": " + test . description ( ) + "</span>" )
} else {
runtime . log ( "Running " + testName + ": " + test . description )
}
tests = test . tests ( ) ;
for ( i = 0 ; i < tests . length ; i += 1 ) {
t = tests [ i ] ;
tname = Runtime . getFunctionName ( t ) || t [ testNameString ] ;
if ( testNames . length && testNames . indexOf ( tname ) === - 1 ) {
continue
}
if ( inBrowser ) {
runtime . log ( "<span>Running " + link ( tname , 'runTest("' + testName + '","' + tname + '")' ) + "</span>" )
} else {
runtime . log ( "Running " + tname )
}
lastFailCount = runner . countFailedTests ( ) ;
test . setUp ( ) ;
t ( ) ;
test . tearDown ( ) ;
testResults [ tname ] = lastFailCount === runner . countFailedTests ( )
}
function runAsyncTests ( todo ) {
if ( todo . length === 0 ) {
results [ testName ] = testResults ;
failedTests += runner . countFailedTests ( ) ;
callback ( ) ;
return
}
t = todo [ 0 ] ;
var fname = Runtime . getFunctionName ( t ) ;
runtime . log ( "Running " + fname ) ;
lastFailCount = runner . countFailedTests ( ) ;
test . setUp ( ) ;
t ( function ( ) {
test . tearDown ( ) ;
testResults [ fname ] = lastFailCount === runner . countFailedTests ( ) ;
runAsyncTests ( todo . slice ( 1 ) )
} )
}
runAsyncTests ( test . asyncTests ( ) )
} ;
this . countFailedTests = function ( ) {
return failedTests
} ;
this . results = function ( ) {
return results
}
} ;
core . PositionIterator = function PositionIterator ( root , whatToShow , filter , expandEntityReferences ) {
function EmptyTextNodeFilter ( ) {
this . acceptNode = function ( node ) {
if ( node . nodeType === Node . TEXT _NODE && node . length === 0 ) {
return NodeFilter . FILTER _REJECT
}
return NodeFilter . FILTER _ACCEPT
}
}
function FilteredEmptyTextNodeFilter ( filter ) {
this . acceptNode = function ( node ) {
if ( node . nodeType === Node . TEXT _NODE && node . length === 0 ) {
return NodeFilter . FILTER _REJECT
}
return filter . acceptNode ( node )
}
}
var self = this , walker , currentPos , nodeFilter ;
this . nextPosition = function ( ) {
if ( walker . currentNode === root ) {
return false
}
if ( currentPos === 0 && walker . currentNode . nodeType === Node . ELEMENT _NODE ) {
if ( walker . firstChild ( ) === null ) {
currentPos = 1
}
} else {
if ( walker . currentNode . nodeType === Node . TEXT _NODE && currentPos + 1 < walker . currentNode . length ) {
currentPos += 1
} else {
if ( walker . nextSibling ( ) !== null ) {
currentPos = 0
} else {
if ( walker . parentNode ( ) ) {
currentPos = 1
} else {
return false
}
}
}
}
return true
} ;
function setAtEnd ( ) {
var type = walker . currentNode . nodeType ;
if ( type === Node . TEXT _NODE ) {
currentPos = walker . currentNode . length - 1
} else {
currentPos = type === Node . ELEMENT _NODE ? 1 : 0
}
}
this . previousPosition = function ( ) {
var moved = true ;
if ( currentPos === 0 ) {
if ( walker . previousSibling ( ) === null ) {
if ( ! walker . parentNode ( ) || walker . currentNode === root ) {
walker . firstChild ( ) ;
return false
}
currentPos = 0
} else {
setAtEnd ( )
}
} else {
if ( walker . currentNode . nodeType === Node . TEXT _NODE ) {
currentPos -= 1
} else {
if ( walker . lastChild ( ) !== null ) {
setAtEnd ( )
} else {
if ( walker . currentNode === root ) {
moved = false
} else {
currentPos = 0
}
}
}
}
return moved
} ;
this . container = function ( ) {
var n = walker . currentNode , t = n . nodeType ;
if ( currentPos === 0 && t !== Node . TEXT _NODE ) {
return ( n . parentNode )
}
return n
} ;
this . rightNode = function ( ) {
var n = walker . currentNode , nodeType = n . nodeType ;
if ( nodeType === Node . TEXT _NODE && currentPos === n . length ) {
n = n . nextSibling ;
while ( n && nodeFilter ( n ) !== 1 ) {
n = n . nextSibling
}
} else {
if ( nodeType === Node . ELEMENT _NODE && currentPos === 1 ) {
n = null
}
}
return n
} ;
this . leftNode = function ( ) {
var n = walker . currentNode ;
if ( currentPos === 0 ) {
n = n . previousSibling ;
while ( n && nodeFilter ( n ) !== 1 ) {
n = n . previousSibling
}
} else {
if ( n . nodeType === Node . ELEMENT _NODE ) {
n = n . lastChild ;
while ( n && nodeFilter ( n ) !== 1 ) {
n = n . previousSibling
}
}
}
return n
} ;
this . getCurrentNode = function ( ) {
return walker . currentNode
} ;
this . domOffset = function ( ) {
if ( walker . currentNode . nodeType === Node . TEXT _NODE ) {
return currentPos
}
var c = 0 , startNode = walker . currentNode , n ;
if ( currentPos === 1 ) {
n = walker . lastChild ( )
} else {
n = walker . previousSibling ( )
}
while ( n ) {
c += 1 ;
n = walker . previousSibling ( )
}
walker . currentNode = startNode ;
return c
} ;
this . unfilteredDomOffset = function ( ) {
if ( walker . currentNode . nodeType === Node . TEXT _NODE ) {
return currentPos
}
var c = 0 , n = walker . currentNode ;
if ( currentPos === 1 ) {
n = n . lastChild
} else {
n = n . previousSibling
}
while ( n ) {
c += 1 ;
n = n . previousSibling
}
return c
} ;
this . getPreviousSibling = function ( ) {
var currentNode = walker . currentNode , sibling = walker . previousSibling ( ) ;
walker . currentNode = currentNode ;
return sibling
} ;
this . getNextSibling = function ( ) {
var currentNode = walker . currentNode , sibling = walker . nextSibling ( ) ;
walker . currentNode = currentNode ;
return sibling
} ;
this . setUnfilteredPosition = function ( container , offset ) {
var filterResult ;
runtime . assert ( container !== null && container !== undefined , "PositionIterator.setUnfilteredPosition called without container" ) ;
walker . currentNode = container ;
if ( container . nodeType === Node . TEXT _NODE ) {
currentPos = offset ;
runtime . assert ( offset <= container . length , "Error in setPosition: " + offset + " > " + container . length ) ;
runtime . assert ( offset >= 0 , "Error in setPosition: " + offset + " < 0" ) ;
if ( offset === container . length ) {
currentPos = undefined ;
if ( walker . nextSibling ( ) ) {
currentPos = 0
} else {
if ( walker . parentNode ( ) ) {
currentPos = 1
}
}
runtime . assert ( currentPos !== undefined , "Error in setPosition: position not valid." )
}
return true
}
filterResult = nodeFilter ( container ) ;
if ( offset < container . childNodes . length && filterResult !== NodeFilter . FILTER _REJECT ) {
walker . currentNode = container . childNodes [ offset ] ;
filterResult = nodeFilter ( walker . currentNode ) ;
currentPos = 0
} else {
currentPos = offset === 0 ? 0 : 1
}
if ( filterResult === NodeFilter . FILTER _REJECT ) {
currentPos = 1
}
if ( filterResult !== NodeFilter . FILTER _ACCEPT ) {
return self . nextPosition ( )
}
runtime . assert ( nodeFilter ( walker . currentNode ) === NodeFilter . FILTER _ACCEPT , "PositionIterater.setUnfilteredPosition call resulted in an non-visible node being set" ) ;
return true
} ;
this . moveToEnd = function ( ) {
walker . currentNode = root ;
currentPos = 1
} ;
this . moveToEndOfNode = function ( node ) {
if ( node . nodeType === Node . TEXT _NODE ) {
self . setUnfilteredPosition ( node , node . length )
} else {
walker . currentNode = node ;
currentPos = 1
}
} ;
this . getNodeFilter = function ( ) {
return nodeFilter
} ;
function init ( ) {
var f ;
if ( filter ) {
f = new FilteredEmptyTextNodeFilter ( filter )
} else {
f = new EmptyTextNodeFilter
}
nodeFilter = ( f . acceptNode ) ;
nodeFilter . acceptNode = nodeFilter ;
whatToShow = whatToShow || 4294967295 ;
walker = root . ownerDocument . createTreeWalker ( root , whatToShow , nodeFilter , expandEntityReferences ) ;
currentPos = 0 ;
if ( walker . firstChild ( ) === null ) {
currentPos = 1
}
}
init ( )
} ;
runtime . loadClass ( "core.PositionIterator" ) ;
core . PositionFilter = function PositionFilter ( ) {
} ;
core . PositionFilter . FilterResult = { FILTER _ACCEPT : 1 , FILTER _REJECT : 2 , FILTER _SKIP : 3 } ;
core . PositionFilter . prototype . acceptPosition = function ( point ) {
} ;
( function ( ) {
return core . PositionFilter
} ) ( ) ;
runtime . loadClass ( "core.PositionFilter" ) ;
core . PositionFilterChain = function PositionFilterChain ( ) {
var filterChain = { } , FILTER _ACCEPT = core . PositionFilter . FilterResult . FILTER _ACCEPT , FILTER _REJECT = core . PositionFilter . FilterResult . FILTER _REJECT ;
this . acceptPosition = function ( iterator ) {
var filterName ;
for ( filterName in filterChain ) {
if ( filterChain . hasOwnProperty ( filterName ) ) {
if ( filterChain [ filterName ] . acceptPosition ( iterator ) === FILTER _REJECT ) {
return FILTER _REJECT
}
}
}
return FILTER _ACCEPT
} ;
this . addFilter = function ( filterName , filterInstance ) {
filterChain [ filterName ] = filterInstance
} ;
this . removeFilter = function ( filterName ) {
delete filterChain [ filterName ]
}
} ;
core . Async = function Async ( ) {
this . forEach = function ( items , f , callback ) {
var i , l = items . length , itemsDone = 0 ;
function end ( err ) {
if ( itemsDone !== l ) {
if ( err ) {
itemsDone = l ;
callback ( err )
} else {
itemsDone += 1 ;
if ( itemsDone === l ) {
callback ( null )
}
}
}
}
for ( i = 0 ; i < l ; i += 1 ) {
f ( items [ i ] , end )
}
}
} ;
/ *
WebODF
Copyright ( c ) 2010 Jos van den Oever
Licensed under the ... License :
Project home : http : //www.webodf.org/
* /
runtime . loadClass ( "core.RawInflate" ) ;
runtime . loadClass ( "core.ByteArray" ) ;
runtime . loadClass ( "core.ByteArrayWriter" ) ;
runtime . loadClass ( "core.Base64" ) ;
core . Zip = function Zip ( url , entriesReadCallback ) {
var entries , filesize , nEntries , inflate = ( new core . RawInflate ) . inflate , zip = this , base64 = new core . Base64 ;
function crc32 ( data ) {
var table = [ 0 , 1996959894 , 3993919788 , 2567524794 , 124634137 , 1886057615 , 3915621685 , 2657392035 , 249268274 , 2044508324 , 3772115230 , 2547177864 , 162941995 , 2125561021 , 3887607047 , 2428444049 , 498536548 , 1789927666 , 4089016648 , 2227061214 , 450548861 , 1843258603 , 4107580753 , 2211677639 , 325883990 , 1684777152 , 4251122042 , 2321926636 , 335633487 , 1661365465 , 4195302755 , 2366115317 , 997073096 , 1281953886 , 3579855332 , 2724688242 , 1006888145 , 1258607687 , 3524101629 , 2768942443 , 901097722 , 1119000684 ,
3686517206 , 2898065728 , 853044451 , 1172266101 , 3705015759 , 2882616665 , 651767980 , 1373503546 , 3369554304 , 3218104598 , 565507253 , 1454621731 , 3485111705 , 3099436303 , 671266974 , 1594198024 , 3322730930 , 2970347812 , 795835527 , 1483230225 , 3244367275 , 3060149565 , 1994146192 , 31158534 , 2563907772 , 4023717930 , 1907459465 , 112637215 , 2680153253 , 3904427059 , 2013776290 , 251722036 , 2517215374 , 3775830040 , 2137656763 , 141376813 , 2439277719 , 3865271297 , 1802195444 , 476864866 , 2238001368 , 4066508878 , 1812370925 ,
453092731 , 2181625025 , 4111451223 , 1706088902 , 314042704 , 2344532202 , 4240017532 , 1658658271 , 366619977 , 2362670323 , 4224994405 , 1303535960 , 984961486 , 2747007092 , 3569037538 , 1256170817 , 1037604311 , 2765210733 , 3554079995 , 1131014506 , 879679996 , 2909243462 , 3663771856 , 1141124467 , 855842277 , 2852801631 , 3708648649 , 1342533948 , 654459306 , 3188396048 , 3373015174 , 1466479909 , 544179635 , 3110523913 , 3462522015 , 1591671054 , 702138776 , 2966460450 , 3352799412 , 1504918807 , 783551873 , 3082640443 , 3233442989 ,
3988292384 , 2596254646 , 62317068 , 1957810842 , 3939845945 , 2647816111 , 81470997 , 1943803523 , 3814918930 , 2489596804 , 225274430 , 2053790376 , 3826175755 , 2466906013 , 167816743 , 2097651377 , 4027552580 , 2265490386 , 503444072 , 1762050814 , 4150417245 , 2154129355 , 426522225 , 1852507879 , 4275313526 , 2312317920 , 282753626 , 1742555852 , 4189708143 , 2394877945 , 397917763 , 1622183637 , 3604390888 , 2714866558 , 953729732 , 1340076626 , 3518719985 , 2797360999 , 1068828381 , 1219638859 , 3624741850 , 2936675148 , 906185462 ,
1090812512 , 3747672003 , 2825379669 , 829329135 , 1181335161 , 3412177804 , 3160834842 , 628085408 , 1382605366 , 3423369109 , 3138078467 , 570562233 , 1426400815 , 3317316542 , 2998733608 , 733239954 , 1555261956 , 3268935591 , 3050360625 , 752459403 , 1541320221 , 2607071920 , 3965973030 , 1969922972 , 40735498 , 2617837225 , 3943577151 , 1913087877 , 83908371 , 2512341634 , 3803740692 , 2075208622 , 213261112 , 2463272603 , 3855990285 , 2094854071 , 198958881 , 2262029012 , 4057260610 , 1759359992 , 534414190 , 2176718541 , 4139329115 ,
1873836001 , 414664567 , 2282248934 , 4279200368 , 1711684554 , 285281116 , 2405801727 , 4167216745 , 1634467795 , 376229701 , 2685067896 , 3608007406 , 1308918612 , 956543938 , 2808555105 , 3495958263 , 1231636301 , 1047427035 , 2932959818 , 3654703836 , 1088359270 , 936918E3 , 2847714899 , 3736837829 , 1202900863 , 817233897 , 3183342108 , 3401237130 , 1404277552 , 615818150 , 3134207493 , 3453421203 , 1423857449 , 601450431 , 3009837614 , 3294710456 , 1567103746 , 711928724 , 3020668471 , 3272380065 , 1510334235 , 755167117 ] , crc =
0 , i , iTop = data . length , x = 0 , y = 0 ;
crc = crc ^ - 1 ;
for ( i = 0 ; i < iTop ; i += 1 ) {
y = ( crc ^ data [ i ] ) & 255 ;
x = table [ y ] ;
crc = crc >>> 8 ^ x
}
return crc ^ - 1
}
function dosTime2Date ( dostime ) {
var year = ( dostime >> 25 & 127 ) + 1980 , month = ( dostime >> 21 & 15 ) - 1 , mday = dostime >> 16 & 31 , hour = dostime >> 11 & 15 , min = dostime >> 5 & 63 , sec = ( dostime & 31 ) << 1 , d = new Date ( year , month , mday , hour , min , sec ) ;
return d
}
function date2DosTime ( date ) {
var y = date . getFullYear ( ) ;
return y < 1980 ? 0 : y - 1980 << 25 | date . getMonth ( ) + 1 << 21 | date . getDate ( ) << 16 | date . getHours ( ) << 11 | date . getMinutes ( ) << 5 | date . getSeconds ( ) >> 1
}
function ZipEntry ( url , stream ) {
var sig , namelen , extralen , commentlen , compressionMethod , compressedSize , uncompressedSize , offset , entry = this ;
function handleEntryData ( data , callback ) {
var estream = new core . ByteArray ( data ) , esig = estream . readUInt32LE ( ) , filenamelen , eextralen ;
if ( esig !== 67324752 ) {
callback ( "File entry signature is wrong." + esig . toString ( ) + " " + data . length . toString ( ) , null ) ;
return
}
estream . pos += 22 ;
filenamelen = estream . readUInt16LE ( ) ;
eextralen = estream . readUInt16LE ( ) ;
estream . pos += filenamelen + eextralen ;
if ( compressionMethod ) {
data = data . slice ( estream . pos , estream . pos + compressedSize ) ;
if ( compressedSize !== data . length ) {
callback ( "The amount of compressed bytes read was " + data . length . toString ( ) + " instead of " + compressedSize . toString ( ) + " for " + entry . filename + " in " + url + "." , null ) ;
return
}
data = inflate ( data , uncompressedSize )
} else {
data = data . slice ( estream . pos , estream . pos + uncompressedSize )
}
if ( uncompressedSize !== data . length ) {
callback ( "The amount of bytes read was " + data . length . toString ( ) + " instead of " + uncompressedSize . toString ( ) + " for " + entry . filename + " in " + url + "." , null ) ;
return
}
entry . data = data ;
callback ( null , data )
}
function load ( callback ) {
if ( entry . data !== undefined ) {
callback ( null , entry . data ) ;
return
}
var size = compressedSize + 34 + namelen + extralen + 256 ;
if ( size + offset > filesize ) {
size = filesize - offset
}
runtime . read ( url , offset , size , function ( err , data ) {
if ( err || data === null ) {
callback ( err , data )
} else {
handleEntryData ( data , callback )
}
} )
}
this . load = load ;
function set ( filename , data , compressed , date ) {
entry . filename = filename ;
entry . data = data ;
entry . compressed = compressed ;
entry . date = date
}
this . set = set ;
this . error = null ;
if ( ! stream ) {
return
}
sig = stream . readUInt32LE ( ) ;
if ( sig !== 33639248 ) {
this . error = "Central directory entry has wrong signature at position " + ( stream . pos - 4 ) . toString ( ) + ' for file "' + url + '": ' + stream . data . length . toString ( ) ;
return
}
stream . pos += 6 ;
compressionMethod = stream . readUInt16LE ( ) ;
this . date = dosTime2Date ( stream . readUInt32LE ( ) ) ;
stream . readUInt32LE ( ) ;
compressedSize = stream . readUInt32LE ( ) ;
uncompressedSize = stream . readUInt32LE ( ) ;
namelen = stream . readUInt16LE ( ) ;
extralen = stream . readUInt16LE ( ) ;
commentlen = stream . readUInt16LE ( ) ;
stream . pos += 8 ;
offset = stream . readUInt32LE ( ) ;
this . filename = runtime . byteArrayToString ( stream . data . slice ( stream . pos , stream . pos + namelen ) , "utf8" ) ;
stream . pos += namelen + extralen + commentlen
}
function handleCentralDirectory ( data , callback ) {
var stream = new core . ByteArray ( data ) , i , e ;
entries = [ ] ;
for ( i = 0 ; i < nEntries ; i += 1 ) {
e = new ZipEntry ( url , stream ) ;
if ( e . error ) {
callback ( e . error , zip ) ;
return
}
entries [ entries . length ] = e
}
callback ( null , zip )
}
function handleCentralDirectoryEnd ( data , callback ) {
if ( data . length !== 22 ) {
callback ( "Central directory length should be 22." , zip ) ;
return
}
var stream = new core . ByteArray ( data ) , sig , disk , cddisk , diskNEntries , cdsSize , cdsOffset ;
sig = stream . readUInt32LE ( ) ;
if ( sig !== 101010256 ) {
callback ( "Central directory signature is wrong: " + sig . toString ( ) , zip ) ;
return
}
disk = stream . readUInt16LE ( ) ;
if ( disk !== 0 ) {
callback ( "Zip files with non-zero disk numbers are not supported." , zip ) ;
return
}
cddisk = stream . readUInt16LE ( ) ;
if ( cddisk !== 0 ) {
callback ( "Zip files with non-zero disk numbers are not supported." , zip ) ;
return
}
diskNEntries = stream . readUInt16LE ( ) ;
nEntries = stream . readUInt16LE ( ) ;
if ( diskNEntries !== nEntries ) {
callback ( "Number of entries is inconsistent." , zip ) ;
return
}
cdsSize = stream . readUInt32LE ( ) ;
cdsOffset = stream . readUInt16LE ( ) ;
cdsOffset = filesize - 22 - cdsSize ;
runtime . read ( url , cdsOffset , filesize - cdsOffset , function ( err , data ) {
if ( err || data === null ) {
callback ( err , zip )
} else {
handleCentralDirectory ( data , callback )
}
} )
}
function load ( filename , callback ) {
var entry = null , e , i ;
for ( i = 0 ; i < entries . length ; i += 1 ) {
e = entries [ i ] ;
if ( e . filename === filename ) {
entry = e ;
break
}
}
if ( entry ) {
if ( entry . data ) {
callback ( null , entry . data )
} else {
entry . load ( callback )
}
} else {
callback ( filename + " not found." , null )
}
}
function loadAsString ( filename , callback ) {
load ( filename , function ( err , data ) {
if ( err || data === null ) {
return callback ( err , null )
}
var d = runtime . byteArrayToString ( data , "utf8" ) ;
callback ( null , d )
} )
}
function loadContentXmlAsFragments ( filename , handler ) {
zip . loadAsString ( filename , function ( err , data ) {
if ( err ) {
return handler . rootElementReady ( err )
}
handler . rootElementReady ( null , data , true )
} )
}
function loadAsDataURL ( filename , mimetype , callback ) {
load ( filename , function ( err , data ) {
if ( err ) {
return callback ( err , null )
}
var p = data , chunksize = 45E3 , i = 0 , dataurl ;
if ( ! mimetype ) {
if ( p [ 1 ] === 80 && p [ 2 ] === 78 && p [ 3 ] === 71 ) {
mimetype = "image/png"
} else {
if ( p [ 0 ] === 255 && p [ 1 ] === 216 && p [ 2 ] === 255 ) {
mimetype = "image/jpeg"
} else {
if ( p [ 0 ] === 71 && p [ 1 ] === 73 && p [ 2 ] === 70 ) {
mimetype = "image/gif"
} else {
mimetype = ""
}
}
}
}
dataurl = "data:" + mimetype + ";base64," ;
while ( i < data . length ) {
dataurl += base64 . convertUTF8ArrayToBase64 ( p . slice ( i , Math . min ( i + chunksize , p . length ) ) ) ;
i += chunksize
}
callback ( null , dataurl )
} )
}
function loadAsDOM ( filename , callback ) {
zip . loadAsString ( filename , function ( err , xmldata ) {
if ( err || xmldata === null ) {
callback ( err , null ) ;
return
}
var parser = new DOMParser , dom = parser . parseFromString ( xmldata , "text/xml" ) ;
callback ( null , dom )
} )
}
function save ( filename , data , compressed , date ) {
var i , entry ;
for ( i = 0 ; i < entries . length ; i += 1 ) {
entry = entries [ i ] ;
if ( entry . filename === filename ) {
entry . set ( filename , data , compressed , date ) ;
return
}
}
entry = new ZipEntry ( url ) ;
entry . set ( filename , data , compressed , date ) ;
entries . push ( entry )
}
function writeEntry ( entry ) {
var data = new core . ByteArrayWriter ( "utf8" ) , length = 0 ;
data . appendArray ( [ 80 , 75 , 3 , 4 , 20 , 0 , 0 , 0 , 0 , 0 ] ) ;
if ( entry . data ) {
length = entry . data . length
}
data . appendUInt32LE ( date2DosTime ( entry . date ) ) ;
data . appendUInt32LE ( crc32 ( entry . data ) ) ;
data . appendUInt32LE ( length ) ;
data . appendUInt32LE ( length ) ;
data . appendUInt16LE ( entry . filename . length ) ;
data . appendUInt16LE ( 0 ) ;
data . appendString ( entry . filename ) ;
if ( entry . data ) {
data . appendByteArray ( entry . data )
}
return data
}
function writeCODEntry ( entry , offset ) {
var data = new core . ByteArrayWriter ( "utf8" ) , length = 0 ;
data . appendArray ( [ 80 , 75 , 1 , 2 , 20 , 0 , 20 , 0 , 0 , 0 , 0 , 0 ] ) ;
if ( entry . data ) {
length = entry . data . length
}
data . appendUInt32LE ( date2DosTime ( entry . date ) ) ;
data . appendUInt32LE ( crc32 ( entry . data ) ) ;
data . appendUInt32LE ( length ) ;
data . appendUInt32LE ( length ) ;
data . appendUInt16LE ( entry . filename . length ) ;
data . appendArray ( [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ) ;
data . appendUInt32LE ( offset ) ;
data . appendString ( entry . filename ) ;
return data
}
function loadAllEntries ( position , callback ) {
if ( position === entries . length ) {
callback ( null ) ;
return
}
var entry = entries [ position ] ;
if ( entry . data !== undefined ) {
loadAllEntries ( position + 1 , callback ) ;
return
}
entry . load ( function ( err ) {
if ( err ) {
callback ( err ) ;
return
}
loadAllEntries ( position + 1 , callback )
} )
}
function createByteArray ( successCallback , errorCallback ) {
loadAllEntries ( 0 , function ( err ) {
if ( err ) {
errorCallback ( err ) ;
return
}
var data = new core . ByteArrayWriter ( "utf8" ) , i , e , codoffset , codsize , offsets = [ 0 ] ;
for ( i = 0 ; i < entries . length ; i += 1 ) {
data . appendByteArrayWriter ( writeEntry ( entries [ i ] ) ) ;
offsets . push ( data . getLength ( ) )
}
codoffset = data . getLength ( ) ;
for ( i = 0 ; i < entries . length ; i += 1 ) {
e = entries [ i ] ;
data . appendByteArrayWriter ( writeCODEntry ( e , offsets [ i ] ) )
}
codsize = data . getLength ( ) - codoffset ;
data . appendArray ( [ 80 , 75 , 5 , 6 , 0 , 0 , 0 , 0 ] ) ;
data . appendUInt16LE ( entries . length ) ;
data . appendUInt16LE ( entries . length ) ;
data . appendUInt32LE ( codsize ) ;
data . appendUInt32LE ( codoffset ) ;
data . appendArray ( [ 0 , 0 ] ) ;
successCallback ( data . getByteArray ( ) )
} )
}
function writeAs ( newurl , callback ) {
createByteArray ( function ( data ) {
runtime . writeFile ( newurl , data , callback )
} , callback )
}
function write ( callback ) {
writeAs ( url , callback )
}
this . load = load ;
this . save = save ;
this . write = write ;
this . writeAs = writeAs ;
this . createByteArray = createByteArray ;
this . loadContentXmlAsFragments = loadContentXmlAsFragments ;
this . loadAsString = loadAsString ;
this . loadAsDOM = loadAsDOM ;
this . loadAsDataURL = loadAsDataURL ;
this . getEntries = function ( ) {
return entries . slice ( )
} ;
filesize = - 1 ;
if ( entriesReadCallback === null ) {
entries = [ ] ;
return
}
runtime . getFileSize ( url , function ( size ) {
filesize = size ;
if ( filesize < 0 ) {
entriesReadCallback ( "File '" + url + "' cannot be read." , zip )
} else {
runtime . read ( url , filesize - 22 , 22 , function ( err , data ) {
if ( err || entriesReadCallback === null || data === null ) {
entriesReadCallback ( err , zip )
} else {
handleCentralDirectoryEnd ( data , entriesReadCallback )
}
} )
}
} )
} ;
core . CSSUnits = function CSSUnits ( ) {
var sizemap = { "in" : 1 , "cm" : 2.54 , "mm" : 25.4 , "pt" : 72 , "pc" : 12 } ;
this . convert = function ( value , oldUnit , newUnit ) {
return value * sizemap [ newUnit ] / sizemap [ oldUnit ]
} ;
this . convertMeasure = function ( measure , newUnit ) {
var value , oldUnit , newMeasure ;
if ( measure && newUnit ) {
value = parseFloat ( measure ) ;
oldUnit = measure . replace ( value . toString ( ) , "" ) ;
newMeasure = this . convert ( value , oldUnit , newUnit )
} else {
newMeasure = ""
}
return newMeasure . toString ( )
} ;
this . getUnits = function ( measure ) {
return measure . substr ( measure . length - 2 , measure . length )
}
} ;
xmldom . LSSerializerFilter = function LSSerializerFilter ( ) {
} ;
if ( typeof Object . create !== "function" ) {
Object [ "create" ] = function ( o ) {
var F = function ( ) {
} ;
F . prototype = o ;
return new F
}
}
xmldom . LSSerializer = function LSSerializer ( ) {
var self = this ;
function Namespaces ( nsmap ) {
function invertMap ( map ) {
var m = { } , i ;
for ( i in map ) {
if ( map . hasOwnProperty ( i ) ) {
m [ map [ i ] ] = i
}
}
return m
}
var current = nsmap || { } , currentrev = invertMap ( nsmap ) , levels = [ current ] , levelsrev = [ currentrev ] , level = 0 ;
this . push = function ( ) {
level += 1 ;
current = levels [ level ] = Object . create ( current ) ;
currentrev = levelsrev [ level ] = Object . create ( currentrev )
} ;
this . pop = function ( ) {
levels [ level ] = undefined ;
levelsrev [ level ] = undefined ;
level -= 1 ;
current = levels [ level ] ;
currentrev = levelsrev [ level ]
} ;
this . getLocalNamespaceDefinitions = function ( ) {
return currentrev
} ;
this . getQName = function ( node ) {
var ns = node . namespaceURI , i = 0 , p ;
if ( ! ns ) {
return node . localName
}
p = currentrev [ ns ] ;
if ( p ) {
return p + ":" + node . localName
}
do {
if ( p || ! node . prefix ) {
p = "ns" + i ;
i += 1
} else {
p = node . prefix
}
if ( current [ p ] === ns ) {
break
}
if ( ! current [ p ] ) {
current [ p ] = ns ;
currentrev [ ns ] = p ;
break
}
p = null
} while ( p === null ) ;
return p + ":" + node . localName
}
}
function escapeContent ( value ) {
return value . replace ( /&/g , "&" ) . replace ( /</g , "<" ) . replace ( />/g , ">" ) . replace ( /'/g , "'" ) . replace ( /"/g , """ )
}
function serializeAttribute ( qname , attr ) {
var escapedValue = typeof attr . value === "string" ? escapeContent ( attr . value ) : attr . value , s = qname + '="' + escapedValue + '"' ;
return s
}
function startElement ( ns , qname , element ) {
var s = "" , atts = element . attributes , length , i , attr , attstr = "" , accept , prefix , nsmap ;
s += "<" + qname ;
length = atts . length ;
for ( i = 0 ; i < length ; i += 1 ) {
attr = ( atts . item ( i ) ) ;
if ( attr . namespaceURI !== "http://www.w3.org/2000/xmlns/" ) {
accept = self . filter ? self . filter . acceptNode ( attr ) : NodeFilter . FILTER _ACCEPT ;
if ( accept === NodeFilter . FILTER _ACCEPT ) {
attstr += " " + serializeAttribute ( ns . getQName ( attr ) , attr )
}
}
}
nsmap = ns . getLocalNamespaceDefinitions ( ) ;
for ( i in nsmap ) {
if ( nsmap . hasOwnProperty ( i ) ) {
prefix = nsmap [ i ] ;
if ( ! prefix ) {
s += ' xmlns="' + i + '"'
} else {
if ( prefix !== "xmlns" ) {
s += " xmlns:" + nsmap [ i ] + '="' + i + '"'
}
}
}
}
s += attstr + ">" ;
return s
}
function serializeNode ( ns , node ) {
var s = "" , accept = self . filter ? self . filter . acceptNode ( node ) : NodeFilter . FILTER _ACCEPT , child , qname ;
if ( accept === NodeFilter . FILTER _ACCEPT && node . nodeType === Node . ELEMENT _NODE ) {
ns . push ( ) ;
qname = ns . getQName ( node ) ;
s += startElement ( ns , qname , node )
}
if ( accept === NodeFilter . FILTER _ACCEPT || accept === NodeFilter . FILTER _SKIP ) {
child = node . firstChild ;
while ( child ) {
s += serializeNode ( ns , child ) ;
child = child . nextSibling
}
if ( node . nodeValue ) {
s += escapeContent ( node . nodeValue )
}
}
if ( qname ) {
s += "</" + qname + ">" ;
ns . pop ( )
}
return s
}
this . filter = null ;
this . writeToString = function ( node , nsmap ) {
if ( ! node ) {
return ""
}
var ns = new Namespaces ( nsmap ) ;
return serializeNode ( ns , node )
}
} ;
xmldom . RelaxNGParser = function RelaxNGParser ( ) {
var self = this , rngns = "http://relaxng.org/ns/structure/1.0" , xmlnsns = "http://www.w3.org/2000/xmlns/" , start , nsmap = { "http://www.w3.org/XML/1998/namespace" : "xml" } , parse ;
function RelaxNGParseError ( error , context ) {
this . message = function ( ) {
if ( context ) {
error += context . nodeType === 1 ? " Element " : " Node " ;
error += context . nodeName ;
if ( context . nodeValue ) {
error += " with value '" + context . nodeValue + "'"
}
error += "."
}
return error
}
}
function splitToDuos ( e ) {
if ( e . e . length <= 2 ) {
return e
}
var o = { name : e . name , e : e . e . slice ( 0 , 2 ) } ;
return splitToDuos ( { name : e . name , e : [ o ] . concat ( e . e . slice ( 2 ) ) } )
}
function splitQName ( name ) {
var r = name . split ( ":" , 2 ) , prefix = "" , i ;
if ( r . length === 1 ) {
r = [ "" , r [ 0 ] ]
} else {
prefix = r [ 0 ]
}
for ( i in nsmap ) {
if ( nsmap [ i ] === prefix ) {
r [ 0 ] = i
}
}
return r
}
function splitQNames ( def ) {
var i , l = def . names ? def . names . length : 0 , name , localnames = [ ] , namespaces = [ ] ;
for ( i = 0 ; i < l ; i += 1 ) {
name = splitQName ( def . names [ i ] ) ;
namespaces [ i ] = name [ 0 ] ;
localnames [ i ] = name [ 1 ]
}
def . localnames = localnames ;
def . namespaces = namespaces
}
function trim ( str ) {
str = str . replace ( /^\s\s*/ , "" ) ;
var ws = /\s/ , i = str . length - 1 ;
while ( ws . test ( str . charAt ( i ) ) ) {
i -= 1
}
return str . slice ( 0 , i + 1 )
}
function copyAttributes ( atts , name , names ) {
var a = { } , i , att ;
for ( i = 0 ; i < atts . length ; i += 1 ) {
att = atts . item ( i ) ;
if ( ! att . namespaceURI ) {
if ( att . localName === "name" && ( name === "element" || name === "attribute" ) ) {
names . push ( att . value )
}
if ( att . localName === "name" || att . localName === "combine" || att . localName === "type" ) {
att . value = trim ( att . value )
}
a [ att . localName ] = att . value
} else {
if ( att . namespaceURI === xmlnsns ) {
nsmap [ att . value ] = att . localName
}
}
}
return a
}
function parseChildren ( c , e , elements , names ) {
var text = "" , ce ;
while ( c ) {
if ( c . nodeType === Node . ELEMENT _NODE && c . namespaceURI === rngns ) {
ce = parse ( c , elements , e ) ;
if ( ce ) {
if ( ce . name === "name" ) {
names . push ( nsmap [ ce . a . ns ] + ":" + ce . text ) ;
e . push ( ce )
} else {
if ( ce . name === "choice" && ce . names && ce . names . length ) {
names = names . concat ( ce . names ) ;
delete ce . names ;
e . push ( ce )
} else {
e . push ( ce )
}
}
}
} else {
if ( c . nodeType === Node . TEXT _NODE ) {
text += c . nodeValue
}
}
c = c . nextSibling
}
return text
}
function combineDefines ( combine , name , e , siblings ) {
var i , ce ;
for ( i = 0 ; siblings && i < siblings . length ; i += 1 ) {
ce = siblings [ i ] ;
if ( ce . name === "define" && ce . a && ce . a . name === name ) {
ce . e = [ { name : combine , e : ce . e . concat ( e ) } ] ;
return ce
}
}
return null
}
parse = function parse ( element , elements , siblings ) {
var e = [ ] , a , ce , i , text , name = element . localName , names = [ ] ;
a = copyAttributes ( element . attributes , name , names ) ;
a . combine = a . combine || undefined ;
text = parseChildren ( element . firstChild , e , elements , names ) ;
if ( name !== "value" && name !== "param" ) {
text = /^\s*([\s\S]*\S)?\s*$/ . exec ( text ) [ 1 ]
}
if ( name === "value" && a . type === undefined ) {
a . type = "token" ;
a . datatypeLibrary = ""
}
if ( ( name === "attribute" || name === "element" ) && a . name !== undefined ) {
i = splitQName ( a . name ) ;
e = [ { name : "name" , text : i [ 1 ] , a : { ns : i [ 0 ] } } ] . concat ( e ) ;
delete a . name
}
if ( name === "name" || name === "nsName" || name === "value" ) {
if ( a . ns === undefined ) {
a . ns = ""
}
} else {
delete a . ns
}
if ( name === "name" ) {
i = splitQName ( text ) ;
a . ns = i [ 0 ] ;
text = i [ 1 ]
}
if ( e . length > 1 && ( name === "define" || name === "oneOrMore" || name === "zeroOrMore" || name === "optional" || name === "list" || name === "mixed" ) ) {
e = [ { name : "group" , e : splitToDuos ( { name : "group" , e : e } ) . e } ]
}
if ( e . length > 2 && name === "element" ) {
e = [ e [ 0 ] ] . concat ( { name : "group" , e : splitToDuos ( { name : "group" , e : e . slice ( 1 ) } ) . e } )
}
if ( e . length === 1 && name === "attribute" ) {
e . push ( { name : "text" , text : text } )
}
if ( e . length === 1 && ( name === "choice" || name === "group" || name === "interleave" ) ) {
name = e [ 0 ] . name ;
names = e [ 0 ] . names ;
a = e [ 0 ] . a ;
text = e [ 0 ] . text ;
e = e [ 0 ] . e
} else {
if ( e . length > 2 && ( name === "choice" || name === "group" || name === "interleave" ) ) {
e = splitToDuos ( { name : name , e : e } ) . e
}
}
if ( name === "mixed" ) {
name = "interleave" ;
e = [ e [ 0 ] , { name : "text" } ]
}
if ( name === "optional" ) {
name = "choice" ;
e = [ e [ 0 ] , { name : "empty" } ]
}
if ( name === "zeroOrMore" ) {
name = "choice" ;
e = [ { name : "oneOrMore" , e : [ e [ 0 ] ] } , { name : "empty" } ]
}
if ( name === "define" && a . combine ) {
ce = combineDefines ( a . combine , a . name , e , siblings ) ;
if ( ce ) {
return
}
}
ce = { name : name } ;
if ( e && e . length > 0 ) {
ce . e = e
}
for ( i in a ) {
if ( a . hasOwnProperty ( i ) ) {
ce . a = a ;
break
}
}
if ( text !== undefined ) {
ce . text = text
}
if ( names && names . length > 0 ) {
ce . names = names
}
if ( name === "element" ) {
ce . id = elements . length ;
elements . push ( ce ) ;
ce = { name : "elementref" , id : ce . id }
}
return ce
} ;
function resolveDefines ( def , defines ) {
var i = 0 , e , defs , end , name = def . name ;
while ( def . e && i < def . e . length ) {
e = def . e [ i ] ;
if ( e . name === "ref" ) {
defs = defines [ e . a . name ] ;
if ( ! defs ) {
throw e . a . name + " was not defined." ;
}
end = def . e . slice ( i + 1 ) ;
def . e = def . e . slice ( 0 , i ) ;
def . e = def . e . concat ( defs . e ) ;
def . e = def . e . concat ( end )
} else {
i += 1 ;
resolveDefines ( e , defines )
}
}
e = def . e ;
if ( name === "choice" ) {
if ( ! e || ! e [ 1 ] || e [ 1 ] . name === "empty" ) {
if ( ! e || ! e [ 0 ] || e [ 0 ] . name === "empty" ) {
delete def . e ;
def . name = "empty"
} else {
e [ 1 ] = e [ 0 ] ;
e [ 0 ] = { name : "empty" }
}
}
}
if ( name === "group" || name === "interleave" ) {
if ( e [ 0 ] . name === "empty" ) {
if ( e [ 1 ] . name === "empty" ) {
delete def . e ;
def . name = "empty"
} else {
name = def . name = e [ 1 ] . name ;
def . names = e [ 1 ] . names ;
e = def . e = e [ 1 ] . e
}
} else {
if ( e [ 1 ] . name === "empty" ) {
name = def . name = e [ 0 ] . name ;
def . names = e [ 0 ] . names ;
e = def . e = e [ 0 ] . e
}
}
}
if ( name === "oneOrMore" && e [ 0 ] . name === "empty" ) {
delete def . e ;
def . name = "empty"
}
if ( name === "attribute" ) {
splitQNames ( def )
}
if ( name === "interleave" ) {
if ( e [ 0 ] . name === "interleave" ) {
if ( e [ 1 ] . name === "interleave" ) {
e = def . e = e [ 0 ] . e . concat ( e [ 1 ] . e )
} else {
e = def . e = [ e [ 1 ] ] . concat ( e [ 0 ] . e )
}
} else {
if ( e [ 1 ] . name === "interleave" ) {
e = def . e = [ e [ 0 ] ] . concat ( e [ 1 ] . e )
}
}
}
}
function resolveElements ( def , elements ) {
var i = 0 , e ;
while ( def . e && i < def . e . length ) {
e = def . e [ i ] ;
if ( e . name === "elementref" ) {
e . id = e . id || 0 ;
def . e [ i ] = elements [ e . id ]
} else {
if ( e . name !== "element" ) {
resolveElements ( e , elements )
}
}
i += 1
}
}
function main ( dom , callback ) {
var elements = [ ] , grammar = parse ( dom && dom . documentElement , elements , undefined ) , i , e , defines = { } ;
for ( i = 0 ; i < grammar . e . length ; i += 1 ) {
e = grammar . e [ i ] ;
if ( e . name === "define" ) {
defines [ e . a . name ] = e
} else {
if ( e . name === "start" ) {
start = e
}
}
}
if ( ! start ) {
return [ new RelaxNGParseError ( "No Relax NG start element was found." ) ]
}
resolveDefines ( start , defines ) ;
for ( i in defines ) {
if ( defines . hasOwnProperty ( i ) ) {
resolveDefines ( defines [ i ] , defines )
}
}
for ( i = 0 ; i < elements . length ; i += 1 ) {
resolveDefines ( elements [ i ] , defines )
}
if ( callback ) {
self . rootPattern = callback ( start . e [ 0 ] , elements )
}
resolveElements ( start , elements ) ;
for ( i = 0 ; i < elements . length ; i += 1 ) {
resolveElements ( elements [ i ] , elements )
}
self . start = start ;
self . elements = elements ;
self . nsmap = nsmap ;
return null
}
this . parseRelaxNGDOM = main
} ;
runtime . loadClass ( "xmldom.RelaxNGParser" ) ;
xmldom . RelaxNG = function RelaxNG ( ) {
var xmlnsns = "http://www.w3.org/2000/xmlns/" , createChoice , createInterleave , createGroup , createAfter , createOneOrMore , createValue , createAttribute , createNameClass , createData , makePattern , notAllowed = { type : "notAllowed" , nullable : false , hash : "notAllowed" , textDeriv : function ( ) {
return notAllowed
} , startTagOpenDeriv : function ( ) {
return notAllowed
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return notAllowed
} , endTagDeriv : function ( ) {
return notAllowed
} } , empty = { type : "empty" , nullable : true , hash : "empty" , textDeriv : function ( ) {
return notAllowed
} , startTagOpenDeriv : function ( ) {
return notAllowed
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return empty
} , endTagDeriv : function ( ) {
return notAllowed
} } , text = { type : "text" , nullable : true , hash : "text" , textDeriv : function ( ) {
return text
} , startTagOpenDeriv : function ( ) {
return notAllowed
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return text
} , endTagDeriv : function ( ) {
return notAllowed
} } , applyAfter , childDeriv , rootPattern ;
function memoize0arg ( func ) {
return function ( ) {
var cache ;
return function ( ) {
if ( cache === undefined ) {
cache = func ( )
}
return cache
}
} ( )
}
function memoize1arg ( type , func ) {
return function ( ) {
var cache = { } , cachecount = 0 ;
return function ( a ) {
var ahash = a . hash || a . toString ( ) , v ;
v = cache [ ahash ] ;
if ( v !== undefined ) {
return v
}
cache [ ahash ] = v = func ( a ) ;
v . hash = type + cachecount . toString ( ) ;
cachecount += 1 ;
return v
}
} ( )
}
function memoizeNode ( func ) {
return function ( ) {
var cache = { } ;
return function ( node ) {
var v , m ;
m = cache [ node . localName ] ;
if ( m === undefined ) {
cache [ node . localName ] = m = { }
} else {
v = m [ node . namespaceURI ] ;
if ( v !== undefined ) {
return v
}
}
m [ node . namespaceURI ] = v = func ( node ) ;
return v
}
} ( )
}
function memoize2arg ( type , fastfunc , func ) {
return function ( ) {
var cache = { } , cachecount = 0 ;
return function ( a , b ) {
var v = fastfunc && fastfunc ( a , b ) , ahash , bhash , m ;
if ( v !== undefined ) {
return v
}
ahash = a . hash || a . toString ( ) ;
bhash = b . hash || b . toString ( ) ;
m = cache [ ahash ] ;
if ( m === undefined ) {
cache [ ahash ] = m = { }
} else {
v = m [ bhash ] ;
if ( v !== undefined ) {
return v
}
}
m [ bhash ] = v = func ( a , b ) ;
v . hash = type + cachecount . toString ( ) ;
cachecount += 1 ;
return v
}
} ( )
}
function unorderedMemoize2arg ( type , fastfunc , func ) {
return function ( ) {
var cache = { } , cachecount = 0 ;
return function ( a , b ) {
var v = fastfunc && fastfunc ( a , b ) , ahash , bhash , m ;
if ( v !== undefined ) {
return v
}
ahash = a . hash || a . toString ( ) ;
bhash = b . hash || b . toString ( ) ;
if ( ahash < bhash ) {
m = ahash ;
ahash = bhash ;
bhash = m ;
m = a ;
a = b ;
b = m
}
m = cache [ ahash ] ;
if ( m === undefined ) {
cache [ ahash ] = m = { }
} else {
v = m [ bhash ] ;
if ( v !== undefined ) {
return v
}
}
m [ bhash ] = v = func ( a , b ) ;
v . hash = type + cachecount . toString ( ) ;
cachecount += 1 ;
return v
}
} ( )
}
function getUniqueLeaves ( leaves , pattern ) {
if ( pattern . p1 . type === "choice" ) {
getUniqueLeaves ( leaves , pattern . p1 )
} else {
leaves [ pattern . p1 . hash ] = pattern . p1
}
if ( pattern . p2 . type === "choice" ) {
getUniqueLeaves ( leaves , pattern . p2 )
} else {
leaves [ pattern . p2 . hash ] = pattern . p2
}
}
createChoice = memoize2arg ( "choice" , function ( p1 , p2 ) {
if ( p1 === notAllowed ) {
return p2
}
if ( p2 === notAllowed ) {
return p1
}
if ( p1 === p2 ) {
return p1
}
} , function ( p1 , p2 ) {
function makeChoice ( p1 , p2 ) {
return { type : "choice" , p1 : p1 , p2 : p2 , nullable : p1 . nullable || p2 . nullable , textDeriv : function ( context , text ) {
return createChoice ( p1 . textDeriv ( context , text ) , p2 . textDeriv ( context , text ) )
} , startTagOpenDeriv : memoizeNode ( function ( node ) {
return createChoice ( p1 . startTagOpenDeriv ( node ) , p2 . startTagOpenDeriv ( node ) )
} ) , attDeriv : function ( context , attribute ) {
return createChoice ( p1 . attDeriv ( context , attribute ) , p2 . attDeriv ( context , attribute ) )
} , startTagCloseDeriv : memoize0arg ( function ( ) {
return createChoice ( p1 . startTagCloseDeriv ( ) , p2 . startTagCloseDeriv ( ) )
} ) , endTagDeriv : memoize0arg ( function ( ) {
return createChoice ( p1 . endTagDeriv ( ) , p2 . endTagDeriv ( ) )
} ) }
}
var leaves = { } , i ;
getUniqueLeaves ( leaves , { p1 : p1 , p2 : p2 } ) ;
p1 = undefined ;
p2 = undefined ;
for ( i in leaves ) {
if ( leaves . hasOwnProperty ( i ) ) {
if ( p1 === undefined ) {
p1 = leaves [ i ]
} else {
if ( p2 === undefined ) {
p2 = leaves [ i ]
} else {
p2 = createChoice ( p2 , leaves [ i ] )
}
}
}
}
return makeChoice ( p1 , p2 )
} ) ;
createInterleave = unorderedMemoize2arg ( "interleave" , function ( p1 , p2 ) {
if ( p1 === notAllowed || p2 === notAllowed ) {
return notAllowed
}
if ( p1 === empty ) {
return p2
}
if ( p2 === empty ) {
return p1
}
} , function ( p1 , p2 ) {
return { type : "interleave" , p1 : p1 , p2 : p2 , nullable : p1 . nullable && p2 . nullable , textDeriv : function ( context , text ) {
return createChoice ( createInterleave ( p1 . textDeriv ( context , text ) , p2 ) , createInterleave ( p1 , p2 . textDeriv ( context , text ) ) )
} , startTagOpenDeriv : memoizeNode ( function ( node ) {
return createChoice ( applyAfter ( function ( p ) {
return createInterleave ( p , p2 )
} , p1 . startTagOpenDeriv ( node ) ) , applyAfter ( function ( p ) {
return createInterleave ( p1 , p )
} , p2 . startTagOpenDeriv ( node ) ) )
} ) , attDeriv : function ( context , attribute ) {
return createChoice ( createInterleave ( p1 . attDeriv ( context , attribute ) , p2 ) , createInterleave ( p1 , p2 . attDeriv ( context , attribute ) ) )
} , startTagCloseDeriv : memoize0arg ( function ( ) {
return createInterleave ( p1 . startTagCloseDeriv ( ) , p2 . startTagCloseDeriv ( ) )
} ) }
} ) ;
createGroup = memoize2arg ( "group" , function ( p1 , p2 ) {
if ( p1 === notAllowed || p2 === notAllowed ) {
return notAllowed
}
if ( p1 === empty ) {
return p2
}
if ( p2 === empty ) {
return p1
}
} , function ( p1 , p2 ) {
return { type : "group" , p1 : p1 , p2 : p2 , nullable : p1 . nullable && p2 . nullable , textDeriv : function ( context , text ) {
var p = createGroup ( p1 . textDeriv ( context , text ) , p2 ) ;
if ( p1 . nullable ) {
return createChoice ( p , p2 . textDeriv ( context , text ) )
}
return p
} , startTagOpenDeriv : function ( node ) {
var x = applyAfter ( function ( p ) {
return createGroup ( p , p2 )
} , p1 . startTagOpenDeriv ( node ) ) ;
if ( p1 . nullable ) {
return createChoice ( x , p2 . startTagOpenDeriv ( node ) )
}
return x
} , attDeriv : function ( context , attribute ) {
return createChoice ( createGroup ( p1 . attDeriv ( context , attribute ) , p2 ) , createGroup ( p1 , p2 . attDeriv ( context , attribute ) ) )
} , startTagCloseDeriv : memoize0arg ( function ( ) {
return createGroup ( p1 . startTagCloseDeriv ( ) , p2 . startTagCloseDeriv ( ) )
} ) }
} ) ;
createAfter = memoize2arg ( "after" , function ( p1 , p2 ) {
if ( p1 === notAllowed || p2 === notAllowed ) {
return notAllowed
}
} , function ( p1 , p2 ) {
return { type : "after" , p1 : p1 , p2 : p2 , nullable : false , textDeriv : function ( context , text ) {
return createAfter ( p1 . textDeriv ( context , text ) , p2 )
} , startTagOpenDeriv : memoizeNode ( function ( node ) {
return applyAfter ( function ( p ) {
return createAfter ( p , p2 )
} , p1 . startTagOpenDeriv ( node ) )
} ) , attDeriv : function ( context , attribute ) {
return createAfter ( p1 . attDeriv ( context , attribute ) , p2 )
} , startTagCloseDeriv : memoize0arg ( function ( ) {
return createAfter ( p1 . startTagCloseDeriv ( ) , p2 )
} ) , endTagDeriv : memoize0arg ( function ( ) {
return p1 . nullable ? p2 : notAllowed
} ) }
} ) ;
createOneOrMore = memoize1arg ( "oneormore" , function ( p ) {
if ( p === notAllowed ) {
return notAllowed
}
return { type : "oneOrMore" , p : p , nullable : p . nullable , textDeriv : function ( context , text ) {
return createGroup ( p . textDeriv ( context , text ) , createChoice ( this , empty ) )
} , startTagOpenDeriv : function ( node ) {
var oneOrMore = this ;
return applyAfter ( function ( pf ) {
return createGroup ( pf , createChoice ( oneOrMore , empty ) )
} , p . startTagOpenDeriv ( node ) )
} , attDeriv : function ( context , attribute ) {
var oneOrMore = this ;
return createGroup ( p . attDeriv ( context , attribute ) , createChoice ( oneOrMore , empty ) )
} , startTagCloseDeriv : memoize0arg ( function ( ) {
return createOneOrMore ( p . startTagCloseDeriv ( ) )
} ) }
} ) ;
function createElement ( nc , p ) {
return { type : "element" , nc : nc , nullable : false , textDeriv : function ( ) {
return notAllowed
} , startTagOpenDeriv : function ( node ) {
if ( nc . contains ( node ) ) {
return createAfter ( p , empty )
}
return notAllowed
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return this
} }
}
function valueMatch ( context , pattern , text ) {
return pattern . nullable && /^\s+$/ . test ( text ) || pattern . textDeriv ( context , text ) . nullable
}
createAttribute = memoize2arg ( "attribute" , undefined , function ( nc , p ) {
return { type : "attribute" , nullable : false , nc : nc , p : p , attDeriv : function ( context , attribute ) {
if ( nc . contains ( attribute ) && valueMatch ( context , p , attribute . nodeValue ) ) {
return empty
}
return notAllowed
} , startTagCloseDeriv : function ( ) {
return notAllowed
} }
} ) ;
function createList ( ) {
return { type : "list" , nullable : false , hash : "list" , textDeriv : function ( ) {
return empty
} }
}
createValue = memoize1arg ( "value" , function ( value ) {
return { type : "value" , nullable : false , value : value , textDeriv : function ( context , text ) {
return text === value ? empty : notAllowed
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return this
} }
} ) ;
createData = memoize1arg ( "data" , function ( type ) {
return { type : "data" , nullable : false , dataType : type , textDeriv : function ( ) {
return empty
} , attDeriv : function ( ) {
return notAllowed
} , startTagCloseDeriv : function ( ) {
return this
} }
} ) ;
applyAfter = function applyAfter ( f , p ) {
var result ;
if ( p . type === "after" ) {
result = createAfter ( p . p1 , f ( p . p2 ) )
} else {
if ( p . type === "choice" ) {
result = createChoice ( applyAfter ( f , p . p1 ) , applyAfter ( f , p . p2 ) )
} else {
result = p
}
}
return result
} ;
function attsDeriv ( context , pattern , attributes , position ) {
if ( pattern === notAllowed ) {
return notAllowed
}
if ( position >= attributes . length ) {
return pattern
}
if ( position === 0 ) {
position = 0
}
var a = attributes . item ( position ) ;
while ( a . namespaceURI === xmlnsns ) {
position += 1 ;
if ( position >= attributes . length ) {
return pattern
}
a = attributes . item ( position )
}
a = attsDeriv ( context , pattern . attDeriv ( context , attributes . item ( position ) ) , attributes , position + 1 ) ;
return a
}
function childrenDeriv ( context , pattern , walker ) {
var element = walker . currentNode , childNode = walker . firstChild ( ) , childNodes = [ ] , i , p ;
while ( childNode ) {
if ( childNode . nodeType === Node . ELEMENT _NODE ) {
childNodes . push ( childNode )
} else {
if ( childNode . nodeType === Node . TEXT _NODE && ! /^\s*$/ . test ( childNode . nodeValue ) ) {
childNodes . push ( childNode . nodeValue )
}
}
childNode = walker . nextSibling ( )
}
if ( childNodes . length === 0 ) {
childNodes = [ "" ]
}
p = pattern ;
for ( i = 0 ; p !== notAllowed && i < childNodes . length ; i += 1 ) {
childNode = childNodes [ i ] ;
if ( typeof childNode === "string" ) {
if ( /^\s*$/ . test ( childNode ) ) {
p = createChoice ( p , p . textDeriv ( context , childNode ) )
} else {
p = p . textDeriv ( context , childNode )
}
} else {
walker . currentNode = childNode ;
p = childDeriv ( context , p , walker )
}
}
walker . currentNode = element ;
return p
}
childDeriv = function childDeriv ( context , pattern , walker ) {
var childNode = walker . currentNode , p ;
p = pattern . startTagOpenDeriv ( childNode ) ;
p = attsDeriv ( context , p , childNode . attributes , 0 ) ;
p = p . startTagCloseDeriv ( ) ;
p = childrenDeriv ( context , p , walker ) ;
p = p . endTagDeriv ( ) ;
return p
} ;
function addNames ( name , ns , pattern ) {
if ( pattern . e [ 0 ] . a ) {
name . push ( pattern . e [ 0 ] . text ) ;
ns . push ( pattern . e [ 0 ] . a . ns )
} else {
addNames ( name , ns , pattern . e [ 0 ] )
}
if ( pattern . e [ 1 ] . a ) {
name . push ( pattern . e [ 1 ] . text ) ;
ns . push ( pattern . e [ 1 ] . a . ns )
} else {
addNames ( name , ns , pattern . e [ 1 ] )
}
}
createNameClass = function createNameClass ( pattern ) {
var name , ns , hash , i , result ;
if ( pattern . name === "name" ) {
name = pattern . text ;
ns = pattern . a . ns ;
result = { name : name , ns : ns , hash : "{" + ns + "}" + name , contains : function ( node ) {
return node . namespaceURI === ns && node . localName === name
} }
} else {
if ( pattern . name === "choice" ) {
name = [ ] ;
ns = [ ] ;
addNames ( name , ns , pattern ) ;
hash = "" ;
for ( i = 0 ; i < name . length ; i += 1 ) {
hash += "{" + ns [ i ] + "}" + name [ i ] + ","
}
result = { hash : hash , contains : function ( node ) {
var j ;
for ( j = 0 ; j < name . length ; j += 1 ) {
if ( name [ j ] === node . localName && ns [ j ] === node . namespaceURI ) {
return true
}
}
return false
} }
} else {
result = { hash : "anyName" , contains : function ( ) {
return true
} }
}
}
return result
} ;
function resolveElement ( pattern , elements ) {
var element , p , i , hash ;
hash = "element" + pattern . id . toString ( ) ;
p = elements [ pattern . id ] = { hash : hash } ;
element = createElement ( createNameClass ( pattern . e [ 0 ] ) , makePattern ( pattern . e [ 1 ] , elements ) ) ;
for ( i in element ) {
if ( element . hasOwnProperty ( i ) ) {
p [ i ] = element [ i ]
}
}
return p
}
makePattern = function makePattern ( pattern , elements ) {
var p , i ;
if ( pattern . name === "elementref" ) {
p = pattern . id || 0 ;
pattern = elements [ p ] ;
if ( pattern . name !== undefined ) {
return resolveElement ( pattern , elements )
}
return pattern
}
switch ( pattern . name ) {
case "empty" :
return empty ;
case "notAllowed" :
return notAllowed ;
case "text" :
return text ;
case "choice" :
return createChoice ( makePattern ( pattern . e [ 0 ] , elements ) , makePattern ( pattern . e [ 1 ] , elements ) ) ;
case "interleave" :
p = makePattern ( pattern . e [ 0 ] , elements ) ;
for ( i = 1 ; i < pattern . e . length ; i += 1 ) {
p = createInterleave ( p , makePattern ( pattern . e [ i ] , elements ) )
}
return p ;
case "group" :
return createGroup ( makePattern ( pattern . e [ 0 ] , elements ) , makePattern ( pattern . e [ 1 ] , elements ) ) ;
case "oneOrMore" :
return createOneOrMore ( makePattern ( pattern . e [ 0 ] , elements ) ) ;
case "attribute" :
return createAttribute ( createNameClass ( pattern . e [ 0 ] ) , makePattern ( pattern . e [ 1 ] , elements ) ) ;
case "value" :
return createValue ( pattern . text ) ;
case "data" :
p = pattern . a && pattern . a . type ;
if ( p === undefined ) {
p = ""
}
return createData ( p ) ;
case "list" :
return createList ( )
}
throw "No support for " + pattern . name ;
} ;
this . makePattern = function ( pattern , elements ) {
var copy = { } , i ;
for ( i in elements ) {
if ( elements . hasOwnProperty ( i ) ) {
copy [ i ] = elements [ i ]
}
}
i = makePattern ( pattern , copy ) ;
return i
} ;
this . validate = function validate ( walker , callback ) {
var errors ;
walker . currentNode = walker . root ;
errors = childDeriv ( null , rootPattern , walker ) ;
if ( ! errors . nullable ) {
runtime . log ( "Error in Relax NG validation: " + errors ) ;
callback ( [ "Error in Relax NG validation: " + errors ] )
} else {
callback ( null )
}
} ;
this . init = function init ( rootPattern1 ) {
rootPattern = rootPattern1
}
} ;
runtime . loadClass ( "xmldom.RelaxNGParser" ) ;
xmldom . RelaxNG2 = function RelaxNG2 ( ) {
var start , validateNonEmptyPattern , nsmap ;
function RelaxNGParseError ( error , context ) {
this . message = function ( ) {
if ( context ) {
error += context . nodeType === Node . ELEMENT _NODE ? " Element " : " Node " ;
error += context . nodeName ;
if ( context . nodeValue ) {
error += " with value '" + context . nodeValue + "'"
}
error += "."
}
return error
}
}
function validateOneOrMore ( elementdef , walker , element ) {
var node , i = 0 , err ;
do {
node = walker . currentNode ;
err = validateNonEmptyPattern ( elementdef . e [ 0 ] , walker , element ) ;
i += 1
} while ( ! err && node !== walker . currentNode ) ;
if ( i > 1 ) {
walker . currentNode = node ;
return null
}
return err
}
function qName ( node ) {
return nsmap [ node . namespaceURI ] + ":" + node . localName
}
function isWhitespace ( node ) {
return node && node . nodeType === Node . TEXT _NODE && /^\s+$/ . test ( node . nodeValue )
}
function validatePattern ( elementdef , walker , element , data ) {
if ( elementdef . name === "empty" ) {
return null
}
return validateNonEmptyPattern ( elementdef , walker , element , data )
}
function validateAttribute ( elementdef , walker , element ) {
if ( elementdef . e . length !== 2 ) {
throw "Attribute with wrong # of elements: " + elementdef . e . length ;
}
var att , a , l = elementdef . localnames . length , i ;
for ( i = 0 ; i < l ; i += 1 ) {
a = element . getAttributeNS ( elementdef . namespaces [ i ] , elementdef . localnames [ i ] ) ;
if ( a === "" && ! element . hasAttributeNS ( elementdef . namespaces [ i ] , elementdef . localnames [ i ] ) ) {
a = undefined
}
if ( att !== undefined && a !== undefined ) {
return [ new RelaxNGParseError ( "Attribute defined too often." , element ) ]
}
att = a
}
if ( att === undefined ) {
return [ new RelaxNGParseError ( "Attribute not found: " + elementdef . names , element ) ]
}
return validatePattern ( elementdef . e [ 1 ] , walker , element , att )
}
function validateTop ( elementdef , walker , element ) {
return validatePattern ( elementdef , walker , element )
}
function validateElement ( elementdef , walker ) {
if ( elementdef . e . length !== 2 ) {
throw "Element with wrong # of elements: " + elementdef . e . length ;
}
var node = walker . currentNode , type = node ? node . nodeType : 0 , error = null ;
while ( type > Node . ELEMENT _NODE ) {
if ( type !== Node . COMMENT _NODE && ( type !== Node . TEXT _NODE || ! /^\s+$/ . test ( walker . currentNode . nodeValue ) ) ) {
return [ new RelaxNGParseError ( "Not allowed node of type " + type + "." ) ]
}
node = walker . nextSibling ( ) ;
type = node ? node . nodeType : 0
}
if ( ! node ) {
return [ new RelaxNGParseError ( "Missing element " + elementdef . names ) ]
}
if ( elementdef . names && elementdef . names . indexOf ( qName ( node ) ) === - 1 ) {
return [ new RelaxNGParseError ( "Found " + node . nodeName + " instead of " + elementdef . names + "." , node ) ]
}
if ( walker . firstChild ( ) ) {
error = validateTop ( elementdef . e [ 1 ] , walker , node ) ;
while ( walker . nextSibling ( ) ) {
type = walker . currentNode . nodeType ;
if ( ! isWhitespace ( walker . currentNode ) && type !== Node . COMMENT _NODE ) {
return [ new RelaxNGParseError ( "Spurious content." , walker . currentNode ) ]
}
}
if ( walker . parentNode ( ) !== node ) {
return [ new RelaxNGParseError ( "Implementation error." ) ]
}
} else {
error = validateTop ( elementdef . e [ 1 ] , walker , node )
}
node = walker . nextSibling ( ) ;
return error
}
function validateChoice ( elementdef , walker , element , data ) {
if ( elementdef . e . length !== 2 ) {
throw "Choice with wrong # of options: " + elementdef . e . length ;
}
var node = walker . currentNode , err ;
if ( elementdef . e [ 0 ] . name === "empty" ) {
err = validateNonEmptyPattern ( elementdef . e [ 1 ] , walker , element , data ) ;
if ( err ) {
walker . currentNode = node
}
return null
}
err = validatePattern ( elementdef . e [ 0 ] , walker , element , data ) ;
if ( err ) {
walker . currentNode = node ;
err = validateNonEmptyPattern ( elementdef . e [ 1 ] , walker , element , data )
}
return err
}
function validateInterleave ( elementdef , walker , element ) {
var l = elementdef . e . length , n = [ l ] , err , i , todo = l , donethisround , node , subnode , e ;
while ( todo > 0 ) {
donethisround = 0 ;
node = walker . currentNode ;
for ( i = 0 ; i < l ; i += 1 ) {
subnode = walker . currentNode ;
if ( n [ i ] !== true && n [ i ] !== subnode ) {
e = elementdef . e [ i ] ;
err = validateNonEmptyPattern ( e , walker , element ) ;
if ( err ) {
walker . currentNode = subnode ;
if ( n [ i ] === undefined ) {
n [ i ] = false
}
} else {
if ( subnode === walker . currentNode || e . name === "oneOrMore" || e . name === "choice" && ( e . e [ 0 ] . name === "oneOrMore" || e . e [ 1 ] . name === "oneOrMore" ) ) {
donethisround += 1 ;
n [ i ] = subnode
} else {
donethisround += 1 ;
n [ i ] = true
}
}
}
}
if ( node === walker . currentNode && donethisround === todo ) {
return null
}
if ( donethisround === 0 ) {
for ( i = 0 ; i < l ; i += 1 ) {
if ( n [ i ] === false ) {
return [ new RelaxNGParseError ( "Interleave does not match." , element ) ]
}
}
return null
}
todo = 0 ;
for ( i = 0 ; i < l ; i += 1 ) {
if ( n [ i ] !== true ) {
todo += 1
}
}
}
return null
}
function validateGroup ( elementdef , walker , element ) {
if ( elementdef . e . length !== 2 ) {
throw "Group with wrong # of members: " + elementdef . e . length ;
}
return validateNonEmptyPattern ( elementdef . e [ 0 ] , walker , element ) || validateNonEmptyPattern ( elementdef . e [ 1 ] , walker , element )
}
function validateText ( elementdef , walker , element ) {
var node = walker . currentNode , type = node ? node . nodeType : 0 ;
while ( node !== element && type !== 3 ) {
if ( type === 1 ) {
return [ new RelaxNGParseError ( "Element not allowed here." , node ) ]
}
node = walker . nextSibling ( ) ;
type = node ? node . nodeType : 0
}
walker . nextSibling ( ) ;
return null
}
validateNonEmptyPattern = function validateNonEmptyPattern ( elementdef , walker , element , data ) {
var name = elementdef . name , err = null ;
if ( name === "text" ) {
err = validateText ( elementdef , walker , element )
} else {
if ( name === "data" ) {
err = null
} else {
if ( name === "value" ) {
if ( data !== elementdef . text ) {
err = [ new RelaxNGParseError ( "Wrong value, should be '" + elementdef . text + "', not '" + data + "'" , element ) ]
}
} else {
if ( name === "list" ) {
err = null
} else {
if ( name === "attribute" ) {
err = validateAttribute ( elementdef , walker , element )
} else {
if ( name === "element" ) {
err = validateElement ( elementdef , walker )
} else {
if ( name === "oneOrMore" ) {
err = validateOneOrMore ( elementdef , walker , element )
} else {
if ( name === "choice" ) {
err = validateChoice ( elementdef , walker , element , data )
} else {
if ( name === "group" ) {
err = validateGroup ( elementdef , walker , element )
} else {
if ( name === "interleave" ) {
err = validateInterleave ( elementdef , walker , element )
} else {
throw name + " not allowed in nonEmptyPattern." ;
}
}
}
}
}
}
}
}
}
}
return err
} ;
this . validate = function validate ( walker , callback ) {
walker . currentNode = walker . root ;
var errors = validatePattern ( start . e [ 0 ] , walker , walker . root ) ;
callback ( errors )
} ;
this . init = function init ( start1 , nsmap1 ) {
start = start1 ;
nsmap = nsmap1
}
} ;
xmldom . XPathIterator = function XPathIterator ( ) {
} ;
xmldom . XPath = function ( ) {
var createXPathPathIterator , parsePredicates ;
function isSmallestPositive ( a , b , c ) {
return a !== - 1 && ( a < b || b === - 1 ) && ( a < c || c === - 1 )
}
function parseXPathStep ( xpath , pos , end , steps ) {
var location = "" , predicates = [ ] , brapos = xpath . indexOf ( "[" , pos ) , slapos = xpath . indexOf ( "/" , pos ) , eqpos = xpath . indexOf ( "=" , pos ) ;
if ( isSmallestPositive ( slapos , brapos , eqpos ) ) {
location = xpath . substring ( pos , slapos ) ;
pos = slapos + 1
} else {
if ( isSmallestPositive ( brapos , slapos , eqpos ) ) {
location = xpath . substring ( pos , brapos ) ;
pos = parsePredicates ( xpath , brapos , predicates )
} else {
if ( isSmallestPositive ( eqpos , slapos , brapos ) ) {
location = xpath . substring ( pos , eqpos ) ;
pos = eqpos
} else {
location = xpath . substring ( pos , end ) ;
pos = end
}
}
}
steps . push ( { location : location , predicates : predicates } ) ;
return pos
}
function parseXPath ( xpath ) {
var steps = [ ] , p = 0 , end = xpath . length , value ;
while ( p < end ) {
p = parseXPathStep ( xpath , p , end , steps ) ;
if ( p < end && xpath [ p ] === "=" ) {
value = xpath . substring ( p + 1 , end ) ;
if ( value . length > 2 && ( value [ 0 ] === "'" || value [ 0 ] === '"' ) ) {
value = value . slice ( 1 , value . length - 1 )
} else {
try {
value = parseInt ( value , 10 )
} catch ( ignore ) {
}
}
p = end
}
}
return { steps : steps , value : value }
}
parsePredicates = function parsePredicates ( xpath , start , predicates ) {
var pos = start , l = xpath . length , depth = 0 ;
while ( pos < l ) {
if ( xpath [ pos ] === "]" ) {
depth -= 1 ;
if ( depth <= 0 ) {
predicates . push ( parseXPath ( xpath . substring ( start , pos ) ) )
}
} else {
if ( xpath [ pos ] === "[" ) {
if ( depth <= 0 ) {
start = pos + 1
}
depth += 1
}
}
pos += 1
}
return pos
} ;
xmldom . XPathIterator . prototype . next = function ( ) {
} ;
xmldom . XPathIterator . prototype . reset = function ( ) {
} ;
function XPathNodeIterator ( ) {
var node , done = false ;
this . setNode = function setNode ( n ) {
node = n
} ;
this . reset = function ( ) {
done = false
} ;
this . next = function next ( ) {
var val = done ? null : node ;
done = true ;
return val
}
}
function AttributeIterator ( it , namespace , localName ) {
this . reset = function reset ( ) {
it . reset ( )
} ;
this . next = function next ( ) {
var node = it . next ( ) ;
while ( node ) {
node = node . getAttributeNodeNS ( namespace , localName ) ;
if ( node ) {
return node
}
node = it . next ( )
}
return node
}
}
function AllChildElementIterator ( it , recurse ) {
var root = it . next ( ) , node = null ;
this . reset = function reset ( ) {
it . reset ( ) ;
root = it . next ( ) ;
node = null
} ;
this . next = function next ( ) {
while ( root ) {
if ( node ) {
if ( recurse && node . firstChild ) {
node = node . firstChild
} else {
while ( ! node . nextSibling && node !== root ) {
node = node . parentNode
}
if ( node === root ) {
root = it . next ( )
} else {
node = node . nextSibling
}
}
} else {
do {
node = root . firstChild ;
if ( ! node ) {
root = it . next ( )
}
} while ( root && ! node )
}
if ( node && node . nodeType === Node . ELEMENT _NODE ) {
return node
}
}
return null
}
}
function ConditionIterator ( it , condition ) {
this . reset = function reset ( ) {
it . reset ( )
} ;
this . next = function next ( ) {
var n = it . next ( ) ;
while ( n && ! condition ( n ) ) {
n = it . next ( )
}
return n
}
}
function createNodenameFilter ( it , name , namespaceResolver ) {
var s = name . split ( ":" , 2 ) , namespace = namespaceResolver ( s [ 0 ] ) , localName = s [ 1 ] ;
return new ConditionIterator ( it , function ( node ) {
return node . localName === localName && node . namespaceURI === namespace
} )
}
function createPredicateFilteredIterator ( it , p , namespaceResolver ) {
var nit = new XPathNodeIterator , pit = createXPathPathIterator ( nit , p , namespaceResolver ) , value = p . value ;
if ( value === undefined ) {
return new ConditionIterator ( it , function ( node ) {
nit . setNode ( node ) ;
pit . reset ( ) ;
return pit . next ( )
} )
}
return new ConditionIterator ( it , function ( node ) {
nit . setNode ( node ) ;
pit . reset ( ) ;
var n = pit . next ( ) ;
return n && n . nodeValue === value
} )
}
createXPathPathIterator = function createXPathPathIterator ( it , xpath , namespaceResolver ) {
var i , j , step , location , p ;
for ( i = 0 ; i < xpath . steps . length ; i += 1 ) {
step = xpath . steps [ i ] ;
location = step . location ;
if ( location === "" ) {
it = new AllChildElementIterator ( it , false )
} else {
if ( location [ 0 ] === "@" ) {
p = location . slice ( 1 ) . split ( ":" , 2 ) ;
it = new AttributeIterator ( it , namespaceResolver ( p [ 0 ] ) , p [ 1 ] )
} else {
if ( location !== "." ) {
it = new AllChildElementIterator ( it , false ) ;
if ( location . indexOf ( ":" ) !== - 1 ) {
it = createNodenameFilter ( it , location , namespaceResolver )
}
}
}
}
for ( j = 0 ; j < step . predicates . length ; j += 1 ) {
p = step . predicates [ j ] ;
it = createPredicateFilteredIterator ( it , p , namespaceResolver )
}
}
return it
} ;
function fallback ( node , xpath , namespaceResolver ) {
var it = new XPathNodeIterator , i , nodelist , parsedXPath ;
it . setNode ( node ) ;
parsedXPath = parseXPath ( xpath ) ;
it = createXPathPathIterator ( it , parsedXPath , namespaceResolver ) ;
nodelist = [ ] ;
i = it . next ( ) ;
while ( i ) {
nodelist . push ( i ) ;
i = it . next ( )
}
return nodelist
}
function getODFElementsWithXPath ( node , xpath , namespaceResolver ) {
var doc = node . ownerDocument , nodes , elements = [ ] , n = null ;
if ( ! doc || ! doc . evaluate ) {
elements = fallback ( node , xpath , namespaceResolver )
} else {
nodes = doc . evaluate ( xpath , node , namespaceResolver , XPathResult . UNORDERED _NODE _ITERATOR _TYPE , null ) ;
n = nodes . iterateNext ( ) ;
while ( n !== null ) {
if ( n . nodeType === Node . ELEMENT _NODE ) {
elements . push ( n )
}
n = nodes . iterateNext ( )
}
}
return elements
}
xmldom . XPath = function XPath ( ) {
this . getODFElementsWithXPath = getODFElementsWithXPath
} ;
return xmldom . XPath
} ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
gui . AnnotationViewManager = function AnnotationViewManager ( odfCanvas , odfFragment , annotationsPane ) {
var annotations = [ ] , doc = odfFragment . ownerDocument , odfUtils = new odf . OdfUtils , CONNECTOR _MARGIN = 30 , NOTE _MARGIN = 20 , window = runtime . getWindow ( ) ;
runtime . assert ( Boolean ( window ) , "Expected to be run in an environment which has a global window, like a browser." ) ;
function wrapAnnotation ( annotation ) {
var annotationWrapper = doc . createElement ( "div" ) , annotationNote = doc . createElement ( "div" ) , connectorHorizontal = doc . createElement ( "div" ) , connectorAngular = doc . createElement ( "div" ) , removeButton = doc . createElement ( "div" ) , annotationNode = annotation . node ;
annotationWrapper . className = "annotationWrapper" ;
annotationNode . parentNode . insertBefore ( annotationWrapper , annotationNode ) ;
annotationNote . className = "annotationNote" ;
annotationNote . appendChild ( annotationNode ) ;
removeButton . className = "annotationRemoveButton" ;
annotationNote . appendChild ( removeButton ) ;
connectorHorizontal . className = "annotationConnector horizontal" ;
connectorAngular . className = "annotationConnector angular" ;
annotationWrapper . appendChild ( annotationNote ) ;
annotationWrapper . appendChild ( connectorHorizontal ) ;
annotationWrapper . appendChild ( connectorAngular )
}
function unwrapAnnotation ( annotation ) {
var annotationNode = annotation . node , annotationWrapper = annotationNode . parentNode . parentNode ;
if ( annotationWrapper . localName === "div" ) {
annotationWrapper . parentNode . insertBefore ( annotationNode , annotationWrapper ) ;
annotationWrapper . parentNode . removeChild ( annotationWrapper )
}
}
function highlightAnnotation ( annotation ) {
var annotationNode = annotation . node , annotationEnd = annotation . end , range = doc . createRange ( ) , textNodes ;
if ( annotationEnd ) {
range . setStart ( annotationNode , annotationNode . childNodes . length ) ;
range . setEnd ( annotationEnd , 0 ) ;
textNodes = odfUtils . getTextNodes ( range , false ) ;
textNodes . forEach ( function ( n ) {
var container = doc . createElement ( "span" ) ;
container . className = "annotationHighlight" ;
container . setAttribute ( "annotation" , annotationNode . getAttributeNS ( odf . Namespaces . officens , "name" ) ) ;
n . parentNode . insertBefore ( container , n ) ;
container . appendChild ( n )
} )
}
range . detach ( )
}
function unhighlightAnnotation ( annotation ) {
var annotationName = annotation . node . getAttributeNS ( odf . Namespaces . officens , "name" ) , highlightSpans = doc . querySelectorAll ( 'span.annotationHighlight[annotation="' + annotationName + '"]' ) , i , container ;
for ( i = 0 ; i < highlightSpans . length ; i += 1 ) {
container = highlightSpans [ i ] ;
while ( container . firstChild ) {
container . parentNode . insertBefore ( container . firstChild , container )
}
container . parentNode . removeChild ( container )
}
}
function lineDistance ( point1 , point2 ) {
var xs = 0 , ys = 0 ;
xs = point2 . x - point1 . x ;
xs = xs * xs ;
ys = point2 . y - point1 . y ;
ys = ys * ys ;
return Math . sqrt ( xs + ys )
}
function renderAnnotation ( annotation ) {
var annotationNote = annotation . node . parentNode , connectorHorizontal = annotationNote . nextSibling , connectorAngular = connectorHorizontal . nextSibling , annotationWrapper = annotationNote . parentNode , connectorAngle = 0 , previousAnnotation = annotations [ annotations . indexOf ( annotation ) - 1 ] , previousRect , creatorNode = annotation . node . getElementsByTagNameNS ( odf . Namespaces . dcns , "creator" ) [ 0 ] , creatorName , zoomLevel = odfCanvas . getZoomLevel ( ) ;
annotationNote . style . left = ( annotationsPane . getBoundingClientRect ( ) . left - annotationWrapper . getBoundingClientRect ( ) . left ) / zoomLevel + "px" ;
annotationNote . style . width = annotationsPane . getBoundingClientRect ( ) . width / zoomLevel + "px" ;
connectorHorizontal . style . width = parseFloat ( annotationNote . style . left ) - CONNECTOR _MARGIN + "px" ;
if ( previousAnnotation ) {
previousRect = previousAnnotation . node . parentNode . getBoundingClientRect ( ) ;
if ( ( annotationWrapper . getBoundingClientRect ( ) . top - previousRect . bottom ) / zoomLevel <= NOTE _MARGIN ) {
annotationNote . style . top = Math . abs ( annotationWrapper . getBoundingClientRect ( ) . top - previousRect . bottom ) / zoomLevel + NOTE _MARGIN + "px"
} else {
annotationNote . style . top = "0px"
}
}
connectorAngular . style . left = connectorHorizontal . getBoundingClientRect ( ) . width / zoomLevel + "px" ;
connectorAngular . style . width = lineDistance ( { x : connectorAngular . getBoundingClientRect ( ) . left / zoomLevel , y : connectorAngular . getBoundingClientRect ( ) . top / zoomLevel } , { x : annotationNote . getBoundingClientRect ( ) . left / zoomLevel , y : annotationNote . getBoundingClientRect ( ) . top / zoomLevel } ) + "px" ;
connectorAngle = Math . asin ( ( annotationNote . getBoundingClientRect ( ) . top - connectorAngular . getBoundingClientRect ( ) . top ) / ( zoomLevel * parseFloat ( connectorAngular . style . width ) ) ) ;
connectorAngular . style . transform = "rotate(" + connectorAngle + "rad)" ;
connectorAngular . style . MozTransform = "rotate(" + connectorAngle + "rad)" ;
connectorAngular . style . WebkitTransform = "rotate(" + connectorAngle + "rad)" ;
connectorAngular . style . msTransform = "rotate(" + connectorAngle + "rad)" ;
if ( creatorNode ) {
creatorName = window . getComputedStyle ( ( creatorNode ) , ":before" ) . content ;
if ( creatorName && creatorName !== "none" ) {
creatorName = creatorName . substring ( 1 , creatorName . length - 1 ) ;
if ( creatorNode . firstChild ) {
creatorNode . firstChild . nodeValue = creatorName
} else {
creatorNode . appendChild ( doc . createTextNode ( creatorName ) )
}
}
}
}
function showAnnotationsPane ( show ) {
var sizer = odfCanvas . getSizer ( ) ;
if ( show ) {
annotationsPane . style . display = "inline-block" ;
sizer . style . paddingRight = window . getComputedStyle ( annotationsPane ) . width
} else {
annotationsPane . style . display = "none" ;
sizer . style . paddingRight = 0
}
odfCanvas . refreshSize ( )
}
function sortAnnotations ( ) {
annotations . sort ( function ( a , b ) {
if ( a . node . compareDocumentPosition ( b . node ) === Node . DOCUMENT _POSITION _FOLLOWING ) {
return - 1
}
return 1
} )
}
function rerenderAnnotations ( ) {
var i ;
for ( i = 0 ; i < annotations . length ; i += 1 ) {
renderAnnotation ( annotations [ i ] )
}
}
this . rerenderAnnotations = rerenderAnnotations ;
function addAnnotation ( annotation ) {
showAnnotationsPane ( true ) ;
annotations . push ( { node : annotation . node , end : annotation . end } ) ;
sortAnnotations ( ) ;
wrapAnnotation ( annotation ) ;
if ( annotation . end ) {
highlightAnnotation ( annotation )
}
rerenderAnnotations ( )
}
this . addAnnotation = addAnnotation ;
function forgetAnnotation ( annotation ) {
var index = annotations . indexOf ( annotation ) ;
unwrapAnnotation ( annotation ) ;
unhighlightAnnotation ( annotation ) ;
if ( index !== - 1 ) {
annotations . splice ( index , 1 )
}
if ( annotations . length === 0 ) {
showAnnotationsPane ( false )
}
}
function forgetAnnotations ( ) {
while ( annotations . length ) {
forgetAnnotation ( annotations [ 0 ] )
}
}
this . forgetAnnotations = forgetAnnotations
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
odf . OdfNodeFilter = function OdfNodeFilter ( ) {
this . acceptNode = function ( node ) {
var result ;
if ( node . namespaceURI === "http://www.w3.org/1999/xhtml" ) {
result = NodeFilter . FILTER _SKIP
} else {
if ( node . namespaceURI && node . namespaceURI . match ( /^urn:webodf:/ ) ) {
result = NodeFilter . FILTER _REJECT
} else {
result = NodeFilter . FILTER _ACCEPT
}
}
return result
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
odf . Namespaces = function ( ) {
var drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" , fons = "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" , officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0" , presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" , stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0" , svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" , tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0" , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" ,
dr3dns = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" , numberns = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" , xlinkns = "http://www.w3.org/1999/xlink" , xmlns = "http://www.w3.org/XML/1998/namespace" , dcns = "http://purl.org/dc/elements/1.1/" , webodfns = "urn:webodf" , namespaceMap = { "draw" : drawns , "fo" : fons , "office" : officens , "presentation" : presentationns , "style" : stylens , "svg" : svgns , "table" : tablens , "text" : textns , "dr3d" : dr3dns , "numberns" : numberns , "xlink" : xlinkns , "xml" : xmlns ,
"dc" : dcns , "webodf" : webodfns } , namespaces ;
function forEachPrefix ( cb ) {
var prefix ;
for ( prefix in namespaceMap ) {
if ( namespaceMap . hasOwnProperty ( prefix ) ) {
cb ( prefix , namespaceMap [ prefix ] )
}
}
}
function resolvePrefix ( prefix ) {
return namespaceMap [ prefix ] || null
}
resolvePrefix . lookupNamespaceURI = resolvePrefix ;
namespaces = function Namespaces ( ) {
} ;
namespaces . forEachPrefix = forEachPrefix ;
namespaces . resolvePrefix = resolvePrefix ;
namespaces . namespaceMap = namespaceMap ;
namespaces . drawns = drawns ;
namespaces . fons = fons ;
namespaces . officens = officens ;
namespaces . presentationns = presentationns ;
namespaces . stylens = stylens ;
namespaces . svgns = svgns ;
namespaces . tablens = tablens ;
namespaces . textns = textns ;
namespaces . dr3dns = dr3dns ;
namespaces . numberns = numberns ;
namespaces . xlinkns = xlinkns ;
namespaces . xmlns = xmlns ;
namespaces . dcns = dcns ;
namespaces . webodfns = webodfns ;
return namespaces
} ( ) ;
runtime . loadClass ( "xmldom.XPath" ) ;
odf . StyleInfo = function StyleInfo ( ) {
var chartns = "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" , dbns = "urn:oasis:names:tc:opendocument:xmlns:database:1.0" , dr3dns = "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" , drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" , formns = "urn:oasis:names:tc:opendocument:xmlns:form:1.0" , numberns = "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" , officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0" , presentationns = "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" ,
stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0" , tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0" , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" , nsprefixes = { "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" : "chart:" , "urn:oasis:names:tc:opendocument:xmlns:database:1.0" : "db:" , "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" : "dr3d:" , "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" : "draw:" , "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" : "fo:" ,
"urn:oasis:names:tc:opendocument:xmlns:form:1.0" : "form:" , "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" : "number:" , "urn:oasis:names:tc:opendocument:xmlns:office:1.0" : "office:" , "urn:oasis:names:tc:opendocument:xmlns:presentation:1.0" : "presentation:" , "urn:oasis:names:tc:opendocument:xmlns:style:1.0" : "style:" , "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" : "svg:" , "urn:oasis:names:tc:opendocument:xmlns:table:1.0" : "table:" , "urn:oasis:names:tc:opendocument:xmlns:text:1.0" : "chart:" ,
"http://www.w3.org/XML/1998/namespace" : "xml:" } , elementstyles = { "text" : [ { ens : stylens , en : "tab-stop" , ans : stylens , a : "leader-text-style" } , { ens : stylens , en : "drop-cap" , ans : stylens , a : "style-name" } , { ens : textns , en : "notes-configuration" , ans : textns , a : "citation-body-style-name" } , { ens : textns , en : "notes-configuration" , ans : textns , a : "citation-style-name" } , { ens : textns , en : "a" , ans : textns , a : "style-name" } , { ens : textns , en : "alphabetical-index" , ans : textns , a : "style-name" } , { ens : textns , en : "linenumbering-configuration" ,
ans : textns , a : "style-name" } , { ens : textns , en : "list-level-style-number" , ans : textns , a : "style-name" } , { ens : textns , en : "ruby-text" , ans : textns , a : "style-name" } , { ens : textns , en : "span" , ans : textns , a : "style-name" } , { ens : textns , en : "a" , ans : textns , a : "visited-style-name" } , { ens : stylens , en : "text-properties" , ans : stylens , a : "text-line-through-text-style" } , { ens : textns , en : "alphabetical-index-source" , ans : textns , a : "main-entry-style-name" } , { ens : textns , en : "index-entry-bibliography" , ans : textns , a : "style-name" } ,
{ ens : textns , en : "index-entry-chapter" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-link-end" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-link-start" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-page-number" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-span" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-tab-stop" , ans : textns , a : "style-name" } , { ens : textns , en : "index-entry-text" , ans : textns , a : "style-name" } , { ens : textns , en : "index-title-template" ,
ans : textns , a : "style-name" } , { ens : textns , en : "list-level-style-bullet" , ans : textns , a : "style-name" } , { ens : textns , en : "outline-level-style" , ans : textns , a : "style-name" } ] , "paragraph" : [ { ens : drawns , en : "caption" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "circle" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "connector" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "control" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "custom-shape" , ans : drawns , a : "text-style-name" } , { ens : drawns ,
en : "ellipse" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "frame" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "line" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "measure" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "path" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "polygon" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "polyline" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "rect" , ans : drawns , a : "text-style-name" } , { ens : drawns , en : "regular-polygon" ,
ans : drawns , a : "text-style-name" } , { ens : officens , en : "annotation" , ans : drawns , a : "text-style-name" } , { ens : formns , en : "column" , ans : formns , a : "text-style-name" } , { ens : stylens , en : "style" , ans : stylens , a : "next-style-name" } , { ens : tablens , en : "body" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "even-columns" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "even-rows" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "first-column" , ans : tablens , a : "paragraph-style-name" } ,
{ ens : tablens , en : "first-row" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "last-column" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "last-row" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "odd-columns" , ans : tablens , a : "paragraph-style-name" } , { ens : tablens , en : "odd-rows" , ans : tablens , a : "paragraph-style-name" } , { ens : textns , en : "notes-configuration" , ans : textns , a : "default-style-name" } , { ens : textns , en : "alphabetical-index-entry-template" , ans : textns , a : "style-name" } ,
{ ens : textns , en : "bibliography-entry-template" , ans : textns , a : "style-name" } , { ens : textns , en : "h" , ans : textns , a : "style-name" } , { ens : textns , en : "illustration-index-entry-template" , ans : textns , a : "style-name" } , { ens : textns , en : "index-source-style" , ans : textns , a : "style-name" } , { ens : textns , en : "object-index-entry-template" , ans : textns , a : "style-name" } , { ens : textns , en : "p" , ans : textns , a : "style-name" } , { ens : textns , en : "table-index-entry-template" , ans : textns , a : "style-name" } , { ens : textns , en : "table-of-content-entry-template" ,
ans : textns , a : "style-name" } , { ens : textns , en : "table-index-entry-template" , ans : textns , a : "style-name" } , { ens : textns , en : "user-index-entry-template" , ans : textns , a : "style-name" } , { ens : stylens , en : "page-layout-properties" , ans : stylens , a : "register-truth-ref-style-name" } ] , "chart" : [ { ens : chartns , en : "axis" , ans : chartns , a : "style-name" } , { ens : chartns , en : "chart" , ans : chartns , a : "style-name" } , { ens : chartns , en : "data-label" , ans : chartns , a : "style-name" } , { ens : chartns , en : "data-point" , ans : chartns , a : "style-name" } ,
{ ens : chartns , en : "equation" , ans : chartns , a : "style-name" } , { ens : chartns , en : "error-indicator" , ans : chartns , a : "style-name" } , { ens : chartns , en : "floor" , ans : chartns , a : "style-name" } , { ens : chartns , en : "footer" , ans : chartns , a : "style-name" } , { ens : chartns , en : "grid" , ans : chartns , a : "style-name" } , { ens : chartns , en : "legend" , ans : chartns , a : "style-name" } , { ens : chartns , en : "mean-value" , ans : chartns , a : "style-name" } , { ens : chartns , en : "plot-area" , ans : chartns , a : "style-name" } , { ens : chartns , en : "regression-curve" ,
ans : chartns , a : "style-name" } , { ens : chartns , en : "series" , ans : chartns , a : "style-name" } , { ens : chartns , en : "stock-gain-marker" , ans : chartns , a : "style-name" } , { ens : chartns , en : "stock-loss-marker" , ans : chartns , a : "style-name" } , { ens : chartns , en : "stock-range-line" , ans : chartns , a : "style-name" } , { ens : chartns , en : "subtitle" , ans : chartns , a : "style-name" } , { ens : chartns , en : "title" , ans : chartns , a : "style-name" } , { ens : chartns , en : "wall" , ans : chartns , a : "style-name" } ] , "section" : [ { ens : textns , en : "alphabetical-index" ,
ans : textns , a : "style-name" } , { ens : textns , en : "bibliography" , ans : textns , a : "style-name" } , { ens : textns , en : "illustration-index" , ans : textns , a : "style-name" } , { ens : textns , en : "index-title" , ans : textns , a : "style-name" } , { ens : textns , en : "object-index" , ans : textns , a : "style-name" } , { ens : textns , en : "section" , ans : textns , a : "style-name" } , { ens : textns , en : "table-of-content" , ans : textns , a : "style-name" } , { ens : textns , en : "table-index" , ans : textns , a : "style-name" } , { ens : textns , en : "user-index" , ans : textns ,
a : "style-name" } ] , "ruby" : [ { ens : textns , en : "ruby" , ans : textns , a : "style-name" } ] , "table" : [ { ens : dbns , en : "query" , ans : dbns , a : "style-name" } , { ens : dbns , en : "table-representation" , ans : dbns , a : "style-name" } , { ens : tablens , en : "background" , ans : tablens , a : "style-name" } , { ens : tablens , en : "table" , ans : tablens , a : "style-name" } ] , "table-column" : [ { ens : dbns , en : "column" , ans : dbns , a : "style-name" } , { ens : tablens , en : "table-column" , ans : tablens , a : "style-name" } ] , "table-row" : [ { ens : dbns , en : "query" , ans : dbns ,
a : "default-row-style-name" } , { ens : dbns , en : "table-representation" , ans : dbns , a : "default-row-style-name" } , { ens : tablens , en : "table-row" , ans : tablens , a : "style-name" } ] , "table-cell" : [ { ens : dbns , en : "column" , ans : dbns , a : "default-cell-style-name" } , { ens : tablens , en : "table-column" , ans : tablens , a : "default-cell-style-name" } , { ens : tablens , en : "table-row" , ans : tablens , a : "default-cell-style-name" } , { ens : tablens , en : "body" , ans : tablens , a : "style-name" } , { ens : tablens , en : "covered-table-cell" , ans : tablens ,
a : "style-name" } , { ens : tablens , en : "even-columns" , ans : tablens , a : "style-name" } , { ens : tablens , en : "covered-table-cell" , ans : tablens , a : "style-name" } , { ens : tablens , en : "even-columns" , ans : tablens , a : "style-name" } , { ens : tablens , en : "even-rows" , ans : tablens , a : "style-name" } , { ens : tablens , en : "first-column" , ans : tablens , a : "style-name" } , { ens : tablens , en : "first-row" , ans : tablens , a : "style-name" } , { ens : tablens , en : "last-column" , ans : tablens , a : "style-name" } , { ens : tablens , en : "last-row" , ans : tablens ,
a : "style-name" } , { ens : tablens , en : "odd-columns" , ans : tablens , a : "style-name" } , { ens : tablens , en : "odd-rows" , ans : tablens , a : "style-name" } , { ens : tablens , en : "table-cell" , ans : tablens , a : "style-name" } ] , "graphic" : [ { ens : dr3dns , en : "cube" , ans : drawns , a : "style-name" } , { ens : dr3dns , en : "extrude" , ans : drawns , a : "style-name" } , { ens : dr3dns , en : "rotate" , ans : drawns , a : "style-name" } , { ens : dr3dns , en : "scene" , ans : drawns , a : "style-name" } , { ens : dr3dns , en : "sphere" , ans : drawns , a : "style-name" } , { ens : drawns , en : "caption" ,
ans : drawns , a : "style-name" } , { ens : drawns , en : "circle" , ans : drawns , a : "style-name" } , { ens : drawns , en : "connector" , ans : drawns , a : "style-name" } , { ens : drawns , en : "control" , ans : drawns , a : "style-name" } , { ens : drawns , en : "custom-shape" , ans : drawns , a : "style-name" } , { ens : drawns , en : "ellipse" , ans : drawns , a : "style-name" } , { ens : drawns , en : "frame" , ans : drawns , a : "style-name" } , { ens : drawns , en : "g" , ans : drawns , a : "style-name" } , { ens : drawns , en : "line" , ans : drawns , a : "style-name" } , { ens : drawns , en : "measure" ,
ans : drawns , a : "style-name" } , { ens : drawns , en : "page-thumbnail" , ans : drawns , a : "style-name" } , { ens : drawns , en : "path" , ans : drawns , a : "style-name" } , { ens : drawns , en : "polygon" , ans : drawns , a : "style-name" } , { ens : drawns , en : "polyline" , ans : drawns , a : "style-name" } , { ens : drawns , en : "rect" , ans : drawns , a : "style-name" } , { ens : drawns , en : "regular-polygon" , ans : drawns , a : "style-name" } , { ens : officens , en : "annotation" , ans : drawns , a : "style-name" } ] , "presentation" : [ { ens : dr3dns , en : "cube" , ans : presentationns , a : "style-name" } ,
{ ens : dr3dns , en : "extrude" , ans : presentationns , a : "style-name" } , { ens : dr3dns , en : "rotate" , ans : presentationns , a : "style-name" } , { ens : dr3dns , en : "scene" , ans : presentationns , a : "style-name" } , { ens : dr3dns , en : "sphere" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "caption" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "circle" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "connector" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "control" , ans : presentationns , a : "style-name" } ,
{ ens : drawns , en : "custom-shape" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "ellipse" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "frame" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "g" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "line" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "measure" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "page-thumbnail" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "path" , ans : presentationns , a : "style-name" } ,
{ ens : drawns , en : "polygon" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "polyline" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "rect" , ans : presentationns , a : "style-name" } , { ens : drawns , en : "regular-polygon" , ans : presentationns , a : "style-name" } , { ens : officens , en : "annotation" , ans : presentationns , a : "style-name" } ] , "drawing-page" : [ { ens : drawns , en : "page" , ans : drawns , a : "style-name" } , { ens : presentationns , en : "notes" , ans : drawns , a : "style-name" } , { ens : stylens , en : "handout-master" , ans : drawns ,
a : "style-name" } , { ens : stylens , en : "master-page" , ans : drawns , a : "style-name" } ] , "list-style" : [ { ens : textns , en : "list" , ans : textns , a : "style-name" } , { ens : textns , en : "numbered-paragraph" , ans : textns , a : "style-name" } , { ens : textns , en : "list-item" , ans : textns , a : "style-override" } , { ens : stylens , en : "style" , ans : stylens , a : "list-style-name" } ] , "data" : [ { ens : stylens , en : "style" , ans : stylens , a : "data-style-name" } , { ens : stylens , en : "style" , ans : stylens , a : "percentage-data-style-name" } , { ens : presentationns ,
en : "date-time-decl" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "creation-date" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "creation-time" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "database-display" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "date" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "editing-duration" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "expression" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "meta-field" , ans : stylens ,
a : "data-style-name" } , { ens : textns , en : "modification-date" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "modification-time" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "print-date" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "print-time" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "table-formula" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "time" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "user-defined" , ans : stylens , a : "data-style-name" } , { ens : textns ,
en : "user-field-get" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "user-field-input" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "variable-get" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "variable-input" , ans : stylens , a : "data-style-name" } , { ens : textns , en : "variable-set" , ans : stylens , a : "data-style-name" } ] , "page-layout" : [ { ens : presentationns , en : "notes" , ans : stylens , a : "page-layout-name" } , { ens : stylens , en : "handout-master" , ans : stylens , a : "page-layout-name" } , { ens : stylens ,
en : "master-page" , ans : stylens , a : "page-layout-name" } ] } , elements , xpath = new xmldom . XPath ;
function hasDerivedStyles ( odfbody , nsResolver , styleElement ) {
var nodes , xp , resolver = nsResolver ( "style" ) , styleName = styleElement . getAttributeNS ( resolver , "name" ) , styleFamily = styleElement . getAttributeNS ( resolver , "family" ) ;
xp = "//style:*[@style:parent-style-name='" + styleName + "'][@style:family='" + styleFamily + "']" ;
nodes = xpath . getODFElementsWithXPath ( odfbody , xp , nsResolver ) ;
if ( nodes . length ) {
return true
}
return false
}
function prefixUsedStyleNames ( styleUsingElementsRoot , prefix ) {
var elname = elements [ styleUsingElementsRoot . localName ] , elns = elname && elname [ styleUsingElementsRoot . namespaceURI ] , length = elns ? elns . length : 0 , i , stylename , e ;
for ( i = 0 ; i < length ; i += 1 ) {
stylename = styleUsingElementsRoot . getAttributeNS ( elns [ i ] . ns , elns [ i ] . localname ) ;
if ( stylename ) {
styleUsingElementsRoot . setAttributeNS ( elns [ i ] . ns , nsprefixes [ elns [ i ] . ns ] + elns [ i ] . localname , prefix + stylename )
}
}
i = styleUsingElementsRoot . firstChild ;
while ( i ) {
if ( i . nodeType === Node . ELEMENT _NODE ) {
e = ( i ) ;
prefixUsedStyleNames ( e , prefix )
}
i = i . nextSibling
}
}
function prefixStyleName ( styleElement , prefix ) {
var stylename = styleElement . getAttributeNS ( drawns , "name" ) , ns ;
if ( stylename ) {
ns = drawns
} else {
stylename = styleElement . getAttributeNS ( stylens , "name" ) ;
if ( stylename ) {
ns = stylens
}
}
if ( ns ) {
styleElement . setAttributeNS ( ns , nsprefixes [ ns ] + "name" , prefix + stylename )
}
}
function prefixStyleNames ( styleElementsRoot , prefix , styleUsingElementsRoot ) {
var s ;
if ( styleElementsRoot ) {
s = styleElementsRoot . firstChild ;
while ( s ) {
if ( s . nodeType === Node . ELEMENT _NODE ) {
prefixStyleName ( ( s ) , prefix )
}
s = s . nextSibling
}
prefixUsedStyleNames ( styleElementsRoot , prefix ) ;
if ( styleUsingElementsRoot ) {
prefixUsedStyleNames ( styleUsingElementsRoot , prefix )
}
}
}
function removeRegExpFromUsedStyleNames ( styleUsingElementsRoot , regExp ) {
var elname = elements [ styleUsingElementsRoot . localName ] , elns = elname && elname [ styleUsingElementsRoot . namespaceURI ] , length = elns ? elns . length : 0 , i , stylename , e ;
for ( i = 0 ; i < length ; i += 1 ) {
stylename = styleUsingElementsRoot . getAttributeNS ( elns [ i ] . ns , elns [ i ] . localname ) ;
if ( stylename ) {
stylename = stylename . replace ( regExp , "" ) ;
styleUsingElementsRoot . setAttributeNS ( elns [ i ] . ns , nsprefixes [ elns [ i ] . ns ] + elns [ i ] . localname , stylename )
}
}
i = styleUsingElementsRoot . firstChild ;
while ( i ) {
if ( i . nodeType === Node . ELEMENT _NODE ) {
e = ( i ) ;
removeRegExpFromUsedStyleNames ( e , regExp )
}
i = i . nextSibling
}
}
function removeRegExpFromStyleName ( styleElement , regExp ) {
var stylename = styleElement . getAttributeNS ( drawns , "name" ) , ns ;
if ( stylename ) {
ns = drawns
} else {
stylename = styleElement . getAttributeNS ( stylens , "name" ) ;
if ( stylename ) {
ns = stylens
}
}
if ( ns ) {
stylename = stylename . replace ( regExp , "" ) ;
styleElement . setAttributeNS ( ns , nsprefixes [ ns ] + "name" , stylename )
}
}
function removePrefixFromStyleNames ( styleElementsRoot , prefix , styleUsingElementsRoot ) {
var s , regExp = new RegExp ( "^" + prefix ) ;
if ( styleElementsRoot ) {
s = styleElementsRoot . firstChild ;
while ( s ) {
if ( s . nodeType === Node . ELEMENT _NODE ) {
removeRegExpFromStyleName ( ( s ) , regExp )
}
s = s . nextSibling
}
removeRegExpFromUsedStyleNames ( styleElementsRoot , regExp ) ;
if ( styleUsingElementsRoot ) {
removeRegExpFromUsedStyleNames ( styleUsingElementsRoot , regExp )
}
}
}
function determineStylesForNode ( node , usedStyles ) {
var elname = elements [ node . localName ] , elns = elname && elname [ node . namespaceURI ] , length = elns ? elns . length : 0 , stylename , keyname , map , i ;
for ( i = 0 ; i < length ; i += 1 ) {
stylename = node . getAttributeNS ( elns [ i ] . ns , elns [ i ] . localname ) ;
if ( stylename ) {
usedStyles = usedStyles || { } ;
keyname = elns [ i ] . keyname ;
map = usedStyles [ keyname ] = usedStyles [ keyname ] || { } ;
map [ stylename ] = 1
}
}
return usedStyles
}
function determineUsedStyles ( styleUsingElementsRoot , usedStyles ) {
var i , e ;
determineStylesForNode ( styleUsingElementsRoot , usedStyles ) ;
i = styleUsingElementsRoot . firstChild ;
while ( i ) {
if ( i . nodeType === Node . ELEMENT _NODE ) {
e = ( i ) ;
determineUsedStyles ( e , usedStyles )
}
i = i . nextSibling
}
}
function StyleDefinition ( key , name , family ) {
this . key = key ;
this . name = name ;
this . family = family ;
this . requires = { }
}
function getStyleDefinition ( stylename , stylefamily , knownStyles ) {
var styleKey = stylename + '"' + stylefamily , styleDefinition = knownStyles [ styleKey ] ;
if ( ! styleDefinition ) {
styleDefinition = knownStyles [ styleKey ] = new StyleDefinition ( styleKey , stylename , stylefamily )
}
return styleDefinition
}
function determineDependentStyles ( styleUsingElementsRoot , styleScope , knownStyles ) {
var elname = elements [ styleUsingElementsRoot . localName ] , elns = elname && elname [ styleUsingElementsRoot . namespaceURI ] , length = elns ? elns . length : 0 , newScopeName = styleUsingElementsRoot . getAttributeNS ( stylens , "name" ) , newScopeFamily = styleUsingElementsRoot . getAttributeNS ( stylens , "family" ) , referencedStyleName , referencedStyleFamily , referencedStyleDef , i , e ;
if ( newScopeName && newScopeFamily ) {
styleScope = getStyleDefinition ( newScopeName , newScopeFamily , knownStyles )
}
if ( styleScope ) {
for ( i = 0 ; i < length ; i += 1 ) {
referencedStyleName = styleUsingElementsRoot . getAttributeNS ( elns [ i ] . ns , elns [ i ] . localname ) ;
if ( referencedStyleName ) {
referencedStyleFamily = elns [ i ] . keyname ;
referencedStyleDef = getStyleDefinition ( referencedStyleName , referencedStyleFamily , knownStyles ) ;
styleScope . requires [ referencedStyleDef . key ] = referencedStyleDef
}
}
}
i = styleUsingElementsRoot . firstChild ;
while ( i ) {
if ( i . nodeType === Node . ELEMENT _NODE ) {
e = ( i ) ;
determineDependentStyles ( e , styleScope , knownStyles )
}
i = i . nextSibling
}
return knownStyles
}
function inverse ( elementstyles ) {
var keyname , i , l , list , item , e = { } , map , array ;
for ( keyname in elementstyles ) {
if ( elementstyles . hasOwnProperty ( keyname ) ) {
list = elementstyles [ keyname ] ;
l = list . length ;
for ( i = 0 ; i < l ; i += 1 ) {
item = list [ i ] ;
map = e [ item . en ] = e [ item . en ] || { } ;
array = map [ item . ens ] = map [ item . ens ] || [ ] ;
array . push ( { ns : item . ans , localname : item . a , keyname : keyname } )
}
}
}
return e
}
function mergeRequiredStyles ( styleDependency , usedStyles ) {
var family = usedStyles [ styleDependency . family ] ;
if ( ! family ) {
family = usedStyles [ styleDependency . family ] = { }
}
family [ styleDependency . name ] = 1 ;
Object . keys ( ( styleDependency . requires ) ) . forEach ( function ( requiredStyleKey ) {
mergeRequiredStyles ( ( styleDependency . requires [ requiredStyleKey ] ) , usedStyles )
} )
}
function mergeUsedAutomaticStyles ( automaticStylesRoot , usedStyles ) {
var automaticStyles = determineDependentStyles ( automaticStylesRoot , null , { } ) ;
Object . keys ( automaticStyles ) . forEach ( function ( styleKey ) {
var automaticStyleDefinition = automaticStyles [ styleKey ] , usedFamily = usedStyles [ automaticStyleDefinition . family ] ;
if ( usedFamily && usedFamily . hasOwnProperty ( automaticStyleDefinition . name ) ) {
mergeRequiredStyles ( automaticStyleDefinition , usedStyles )
}
} )
}
this . UsedStyleList = function ( styleUsingElementsRoot , automaticStylesRoot ) {
var usedStyles = { } ;
this . uses = function ( element ) {
var localName = element . localName , name = element . getAttributeNS ( drawns , "name" ) || element . getAttributeNS ( stylens , "name" ) , keyName , map ;
if ( localName === "style" ) {
keyName = element . getAttributeNS ( stylens , "family" )
} else {
if ( element . namespaceURI === numberns ) {
keyName = "data"
} else {
keyName = localName
}
}
map = usedStyles [ keyName ] ;
return map ? map [ name ] > 0 : false
} ;
determineUsedStyles ( styleUsingElementsRoot , usedStyles ) ;
if ( automaticStylesRoot ) {
mergeUsedAutomaticStyles ( automaticStylesRoot , usedStyles )
}
} ;
this . hasDerivedStyles = hasDerivedStyles ;
this . prefixStyleNames = prefixStyleNames ;
this . removePrefixFromStyleNames = removePrefixFromStyleNames ;
this . determineStylesForNode = determineStylesForNode ;
elements = inverse ( elementstyles )
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.DomUtils" ) ;
odf . OdfUtils = function OdfUtils ( ) {
var textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" , drawns = "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" , whitespaceOnly = /^\s*$/ , domUtils = new core . DomUtils ;
function isParagraph ( e ) {
var name = e && e . localName ;
return ( name === "p" || name === "h" ) && e . namespaceURI === textns
}
this . isParagraph = isParagraph ;
function getParagraphElement ( node ) {
while ( node && ! isParagraph ( node ) ) {
node = node . parentNode
}
return node
}
this . getParagraphElement = getParagraphElement ;
this . isWithinTrackedChanges = function ( node , container ) {
while ( node && node !== container ) {
if ( node . namespaceURI === textns && node . localName === "tracked-changes" ) {
return true
}
node = node . parentNode
}
return false
} ;
this . isListItem = function ( e ) {
var name = e && e . localName ;
return name === "list-item" && e . namespaceURI === textns
} ;
function isODFWhitespace ( text ) {
return /^[ \t\r\n]+$/ . test ( text )
}
this . isODFWhitespace = isODFWhitespace ;
function isGroupingElement ( e ) {
var localName = e && e . localName ;
if ( /^(span|p|h|a|meta)$/ . test ( localName ) && e . namespaceURI === textns || localName === "span" && e . className === "annotationHighlight" ) {
return true
}
return false
}
this . isGroupingElement = isGroupingElement ;
function isCharacterElement ( e ) {
var n = e && e . localName , ns , r = false ;
if ( n ) {
ns = e . namespaceURI ;
if ( ns === textns ) {
r = n === "s" || n === "tab" || n === "line-break"
} else {
if ( ns === drawns ) {
r = n === "frame" && e . getAttributeNS ( textns , "anchor-type" ) === "as-char"
}
}
}
return r
}
this . isCharacterElement = isCharacterElement ;
function firstChild ( node ) {
while ( node . firstChild !== null && isGroupingElement ( node ) ) {
node = node . firstChild
}
return node
}
this . firstChild = firstChild ;
function lastChild ( node ) {
while ( node . lastChild !== null && isGroupingElement ( node ) ) {
node = node . lastChild
}
return node
}
this . lastChild = lastChild ;
function previousNode ( node ) {
while ( ! isParagraph ( node ) && node . previousSibling === null ) {
node = ( node . parentNode )
}
return isParagraph ( node ) ? null : lastChild ( ( node . previousSibling ) )
}
this . previousNode = previousNode ;
function nextNode ( node ) {
while ( ! isParagraph ( node ) && node . nextSibling === null ) {
node = ( node . parentNode )
}
return isParagraph ( node ) ? null : firstChild ( ( node . nextSibling ) )
}
this . nextNode = nextNode ;
function scanLeftForNonWhitespace ( node ) {
var r = false ;
while ( node ) {
if ( node . nodeType === Node . TEXT _NODE ) {
if ( node . length === 0 ) {
node = previousNode ( node )
} else {
return ! isODFWhitespace ( node . data . substr ( node . length - 1 , 1 ) )
}
} else {
if ( isCharacterElement ( node ) ) {
r = true ;
node = null
} else {
node = previousNode ( node )
}
}
}
return r
}
this . scanLeftForNonWhitespace = scanLeftForNonWhitespace ;
function lookLeftForCharacter ( node ) {
var text , r = 0 ;
if ( node . nodeType === Node . TEXT _NODE && node . length > 0 ) {
text = node . data ;
if ( ! isODFWhitespace ( text . substr ( text . length - 1 , 1 ) ) ) {
r = 1
} else {
if ( text . length === 1 ) {
r = scanLeftForNonWhitespace ( previousNode ( node ) ) ? 2 : 0
} else {
r = isODFWhitespace ( text . substr ( text . length - 2 , 1 ) ) ? 0 : 2
}
}
} else {
if ( isCharacterElement ( node ) ) {
r = 1
}
}
return r
}
this . lookLeftForCharacter = lookLeftForCharacter ;
function lookRightForCharacter ( node ) {
var r = false ;
if ( node && node . nodeType === Node . TEXT _NODE && node . length > 0 ) {
r = ! isODFWhitespace ( node . data . substr ( 0 , 1 ) )
} else {
if ( isCharacterElement ( node ) ) {
r = true
}
}
return r
}
this . lookRightForCharacter = lookRightForCharacter ;
function scanLeftForAnyCharacter ( node ) {
var r = false ;
node = node && lastChild ( node ) ;
while ( node ) {
if ( node . nodeType === Node . TEXT _NODE && node . length > 0 && ! isODFWhitespace ( node . data ) ) {
r = true ;
break
}
if ( isCharacterElement ( node ) ) {
r = true ;
break
}
node = previousNode ( node )
}
return r
}
this . scanLeftForAnyCharacter = scanLeftForAnyCharacter ;
function scanRightForAnyCharacter ( node ) {
var r = false ;
node = node && firstChild ( node ) ;
while ( node ) {
if ( node . nodeType === Node . TEXT _NODE && node . length > 0 && ! isODFWhitespace ( node . data ) ) {
r = true ;
break
}
if ( isCharacterElement ( node ) ) {
r = true ;
break
}
node = nextNode ( node )
}
return r
}
this . scanRightForAnyCharacter = scanRightForAnyCharacter ;
function isTrailingWhitespace ( textnode , offset ) {
if ( ! isODFWhitespace ( textnode . data . substr ( offset ) ) ) {
return false
}
return ! scanRightForAnyCharacter ( nextNode ( textnode ) )
}
this . isTrailingWhitespace = isTrailingWhitespace ;
function isSignificantWhitespace ( textNode , offset ) {
var text = textNode . data , result ;
if ( ! isODFWhitespace ( text [ offset ] ) ) {
return false
}
if ( isCharacterElement ( textNode . parentNode ) ) {
return false
}
if ( offset > 0 ) {
if ( ! isODFWhitespace ( text [ offset - 1 ] ) ) {
result = true
}
} else {
if ( scanLeftForNonWhitespace ( previousNode ( textNode ) ) ) {
result = true
}
}
if ( result === true ) {
return isTrailingWhitespace ( textNode , offset ) ? false : true
}
return false
}
this . isSignificantWhitespace = isSignificantWhitespace ;
function getFirstNonWhitespaceChild ( node ) {
var child = node && node . firstChild ;
while ( child && child . nodeType === Node . TEXT _NODE && whitespaceOnly . test ( child . nodeValue ) ) {
child = child . nextSibling
}
return child
}
this . getFirstNonWhitespaceChild = getFirstNonWhitespaceChild ;
function parseLength ( length ) {
var re = /-?([0-9]*[0-9][0-9]*(\.[0-9]*)?|0+\.[0-9]*[1-9][0-9]*|\.[0-9]*[1-9][0-9]*)((cm)|(mm)|(in)|(pt)|(pc)|(px)|(%))/ , m = re . exec ( length ) ;
if ( ! m ) {
return null
}
return { value : parseFloat ( m [ 1 ] ) , unit : m [ 3 ] }
}
this . parseLength = parseLength ;
function parsePositiveLength ( length ) {
var result = parseLength ( length ) ;
if ( result && ( result . value <= 0 || result . unit === "%" ) ) {
return null
}
return result
}
function parseNonNegativeLength ( length ) {
var result = parseLength ( length ) ;
if ( result && ( result . value < 0 || result . unit === "%" ) ) {
return null
}
return result
}
function parsePercentage ( length ) {
var result = parseLength ( length ) ;
if ( result && result . unit !== "%" ) {
return null
}
return result
}
function parseFoFontSize ( fontSize ) {
return parsePositiveLength ( fontSize ) || parsePercentage ( fontSize )
}
this . parseFoFontSize = parseFoFontSize ;
function parseFoLineHeight ( lineHeight ) {
return parseNonNegativeLength ( lineHeight ) || parsePercentage ( lineHeight )
}
this . parseFoLineHeight = parseFoLineHeight ;
function getImpactedParagraphs ( range ) {
var outerContainer = ( range . commonAncestorContainer ) , impactedParagraphs = [ ] ;
if ( outerContainer . nodeType === Node . ELEMENT _NODE ) {
impactedParagraphs = domUtils . getElementsByTagNameNS ( outerContainer , textns , "p" ) . concat ( domUtils . getElementsByTagNameNS ( outerContainer , textns , "h" ) )
}
while ( outerContainer && ! isParagraph ( outerContainer ) ) {
outerContainer = outerContainer . parentNode
}
if ( outerContainer ) {
impactedParagraphs . push ( outerContainer )
}
return impactedParagraphs . filter ( function ( n ) {
return domUtils . rangeIntersectsNode ( range , n )
} )
}
this . getImpactedParagraphs = getImpactedParagraphs ;
function isAcceptedNode ( node ) {
switch ( node . namespaceURI ) {
case odf . Namespaces . drawns :
;
case odf . Namespaces . svgns :
;
case odf . Namespaces . dr3dns :
return false ;
case odf . Namespaces . textns :
switch ( node . localName ) {
case "note-body" :
;
case "ruby-text" :
return false
}
break ;
case odf . Namespaces . officens :
switch ( node . localName ) {
case "annotation" :
;
case "binary-data" :
;
case "event-listeners" :
return false
}
break ;
default :
switch ( node . localName ) {
case "editinfo" :
return false
}
break
}
return true
}
function isSignificantTextContent ( textNode ) {
return Boolean ( getParagraphElement ( textNode ) && ( ! isODFWhitespace ( textNode . textContent ) || isSignificantWhitespace ( textNode , 0 ) ) )
}
function getTextNodes ( range , includePartial ) {
var document = range . startContainer . ownerDocument , nodeRange = document . createRange ( ) , textNodes ;
function nodeFilter ( node ) {
nodeRange . selectNodeContents ( node ) ;
if ( node . nodeType === Node . TEXT _NODE ) {
if ( includePartial && domUtils . rangesIntersect ( range , nodeRange ) || domUtils . containsRange ( range , nodeRange ) ) {
return isSignificantTextContent ( node ) ? NodeFilter . FILTER _ACCEPT : NodeFilter . FILTER _REJECT
}
} else {
if ( domUtils . rangesIntersect ( range , nodeRange ) ) {
if ( isAcceptedNode ( node ) ) {
return NodeFilter . FILTER _SKIP
}
}
}
return NodeFilter . FILTER _REJECT
}
textNodes = domUtils . getNodesInRange ( range , nodeFilter ) ;
nodeRange . detach ( ) ;
return textNodes
}
this . getTextNodes = getTextNodes ;
this . getTextElements = function ( range , includeInsignificantWhitespace ) {
var document = range . startContainer . ownerDocument , nodeRange = document . createRange ( ) , elements ;
function nodeFilter ( node ) {
var nodeType = node . nodeType ;
nodeRange . selectNodeContents ( node ) ;
if ( nodeType === Node . TEXT _NODE ) {
if ( domUtils . containsRange ( range , nodeRange ) && ( includeInsignificantWhitespace || isSignificantTextContent ( node ) ) ) {
return NodeFilter . FILTER _ACCEPT
}
} else {
if ( isCharacterElement ( node ) ) {
if ( domUtils . containsRange ( range , nodeRange ) ) {
return NodeFilter . FILTER _ACCEPT
}
} else {
if ( isAcceptedNode ( node ) || isGroupingElement ( node ) ) {
return NodeFilter . FILTER _SKIP
}
}
}
return NodeFilter . FILTER _REJECT
}
elements = domUtils . getNodesInRange ( range , nodeFilter ) ;
nodeRange . detach ( ) ;
return elements
} ;
this . getParagraphElements = function ( range ) {
var document = range . startContainer . ownerDocument , nodeRange = document . createRange ( ) , elements ;
function nodeFilter ( node ) {
nodeRange . selectNodeContents ( node ) ;
if ( isParagraph ( node ) ) {
if ( domUtils . rangesIntersect ( range , nodeRange ) ) {
return NodeFilter . FILTER _ACCEPT
}
} else {
if ( isAcceptedNode ( node ) || isGroupingElement ( node ) ) {
return NodeFilter . FILTER _SKIP
}
}
return NodeFilter . FILTER _REJECT
}
elements = domUtils . getNodesInRange ( range , nodeFilter ) ;
nodeRange . detach ( ) ;
return elements
}
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.OdfUtils" ) ;
odf . TextSerializer = function TextSerializer ( ) {
var self = this , odfUtils = new odf . OdfUtils ;
function serializeNode ( node ) {
var s = "" , accept = self . filter ? self . filter . acceptNode ( node ) : NodeFilter . FILTER _ACCEPT , nodeType = node . nodeType , child ;
if ( accept === NodeFilter . FILTER _ACCEPT || accept === NodeFilter . FILTER _SKIP ) {
child = node . firstChild ;
while ( child ) {
s += serializeNode ( child ) ;
child = child . nextSibling
}
}
if ( accept === NodeFilter . FILTER _ACCEPT ) {
if ( nodeType === Node . ELEMENT _NODE && odfUtils . isParagraph ( node ) ) {
s += "\n"
} else {
if ( nodeType === Node . TEXT _NODE && node . textContent ) {
s += node . textContent
}
}
}
return s
}
this . filter = null ;
this . writeToString = function ( node ) {
if ( ! node ) {
return ""
}
return serializeNode ( node )
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.DomUtils" ) ;
runtime . loadClass ( "core.LoopWatchDog" ) ;
runtime . loadClass ( "odf.Namespaces" ) ;
odf . TextStyleApplicator = function TextStyleApplicator ( newStylePrefix , formatting , automaticStyles ) {
var domUtils = new core . DomUtils , textns = odf . Namespaces . textns , stylens = odf . Namespaces . stylens , textProperties = "style:text-properties" , webodfns = "urn:webodf:names:scope" ;
function StyleLookup ( info ) {
function compare ( expected , actual ) {
if ( typeof expected === "object" && typeof actual === "object" ) {
return Object . keys ( expected ) . every ( function ( key ) {
return compare ( expected [ key ] , actual [ key ] )
} )
}
return expected === actual
}
this . isStyleApplied = function ( textNode ) {
var appliedStyle = formatting . getAppliedStylesForElement ( textNode ) ;
return compare ( info , appliedStyle )
}
}
function StyleManager ( info ) {
var createdStyles = { } ;
function createDirectFormat ( existingStyleName , document ) {
var existingStyleNode , styleNode ;
if ( existingStyleName ) {
existingStyleNode = formatting . getStyleElement ( existingStyleName , "text" ) ;
if ( existingStyleNode . parentNode === automaticStyles ) {
styleNode = existingStyleNode . cloneNode ( true )
} else {
styleNode = document . createElementNS ( stylens , "style:style" ) ;
styleNode . setAttributeNS ( stylens , "style:parent-style-name" , existingStyleName ) ;
styleNode . setAttributeNS ( stylens , "style:family" , "text" ) ;
styleNode . setAttributeNS ( webodfns , "scope" , "document-content" )
}
} else {
styleNode = document . createElementNS ( stylens , "style:style" ) ;
styleNode . setAttributeNS ( stylens , "style:family" , "text" ) ;
styleNode . setAttributeNS ( webodfns , "scope" , "document-content" )
}
formatting . updateStyle ( styleNode , info , newStylePrefix ) ;
automaticStyles . appendChild ( styleNode ) ;
return styleNode
}
function getDirectStyle ( existingStyleName , document ) {
existingStyleName = existingStyleName || "" ;
if ( ! createdStyles . hasOwnProperty ( existingStyleName ) ) {
createdStyles [ existingStyleName ] = createDirectFormat ( existingStyleName , document )
}
return createdStyles [ existingStyleName ] . getAttributeNS ( stylens , "name" )
}
this . applyStyleToContainer = function ( container ) {
var name = getDirectStyle ( container . getAttributeNS ( textns , "style-name" ) , container . ownerDocument ) ;
container . setAttributeNS ( textns , "text:style-name" , name )
}
}
function isTextSpan ( node ) {
return node . localName === "span" && node . namespaceURI === textns
}
function moveToNewSpan ( startNode , limits ) {
var document = startNode . ownerDocument , originalContainer = ( startNode . parentNode ) , styledContainer , trailingContainer , moveTrailing , node = startNode , nextNode , loopGuard = new core . LoopWatchDog ( 1E3 ) ;
if ( ! isTextSpan ( originalContainer ) ) {
styledContainer = document . createElementNS ( textns , "text:span" ) ;
originalContainer . insertBefore ( styledContainer , startNode ) ;
moveTrailing = false
} else {
if ( startNode . previousSibling && ! domUtils . rangeContainsNode ( limits , startNode . previousSibling ) ) {
styledContainer = originalContainer . cloneNode ( false ) ;
originalContainer . parentNode . insertBefore ( styledContainer , originalContainer . nextSibling ) ;
moveTrailing = true
} else {
styledContainer = originalContainer ;
moveTrailing = true
}
}
while ( node && ( node === startNode || domUtils . rangeContainsNode ( limits , node ) ) ) {
loopGuard . check ( ) ;
nextNode = node . nextSibling ;
if ( node . parentNode !== styledContainer ) {
styledContainer . appendChild ( node )
}
node = nextNode
}
if ( node && moveTrailing ) {
trailingContainer = styledContainer . cloneNode ( false ) ;
styledContainer . parentNode . insertBefore ( trailingContainer , styledContainer . nextSibling ) ;
while ( node ) {
loopGuard . check ( ) ;
nextNode = node . nextSibling ;
trailingContainer . appendChild ( node ) ;
node = nextNode
}
}
return ( styledContainer )
}
this . applyStyle = function ( textNodes , limits , info ) {
var textPropsOnly = { } , isStyled , container , styleCache , styleLookup ;
runtime . assert ( info && info [ textProperties ] , "applyStyle without any text properties" ) ;
textPropsOnly [ textProperties ] = info [ textProperties ] ;
styleCache = new StyleManager ( textPropsOnly ) ;
styleLookup = new StyleLookup ( textPropsOnly ) ;
textNodes . forEach ( function ( n ) {
isStyled = styleLookup . isStyleApplied ( n ) ;
if ( isStyled === false ) {
container = moveToNewSpan ( ( n ) , limits ) ;
styleCache . applyStyleToContainer ( container )
}
} )
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "xmldom.XPath" ) ;
runtime . loadClass ( "core.CSSUnits" ) ;
odf . Style2CSS = function Style2CSS ( ) {
var drawns = odf . Namespaces . drawns , fons = odf . Namespaces . fons , stylens = odf . Namespaces . stylens , svgns = odf . Namespaces . svgns , tablens = odf . Namespaces . tablens , textns = odf . Namespaces . textns , xlinkns = odf . Namespaces . xlinkns , presentationns = odf . Namespaces . presentationns , familynamespaceprefixes = { "graphic" : "draw" , "drawing-page" : "draw" , "paragraph" : "text" , "presentation" : "presentation" , "ruby" : "text" , "section" : "text" , "table" : "table" , "table-cell" : "table" , "table-column" : "table" , "table-row" : "table" ,
"text" : "text" , "list" : "text" , "page" : "office" } , familytagnames = { "graphic" : [ "circle" , "connected" , "control" , "custom-shape" , "ellipse" , "frame" , "g" , "line" , "measure" , "page" , "page-thumbnail" , "path" , "polygon" , "polyline" , "rect" , "regular-polygon" ] , "paragraph" : [ "alphabetical-index-entry-template" , "h" , "illustration-index-entry-template" , "index-source-style" , "object-index-entry-template" , "p" , "table-index-entry-template" , "table-of-content-entry-template" , "user-index-entry-template" ] ,
"presentation" : [ "caption" , "circle" , "connector" , "control" , "custom-shape" , "ellipse" , "frame" , "g" , "line" , "measure" , "page-thumbnail" , "path" , "polygon" , "polyline" , "rect" , "regular-polygon" ] , "drawing-page" : [ "caption" , "circle" , "connector" , "control" , "page" , "custom-shape" , "ellipse" , "frame" , "g" , "line" , "measure" , "page-thumbnail" , "path" , "polygon" , "polyline" , "rect" , "regular-polygon" ] , "ruby" : [ "ruby" , "ruby-text" ] , "section" : [ "alphabetical-index" , "bibliography" , "illustration-index" ,
"index-title" , "object-index" , "section" , "table-of-content" , "table-index" , "user-index" ] , "table" : [ "background" , "table" ] , "table-cell" : [ "body" , "covered-table-cell" , "even-columns" , "even-rows" , "first-column" , "first-row" , "last-column" , "last-row" , "odd-columns" , "odd-rows" , "table-cell" ] , "table-column" : [ "table-column" ] , "table-row" : [ "table-row" ] , "text" : [ "a" , "index-entry-chapter" , "index-entry-link-end" , "index-entry-link-start" , "index-entry-page-number" , "index-entry-span" , "index-entry-tab-stop" ,
"index-entry-text" , "index-title-template" , "linenumbering-configuration" , "list-level-style-number" , "list-level-style-bullet" , "outline-level-style" , "span" ] , "list" : [ "list-item" ] } , textPropertySimpleMapping = [ [ fons , "color" , "color" ] , [ fons , "background-color" , "background-color" ] , [ fons , "font-weight" , "font-weight" ] , [ fons , "font-style" , "font-style" ] ] , bgImageSimpleMapping = [ [ stylens , "repeat" , "background-repeat" ] ] , paragraphPropertySimpleMapping = [ [ fons , "background-color" , "background-color" ] ,
[ fons , "text-align" , "text-align" ] , [ fons , "text-indent" , "text-indent" ] , [ fons , "padding" , "padding" ] , [ fons , "padding-left" , "padding-left" ] , [ fons , "padding-right" , "padding-right" ] , [ fons , "padding-top" , "padding-top" ] , [ fons , "padding-bottom" , "padding-bottom" ] , [ fons , "border-left" , "border-left" ] , [ fons , "border-right" , "border-right" ] , [ fons , "border-top" , "border-top" ] , [ fons , "border-bottom" , "border-bottom" ] , [ fons , "margin" , "margin" ] , [ fons , "margin-left" , "margin-left" ] , [ fons , "margin-right" ,
"margin-right" ] , [ fons , "margin-top" , "margin-top" ] , [ fons , "margin-bottom" , "margin-bottom" ] , [ fons , "border" , "border" ] ] , graphicPropertySimpleMapping = [ [ fons , "background-color" , "background-color" ] , [ fons , "min-height" , "min-height" ] , [ drawns , "stroke" , "border" ] , [ svgns , "stroke-color" , "border-color" ] , [ svgns , "stroke-width" , "border-width" ] , [ fons , "border" , "border" ] , [ fons , "border-left" , "border-left" ] , [ fons , "border-right" , "border-right" ] , [ fons , "border-top" , "border-top" ] , [ fons ,
"border-bottom" , "border-bottom" ] ] , tablecellPropertySimpleMapping = [ [ fons , "background-color" , "background-color" ] , [ fons , "border-left" , "border-left" ] , [ fons , "border-right" , "border-right" ] , [ fons , "border-top" , "border-top" ] , [ fons , "border-bottom" , "border-bottom" ] , [ fons , "border" , "border" ] ] , tablecolumnPropertySimpleMapping = [ [ stylens , "column-width" , "width" ] ] , tablerowPropertySimpleMapping = [ [ stylens , "row-height" , "height" ] , [ fons , "keep-together" , null ] ] , tablePropertySimpleMapping =
[ [ stylens , "width" , "width" ] , [ fons , "margin-left" , "margin-left" ] , [ fons , "margin-right" , "margin-right" ] , [ fons , "margin-top" , "margin-top" ] , [ fons , "margin-bottom" , "margin-bottom" ] ] , pageContentPropertySimpleMapping = [ [ fons , "background-color" , "background-color" ] , [ fons , "padding" , "padding" ] , [ fons , "padding-left" , "padding-left" ] , [ fons , "padding-right" , "padding-right" ] , [ fons , "padding-top" , "padding-top" ] , [ fons , "padding-bottom" , "padding-bottom" ] , [ fons , "border" , "border" ] , [ fons ,
"border-left" , "border-left" ] , [ fons , "border-right" , "border-right" ] , [ fons , "border-top" , "border-top" ] , [ fons , "border-bottom" , "border-bottom" ] , [ fons , "margin" , "margin" ] , [ fons , "margin-left" , "margin-left" ] , [ fons , "margin-right" , "margin-right" ] , [ fons , "margin-top" , "margin-top" ] , [ fons , "margin-bottom" , "margin-bottom" ] ] , pageSizePropertySimpleMapping = [ [ fons , "page-width" , "width" ] , [ fons , "page-height" , "height" ] ] , borderPropertyMap = { "border" : true , "border-left" : true , "border-right" : true ,
"border-top" : true , "border-bottom" : true , "stroke-width" : true } , fontFaceDeclsMap = { } , utils = new odf . OdfUtils , documentType , odfRoot , defaultFontSize , xpath = new xmldom . XPath , cssUnits = new core . CSSUnits ;
function getStyleMap ( stylesnode ) {
var stylemap = { } , node , name , family , style ;
if ( ! stylesnode ) {
return stylemap
}
node = stylesnode . firstChild ;
while ( node ) {
if ( node . namespaceURI === stylens && ( node . localName === "style" || node . localName === "default-style" ) ) {
family = node . getAttributeNS ( stylens , "family" )
} else {
if ( node . namespaceURI === textns && node . localName === "list-style" ) {
family = "list"
} else {
if ( node . namespaceURI === stylens && ( node . localName === "page-layout" || node . localName === "default-page-layout" ) ) {
family = "page"
} else {
family = undefined
}
}
}
if ( family ) {
name = node . getAttributeNS && node . getAttributeNS ( stylens , "name" ) ;
if ( ! name ) {
name = ""
}
style = stylemap [ family ] = stylemap [ family ] || { } ;
style [ name ] = node
}
node = node . nextSibling
}
return stylemap
}
function findStyle ( stylestree , name ) {
if ( ! name || ! stylestree ) {
return null
}
if ( stylestree [ name ] ) {
return stylestree [ name ]
}
var n , style ;
for ( n in stylestree ) {
if ( stylestree . hasOwnProperty ( n ) ) {
style = findStyle ( stylestree [ n ] . derivedStyles , name ) ;
if ( style ) {
return style
}
}
}
return null
}
function addStyleToStyleTree ( stylename , stylesmap , stylestree ) {
var style = stylesmap [ stylename ] , parentname , parentstyle ;
if ( ! style ) {
return
}
parentname = style . getAttributeNS ( stylens , "parent-style-name" ) ;
parentstyle = null ;
if ( parentname ) {
parentstyle = findStyle ( stylestree , parentname ) ;
if ( ! parentstyle && stylesmap [ parentname ] ) {
addStyleToStyleTree ( parentname , stylesmap , stylestree ) ;
parentstyle = stylesmap [ parentname ] ;
stylesmap [ parentname ] = null
}
}
if ( parentstyle ) {
if ( ! parentstyle . derivedStyles ) {
parentstyle . derivedStyles = { }
}
parentstyle . derivedStyles [ stylename ] = style
} else {
stylestree [ stylename ] = style
}
}
function addStyleMapToStyleTree ( stylesmap , stylestree ) {
var name ;
for ( name in stylesmap ) {
if ( stylesmap . hasOwnProperty ( name ) ) {
addStyleToStyleTree ( name , stylesmap , stylestree ) ;
stylesmap [ name ] = null
}
}
}
function createSelector ( family , name ) {
var prefix = familynamespaceprefixes [ family ] , namepart , selector ;
if ( prefix === null ) {
return null
}
if ( name ) {
namepart = "[" + prefix + '|style-name="' + name + '"]'
} else {
namepart = "[" + prefix + "|style-name]"
}
if ( prefix === "presentation" ) {
prefix = "draw" ;
if ( name ) {
namepart = '[presentation|style-name="' + name + '"]'
} else {
namepart = "[presentation|style-name]"
}
}
selector = prefix + "|" + familytagnames [ family ] . join ( namepart + "," + prefix + "|" ) + namepart ;
return selector
}
function getSelectors ( family , name , node ) {
var selectors = [ ] , n , ss , s ;
selectors . push ( createSelector ( family , name ) ) ;
for ( n in node . derivedStyles ) {
if ( node . derivedStyles . hasOwnProperty ( n ) ) {
ss = getSelectors ( family , n , node . derivedStyles [ n ] ) ;
for ( s in ss ) {
if ( ss . hasOwnProperty ( s ) ) {
selectors . push ( ss [ s ] )
}
}
}
}
return selectors
}
function getDirectChild ( node , ns , name ) {
if ( ! node ) {
return null
}
var c = node . firstChild , e ;
while ( c ) {
if ( c . namespaceURI === ns && c . localName === name ) {
e = ( c ) ;
return e
}
c = c . nextSibling
}
return null
}
function fixBorderWidth ( value ) {
var index = value . indexOf ( " " ) , width , theRestOfBorderAttributes ;
if ( index !== - 1 ) {
width = value . substring ( 0 , index ) ;
theRestOfBorderAttributes = value . substring ( index )
} else {
width = value ;
theRestOfBorderAttributes = ""
}
width = utils . parseLength ( width ) ;
if ( width && width . unit === "pt" && width . value < 0.75 ) {
value = "0.75pt" + theRestOfBorderAttributes
}
return value
}
function applySimpleMapping ( props , mapping ) {
var rule = "" , r , value ;
for ( r in mapping ) {
if ( mapping . hasOwnProperty ( r ) ) {
r = mapping [ r ] ;
value = props . getAttributeNS ( r [ 0 ] , r [ 1 ] ) ;
if ( value ) {
value = value . trim ( ) ;
if ( borderPropertyMap . hasOwnProperty ( r [ 1 ] ) ) {
value = fixBorderWidth ( value )
}
if ( r [ 2 ] ) {
rule += r [ 2 ] + ":" + value + ";"
}
}
}
}
return rule
}
function getFontSize ( styleNode ) {
var props = getDirectChild ( ( styleNode ) , stylens , "text-properties" ) ;
if ( props ) {
return utils . parseFoFontSize ( props . getAttributeNS ( fons , "font-size" ) )
}
return null
}
function getParentStyleNode ( styleNode ) {
var parentStyleName = "" , parentStyleFamily = "" , parentStyleNode = null , xp ;
if ( styleNode . localName === "default-style" ) {
return null
}
parentStyleName = styleNode . getAttributeNS ( stylens , "parent-style-name" ) ;
parentStyleFamily = styleNode . getAttributeNS ( stylens , "family" ) ;
if ( parentStyleName ) {
xp = "//style:*[@style:name='" + parentStyleName + "'][@style:family='" + parentStyleFamily + "']"
} else {
xp = "//style:default-style[@style:family='" + parentStyleFamily + "']"
}
parentStyleNode = xpath . getODFElementsWithXPath ( ( odfRoot ) , xp , odf . Namespaces . resolvePrefix ) [ 0 ] ;
return parentStyleNode
}
function getTextProperties ( props ) {
var rule = "" , fontName , fontSize , value , textDecoration = "" , fontSizeRule = "" , sizeMultiplier = 1 , parentStyle ;
rule += applySimpleMapping ( props , textPropertySimpleMapping ) ;
value = props . getAttributeNS ( stylens , "text-underline-style" ) ;
if ( value === "solid" ) {
textDecoration += " underline"
}
value = props . getAttributeNS ( stylens , "text-line-through-style" ) ;
if ( value === "solid" ) {
textDecoration += " line-through"
}
if ( textDecoration . length ) {
textDecoration = "text-decoration:" + textDecoration + ";" ;
rule += textDecoration
}
fontName = props . getAttributeNS ( stylens , "font-name" ) || props . getAttributeNS ( fons , "font-family" ) ;
if ( fontName ) {
value = fontFaceDeclsMap [ fontName ] ;
rule += "font-family: " + ( value || fontName ) + ", sans-serif;"
}
parentStyle = props . parentNode ;
fontSize = getFontSize ( ( parentStyle ) ) ;
if ( ! fontSize ) {
return rule
}
while ( parentStyle ) {
fontSize = getFontSize ( ( parentStyle ) ) ;
if ( fontSize ) {
if ( fontSize . unit !== "%" ) {
fontSizeRule = "font-size: " + fontSize . value * sizeMultiplier + fontSize . unit + ";" ;
break
}
sizeMultiplier *= fontSize . value / 100
}
parentStyle = getParentStyleNode ( parentStyle )
}
if ( ! fontSizeRule ) {
fontSizeRule = "font-size: " + parseFloat ( defaultFontSize ) * sizeMultiplier + cssUnits . getUnits ( defaultFontSize ) + ";"
}
rule += fontSizeRule ;
return rule
}
function getParagraphProperties ( props ) {
var rule = "" , imageProps , url , element , lineHeight ;
rule += applySimpleMapping ( props , paragraphPropertySimpleMapping ) ;
imageProps = props . getElementsByTagNameNS ( stylens , "background-image" ) ;
if ( imageProps . length > 0 ) {
url = imageProps . item ( 0 ) . getAttributeNS ( xlinkns , "href" ) ;
if ( url ) {
rule += "background-image: url('odfkit:" + url + "');" ;
element = ( imageProps . item ( 0 ) ) ;
rule += applySimpleMapping ( element , bgImageSimpleMapping )
}
}
lineHeight = props . getAttributeNS ( fons , "line-height" ) ;
if ( lineHeight && lineHeight !== "normal" ) {
lineHeight = utils . parseFoLineHeight ( lineHeight ) ;
if ( lineHeight . unit !== "%" ) {
rule += "line-height: " + lineHeight . value + lineHeight . unit + ";"
} else {
rule += "line-height: " + lineHeight . value / 100 + ";"
}
}
return rule
}
function hexToRgb ( hex ) {
var result , shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i ;
hex = hex . replace ( shorthandRegex , function ( m , r , g , b ) {
return r + r + g + g + b + b
} ) ;
result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i . exec ( hex ) ;
return result ? { r : parseInt ( result [ 1 ] , 16 ) , g : parseInt ( result [ 2 ] , 16 ) , b : parseInt ( result [ 3 ] , 16 ) } : null
}
function isNumber ( n ) {
return ! isNaN ( parseFloat ( n ) )
}
function getGraphicProperties ( props ) {
var rule = "" , alpha , bgcolor , fill ;
rule += applySimpleMapping ( props , graphicPropertySimpleMapping ) ;
alpha = props . getAttributeNS ( drawns , "opacity" ) ;
fill = props . getAttributeNS ( drawns , "fill" ) ;
bgcolor = props . getAttributeNS ( drawns , "fill-color" ) ;
if ( fill === "solid" || fill === "hatch" ) {
if ( bgcolor && bgcolor !== "none" ) {
alpha = isNumber ( alpha ) ? parseFloat ( alpha ) / 100 : 1 ;
bgcolor = hexToRgb ( bgcolor ) ;
if ( bgcolor ) {
rule += "background-color: rgba(" + bgcolor . r + "," + bgcolor . g + "," + bgcolor . b + "," + alpha + ");"
}
} else {
rule += "background: none;"
}
} else {
if ( fill === "none" ) {
rule += "background: none;"
}
}
return rule
}
function getDrawingPageProperties ( props ) {
var rule = "" ;
rule += applySimpleMapping ( props , graphicPropertySimpleMapping ) ;
if ( props . getAttributeNS ( presentationns , "background-visible" ) === "true" ) {
rule += "background: none;"
}
return rule
}
function getTableCellProperties ( props ) {
var rule = "" ;
rule += applySimpleMapping ( props , tablecellPropertySimpleMapping ) ;
return rule
}
function getTableRowProperties ( props ) {
var rule = "" ;
rule += applySimpleMapping ( props , tablerowPropertySimpleMapping ) ;
return rule
}
function getTableColumnProperties ( props ) {
var rule = "" ;
rule += applySimpleMapping ( props , tablecolumnPropertySimpleMapping ) ;
return rule
}
function getTableProperties ( props ) {
var rule = "" , borderModel ;
rule += applySimpleMapping ( props , tablePropertySimpleMapping ) ;
borderModel = props . getAttributeNS ( tablens , "border-model" ) ;
if ( borderModel === "collapsing" ) {
rule += "border-collapse:collapse;"
} else {
if ( borderModel === "separating" ) {
rule += "border-collapse:separate;"
}
}
return rule
}
function addStyleRule ( sheet , family , name , node ) {
var selectors = getSelectors ( family , name , node ) , selector = selectors . join ( "," ) , rule = "" , properties = getDirectChild ( node , stylens , "text-properties" ) ;
if ( properties ) {
rule += getTextProperties ( properties )
}
properties = getDirectChild ( node , stylens , "paragraph-properties" ) ;
if ( properties ) {
rule += getParagraphProperties ( properties )
}
properties = getDirectChild ( node , stylens , "graphic-properties" ) ;
if ( properties ) {
rule += getGraphicProperties ( properties )
}
properties = getDirectChild ( node , stylens , "drawing-page-properties" ) ;
if ( properties ) {
rule += getDrawingPageProperties ( properties )
}
properties = getDirectChild ( node , stylens , "table-cell-properties" ) ;
if ( properties ) {
rule += getTableCellProperties ( properties )
}
properties = getDirectChild ( node , stylens , "table-row-properties" ) ;
if ( properties ) {
rule += getTableRowProperties ( properties )
}
properties = getDirectChild ( node , stylens , "table-column-properties" ) ;
if ( properties ) {
rule += getTableColumnProperties ( properties )
}
properties = getDirectChild ( node , stylens , "table-properties" ) ;
if ( properties ) {
rule += getTableProperties ( properties )
}
if ( rule . length === 0 ) {
return
}
rule = selector + "{" + rule + "}" ;
try {
sheet . insertRule ( rule , sheet . cssRules . length )
} catch ( e ) {
throw e ;
}
}
function getNumberRule ( node ) {
var style = node . getAttributeNS ( stylens , "num-format" ) , suffix = node . getAttributeNS ( stylens , "num-suffix" ) , prefix = node . getAttributeNS ( stylens , "num-prefix" ) , stylemap = { 1 : "decimal" , "a" : "lower-latin" , "A" : "upper-latin" , "i" : "lower-roman" , "I" : "upper-roman" } , content = prefix || "" ;
if ( stylemap . hasOwnProperty ( style ) ) {
content += " counter(list, " + stylemap [ style ] + ")"
} else {
if ( style ) {
content += "'" + style + "';"
} else {
content += " ''"
}
}
if ( suffix ) {
content += " '" + suffix + "'"
}
return "content: " + content + ";"
}
function getImageRule ( ) {
var rule = "content: none;" ;
return rule
}
function getBulletRule ( node ) {
var bulletChar = node . getAttributeNS ( textns , "bullet-char" ) ;
return "content: '" + bulletChar + "';"
}
function addListStyleRule ( sheet , name , node , itemrule ) {
var selector = 'text|list[text|style-name="' + name + '"]' , level = node . getAttributeNS ( textns , "level" ) , itemSelector , listItemRule , listLevelProps = utils . getFirstNonWhitespaceChild ( node ) , listLevelLabelAlign = utils . getFirstNonWhitespaceChild ( listLevelProps ) , labelAlignAttr , bulletIndent , listIndent , bulletWidth , rule ;
if ( listLevelLabelAlign ) {
labelAlignAttr = listLevelLabelAlign . attributes ;
bulletIndent = labelAlignAttr [ "fo:text-indent" ] ? labelAlignAttr [ "fo:text-indent" ] . value : undefined ;
listIndent = labelAlignAttr [ "fo:margin-left" ] ? labelAlignAttr [ "fo:margin-left" ] . value : undefined
}
if ( ! bulletIndent ) {
bulletIndent = "-0.6cm"
}
if ( bulletIndent . charAt ( 0 ) === "-" ) {
bulletWidth = bulletIndent . substring ( 1 )
} else {
bulletWidth = "-" + bulletIndent
}
level = level && parseInt ( level , 10 ) ;
while ( level > 1 ) {
selector += " > text|list-item > text|list" ;
level -= 1
}
itemSelector = selector ;
itemSelector += " > text|list-item > *:not(text|list):first-child" ;
if ( listIndent !== undefined ) {
listItemRule = itemSelector + "{margin-left:" + listIndent + ";}" ;
sheet . insertRule ( listItemRule , sheet . cssRules . length )
}
selector += " > text|list-item > *:not(text|list):first-child:before" ;
rule = itemrule ;
rule = selector + "{" + rule + ";" ;
rule += "counter-increment:list;" ;
rule += "margin-left:" + bulletIndent + ";" ;
rule += "width:" + bulletWidth + ";" ;
rule += "display:inline-block}" ;
try {
sheet . insertRule ( rule , sheet . cssRules . length )
} catch ( e ) {
throw e ;
}
}
function addPageStyleRules ( sheet , node ) {
var rule = "" , imageProps , url , element , contentLayoutRule = "" , pageSizeRule = "" , props = node . getElementsByTagNameNS ( stylens , "page-layout-properties" ) [ 0 ] , masterStyles = props . parentNode . parentNode . parentNode . masterStyles , masterPages , masterStyleName = "" , i ;
rule += applySimpleMapping ( props , pageContentPropertySimpleMapping ) ;
imageProps = props . getElementsByTagNameNS ( stylens , "background-image" ) ;
if ( imageProps . length > 0 ) {
url = imageProps . item ( 0 ) . getAttributeNS ( xlinkns , "href" ) ;
if ( url ) {
rule += "background-image: url('odfkit:" + url + "');" ;
element = ( imageProps . item ( 0 ) ) ;
rule += applySimpleMapping ( element , bgImageSimpleMapping )
}
}
if ( documentType === "presentation" ) {
if ( masterStyles ) {
masterPages = masterStyles . getElementsByTagNameNS ( stylens , "master-page" ) ;
for ( i = 0 ; i < masterPages . length ; i += 1 ) {
if ( masterPages [ i ] . getAttributeNS ( stylens , "page-layout-name" ) === props . parentNode . getAttributeNS ( stylens , "name" ) ) {
masterStyleName = masterPages [ i ] . getAttributeNS ( stylens , "name" ) ;
contentLayoutRule = "draw|page[draw|master-page-name=" + masterStyleName + "] {" + rule + "}" ;
pageSizeRule = "office|body, draw|page[draw|master-page-name=" + masterStyleName + "] {" + applySimpleMapping ( props , pageSizePropertySimpleMapping ) + " }" ;
try {
sheet . insertRule ( contentLayoutRule , sheet . cssRules . length ) ;
sheet . insertRule ( pageSizeRule , sheet . cssRules . length )
} catch ( e1 ) {
throw e1 ;
}
}
}
}
} else {
if ( documentType === "text" ) {
contentLayoutRule = "office|text {" + rule + "}" ;
rule = "" ;
pageSizeRule = "office|body {" + "width: " + props . getAttributeNS ( fons , "page-width" ) + ";" + "}" ;
try {
sheet . insertRule ( contentLayoutRule , sheet . cssRules . length ) ;
sheet . insertRule ( pageSizeRule , sheet . cssRules . length )
} catch ( e2 ) {
throw e2 ;
}
}
}
}
function addListStyleRules ( sheet , name , node ) {
var n = node . firstChild , e , itemrule ;
while ( n ) {
if ( n . namespaceURI === textns ) {
e = ( n ) ;
if ( n . localName === "list-level-style-number" ) {
itemrule = getNumberRule ( e ) ;
addListStyleRule ( sheet , name , e , itemrule )
} else {
if ( n . localName === "list-level-style-image" ) {
itemrule = getImageRule ( ) ;
addListStyleRule ( sheet , name , e , itemrule )
} else {
if ( n . localName === "list-level-style-bullet" ) {
itemrule = getBulletRule ( e ) ;
addListStyleRule ( sheet , name , e , itemrule )
}
}
}
}
n = n . nextSibling
}
}
function addRule ( sheet , family , name , node ) {
if ( family === "list" ) {
addListStyleRules ( sheet , name , node )
} else {
if ( family === "page" ) {
addPageStyleRules ( sheet , node )
} else {
addStyleRule ( sheet , family , name , node )
}
}
}
function addRules ( sheet , family , name , node ) {
addRule ( sheet , family , name , node ) ;
var n ;
for ( n in node . derivedStyles ) {
if ( node . derivedStyles . hasOwnProperty ( n ) ) {
addRules ( sheet , family , n , node . derivedStyles [ n ] )
}
}
}
this . style2css = function ( doctype , stylesheet , fontFaceMap , styles , autostyles ) {
var doc , styletree , tree , name , rule , family , stylenodes , styleautonodes ;
while ( stylesheet . cssRules . length ) {
stylesheet . deleteRule ( stylesheet . cssRules . length - 1 )
}
doc = null ;
if ( styles ) {
doc = styles . ownerDocument ;
odfRoot = styles . parentNode
}
if ( autostyles ) {
doc = autostyles . ownerDocument ;
odfRoot = autostyles . parentNode
}
if ( ! doc ) {
return
}
odf . Namespaces . forEachPrefix ( function ( prefix , ns ) {
rule = "@namespace " + prefix + " url(" + ns + ");" ;
try {
stylesheet . insertRule ( rule , stylesheet . cssRules . length )
} catch ( ignore ) {
}
} ) ;
fontFaceDeclsMap = fontFaceMap ;
documentType = doctype ;
defaultFontSize = runtime . getWindow ( ) . getComputedStyle ( document . body , null ) . getPropertyValue ( "font-size" ) || "12pt" ;
stylenodes = getStyleMap ( styles ) ;
styleautonodes = getStyleMap ( autostyles ) ;
styletree = { } ;
for ( family in familynamespaceprefixes ) {
if ( familynamespaceprefixes . hasOwnProperty ( family ) ) {
tree = styletree [ family ] = { } ;
addStyleMapToStyleTree ( stylenodes [ family ] , tree ) ;
addStyleMapToStyleTree ( styleautonodes [ family ] , tree ) ;
for ( name in tree ) {
if ( tree . hasOwnProperty ( name ) ) {
addRules ( stylesheet , family , name , tree [ name ] )
}
}
}
}
}
} ;
runtime . loadClass ( "core.Base64" ) ;
runtime . loadClass ( "core.Zip" ) ;
runtime . loadClass ( "xmldom.LSSerializer" ) ;
runtime . loadClass ( "odf.StyleInfo" ) ;
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "odf.OdfNodeFilter" ) ;
odf . OdfContainer = function ( ) {
var styleInfo = new odf . StyleInfo , officens = "urn:oasis:names:tc:opendocument:xmlns:office:1.0" , manifestns = "urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" , webodfns = "urn:webodf:names:scope" , nodeorder = [ "meta" , "settings" , "scripts" , "font-face-decls" , "styles" , "automatic-styles" , "master-styles" , "body" ] , automaticStylePrefix = ( new Date ) . getTime ( ) + "_webodf_" , base64 = new core . Base64 , documentStylesScope = "document-styles" , documentContentScope = "document-content" ;
function getDirectChild ( node , ns , name ) {
node = node ? node . firstChild : null ;
while ( node ) {
if ( node . localName === name && node . namespaceURI === ns ) {
return ( node )
}
node = node . nextSibling
}
return null
}
function getNodePosition ( child ) {
var i , l = nodeorder . length ;
for ( i = 0 ; i < l ; i += 1 ) {
if ( child . namespaceURI === officens && child . localName === nodeorder [ i ] ) {
return i
}
}
return - 1
}
function OdfStylesFilter ( styleUsingElementsRoot , automaticStyles ) {
var usedStyleList = new styleInfo . UsedStyleList ( styleUsingElementsRoot , automaticStyles ) , odfNodeFilter = new odf . OdfNodeFilter ;
this . acceptNode = function ( node ) {
var result = odfNodeFilter . acceptNode ( node ) ;
if ( result === NodeFilter . FILTER _ACCEPT && node . parentNode === automaticStyles && node . nodeType === Node . ELEMENT _NODE ) {
if ( usedStyleList . uses ( ( node ) ) ) {
result = NodeFilter . FILTER _ACCEPT
} else {
result = NodeFilter . FILTER _REJECT
}
}
return result
}
}
function OdfContentFilter ( styleUsingElementsRoot , automaticStyles ) {
var odfStylesFilter = new OdfStylesFilter ( styleUsingElementsRoot , automaticStyles ) ;
this . acceptNode = function ( node ) {
var result = odfStylesFilter . acceptNode ( node ) ;
if ( result === NodeFilter . FILTER _ACCEPT && node . parentNode && node . parentNode . namespaceURI === odf . Namespaces . textns && ( node . parentNode . localName === "s" || node . parentNode . localName === "tab" ) ) {
result = NodeFilter . FILTER _REJECT
}
return result
}
}
function setChild ( node , child ) {
if ( ! child ) {
return
}
var childpos = getNodePosition ( child ) , pos , c = node . firstChild ;
if ( childpos === - 1 ) {
return
}
while ( c ) {
pos = getNodePosition ( c ) ;
if ( pos !== - 1 && pos > childpos ) {
break
}
c = c . nextSibling
}
node . insertBefore ( child , c )
}
function ODFElement ( ) {
}
function ODFDocumentElement ( odfcontainer ) {
this . OdfContainer = odfcontainer
}
ODFDocumentElement . prototype = new ODFElement ;
ODFDocumentElement . prototype . constructor = ODFDocumentElement ;
ODFDocumentElement . namespaceURI = officens ;
ODFDocumentElement . localName = "document" ;
function OdfPart ( name , mimetype , container , zip ) {
var self = this ;
this . size = 0 ;
this . type = null ;
this . name = name ;
this . container = container ;
this . url = null ;
this . mimetype = null ;
this . document = null ;
this . onreadystatechange = null ;
this . onchange = null ;
this . EMPTY = 0 ;
this . LOADING = 1 ;
this . DONE = 2 ;
this . state = this . EMPTY ;
this . load = function ( ) {
if ( zip === null ) {
return
}
this . mimetype = mimetype ;
zip . loadAsDataURL ( name , mimetype , function ( err , url ) {
if ( err ) {
runtime . log ( err )
}
self . url = url ;
if ( self . onchange ) {
self . onchange ( self )
}
if ( self . onstatereadychange ) {
self . onstatereadychange ( self )
}
} )
}
}
OdfPart . prototype . load = function ( ) {
} ;
OdfPart . prototype . getUrl = function ( ) {
if ( this . data ) {
return "data:;base64," + base64 . toBase64 ( this . data )
}
return null
} ;
odf . OdfContainer = function OdfContainer ( url , onstatereadychange ) {
var self = this , zip , partMimetypes = { } , contentElement ;
this . onstatereadychange = onstatereadychange ;
this . onchange = null ;
this . state = null ;
this . rootElement = null ;
function removeProcessingInstructions ( element ) {
var n = element . firstChild , next , e ;
while ( n ) {
next = n . nextSibling ;
if ( n . nodeType === Node . ELEMENT _NODE ) {
e = ( n ) ;
removeProcessingInstructions ( e )
} else {
if ( n . nodeType === Node . PROCESSING _INSTRUCTION _NODE ) {
element . removeChild ( n )
}
}
n = next
}
}
function setAutomaticStylesScope ( stylesRootElement , scope ) {
var n = stylesRootElement && stylesRootElement . firstChild ;
while ( n ) {
if ( n . nodeType === Node . ELEMENT _NODE ) {
n . setAttributeNS ( webodfns , "scope" , scope )
}
n = n . nextSibling
}
}
function cloneStylesInScope ( stylesRootElement , scope ) {
var copy = null , n , s , scopeAttrValue ;
if ( stylesRootElement ) {
copy = stylesRootElement . cloneNode ( true ) ;
n = copy . firstChild ;
while ( n ) {
s = n . nextSibling ;
if ( n . nodeType === Node . ELEMENT _NODE ) {
scopeAttrValue = n . getAttributeNS ( webodfns , "scope" ) ;
if ( scopeAttrValue && scopeAttrValue !== scope ) {
copy . removeChild ( n )
}
}
n = s
}
}
return copy
}
function importRootNode ( xmldoc ) {
var doc = self . rootElement . ownerDocument , node ;
if ( xmldoc ) {
removeProcessingInstructions ( xmldoc . documentElement ) ;
try {
node = doc . importNode ( xmldoc . documentElement , true )
} catch ( ignore ) {
}
}
return node
}
function setState ( state ) {
self . state = state ;
if ( self . onchange ) {
self . onchange ( self )
}
if ( self . onstatereadychange ) {
self . onstatereadychange ( self )
}
}
function setRootElement ( root ) {
contentElement = null ;
self . rootElement = root ;
root . fontFaceDecls = getDirectChild ( root , officens , "font-face-decls" ) ;
root . styles = getDirectChild ( root , officens , "styles" ) ;
root . automaticStyles = getDirectChild ( root , officens , "automatic-styles" ) ;
root . masterStyles = getDirectChild ( root , officens , "master-styles" ) ;
root . body = getDirectChild ( root , officens , "body" ) ;
root . meta = getDirectChild ( root , officens , "meta" )
}
function handleFlatXml ( xmldoc ) {
var root = importRootNode ( xmldoc ) ;
if ( ! root || root . localName !== "document" || root . namespaceURI !== officens ) {
setState ( OdfContainer . INVALID ) ;
return
}
setRootElement ( ( root ) ) ;
setState ( OdfContainer . DONE )
}
function handleStylesXml ( xmldoc ) {
var node = importRootNode ( xmldoc ) , root = self . rootElement ;
if ( ! node || node . localName !== "document-styles" || node . namespaceURI !== officens ) {
setState ( OdfContainer . INVALID ) ;
return
}
root . fontFaceDecls = getDirectChild ( node , officens , "font-face-decls" ) ;
setChild ( root , root . fontFaceDecls ) ;
root . styles = getDirectChild ( node , officens , "styles" ) ;
setChild ( root , root . styles ) ;
root . automaticStyles = getDirectChild ( node , officens , "automatic-styles" ) ;
setAutomaticStylesScope ( root . automaticStyles , documentStylesScope ) ;
setChild ( root , root . automaticStyles ) ;
root . masterStyles = getDirectChild ( node , officens , "master-styles" ) ;
setChild ( root , root . masterStyles ) ;
styleInfo . prefixStyleNames ( root . automaticStyles , automaticStylePrefix , root . masterStyles )
}
function handleContentXml ( xmldoc ) {
var node = importRootNode ( xmldoc ) , root , automaticStyles , fontFaceDecls , c ;
if ( ! node || node . localName !== "document-content" || node . namespaceURI !== officens ) {
setState ( OdfContainer . INVALID ) ;
return
}
root = self . rootElement ;
fontFaceDecls = getDirectChild ( node , officens , "font-face-decls" ) ;
if ( root . fontFaceDecls && fontFaceDecls ) {
c = fontFaceDecls . firstChild ;
while ( c ) {
root . fontFaceDecls . appendChild ( c ) ;
c = fontFaceDecls . firstChild
}
} else {
if ( fontFaceDecls ) {
root . fontFaceDecls = fontFaceDecls ;
setChild ( root , fontFaceDecls )
}
}
automaticStyles = getDirectChild ( node , officens , "automatic-styles" ) ;
setAutomaticStylesScope ( automaticStyles , documentContentScope ) ;
if ( root . automaticStyles && automaticStyles ) {
c = automaticStyles . firstChild ;
while ( c ) {
root . automaticStyles . appendChild ( c ) ;
c = automaticStyles . firstChild
}
} else {
if ( automaticStyles ) {
root . automaticStyles = automaticStyles ;
setChild ( root , automaticStyles )
}
}
root . body = getDirectChild ( node , officens , "body" ) ;
setChild ( root , root . body )
}
function handleMetaXml ( xmldoc ) {
var node = importRootNode ( xmldoc ) , root ;
if ( ! node || node . localName !== "document-meta" || node . namespaceURI !== officens ) {
return
}
root = self . rootElement ;
root . meta = getDirectChild ( node , officens , "meta" ) ;
setChild ( root , root . meta )
}
function handleSettingsXml ( xmldoc ) {
var node = importRootNode ( xmldoc ) , root ;
if ( ! node || node . localName !== "document-settings" || node . namespaceURI !== officens ) {
return
}
root = self . rootElement ;
root . settings = getDirectChild ( node , officens , "settings" ) ;
setChild ( root , root . settings )
}
function handleManifestXml ( xmldoc ) {
var node = importRootNode ( xmldoc ) , root , n ;
if ( ! node || node . localName !== "manifest" || node . namespaceURI !== manifestns ) {
return
}
root = self . rootElement ;
root . manifest = node ;
n = root . manifest . firstChild ;
while ( n ) {
if ( n . nodeType === Node . ELEMENT _NODE && n . localName === "file-entry" && n . namespaceURI === manifestns ) {
partMimetypes [ n . getAttributeNS ( manifestns , "full-path" ) ] = n . getAttributeNS ( manifestns , "media-type" )
}
n = n . nextSibling
}
}
function loadNextComponent ( remainingComponents ) {
var component = remainingComponents . shift ( ) , filepath , callback ;
if ( component ) {
filepath = ( component [ 0 ] ) ;
callback = ( component [ 1 ] ) ;
zip . loadAsDOM ( filepath , function ( err , xmldoc ) {
callback ( xmldoc ) ;
if ( err || self . state === OdfContainer . INVALID ) {
return
}
loadNextComponent ( remainingComponents )
} )
} else {
setState ( OdfContainer . DONE )
}
}
function loadComponents ( ) {
var componentOrder = [ [ "styles.xml" , handleStylesXml ] , [ "content.xml" , handleContentXml ] , [ "meta.xml" , handleMetaXml ] , [ "settings.xml" , handleSettingsXml ] , [ "META-INF/manifest.xml" , handleManifestXml ] ] ;
loadNextComponent ( componentOrder )
}
function createDocumentElement ( name ) {
var s = "" ;
odf . Namespaces . forEachPrefix ( function ( prefix , ns ) {
s += " xmlns:" + prefix + '="' + ns + '"'
} ) ;
return '<?xml version="1.0" encoding="UTF-8"?><office:' + name + " " + s + ' office:version="1.2">'
}
function serializeMetaXml ( ) {
var serializer = new xmldom . LSSerializer , s = createDocumentElement ( "document-meta" ) ;
serializer . filter = new odf . OdfNodeFilter ;
s += serializer . writeToString ( self . rootElement . meta , odf . Namespaces . namespaceMap ) ;
s += "</office:document-meta>" ;
return s
}
function createManifestEntry ( fullPath , mediaType ) {
var element = document . createElementNS ( manifestns , "manifest:file-entry" ) ;
element . setAttributeNS ( manifestns , "manifest:full-path" , fullPath ) ;
element . setAttributeNS ( manifestns , "manifest:media-type" , mediaType ) ;
return element
}
function serializeManifestXml ( ) {
var header = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\n' , xml = '<manifest:manifest xmlns:manifest="' + manifestns + '"></manifest:manifest>' , manifest = ( runtime . parseXML ( xml ) ) , manifestRoot = getDirectChild ( manifest , manifestns , "manifest" ) , serializer = new xmldom . LSSerializer , fullPath ;
for ( fullPath in partMimetypes ) {
if ( partMimetypes . hasOwnProperty ( fullPath ) ) {
manifestRoot . appendChild ( createManifestEntry ( fullPath , partMimetypes [ fullPath ] ) )
}
}
serializer . filter = new odf . OdfNodeFilter ;
return header + serializer . writeToString ( manifest , odf . Namespaces . namespaceMap )
}
function serializeSettingsXml ( ) {
var serializer = new xmldom . LSSerializer , s = createDocumentElement ( "document-settings" ) ;
serializer . filter = new odf . OdfNodeFilter ;
s += serializer . writeToString ( self . rootElement . settings , odf . Namespaces . namespaceMap ) ;
s += "</office:document-settings>" ;
return s
}
function serializeStylesXml ( ) {
var nsmap = odf . Namespaces . namespaceMap , serializer = new xmldom . LSSerializer , automaticStyles = cloneStylesInScope ( self . rootElement . automaticStyles , documentStylesScope ) , masterStyles = self . rootElement . masterStyles && self . rootElement . masterStyles . cloneNode ( true ) , s = createDocumentElement ( "document-styles" ) ;
styleInfo . removePrefixFromStyleNames ( automaticStyles , automaticStylePrefix , masterStyles ) ;
serializer . filter = new OdfStylesFilter ( masterStyles , automaticStyles ) ;
s += serializer . writeToString ( self . rootElement . fontFaceDecls , nsmap ) ;
s += serializer . writeToString ( self . rootElement . styles , nsmap ) ;
s += serializer . writeToString ( automaticStyles , nsmap ) ;
s += serializer . writeToString ( masterStyles , nsmap ) ;
s += "</office:document-styles>" ;
return s
}
function serializeContentXml ( ) {
var nsmap = odf . Namespaces . namespaceMap , serializer = new xmldom . LSSerializer , automaticStyles = cloneStylesInScope ( self . rootElement . automaticStyles , documentContentScope ) , s = createDocumentElement ( "document-content" ) ;
serializer . filter = new OdfContentFilter ( self . rootElement . body , automaticStyles ) ;
s += serializer . writeToString ( automaticStyles , nsmap ) ;
s += serializer . writeToString ( self . rootElement . body , nsmap ) ;
s += "</office:document-content>" ;
return s
}
function createElement ( Type ) {
var original = document . createElementNS ( Type . namespaceURI , Type . localName ) , method , iface = new Type ;
for ( method in iface ) {
if ( iface . hasOwnProperty ( method ) ) {
original [ method ] = iface [ method ]
}
}
return original
}
function loadFromXML ( url , callback ) {
runtime . loadXML ( url , function ( err , dom ) {
if ( err ) {
callback ( err )
} else {
handleFlatXml ( dom )
}
} )
}
this . setRootElement = setRootElement ;
this . getContentElement = function ( ) {
var body ;
if ( ! contentElement ) {
body = self . rootElement . body ;
contentElement = body . getElementsByTagNameNS ( officens , "text" ) [ 0 ] || body . getElementsByTagNameNS ( officens , "presentation" ) [ 0 ] || body . getElementsByTagNameNS ( officens , "spreadsheet" ) [ 0 ]
}
return contentElement
} ;
this . getDocumentType = function ( ) {
var content = self . getContentElement ( ) ;
return content && content . localName
} ;
this . getPart = function ( partname ) {
return new OdfPart ( partname , partMimetypes [ partname ] , self , zip )
} ;
this . getPartData = function ( url , callback ) {
zip . load ( url , callback )
} ;
function createEmptyTextDocument ( ) {
var emptyzip = new core . Zip ( "" , null ) , data = runtime . byteArrayFromString ( "application/vnd.oasis.opendocument.text" , "utf8" ) , root = self . rootElement , text = document . createElementNS ( officens , "text" ) ;
emptyzip . save ( "mimetype" , data , false , new Date ) ;
function addToplevelElement ( memberName , realLocalName ) {
var element ;
if ( ! realLocalName ) {
realLocalName = memberName
}
element = document . createElementNS ( officens , realLocalName ) ;
root [ memberName ] = element ;
root . appendChild ( element )
}
addToplevelElement ( "meta" ) ;
addToplevelElement ( "settings" ) ;
addToplevelElement ( "scripts" ) ;
addToplevelElement ( "fontFaceDecls" , "font-face-decls" ) ;
addToplevelElement ( "styles" ) ;
addToplevelElement ( "automaticStyles" , "automatic-styles" ) ;
addToplevelElement ( "masterStyles" , "master-styles" ) ;
addToplevelElement ( "body" ) ;
root . body . appendChild ( text ) ;
setState ( OdfContainer . DONE ) ;
return emptyzip
}
function fillZip ( ) {
var data , date = new Date ;
data = runtime . byteArrayFromString ( serializeSettingsXml ( ) , "utf8" ) ;
zip . save ( "settings.xml" , data , true , date ) ;
data = runtime . byteArrayFromString ( serializeMetaXml ( ) , "utf8" ) ;
zip . save ( "meta.xml" , data , true , date ) ;
data = runtime . byteArrayFromString ( serializeStylesXml ( ) , "utf8" ) ;
zip . save ( "styles.xml" , data , true , date ) ;
data = runtime . byteArrayFromString ( serializeContentXml ( ) , "utf8" ) ;
zip . save ( "content.xml" , data , true , date ) ;
data = runtime . byteArrayFromString ( serializeManifestXml ( ) , "utf8" ) ;
zip . save ( "META-INF/manifest.xml" , data , true , date )
}
function createByteArray ( successCallback , errorCallback ) {
fillZip ( ) ;
zip . createByteArray ( successCallback , errorCallback )
}
this . createByteArray = createByteArray ;
function saveAs ( newurl , callback ) {
fillZip ( ) ;
zip . writeAs ( newurl , function ( err ) {
callback ( err )
} )
}
this . saveAs = saveAs ;
this . save = function ( callback ) {
saveAs ( url , callback )
} ;
this . getUrl = function ( ) {
return url
} ;
this . state = OdfContainer . LOADING ;
this . rootElement = createElement ( ODFDocumentElement ) ;
if ( url ) {
zip = new core . Zip ( url , function ( err , zipobject ) {
zip = zipobject ;
if ( err ) {
loadFromXML ( url , function ( xmlerr ) {
if ( err ) {
zip . error = err + "\n" + xmlerr ;
setState ( OdfContainer . INVALID )
}
} )
} else {
loadComponents ( )
}
} )
} else {
zip = createEmptyTextDocument ( )
}
} ;
odf . OdfContainer . EMPTY = 0 ;
odf . OdfContainer . LOADING = 1 ;
odf . OdfContainer . DONE = 2 ;
odf . OdfContainer . INVALID = 3 ;
odf . OdfContainer . SAVING = 4 ;
odf . OdfContainer . MODIFIED = 5 ;
odf . OdfContainer . getContainer = function ( url ) {
return new odf . OdfContainer ( url , null )
} ;
return odf . OdfContainer
} ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.Base64" ) ;
runtime . loadClass ( "xmldom.XPath" ) ;
runtime . loadClass ( "odf.OdfContainer" ) ;
odf . FontLoader = function ( ) {
var xpath = new xmldom . XPath , base64 = new core . Base64 ;
function getEmbeddedFontDeclarations ( fontFaceDecls ) {
var decls = { } , fonts , i , font , name , uris , href , family ;
if ( ! fontFaceDecls ) {
return decls
}
fonts = xpath . getODFElementsWithXPath ( fontFaceDecls , "style:font-face[svg:font-face-src]" , odf . Namespaces . resolvePrefix ) ;
for ( i = 0 ; i < fonts . length ; i += 1 ) {
font = fonts [ i ] ;
name = font . getAttributeNS ( odf . Namespaces . stylens , "name" ) ;
family = font . getAttributeNS ( odf . Namespaces . svgns , "font-family" ) ;
uris = xpath . getODFElementsWithXPath ( font , "svg:font-face-src/svg:font-face-uri" , odf . Namespaces . resolvePrefix ) ;
if ( uris . length > 0 ) {
href = uris [ 0 ] . getAttributeNS ( odf . Namespaces . xlinkns , "href" ) ;
decls [ name ] = { href : href , family : family }
}
}
return decls
}
function addFontToCSS ( name , font , fontdata , stylesheet ) {
var cssFamily = font . family || name , rule = "@font-face { font-family: '" + cssFamily + "'; src: " + "url(data:application/x-font-ttf;charset=binary;base64," + base64 . convertUTF8ArrayToBase64 ( fontdata ) + ') format("truetype"); }' ;
try {
stylesheet . insertRule ( rule , stylesheet . cssRules . length )
} catch ( e ) {
runtime . log ( "Problem inserting rule in CSS: " + runtime . toJson ( e ) + "\nRule: " + rule )
}
}
function loadFontIntoCSS ( embeddedFontDeclarations , odfContainer , pos , stylesheet , callback ) {
var name , i = 0 , n ;
for ( n in embeddedFontDeclarations ) {
if ( embeddedFontDeclarations . hasOwnProperty ( n ) ) {
if ( i === pos ) {
name = n ;
break
}
i += 1
}
}
if ( ! name ) {
if ( callback ) {
callback ( )
}
return
}
odfContainer . getPartData ( embeddedFontDeclarations [ name ] . href , function ( err , fontdata ) {
if ( err ) {
runtime . log ( err )
} else {
addFontToCSS ( name , embeddedFontDeclarations [ name ] , fontdata , stylesheet )
}
loadFontIntoCSS ( embeddedFontDeclarations , odfContainer , pos + 1 , stylesheet , callback )
} )
}
function loadFontsIntoCSS ( embeddedFontDeclarations , odfContainer , stylesheet ) {
loadFontIntoCSS ( embeddedFontDeclarations , odfContainer , 0 , stylesheet )
}
odf . FontLoader = function FontLoader ( ) {
this . loadFonts = function ( odfContainer , stylesheet ) {
var embeddedFontDeclarations , fontFaceDecls = odfContainer . rootElement . fontFaceDecls ;
while ( stylesheet . cssRules . length ) {
stylesheet . deleteRule ( stylesheet . cssRules . length - 1 )
}
if ( fontFaceDecls ) {
embeddedFontDeclarations = getEmbeddedFontDeclarations ( fontFaceDecls ) ;
loadFontsIntoCSS ( embeddedFontDeclarations , odfContainer , stylesheet )
}
}
} ;
return odf . FontLoader
} ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.Utils" ) ;
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "odf.OdfContainer" ) ;
runtime . loadClass ( "odf.StyleInfo" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "odf.TextStyleApplicator" ) ;
odf . Formatting = function Formatting ( ) {
var self = this , odfContainer , styleInfo = new odf . StyleInfo , svgns = odf . Namespaces . svgns , stylens = odf . Namespaces . stylens , textns = odf . Namespaces . textns , numberns = odf . Namespaces . numberns , odfUtils = new odf . OdfUtils , utils = new core . Utils ;
function mergeRecursive ( destination , source ) {
Object . keys ( source ) . forEach ( function ( p ) {
try {
if ( source [ p ] . constructor === Object ) {
destination [ p ] = mergeRecursive ( destination [ p ] , source [ p ] )
} else {
destination [ p ] = source [ p ]
}
} catch ( e ) {
destination [ p ] = source [ p ]
}
} ) ;
return destination
}
this . setOdfContainer = function ( odfcontainer ) {
odfContainer = odfcontainer
} ;
this . getFontMap = function ( ) {
var fontFaceDecls = odfContainer . rootElement . fontFaceDecls , fontFaceDeclsMap = { } , node , name , family ;
node = fontFaceDecls && fontFaceDecls . firstChild ;
while ( node ) {
if ( node . nodeType === Node . ELEMENT _NODE ) {
name = node . getAttributeNS ( stylens , "name" ) ;
if ( name ) {
family = node . getAttributeNS ( svgns , "font-family" ) ;
if ( family || node . getElementsByTagNameNS ( svgns , "font-face-uri" ) [ 0 ] ) {
fontFaceDeclsMap [ name ] = family
}
}
}
node = node . nextSibling
}
return fontFaceDeclsMap
} ;
this . getAvailableParagraphStyles = function ( ) {
var node = odfContainer . rootElement . styles && odfContainer . rootElement . styles . firstChild , p _family , p _name , p _displayName , paragraphStyles = [ ] , style ;
while ( node ) {
if ( node . nodeType === Node . ELEMENT _NODE && node . localName === "style" && node . namespaceURI === stylens ) {
style = node ;
p _family = style . getAttributeNS ( stylens , "family" ) ;
if ( p _family === "paragraph" ) {
p _name = style . getAttributeNS ( stylens , "name" ) ;
p _displayName = style . getAttributeNS ( stylens , "display-name" ) || p _name ;
if ( p _name && p _displayName ) {
paragraphStyles . push ( { name : p _name , displayName : p _displayName } )
}
}
}
node = node . nextSibling
}
return paragraphStyles
} ;
this . isStyleUsed = function ( styleElement ) {
var hasDerivedStyles , isUsed ;
hasDerivedStyles = styleInfo . hasDerivedStyles ( odfContainer . rootElement , odf . Namespaces . resolvePrefix , styleElement ) ;
isUsed = ( new styleInfo . UsedStyleList ( odfContainer . rootElement . styles ) ) . uses ( styleElement ) || ( new styleInfo . UsedStyleList ( odfContainer . rootElement . automaticStyles ) ) . uses ( styleElement ) || ( new styleInfo . UsedStyleList ( odfContainer . rootElement . body ) ) . uses ( styleElement ) ;
return hasDerivedStyles || isUsed
} ;
function getDefaultStyleElement ( family ) {
var node = odfContainer . rootElement . styles . firstChild ;
while ( node ) {
if ( node . nodeType === Node . ELEMENT _NODE && node . namespaceURI === stylens && node . localName === "default-style" && node . getAttributeNS ( stylens , "family" ) === family ) {
return node
}
node = node . nextSibling
}
return null
}
function getStyleElement ( styleName , family , styleElements ) {
var node , nodeStyleName , styleListElement ;
styleElements = styleElements || [ odfContainer . rootElement . automaticStyles , odfContainer . rootElement . styles ] ;
styleListElement = styleElements . shift ( ) ;
while ( styleListElement ) {
node = styleListElement . firstChild ;
while ( node ) {
if ( node . nodeType === Node . ELEMENT _NODE ) {
nodeStyleName = node . getAttributeNS ( stylens , "name" ) ;
if ( node . namespaceURI === stylens && node . localName === "style" && node . getAttributeNS ( stylens , "family" ) === family && nodeStyleName === styleName ) {
return node
}
if ( family === "list-style" && node . namespaceURI === textns && node . localName === "list-style" && nodeStyleName === styleName ) {
return node
}
if ( family === "data" && node . namespaceURI === numberns && nodeStyleName === styleName ) {
return node
}
}
node = node . nextSibling
}
styleListElement = styleElements . shift ( )
}
return null
}
this . getStyleElement = getStyleElement ;
function getStyleAttributes ( styleNode ) {
var i , propertiesMap = { } , propertiesNode = styleNode . firstChild ;
while ( propertiesNode ) {
if ( propertiesNode . nodeType === Node . ELEMENT _NODE && propertiesNode . namespaceURI === stylens ) {
propertiesMap [ propertiesNode . nodeName ] = { } ;
for ( i = 0 ; i < propertiesNode . attributes . length ; i += 1 ) {
propertiesMap [ propertiesNode . nodeName ] [ propertiesNode . attributes [ i ] . name ] = propertiesNode . attributes [ i ] . value
}
}
propertiesNode = propertiesNode . nextSibling
}
return propertiesMap
}
this . getStyleAttributes = getStyleAttributes ;
function mapObjOntoNode ( node , properties ) {
Object . keys ( properties ) . forEach ( function ( key ) {
var parts = key . split ( ":" ) , prefix = parts [ 0 ] , localName = parts [ 1 ] , ns = odf . Namespaces . resolvePrefix ( prefix ) , value = properties [ key ] , element ;
if ( typeof value === "object" && Object . keys ( value ) . length ) {
element = node . getElementsByTagNameNS ( ns , localName ) [ 0 ] || node . ownerDocument . createElementNS ( ns , key ) ;
node . appendChild ( element ) ;
mapObjOntoNode ( element , value )
} else {
node . setAttributeNS ( ns , key , value )
}
} )
}
function getInheritedStyleAttributes ( styleNode ) {
var styleListElement = odfContainer . rootElement . styles , parentStyleName , propertiesMap = { } , inheritedPropertiesMap = { } , node = styleNode ;
while ( node ) {
propertiesMap = getStyleAttributes ( node ) ;
inheritedPropertiesMap = mergeRecursive ( propertiesMap , inheritedPropertiesMap ) ;
parentStyleName = node . getAttributeNS ( stylens , "parent-style-name" ) ;
if ( parentStyleName ) {
node = getStyleElement ( parentStyleName , styleNode . getAttributeNS ( stylens , "family" ) , [ styleListElement ] )
} else {
node = null
}
}
node = getDefaultStyleElement ( styleNode . getAttributeNS ( stylens , "family" ) ) ;
if ( node ) {
propertiesMap = getStyleAttributes ( node ) ;
inheritedPropertiesMap = mergeRecursive ( propertiesMap , inheritedPropertiesMap )
}
return inheritedPropertiesMap
}
this . getInheritedStyleAttributes = getInheritedStyleAttributes ;
this . getFirstNamedParentStyleNameOrSelf = function ( styleName ) {
var automaticStyleElementList = odfContainer . rootElement . automaticStyles , styleElementList = odfContainer . rootElement . styles , styleElement ;
styleElement = getStyleElement ( styleName , "paragraph" , [ automaticStyleElementList ] ) ;
while ( styleElement ) {
styleName = styleElement . getAttributeNS ( stylens , "parent-style-name" ) ;
styleElement = getStyleElement ( styleName , "paragraph" , [ automaticStyleElementList ] )
}
styleElement = getStyleElement ( styleName , "paragraph" , [ styleElementList ] ) ;
if ( ! styleElement ) {
return null
}
return styleName
} ;
this . hasParagraphStyle = function ( styleName ) {
return Boolean ( getStyleElement ( styleName , "paragraph" ) )
} ;
function buildStyleChain ( node , collectedChains ) {
var parent = node . nodeType === Node . TEXT _NODE ? node . parentNode : node , nodeStyles , appliedStyles = [ ] , chainKey = "" , foundContainer = false ;
while ( parent ) {
if ( ! foundContainer && odfUtils . isGroupingElement ( parent ) ) {
foundContainer = true
}
nodeStyles = styleInfo . determineStylesForNode ( ( parent ) ) ;
if ( nodeStyles ) {
appliedStyles . push ( nodeStyles )
}
parent = parent . parentNode
}
if ( foundContainer ) {
appliedStyles . forEach ( function ( usedStyleMap ) {
Object . keys ( usedStyleMap ) . forEach ( function ( styleFamily ) {
Object . keys ( usedStyleMap [ styleFamily ] ) . forEach ( function ( styleName ) {
chainKey += "|" + styleFamily + ":" + styleName + "|"
} )
} )
} ) ;
if ( collectedChains ) {
collectedChains [ chainKey ] = appliedStyles
}
}
return foundContainer ? appliedStyles : undefined
}
function calculateAppliedStyle ( styleChain ) {
var mergedChildStyle = { orderedStyles : [ ] } ;
styleChain . forEach ( function ( elementStyleSet ) {
Object . keys ( ( elementStyleSet ) ) . forEach ( function ( styleFamily ) {
var styleName = Object . keys ( elementStyleSet [ styleFamily ] ) [ 0 ] , styleElement , parentStyle , displayName ;
styleElement = getStyleElement ( styleName , styleFamily ) ;
if ( styleElement ) {
parentStyle = getInheritedStyleAttributes ( ( styleElement ) ) ;
mergedChildStyle = mergeRecursive ( parentStyle , mergedChildStyle ) ;
displayName = styleElement . getAttributeNS ( stylens , "display-name" )
} else {
runtime . log ( "No style element found for '" + styleName + "' of family '" + styleFamily + "'" )
}
mergedChildStyle . orderedStyles . push ( { name : styleName , family : styleFamily , displayName : displayName } )
} )
} ) ;
return mergedChildStyle
}
this . getAppliedStyles = function ( textNodes ) {
var styleChains = { } , styles = [ ] ;
textNodes . forEach ( function ( n ) {
buildStyleChain ( n , styleChains )
} ) ;
Object . keys ( styleChains ) . forEach ( function ( key ) {
styles . push ( calculateAppliedStyle ( styleChains [ key ] ) )
} ) ;
return styles
} ;
this . getAppliedStylesForElement = function ( node ) {
var styleChain ;
styleChain = buildStyleChain ( node ) ;
return styleChain ? calculateAppliedStyle ( styleChain ) : undefined
} ;
this . applyStyle = function ( memberId , textNodes , limits , info ) {
var textStyles = new odf . TextStyleApplicator ( "auto" + utils . hashString ( memberId ) + "_" , self , odfContainer . rootElement . automaticStyles ) ;
textStyles . applyStyle ( textNodes , limits , info )
} ;
function getAllStyleNames ( ) {
var styleElements = [ odfContainer . rootElement . automaticStyles , odfContainer . rootElement . styles ] , node , styleNames = [ ] ;
styleElements . forEach ( function ( styleListElement ) {
node = styleListElement . firstChild ;
while ( node ) {
if ( node . nodeType === Node . ELEMENT _NODE ) {
if ( node . namespaceURI === stylens && node . localName === "style" || node . namespaceURI === textns && node . localName === "list-style" ) {
styleNames . push ( node . getAttributeNS ( stylens , "name" ) )
}
}
node = node . nextSibling
}
} ) ;
return styleNames
}
this . updateStyle = function ( styleNode , properties , newStylePrefix ) {
var name , existingNames , startIndex ;
mapObjOntoNode ( styleNode , properties ) ;
if ( newStylePrefix ) {
name = styleNode . getAttributeNS ( stylens , "name" ) ;
existingNames = getAllStyleNames ( ) ;
startIndex = 0 ;
do {
name = newStylePrefix + startIndex ;
startIndex += 1
} while ( existingNames . indexOf ( name ) !== - 1 ) ;
styleNode . setAttributeNS ( stylens , "style:name" , name )
}
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.DomUtils" ) ;
runtime . loadClass ( "odf.OdfContainer" ) ;
runtime . loadClass ( "odf.Formatting" ) ;
runtime . loadClass ( "xmldom.XPath" ) ;
runtime . loadClass ( "odf.FontLoader" ) ;
runtime . loadClass ( "odf.Style2CSS" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "gui.AnnotationViewManager" ) ;
odf . OdfCanvas = function ( ) {
function LoadingQueue ( ) {
var queue = [ ] , taskRunning = false ;
function run ( task ) {
taskRunning = true ;
runtime . setTimeout ( function ( ) {
try {
task ( )
} catch ( e ) {
runtime . log ( e )
}
taskRunning = false ;
if ( queue . length > 0 ) {
run ( queue . pop ( ) )
}
} , 10 )
}
this . clearQueue = function ( ) {
queue . length = 0
} ;
this . addToQueue = function ( loadingTask ) {
if ( queue . length === 0 && ! taskRunning ) {
return run ( loadingTask )
}
queue . push ( loadingTask )
}
}
function PageSwitcher ( css ) {
var sheet = css . sheet , position = 1 ;
function updateCSS ( ) {
while ( sheet . cssRules . length > 0 ) {
sheet . deleteRule ( 0 )
}
sheet . insertRule ( "#shadowContent draw|page {display:none;}" , 0 ) ;
sheet . insertRule ( "office|presentation draw|page {display:none;}" , 1 ) ;
sheet . insertRule ( "#shadowContent draw|page:nth-of-type(" + position + ") {display:block;}" , 2 ) ;
sheet . insertRule ( "office|presentation draw|page:nth-of-type(" + position + ") {display:block;}" , 3 )
}
this . showFirstPage = function ( ) {
position = 1 ;
updateCSS ( )
} ;
this . showNextPage = function ( ) {
position += 1 ;
updateCSS ( )
} ;
this . showPreviousPage = function ( ) {
if ( position > 1 ) {
position -= 1 ;
updateCSS ( )
}
} ;
this . showPage = function ( n ) {
if ( n > 0 ) {
position = n ;
updateCSS ( )
}
} ;
this . css = css
}
function listenEvent ( eventTarget , eventType , eventHandler ) {
if ( eventTarget . addEventListener ) {
eventTarget . addEventListener ( eventType , eventHandler , false )
} else {
if ( eventTarget . attachEvent ) {
eventType = "on" + eventType ;
eventTarget . attachEvent ( eventType , eventHandler )
} else {
eventTarget [ "on" + eventType ] = eventHandler
}
}
}
function SelectionWatcher ( element ) {
var selection = [ ] , listeners = [ ] ;
function isAncestorOf ( ancestor , descendant ) {
while ( descendant ) {
if ( descendant === ancestor ) {
return true
}
descendant = descendant . parentNode
}
return false
}
function fallsWithin ( element , range ) {
return isAncestorOf ( element , range . startContainer ) && isAncestorOf ( element , range . endContainer )
}
function getCurrentSelection ( ) {
var s = [ ] , current = runtime . getWindow ( ) . getSelection ( ) , i , r ;
for ( i = 0 ; i < current . rangeCount ; i += 1 ) {
r = current . getRangeAt ( i ) ;
if ( r !== null && fallsWithin ( element , r ) ) {
s . push ( r )
}
}
return s
}
function rangesNotEqual ( rangeA , rangeB ) {
if ( rangeA === rangeB ) {
return false
}
if ( rangeA === null || rangeB === null ) {
return true
}
return rangeA . startContainer !== rangeB . startContainer || rangeA . startOffset !== rangeB . startOffset || rangeA . endContainer !== rangeB . endContainer || rangeA . endOffset !== rangeB . endOffset
}
function emitNewSelection ( ) {
var i , l = listeners . length ;
for ( i = 0 ; i < l ; i += 1 ) {
listeners [ i ] ( element , selection )
}
}
function copySelection ( selection ) {
var s = [ selection . length ] , i , oldr , r , doc = element . ownerDocument ;
for ( i = 0 ; i < selection . length ; i += 1 ) {
oldr = selection [ i ] ;
r = doc . createRange ( ) ;
r . setStart ( oldr . startContainer , oldr . startOffset ) ;
r . setEnd ( oldr . endContainer , oldr . endOffset ) ;
s [ i ] = r
}
return s
}
function checkSelection ( ) {
var s = getCurrentSelection ( ) , i ;
if ( s . length === selection . length ) {
for ( i = 0 ; i < s . length ; i += 1 ) {
if ( rangesNotEqual ( s [ i ] , selection [ i ] ) ) {
break
}
}
if ( i === s . length ) {
return
}
}
selection = s ;
selection = copySelection ( s ) ;
emitNewSelection ( )
}
this . addListener = function ( eventName , handler ) {
var i , l = listeners . length ;
for ( i = 0 ; i < l ; i += 1 ) {
if ( listeners [ i ] === handler ) {
return
}
}
listeners . push ( handler )
} ;
listenEvent ( element , "mouseup" , checkSelection ) ;
listenEvent ( element , "keyup" , checkSelection ) ;
listenEvent ( element , "keydown" , checkSelection )
}
var drawns = odf . Namespaces . drawns , fons = odf . Namespaces . fons , officens = odf . Namespaces . officens , stylens = odf . Namespaces . stylens , svgns = odf . Namespaces . svgns , tablens = odf . Namespaces . tablens , textns = odf . Namespaces . textns , xlinkns = odf . Namespaces . xlinkns , xmlns = odf . Namespaces . xmlns , presentationns = odf . Namespaces . presentationns , window = runtime . getWindow ( ) , xpath = new xmldom . XPath , utils = new odf . OdfUtils , domUtils = new core . DomUtils , shadowContent , sizer , annotationsPane , allowAnnotations =
false , annotationManager ;
function clear ( element ) {
while ( element . firstChild ) {
element . removeChild ( element . firstChild )
}
}
function handleStyles ( odfcontainer , formatting , stylesxmlcss ) {
var style2css = new odf . Style2CSS ;
style2css . style2css ( odfcontainer . getDocumentType ( ) , stylesxmlcss . sheet , formatting . getFontMap ( ) , odfcontainer . rootElement . styles , odfcontainer . rootElement . automaticStyles )
}
function handleFonts ( odfContainer , fontcss ) {
var fontLoader = new odf . FontLoader ;
fontLoader . loadFonts ( odfContainer , fontcss . sheet )
}
function getMasterPage ( odfContainer , masterPageName ) {
if ( ! masterPageName ) {
return null
}
var masterStyles = odfContainer . rootElement . masterStyles , masterPages = masterStyles . getElementsByTagNameNS ( stylens , "master-page" ) , masterPage = null , i ;
for ( i = 0 ; i < masterPages . length ; i += 1 ) {
if ( masterPages [ i ] . getAttributeNS ( stylens , "name" ) === masterPageName ) {
masterPage = masterPages [ i ] ;
break
}
}
return masterPage
}
function setFramePosition ( odfContainer , id , frame , stylesheet ) {
frame . setAttribute ( "styleid" , id ) ;
var rule , anchor = frame . getAttributeNS ( textns , "anchor-type" ) , x = frame . getAttributeNS ( svgns , "x" ) , y = frame . getAttributeNS ( svgns , "y" ) , width = frame . getAttributeNS ( svgns , "width" ) , height = frame . getAttributeNS ( svgns , "height" ) , minheight = frame . getAttributeNS ( fons , "min-height" ) , minwidth = frame . getAttributeNS ( fons , "min-width" ) , masterPageName = frame . getAttributeNS ( drawns , "master-page-name" ) , masterPage = null , j , clonedPage , clonedNode , pageNumber = 0 , pageNumberContainer , node , document =
odfContainer . rootElement . ownerDocument ;
masterPage = getMasterPage ( odfContainer , masterPageName ) ;
if ( masterPage ) {
clonedPage = document . createElementNS ( drawns , "draw:page" ) ;
node = masterPage . firstElementChild ;
j = 0 ;
while ( node ) {
if ( node . getAttributeNS ( presentationns , "placeholder" ) !== "true" ) {
clonedNode = node . cloneNode ( true ) ;
clonedPage . appendChild ( clonedNode ) ;
setFramePosition ( odfContainer , id + "_" + j , ( clonedNode ) , stylesheet )
}
node = node . nextElementSibling ;
j += 1
}
shadowContent . appendChild ( clonedPage ) ;
pageNumber = shadowContent . getElementsByTagNameNS ( drawns , "page" ) . length ;
pageNumberContainer = clonedPage . getElementsByTagNameNS ( textns , "page-number" ) [ 0 ] ;
if ( pageNumberContainer ) {
while ( pageNumberContainer . firstChild ) {
pageNumberContainer . removeChild ( pageNumberContainer . firstChild )
}
pageNumberContainer . appendChild ( document . createTextNode ( pageNumber ) )
}
setFramePosition ( odfContainer , id , clonedPage , stylesheet ) ;
clonedPage . setAttributeNS ( drawns , "draw:master-page-name" , masterPage . getAttributeNS ( stylens , "name" ) )
}
if ( anchor === "as-char" ) {
rule = "display: inline-block;"
} else {
if ( anchor || x || y ) {
rule = "position: absolute;"
} else {
if ( width || height || minheight || minwidth ) {
rule = "display: block;"
}
}
}
if ( x ) {
rule += "left: " + x + ";"
}
if ( y ) {
rule += "top: " + y + ";"
}
if ( width ) {
rule += "width: " + width + ";"
}
if ( height ) {
rule += "height: " + height + ";"
}
if ( minheight ) {
rule += "min-height: " + minheight + ";"
}
if ( minwidth ) {
rule += "min-width: " + minwidth + ";"
}
if ( rule ) {
rule = "draw|" + frame . localName + '[styleid="' + id + '"] {' + rule + "}" ;
stylesheet . insertRule ( rule , stylesheet . cssRules . length )
}
}
function getUrlFromBinaryDataElement ( image ) {
var node = image . firstChild ;
while ( node ) {
if ( node . namespaceURI === officens && node . localName === "binary-data" ) {
return "data:image/png;base64," + node . textContent . replace ( /[\r\n\s]/g , "" )
}
node = node . nextSibling
}
return ""
}
function setImage ( id , container , image , stylesheet ) {
image . setAttribute ( "styleid" , id ) ;
var url = image . getAttributeNS ( xlinkns , "href" ) , part ;
function callback ( url ) {
var rule ;
if ( url ) {
rule = "background-image: url(" + url + ");" ;
rule = 'draw|image[styleid="' + id + '"] {' + rule + "}" ;
stylesheet . insertRule ( rule , stylesheet . cssRules . length )
}
}
if ( url ) {
try {
part = container . getPart ( url ) ;
part . onchange = function ( part ) {
callback ( part . url )
} ;
part . load ( )
} catch ( e ) {
runtime . log ( "slight problem: " + e )
}
} else {
url = getUrlFromBinaryDataElement ( image ) ;
callback ( url )
}
}
function formatParagraphAnchors ( odfbody ) {
var runtimens = "urn:webodf" , n , i , nodes = xpath . getODFElementsWithXPath ( odfbody , ".//*[*[@text:anchor-type='paragraph']]" , odf . Namespaces . resolvePrefix ) ;
for ( i = 0 ; i < nodes . length ; i += 1 ) {
n = nodes [ i ] ;
if ( n . setAttributeNS ) {
n . setAttributeNS ( runtimens , "containsparagraphanchor" , true )
}
}
}
function modifyTables ( odffragment ) {
var i , tableCells , node ;
function modifyTableCell ( node ) {
if ( node . hasAttributeNS ( tablens , "number-columns-spanned" ) ) {
node . setAttribute ( "colspan" , node . getAttributeNS ( tablens , "number-columns-spanned" ) )
}
if ( node . hasAttributeNS ( tablens , "number-rows-spanned" ) ) {
node . setAttribute ( "rowspan" , node . getAttributeNS ( tablens , "number-rows-spanned" ) )
}
}
tableCells = odffragment . getElementsByTagNameNS ( tablens , "table-cell" ) ;
for ( i = 0 ; i < tableCells . length ; i += 1 ) {
node = ( tableCells . item ( i ) ) ;
modifyTableCell ( node )
}
}
function modifyAnnotations ( odffragment ) {
var annotationNodes = domUtils . getElementsByTagNameNS ( odffragment , officens , "annotation" ) , annotationEnds = domUtils . getElementsByTagNameNS ( odffragment , officens , "annotation-end" ) , currentAnnotationName , i ;
function matchAnnotationEnd ( element ) {
return currentAnnotationName === element . getAttributeNS ( officens , "name" )
}
for ( i = 0 ; i < annotationNodes . length ; i += 1 ) {
currentAnnotationName = annotationNodes [ i ] . getAttributeNS ( officens , "name" ) ;
annotationManager . addAnnotation ( { node : annotationNodes [ i ] , end : annotationEnds . filter ( matchAnnotationEnd ) [ 0 ] || null } )
}
annotationManager . rerenderAnnotations ( )
}
function modifyLinks ( odffragment ) {
var i , links , node ;
function modifyLink ( node ) {
var url , clickHandler ;
if ( ! node . hasAttributeNS ( xlinkns , "href" ) ) {
return
}
url = node . getAttributeNS ( xlinkns , "href" ) ;
if ( url [ 0 ] === "#" ) {
url = url . substring ( 1 ) ;
clickHandler = function ( ) {
var bookmarks = xpath . getODFElementsWithXPath ( odffragment , "//text:bookmark-start[@text:name='" + url + "']" , odf . Namespaces . resolvePrefix ) ;
if ( bookmarks . length === 0 ) {
bookmarks = xpath . getODFElementsWithXPath ( odffragment , "//text:bookmark[@text:name='" + url + "']" , odf . Namespaces . resolvePrefix )
}
if ( bookmarks . length > 0 ) {
bookmarks [ 0 ] . scrollIntoView ( true )
}
return false
}
} else {
clickHandler = function ( ) {
window . open ( url )
}
}
node . onclick = clickHandler
}
links = odffragment . getElementsByTagNameNS ( textns , "a" ) ;
for ( i = 0 ; i < links . length ; i += 1 ) {
node = ( links . item ( i ) ) ;
modifyLink ( node )
}
}
function expandSpaceElements ( odffragment ) {
var spaces , doc = odffragment . ownerDocument ;
function expandSpaceElement ( space ) {
var j , count ;
while ( space . firstChild ) {
space . removeChild ( space . firstChild )
}
space . appendChild ( doc . createTextNode ( " " ) ) ;
count = parseInt ( space . getAttributeNS ( textns , "c" ) , 10 ) ;
if ( count > 1 ) {
space . removeAttributeNS ( textns , "c" ) ;
for ( j = 1 ; j < count ; j += 1 ) {
space . parentNode . insertBefore ( space . cloneNode ( true ) , space )
}
}
}
spaces = domUtils . getElementsByTagNameNS ( odffragment , textns , "s" ) ;
spaces . forEach ( expandSpaceElement )
}
function expandTabElements ( odffragment ) {
var tabs ;
tabs = domUtils . getElementsByTagNameNS ( odffragment , textns , "tab" ) ;
tabs . forEach ( function ( tab ) {
tab . textContent = "\t"
} )
}
function modifyImages ( container , odfbody , stylesheet ) {
var node , frames , i ;
frames = [ ] ;
node = odfbody . firstChild ;
while ( node && node !== odfbody ) {
if ( node . namespaceURI === drawns ) {
frames [ frames . length ] = node
}
if ( node . firstChild ) {
node = node . firstChild
} else {
while ( node && node !== odfbody && ! node . nextSibling ) {
node = node . parentNode
}
if ( node && node . nextSibling ) {
node = node . nextSibling
}
}
}
for ( i = 0 ; i < frames . length ; i += 1 ) {
node = frames [ i ] ;
setFramePosition ( container , "frame" + String ( i ) , node , stylesheet )
}
formatParagraphAnchors ( odfbody )
}
function setVideo ( container , plugin ) {
var video , source , url , doc = plugin . ownerDocument , part ;
url = plugin . getAttributeNS ( xlinkns , "href" ) ;
function callback ( url , mimetype ) {
var ns = doc . documentElement . namespaceURI ;
if ( mimetype . substr ( 0 , 6 ) === "video/" ) {
video = doc . createElementNS ( ns , "video" ) ;
video . setAttribute ( "controls" , "controls" ) ;
source = doc . createElementNS ( ns , "source" ) ;
source . setAttribute ( "src" , url ) ;
source . setAttribute ( "type" , mimetype ) ;
video . appendChild ( source ) ;
plugin . parentNode . appendChild ( video )
} else {
plugin . innerHtml = "Unrecognised Plugin"
}
}
if ( url ) {
try {
part = container . getPart ( url ) ;
part . onchange = function ( part ) {
callback ( part . url , part . mimetype )
} ;
part . load ( )
} catch ( e ) {
runtime . log ( "slight problem: " + e )
}
} else {
runtime . log ( "using MP4 data fallback" ) ;
url = getUrlFromBinaryDataElement ( plugin ) ;
callback ( url , "video/mp4" )
}
}
function getNumberRule ( node ) {
var style = node . getAttributeNS ( stylens , "num-format" ) , suffix = node . getAttributeNS ( stylens , "num-suffix" ) , prefix = node . getAttributeNS ( stylens , "num-prefix" ) , rule = "" , stylemap = { 1 : "decimal" , "a" : "lower-latin" , "A" : "upper-latin" , "i" : "lower-roman" , "I" : "upper-roman" } , content ;
content = prefix || "" ;
if ( stylemap . hasOwnProperty ( style ) ) {
content += " counter(list, " + stylemap [ style ] + ")"
} else {
if ( style ) {
content += "'" + style + "';"
} else {
content += " ''"
}
}
if ( suffix ) {
content += " '" + suffix + "'"
}
rule = "content: " + content + ";" ;
return rule
}
function getImageRule ( ) {
var rule = "content: none;" ;
return rule
}
function getBulletRule ( node ) {
var bulletChar = node . getAttributeNS ( textns , "bullet-char" ) ;
return "content: '" + bulletChar + "';"
}
function getBulletsRule ( node ) {
var itemrule ;
if ( node ) {
if ( node . localName === "list-level-style-number" ) {
itemrule = getNumberRule ( node )
} else {
if ( node . localName === "list-level-style-image" ) {
itemrule = getImageRule ( )
} else {
if ( node . localName === "list-level-style-bullet" ) {
itemrule = getBulletRule ( node )
}
}
}
}
return itemrule
}
function loadLists ( odffragment , stylesheet ) {
var i , lists , node , id , continueList , styleName , rule , listMap = { } , parentList , listStyles , listStyleMap = { } , bulletRule ;
listStyles = window . document . getElementsByTagNameNS ( textns , "list-style" ) ;
for ( i = 0 ; i < listStyles . length ; i += 1 ) {
node = ( listStyles . item ( i ) ) ;
styleName = node . getAttributeNS ( stylens , "name" ) ;
if ( styleName ) {
listStyleMap [ styleName ] = node
}
}
lists = odffragment . getElementsByTagNameNS ( textns , "list" ) ;
for ( i = 0 ; i < lists . length ; i += 1 ) {
node = ( lists . item ( i ) ) ;
id = node . getAttributeNS ( xmlns , "id" ) ;
if ( id ) {
continueList = node . getAttributeNS ( textns , "continue-list" ) ;
node . setAttribute ( "id" , id ) ;
rule = "text|list#" + id + " > text|list-item > *:first-child:before {" ;
styleName = node . getAttributeNS ( textns , "style-name" ) ;
if ( styleName ) {
node = listStyleMap [ styleName ] ;
bulletRule = getBulletsRule ( ( utils . getFirstNonWhitespaceChild ( node ) ) )
}
if ( continueList ) {
parentList = listMap [ continueList ] ;
while ( parentList ) {
continueList = parentList ;
parentList = listMap [ continueList ]
}
rule += "counter-increment:" + continueList + ";" ;
if ( bulletRule ) {
bulletRule = bulletRule . replace ( "list" , continueList ) ;
rule += bulletRule
} else {
rule += "content:counter(" + continueList + ");"
}
} else {
continueList = "" ;
if ( bulletRule ) {
bulletRule = bulletRule . replace ( "list" , id ) ;
rule += bulletRule
} else {
rule += "content: counter(" + id + ");"
}
rule += "counter-increment:" + id + ";" ;
stylesheet . insertRule ( "text|list#" + id + " {counter-reset:" + id + "}" , stylesheet . cssRules . length )
}
rule += "}" ;
listMap [ id ] = continueList ;
if ( rule ) {
stylesheet . insertRule ( rule , stylesheet . cssRules . length )
}
}
}
}
function addWebODFStyleSheet ( document ) {
var head = document . getElementsByTagName ( "head" ) [ 0 ] , style , href ;
if ( String ( typeof webodf _css ) !== "undefined" ) {
style = document . createElementNS ( head . namespaceURI , "style" ) ;
style . setAttribute ( "media" , "screen, print, handheld, projection" ) ;
style . appendChild ( document . createTextNode ( webodf _css ) )
} else {
style = document . createElementNS ( head . namespaceURI , "link" ) ;
href = "webodf.css" ;
if ( runtime . currentDirectory ) {
href = runtime . currentDirectory ( ) + "/../" + href
}
style . setAttribute ( "href" , href ) ;
style . setAttribute ( "rel" , "stylesheet" )
}
style . setAttribute ( "type" , "text/css" ) ;
head . appendChild ( style ) ;
return ( style )
}
function addStyleSheet ( document ) {
var head = document . getElementsByTagName ( "head" ) [ 0 ] , style = document . createElementNS ( head . namespaceURI , "style" ) , text = "" ;
style . setAttribute ( "type" , "text/css" ) ;
style . setAttribute ( "media" , "screen, print, handheld, projection" ) ;
odf . Namespaces . forEachPrefix ( function ( prefix , ns ) {
text += "@namespace " + prefix + " url(" + ns + ");\n"
} ) ;
style . appendChild ( document . createTextNode ( text ) ) ;
head . appendChild ( style ) ;
return ( style )
}
odf . OdfCanvas = function OdfCanvas ( element ) {
runtime . assert ( element !== null && element !== undefined , "odf.OdfCanvas constructor needs DOM element" ) ;
runtime . assert ( element . ownerDocument !== null && element . ownerDocument !== undefined , "odf.OdfCanvas constructor needs DOM" ) ;
var self = this , doc = ( element . ownerDocument ) , odfcontainer , formatting = new odf . Formatting , selectionWatcher = new SelectionWatcher ( element ) , pageSwitcher , fontcss , stylesxmlcss , positioncss , editable = false , zoomLevel = 1 , eventHandlers = { } , editparagraph , loadingQueue = new LoadingQueue ;
addWebODFStyleSheet ( doc ) ;
pageSwitcher = new PageSwitcher ( addStyleSheet ( doc ) ) ;
fontcss = addStyleSheet ( doc ) ;
stylesxmlcss = addStyleSheet ( doc ) ;
positioncss = addStyleSheet ( doc ) ;
function loadImages ( container , odffragment , stylesheet ) {
var i , images , node ;
function loadImage ( name , container , node , stylesheet ) {
loadingQueue . addToQueue ( function ( ) {
setImage ( name , container , node , stylesheet )
} )
}
images = odffragment . getElementsByTagNameNS ( drawns , "image" ) ;
for ( i = 0 ; i < images . length ; i += 1 ) {
node = ( images . item ( i ) ) ;
loadImage ( "image" + String ( i ) , container , node , stylesheet )
}
}
function loadVideos ( container , odffragment ) {
var i , plugins , node ;
function loadVideo ( container , node ) {
loadingQueue . addToQueue ( function ( ) {
setVideo ( container , node )
} )
}
plugins = odffragment . getElementsByTagNameNS ( drawns , "plugin" ) ;
for ( i = 0 ; i < plugins . length ; i += 1 ) {
node = ( plugins . item ( i ) ) ;
loadVideo ( container , node )
}
}
function addEventListener ( eventType , eventHandler ) {
var handlers = eventHandlers [ eventType ] ;
if ( handlers === undefined ) {
handlers = eventHandlers [ eventType ] = [ ]
}
if ( eventHandler && handlers . indexOf ( eventHandler ) === - 1 ) {
handlers . push ( eventHandler )
}
}
function fireEvent ( eventType , args ) {
if ( ! eventHandlers . hasOwnProperty ( eventType ) ) {
return
}
var handlers = eventHandlers [ eventType ] , i ;
for ( i = 0 ; i < handlers . length ; i += 1 ) {
handlers [ i ] . apply ( null , args )
}
}
function fixContainerSize ( ) {
var odfdoc = sizer . firstChild ;
if ( ! odfdoc ) {
return
}
if ( zoomLevel > 1 ) {
sizer . style . MozTransformOrigin = "center top" ;
sizer . style . WebkitTransformOrigin = "center top" ;
sizer . style . OTransformOrigin = "center top" ;
sizer . style . msTransformOrigin = "center top"
} else {
sizer . style . MozTransformOrigin = "left top" ;
sizer . style . WebkitTransformOrigin = "left top" ;
sizer . style . OTransformOrigin = "left top" ;
sizer . style . msTransformOrigin = "left top"
}
sizer . style . WebkitTransform = "scale(" + zoomLevel + ")" ;
sizer . style . MozTransform = "scale(" + zoomLevel + ")" ;
sizer . style . OTransform = "scale(" + zoomLevel + ")" ;
sizer . style . msTransform = "scale(" + zoomLevel + ")" ;
element . style . width = Math . round ( zoomLevel * sizer . offsetWidth ) + "px" ;
element . style . height = Math . round ( zoomLevel * sizer . offsetHeight ) + "px"
}
function handleContent ( container , odfnode ) {
var css = positioncss . sheet ;
clear ( element ) ;
sizer = doc . createElementNS ( element . namespaceURI , "div" ) ;
sizer . style . display = "inline-block" ;
sizer . style . background = "white" ;
sizer . appendChild ( odfnode ) ;
element . appendChild ( sizer ) ;
annotationsPane = doc . createElementNS ( element . namespaceURI , "div" ) ;
annotationsPane . id = "annotationsPane" ;
shadowContent = doc . createElementNS ( element . namespaceURI , "div" ) ;
shadowContent . id = "shadowContent" ;
shadowContent . style . position = "absolute" ;
shadowContent . style . top = 0 ;
shadowContent . style . left = 0 ;
container . getContentElement ( ) . appendChild ( shadowContent ) ;
modifyImages ( container , odfnode . body , css ) ;
modifyTables ( odfnode . body ) ;
modifyLinks ( odfnode . body ) ;
expandSpaceElements ( odfnode . body ) ;
expandTabElements ( odfnode . body ) ;
loadImages ( container , odfnode . body , css ) ;
loadVideos ( container , odfnode . body ) ;
loadLists ( odfnode . body , css ) ;
sizer . insertBefore ( shadowContent , sizer . firstChild ) ;
fixContainerSize ( )
}
function handleAnnotations ( odfnode ) {
if ( allowAnnotations ) {
if ( ! annotationsPane . parentNode ) {
sizer . appendChild ( annotationsPane ) ;
fixContainerSize ( )
}
if ( annotationManager ) {
annotationManager . forgetAnnotations ( )
}
annotationManager = new gui . AnnotationViewManager ( self , odfnode . body , annotationsPane ) ;
modifyAnnotations ( odfnode . body )
} else {
if ( annotationsPane . parentNode ) {
sizer . removeChild ( annotationsPane ) ;
annotationManager . forgetAnnotations ( ) ;
fixContainerSize ( )
}
}
}
function refreshOdf ( suppressEvent ) {
function callback ( ) {
clear ( element ) ;
element . style . display = "inline-block" ;
var odfnode = odfcontainer . rootElement ;
element . ownerDocument . importNode ( odfnode , true ) ;
formatting . setOdfContainer ( odfcontainer ) ;
handleFonts ( odfcontainer , fontcss ) ;
handleStyles ( odfcontainer , formatting , stylesxmlcss ) ;
handleContent ( odfcontainer , odfnode ) ;
handleAnnotations ( odfnode ) ;
if ( ! suppressEvent ) {
fireEvent ( "statereadychange" , [ odfcontainer ] )
}
}
if ( odfcontainer . state === odf . OdfContainer . DONE ) {
callback ( )
} else {
runtime . log ( "WARNING: refreshOdf called but ODF was not DONE." ) ;
runtime . setTimeout ( function later _cb ( ) {
if ( odfcontainer . state === odf . OdfContainer . DONE ) {
callback ( )
} else {
runtime . log ( "will be back later..." ) ;
runtime . setTimeout ( later _cb , 500 )
}
} , 100 )
}
}
this . refreshCSS = function ( ) {
handleStyles ( odfcontainer , formatting , stylesxmlcss ) ;
fixContainerSize ( )
} ;
this . refreshSize = function ( ) {
fixContainerSize ( )
} ;
this . odfContainer = function ( ) {
return odfcontainer
} ;
this . slidevisibilitycss = function ( ) {
return pageSwitcher . css
} ;
this . setOdfContainer = function ( container , suppressEvent ) {
odfcontainer = container ;
refreshOdf ( suppressEvent === true )
} ;
function load ( url ) {
loadingQueue . clearQueue ( ) ;
element . innerHTML = "loading " + url ;
element . removeAttribute ( "style" ) ;
odfcontainer = new odf . OdfContainer ( url , function ( container ) {
odfcontainer = container ;
refreshOdf ( false )
} )
}
this [ "load" ] = load ;
this . load = load ;
function stopEditing ( ) {
if ( ! editparagraph ) {
return
}
var fragment = editparagraph . ownerDocument . createDocumentFragment ( ) ;
while ( editparagraph . firstChild ) {
fragment . insertBefore ( editparagraph . firstChild , null )
}
editparagraph . parentNode . replaceChild ( fragment , editparagraph )
}
this . save = function ( callback ) {
stopEditing ( ) ;
odfcontainer . save ( callback )
} ;
function cancelEvent ( event ) {
if ( event . preventDefault ) {
event . preventDefault ( ) ;
event . stopPropagation ( )
} else {
event . returnValue = false ;
event . cancelBubble = true
}
}
function processClick ( evt ) {
evt = evt || window . event ;
var e = evt . target , selection = window . getSelection ( ) , range = selection . rangeCount > 0 ? selection . getRangeAt ( 0 ) : null , startContainer = range && range . startContainer , startOffset = range && range . startOffset , endContainer = range && range . endContainer , endOffset = range && range . endOffset , clickdoc , ns ;
while ( e && ! ( ( e . localName === "p" || e . localName === "h" ) && e . namespaceURI === textns ) ) {
e = e . parentNode
}
if ( ! editable ) {
return
}
if ( ! e || e . parentNode === editparagraph ) {
return
}
clickdoc = e . ownerDocument ;
ns = clickdoc . documentElement . namespaceURI ;
if ( ! editparagraph ) {
editparagraph = clickdoc . createElementNS ( ns , "p" ) ;
editparagraph . style . margin = "0px" ;
editparagraph . style . padding = "0px" ;
editparagraph . style . border = "0px" ;
editparagraph . setAttribute ( "contenteditable" , true )
} else {
if ( editparagraph . parentNode ) {
stopEditing ( )
}
}
e . parentNode . replaceChild ( editparagraph , e ) ;
editparagraph . appendChild ( e ) ;
editparagraph . focus ( ) ;
if ( range ) {
selection . removeAllRanges ( ) ;
range = e . ownerDocument . createRange ( ) ;
range . setStart ( startContainer , startOffset ) ;
range . setEnd ( endContainer , endOffset ) ;
selection . addRange ( range )
}
cancelEvent ( evt )
}
this . setEditable = function ( iseditable ) {
listenEvent ( element , "click" , processClick ) ;
editable = iseditable ;
if ( ! editable ) {
stopEditing ( )
}
} ;
this . addListener = function ( eventName , handler ) {
switch ( eventName ) {
case "selectionchange" :
selectionWatcher . addListener ( eventName , handler ) ;
break ;
case "click" :
listenEvent ( element , eventName , handler ) ;
break ;
default :
addEventListener ( eventName , handler ) ;
break
}
} ;
this . getFormatting = function ( ) {
return formatting
} ;
this . getAnnotationManager = function ( ) {
return annotationManager
} ;
this . refreshAnnotations = function ( ) {
handleAnnotations ( odfcontainer . rootElement )
} ;
this . rerenderAnnotations = function ( ) {
if ( annotationManager ) {
annotationManager . rerenderAnnotations ( )
}
} ;
this . getSizer = function ( ) {
return sizer
} ;
this . enableAnnotations = function ( allow ) {
if ( allow !== allowAnnotations ) {
allowAnnotations = allow ;
if ( odfcontainer ) {
handleAnnotations ( odfcontainer . rootElement )
}
}
} ;
this . addAnnotation = function ( annotation ) {
if ( annotationManager ) {
annotationManager . addAnnotation ( annotation )
}
} ;
this . forgetAnnotations = function ( ) {
if ( annotationManager ) {
annotationManager . forgetAnnotations ( )
}
} ;
this . setZoomLevel = function ( zoom ) {
zoomLevel = zoom ;
fixContainerSize ( )
} ;
this . getZoomLevel = function ( ) {
return zoomLevel
} ;
this . fitToContainingElement = function ( width , height ) {
var realWidth = element . offsetWidth / zoomLevel , realHeight = element . offsetHeight / zoomLevel ;
zoomLevel = width / realWidth ;
if ( height / realHeight < zoomLevel ) {
zoomLevel = height / realHeight
}
fixContainerSize ( )
} ;
this . fitToWidth = function ( width ) {
var realWidth = element . offsetWidth / zoomLevel ;
zoomLevel = width / realWidth ;
fixContainerSize ( )
} ;
this . fitSmart = function ( width , height ) {
var realWidth , realHeight , newScale ;
realWidth = element . offsetWidth / zoomLevel ;
realHeight = element . offsetHeight / zoomLevel ;
newScale = width / realWidth ;
if ( height !== undefined ) {
if ( height / realHeight < newScale ) {
newScale = height / realHeight
}
}
zoomLevel = Math . min ( 1 , newScale ) ;
fixContainerSize ( )
} ;
this . fitToHeight = function ( height ) {
var realHeight = element . offsetHeight / zoomLevel ;
zoomLevel = height / realHeight ;
fixContainerSize ( )
} ;
this . showFirstPage = function ( ) {
pageSwitcher . showFirstPage ( )
} ;
this . showNextPage = function ( ) {
pageSwitcher . showNextPage ( )
} ;
this . showPreviousPage = function ( ) {
pageSwitcher . showPreviousPage ( )
} ;
this . showPage = function ( n ) {
pageSwitcher . showPage ( n ) ;
fixContainerSize ( )
} ;
this . getElement = function ( ) {
return element
}
} ;
return odf . OdfCanvas
} ( ) ;
runtime . loadClass ( "odf.OdfCanvas" ) ;
odf . CommandLineTools = function CommandLineTools ( ) {
this . roundTrip = function ( inputfilepath , outputfilepath , callback ) {
function onready ( odfcontainer ) {
if ( odfcontainer . state === odf . OdfContainer . INVALID ) {
return callback ( "Document " + inputfilepath + " is invalid." )
}
if ( odfcontainer . state === odf . OdfContainer . DONE ) {
odfcontainer . saveAs ( outputfilepath , function ( err ) {
callback ( err )
} )
} else {
callback ( "Document was not completely loaded." )
}
}
var odfcontainer = new odf . OdfContainer ( inputfilepath , onready ) ;
return odfcontainer
} ;
this . render = function ( inputfilepath , document , callback ) {
var body = document . getElementsByTagName ( "body" ) [ 0 ] , odfcanvas ;
while ( body . firstChild ) {
body . removeChild ( body . firstChild )
}
odfcanvas = new odf . OdfCanvas ( body ) ;
odfcanvas . addListener ( "statereadychange" , function ( err ) {
callback ( err )
} ) ;
odfcanvas . load ( inputfilepath )
}
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . Server = function Server ( ) {
} ;
ops . Server . prototype . connect = function ( timeout , cb ) {
} ;
ops . Server . prototype . networkStatus = function ( ) {
} ;
ops . Server . prototype . login = function ( login , password , successCb , failCb ) {
} ;
ops . Server . prototype . joinSession = function ( userId , sessionId , successCb , failCb ) {
} ;
ops . Server . prototype . leaveSession = function ( sessionId , memberId , successCb , failCb ) {
} ;
ops . Server . prototype . getGenesisUrl = function ( sessionId ) {
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . Operation = function Operation ( ) {
} ;
ops . Operation . prototype . init = function ( data ) {
} ;
ops . Operation . prototype . transform = function ( otherOp , hasPriority ) {
} ;
ops . Operation . prototype . execute = function ( odtDocument ) {
} ;
ops . Operation . prototype . spec = function ( ) {
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpAddCursor = function OpAddCursor ( ) {
var self = this , memberid , timestamp ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp
} ;
this . transform = function ( otherOp , hasPriority ) {
return [ self ]
} ;
this . execute = function ( odtDocument ) {
var cursor = odtDocument . getCursor ( memberid ) ;
if ( cursor ) {
return false
}
cursor = new ops . OdtCursor ( memberid , odtDocument ) ;
odtDocument . addCursor ( cursor ) ;
odtDocument . emit ( ops . OdtDocument . signalCursorAdded , cursor ) ;
return true
} ;
this . spec = function ( ) {
return { optype : "AddCursor" , memberid : memberid , timestamp : timestamp }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.DomUtils" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
gui . StyleHelper = function StyleHelper ( formatting ) {
var domUtils = new core . DomUtils , odfUtils = new odf . OdfUtils ;
this . getAppliedStyles = function ( range ) {
var textNodes = odfUtils . getTextNodes ( range , true ) ;
return formatting . getAppliedStyles ( textNodes )
} ;
this . applyStyle = function ( memberId , range , info ) {
var nextTextNodes = domUtils . splitBoundaries ( range ) , textNodes = odfUtils . getTextNodes ( range , false ) , limits ;
limits = { startContainer : range . startContainer , startOffset : range . startOffset , endContainer : range . endContainer , endOffset : range . endOffset } ;
formatting . applyStyle ( memberId , textNodes , limits , info ) ;
nextTextNodes . forEach ( domUtils . normalizeTextNodes )
} ;
function hasTextPropertyValue ( range , propertyName , propertyValue ) {
var hasOtherValue = true , nodes , styles , properties , container , i ;
if ( range . collapsed ) {
container = range . startContainer ;
if ( container . hasChildNodes ( ) && range . startOffset < container . childNodes . length ) {
container = container . childNodes [ range . startOffset ]
}
nodes = [ container ]
} else {
nodes = odfUtils . getTextNodes ( range , true )
}
styles = formatting . getAppliedStyles ( nodes ) ;
for ( i = 0 ; i < styles . length ; i += 1 ) {
properties = styles [ i ] [ "style:text-properties" ] ;
hasOtherValue = ! properties || properties [ propertyName ] !== propertyValue ;
if ( hasOtherValue ) {
break
}
}
return ! hasOtherValue
}
this . isBold = function ( range ) {
return hasTextPropertyValue ( range , "fo:font-weight" , "bold" )
} ;
this . isItalic = function ( range ) {
return hasTextPropertyValue ( range , "fo:font-style" , "italic" )
} ;
this . hasUnderline = function ( range ) {
return hasTextPropertyValue ( range , "style:text-underline-style" , "solid" )
} ;
this . hasStrikeThrough = function ( range ) {
return hasTextPropertyValue ( range , "style:text-line-through-style" , "solid" )
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "gui.StyleHelper" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
ops . OpApplyDirectStyling = function OpApplyDirectStyling ( ) {
var memberid , timestamp , position , length , setProperties , odfUtils = new odf . OdfUtils ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
length = parseInt ( data . length , 10 ) ;
setProperties = data . setProperties
} ;
this . transform = function ( otherOp , hasPriority ) {
return null
} ;
function getRange ( odtDocument ) {
var point1 = length >= 0 ? position : position + length , point2 = length >= 0 ? position + length : position , p1 = odtDocument . getIteratorAtPosition ( point1 ) , p2 = length ? odtDocument . getIteratorAtPosition ( point2 ) : p1 , range = odtDocument . getDOM ( ) . createRange ( ) ;
range . setStart ( p1 . container ( ) , p1 . unfilteredDomOffset ( ) ) ;
range . setEnd ( p2 . container ( ) , p2 . unfilteredDomOffset ( ) ) ;
return range
}
this . execute = function ( odtDocument ) {
var range = getRange ( odtDocument ) , impactedParagraphs = odfUtils . getImpactedParagraphs ( range ) , styleHelper = new gui . StyleHelper ( odtDocument . getFormatting ( ) ) ;
styleHelper . applyStyle ( memberid , range , setProperties ) ;
range . detach ( ) ;
odtDocument . getOdfCanvas ( ) . refreshCSS ( ) ;
impactedParagraphs . forEach ( function ( n ) {
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : n , memberId : memberid , timeStamp : timestamp } )
} ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
} ;
this . spec = function ( ) {
return { optype : "ApplyDirectStyling" , memberid : memberid , timestamp : timestamp , position : position , length : length , setProperties : setProperties }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpRemoveCursor = function OpRemoveCursor ( ) {
var self = this , optype = "RemoveCursor" , memberid , timestamp ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , result = [ self ] ;
if ( otherOpspec . optype === optype && otherOpspec . memberid === memberid ) {
result = [ ]
}
return result
} ;
this . execute = function ( odtDocument ) {
if ( ! odtDocument . removeCursor ( memberid ) ) {
return false
}
return true
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpMoveCursor = function OpMoveCursor ( ) {
var self = this , memberid , timestamp , position , length ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
length = data . length !== undefined ? parseInt ( data . length , 10 ) : 0
} ;
function countSteps ( number , stepCounter , positionFilter ) {
if ( number > 0 ) {
return stepCounter . countForwardSteps ( number , positionFilter )
}
if ( number < 0 ) {
return - stepCounter . countBackwardSteps ( - number , positionFilter )
}
return 0
}
this . merge = function ( otherOpspec ) {
if ( otherOpspec . optype === "MoveCursor" && otherOpspec . memberid === memberid ) {
position = otherOpspec . position ;
length = otherOpspec . length ;
timestamp = otherOpspec . timestamp ;
return true
}
return false
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , end = position + length , otherOpspecEnd , result = [ self ] ;
switch ( otherOptype ) {
case "RemoveText" :
otherOpspecEnd = otherOpspec . position + otherOpspec . length ;
if ( otherOpspecEnd <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < end ) {
if ( position < otherOpspec . position ) {
if ( otherOpspecEnd < end ) {
length = length - otherOpspec . length
} else {
length = otherOpspec . position - position
}
} else {
position = otherOpspec . position ;
if ( otherOpspecEnd < end ) {
length = end - otherOpspecEnd
} else {
length = 0
}
}
}
}
break ;
case "SplitParagraph" :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position <= end ) {
length += 1
}
}
break ;
case "AddAnnotation" :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position < end ) {
length += 1
}
}
break ;
case "InsertText" :
if ( otherOpspec . position < position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position <= end ) {
length += otherOpspec . text . length
}
}
break ;
case "RemoveCursor" :
if ( otherOpspec . memberid === memberid ) {
result = [ ]
}
break ;
case "InsertTable" :
result = null ;
break
}
return result
} ;
this . execute = function ( odtDocument ) {
var cursor = odtDocument . getCursor ( memberid ) , oldPosition = odtDocument . getCursorPosition ( memberid ) , positionFilter = odtDocument . getPositionFilter ( ) , number = position - oldPosition , stepsToSelectionStart , stepsToSelectionEnd , stepCounter ;
if ( ! cursor ) {
return false
}
stepCounter = cursor . getStepCounter ( ) ;
stepsToSelectionStart = countSteps ( number , stepCounter , positionFilter ) ;
cursor . move ( stepsToSelectionStart ) ;
if ( length ) {
stepsToSelectionEnd = countSteps ( length , stepCounter , positionFilter ) ;
cursor . move ( stepsToSelectionEnd , true )
}
odtDocument . emit ( ops . OdtDocument . signalCursorMoved , cursor ) ;
return true
} ;
this . spec = function ( ) {
return { optype : "MoveCursor" , memberid : memberid , timestamp : timestamp , position : position , length : length }
}
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpInsertTable = function OpInsertTable ( ) {
var self = this , optype = "InsertTable" , memberid , timestamp , initialRows , initialColumns , position , tableName , tableStyleName , tableColumnStyleName , tableCellStyleMatrix , tablens = "urn:oasis:names:tc:opendocument:xmlns:table:1.0" , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
initialRows = parseInt ( data . initialRows , 10 ) ;
initialColumns = parseInt ( data . initialColumns , 10 ) ;
tableName = data . tableName ;
tableStyleName = data . tableStyleName ;
tableColumnStyleName = data . tableColumnStyleName ;
tableCellStyleMatrix = data . tableCellStyleMatrix
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , result = [ self ] ;
switch ( otherOptype ) {
case optype :
result = null ;
break ;
case "AddAnnotation" :
if ( otherOpspec . position < position ) {
position += 1
}
break ;
case "SplitParagraph" :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += 1 ;
result = null
}
}
break ;
case "InsertText" :
if ( otherOpspec . position < position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += otherOpspec . text . length ;
result = null
}
}
break ;
case "RemoveText" :
if ( otherOpspec . position + otherOpspec . length <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < position ) {
position = otherOpspec . position
}
}
break
}
return result
} ;
function getCellStyleName ( row , column ) {
var rowStyles ;
if ( tableCellStyleMatrix . length === 1 ) {
rowStyles = tableCellStyleMatrix [ 0 ]
} else {
if ( tableCellStyleMatrix . length === 3 ) {
switch ( row ) {
case 0 :
rowStyles = tableCellStyleMatrix [ 0 ] ;
break ;
case initialRows - 1 :
rowStyles = tableCellStyleMatrix [ 2 ] ;
break ;
default :
rowStyles = tableCellStyleMatrix [ 1 ] ;
break
}
} else {
rowStyles = tableCellStyleMatrix [ row ]
}
}
if ( rowStyles . length === 1 ) {
return rowStyles [ 0 ]
}
if ( rowStyles . length === 3 ) {
switch ( column ) {
case 0 :
return rowStyles [ 0 ] ;
case initialColumns - 1 :
return rowStyles [ 2 ] ;
default :
return rowStyles [ 1 ]
}
}
return rowStyles [ column ]
}
function createTableNode ( document ) {
var tableNode = document . createElementNS ( tablens , "table:table" ) , columns = document . createElementNS ( tablens , "table:table-column" ) , row , cell , paragraph , rowCounter , columnCounter , cellStyleName ;
if ( tableStyleName ) {
tableNode . setAttributeNS ( tablens , "table:style-name" , tableStyleName )
}
if ( tableName ) {
tableNode . setAttributeNS ( tablens , "table:name" , tableName )
}
columns . setAttributeNS ( tablens , "table:number-columns-repeated" , initialColumns ) ;
if ( tableColumnStyleName ) {
columns . setAttributeNS ( tablens , "table:style-name" , tableColumnStyleName )
}
tableNode . appendChild ( columns ) ;
for ( rowCounter = 0 ; rowCounter < initialRows ; rowCounter += 1 ) {
row = document . createElementNS ( tablens , "table:table-row" ) ;
for ( columnCounter = 0 ; columnCounter < initialColumns ; columnCounter += 1 ) {
cell = document . createElementNS ( tablens , "table:table-cell" ) ;
cellStyleName = getCellStyleName ( rowCounter , columnCounter ) ;
if ( cellStyleName ) {
cell . setAttributeNS ( tablens , "table:style-name" , cellStyleName )
}
paragraph = document . createElementNS ( textns , "text:p" ) ;
cell . appendChild ( paragraph ) ;
row . appendChild ( cell )
}
tableNode . appendChild ( row )
}
return tableNode
}
this . execute = function ( odtDocument ) {
var domPosition = odtDocument . getPositionInTextNode ( position ) , rootNode = odtDocument . getRootNode ( ) , previousSibling , tableNode ;
if ( domPosition ) {
tableNode = createTableNode ( odtDocument . getDOM ( ) ) ;
previousSibling = odtDocument . getParagraphElement ( domPosition . textNode ) ;
rootNode . insertBefore ( tableNode , previousSibling ? previousSibling . nextSibling : undefined ) ;
odtDocument . getOdfCanvas ( ) . refreshSize ( ) ;
odtDocument . emit ( ops . OdtDocument . signalTableAdded , { tableElement : tableNode , memberId : memberid , timeStamp : timestamp } ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
}
return false
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position , initialRows : initialRows , initialColumns : initialColumns , tableName : tableName , tableStyleName : tableStyleName , tableColumnStyleName : tableColumnStyleName , tableCellStyleMatrix : tableCellStyleMatrix }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpInsertText = function OpInsertText ( ) {
var self = this , optype = "InsertText" , memberid , timestamp , position , text ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
text = data . text
} ;
this . merge = function ( otherOpspec ) {
if ( otherOpspec . optype === optype && otherOpspec . memberid === memberid && otherOpspec . position === position + text . length ) {
text = text + otherOpspec . text ;
timestamp = otherOpspec . timestamp ;
return true
}
return false
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , result = [ self ] ;
switch ( otherOptype ) {
case optype :
if ( otherOpspec . position < position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += otherOpspec . text . length ;
result = null
}
}
break ;
case "AddAnnotation" :
if ( otherOpspec . position < position ) {
position += 1
}
break ;
case "SplitParagraph" :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += 1 ;
result = null
}
}
break ;
case "InsertTable" :
result = null ;
break ;
case "RemoveText" :
if ( otherOpspec . position + otherOpspec . length <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < position ) {
position = otherOpspec . position
}
}
break
}
return result
} ;
function triggerLayoutInWebkit ( odtDocument , textNode ) {
var parent = textNode . parentNode , next = textNode . nextSibling , impactedCursors = [ ] ;
odtDocument . getCursors ( ) . forEach ( function ( cursor ) {
var range = cursor . getSelectedRange ( ) ;
if ( range && ( range . startContainer === textNode || range . endContainer === textNode ) ) {
impactedCursors . push ( { cursor : cursor , startContainer : range . startContainer , startOffset : range . startOffset , endContainer : range . endContainer , endOffset : range . endOffset } )
}
} ) ;
parent . removeChild ( textNode ) ;
parent . insertBefore ( textNode , next ) ;
impactedCursors . forEach ( function ( entry ) {
var range = entry . cursor . getSelectedRange ( ) ;
range . setStart ( entry . startContainer , entry . startOffset ) ;
range . setEnd ( entry . endContainer , entry . endOffset )
} )
}
this . execute = function ( odtDocument ) {
var domPosition , previousNode , parent , refNode , ownerDocument = odtDocument . getDOM ( ) , paragraphElement , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" , space = " " , tab = "\t" , append = true , startIndex = 0 , textToInsert , spaceTag , node , i ;
domPosition = odtDocument . getPositionInTextNode ( position , memberid ) ;
if ( domPosition ) {
previousNode = domPosition . textNode ;
parent = previousNode . parentNode ;
refNode = previousNode . nextSibling ;
paragraphElement = odtDocument . getParagraphElement ( previousNode ) ;
if ( domPosition . offset !== previousNode . length ) {
refNode = previousNode . splitText ( domPosition . offset )
}
for ( i = 0 ; i < text . length ; i += 1 ) {
if ( text [ i ] === space || text [ i ] === tab ) {
if ( startIndex < i ) {
textToInsert = text . substring ( startIndex , i ) ;
if ( append ) {
previousNode . appendData ( textToInsert )
} else {
parent . insertBefore ( ownerDocument . createTextNode ( textToInsert ) , refNode )
}
}
startIndex = i + 1 ;
append = false ;
spaceTag = text [ i ] === space ? "text:s" : "text:tab" ;
node = ownerDocument . createElementNS ( textns , spaceTag ) ;
node . appendChild ( ownerDocument . createTextNode ( text [ i ] ) ) ;
parent . insertBefore ( node , refNode )
}
}
textToInsert = text . substring ( startIndex ) ;
if ( textToInsert . length > 0 ) {
if ( append ) {
previousNode . appendData ( textToInsert )
} else {
parent . insertBefore ( ownerDocument . createTextNode ( textToInsert ) , refNode )
}
}
triggerLayoutInWebkit ( odtDocument , previousNode ) ;
if ( previousNode . length === 0 ) {
previousNode . parentNode . removeChild ( previousNode )
}
odtDocument . getOdfCanvas ( ) . refreshSize ( ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : paragraphElement , memberId : memberid , timeStamp : timestamp } ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
}
return false
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position , text : text }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "core.DomUtils" ) ;
ops . OpRemoveText = function OpRemoveText ( ) {
var self = this , optype = "RemoveText" , memberid , timestamp , position , length , odfUtils , domUtils , editinfons = "urn:webodf:names:editinfo" ;
this . init = function ( data ) {
runtime . assert ( data . length >= 0 , "OpRemoveText only supports positive lengths" ) ;
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
length = parseInt ( data . length , 10 ) ;
odfUtils = new odf . OdfUtils ;
domUtils = new core . DomUtils
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , end = position + length , otherOpspecEnd , helperOp , result = [ self ] ;
switch ( otherOptype ) {
case optype :
otherOpspecEnd = otherOpspec . position + otherOpspec . length ;
if ( otherOpspecEnd <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < end ) {
if ( position < otherOpspec . position ) {
if ( otherOpspecEnd < end ) {
length = length - otherOpspec . length
} else {
length = otherOpspec . position - position
}
} else {
if ( otherOpspecEnd < end ) {
position = otherOpspec . position ;
length = end - otherOpspecEnd
} else {
result = [ ]
}
}
}
}
break ;
case "InsertText" :
if ( otherOpspec . position <= position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position < end ) {
length = otherOpspec . position - position ;
helperOp = new ops . OpRemoveText ;
helperOp . init ( { memberid : memberid , timestamp : timestamp , position : otherOpspec . position + otherOpspec . text . length , length : end - otherOpspec . position } ) ;
result = [ helperOp , self ]
}
}
break ;
case "SplitParagraph" :
if ( otherOpspec . position <= position ) {
position += 1
} else {
if ( otherOpspec . position < end ) {
length = otherOpspec . position - position ;
helperOp = new ops . OpRemoveText ;
helperOp . init ( { memberid : memberid , timestamp : timestamp , position : otherOpspec . position + 1 , length : end - otherOpspec . position } ) ;
result = [ helperOp , self ]
}
}
break ;
case "InsertTable" :
result = null ;
break ;
case "AddAnnotation" :
;
case "RemoveAnnotation" :
result = null ;
break ;
case "ApplyDirectStyling" :
result = null ;
break
}
return result
} ;
function CollapsingRules ( rootNode ) {
function isEmpty ( node ) {
var childNode ;
if ( odfUtils . isCharacterElement ( node ) ) {
return false
}
if ( node . nodeType === Node . TEXT _NODE ) {
return node . textContent . length === 0
}
childNode = node . firstChild ;
while ( childNode ) {
if ( ! isEmpty ( childNode ) ) {
return false
}
childNode = childNode . nextSibling
}
return true
}
this . isEmpty = isEmpty ;
function isCollapsibleContainer ( node ) {
return ! odfUtils . isParagraph ( node ) && node !== rootNode && isEmpty ( node )
}
function mergeChildrenIntoParent ( node ) {
var parent = domUtils . mergeIntoParent ( node ) ;
if ( isCollapsibleContainer ( parent ) ) {
return mergeChildrenIntoParent ( parent )
}
return parent
}
this . mergeChildrenIntoParent = mergeChildrenIntoParent
}
function mergeParagraphs ( first , second , collapseRules ) {
var child , mergeForward , destination = first , source = second , secondParent , insertionPoint ;
if ( collapseRules . isEmpty ( first ) ) {
mergeForward = true ;
if ( second . parentNode !== first . parentNode ) {
secondParent = second . parentNode ;
first . parentNode . insertBefore ( second , first . nextSibling )
}
source = first ;
destination = second ;
insertionPoint = destination . getElementsByTagNameNS ( editinfons , "editinfo" ) [ 0 ] || destination . firstChild
}
while ( source . hasChildNodes ( ) ) {
child = mergeForward ? source . lastChild : source . firstChild ;
source . removeChild ( child ) ;
if ( child . localName !== "editinfo" ) {
destination . insertBefore ( child , insertionPoint )
}
}
if ( secondParent && collapseRules . isEmpty ( secondParent ) ) {
collapseRules . mergeChildrenIntoParent ( secondParent )
}
collapseRules . mergeChildrenIntoParent ( source ) ;
return destination
}
function stepsToRange ( odtDocument ) {
var iterator , filter = odtDocument . getPositionFilter ( ) , startContainer , startOffset , endContainer , endOffset , remainingLength = length , range = odtDocument . getDOM ( ) . createRange ( ) ;
iterator = odtDocument . getIteratorAtPosition ( position ) ;
startContainer = iterator . container ( ) ;
startOffset = iterator . unfilteredDomOffset ( ) ;
while ( remainingLength && iterator . nextPosition ( ) ) {
endContainer = iterator . container ( ) ;
endOffset = iterator . unfilteredDomOffset ( ) ;
if ( filter . acceptPosition ( iterator ) === NodeFilter . FILTER _ACCEPT ) {
remainingLength -= 1
}
}
range . setStart ( startContainer , startOffset ) ;
range . setEnd ( endContainer , endOffset ) ;
domUtils . splitBoundaries ( range ) ;
return range
}
this . execute = function ( odtDocument ) {
var paragraphElement , destinationParagraph , range , textNodes , paragraphs , collapseRules = new CollapsingRules ( odtDocument . getRootNode ( ) ) ;
odtDocument . upgradeWhitespacesAtPosition ( position ) ;
odtDocument . upgradeWhitespacesAtPosition ( position + length ) ;
range = stepsToRange ( odtDocument ) ;
paragraphElement = odtDocument . getParagraphElement ( range . startContainer ) ;
textNodes = odtDocument . getTextElements ( range , true ) ;
paragraphs = odtDocument . getParagraphElements ( range ) ;
range . detach ( ) ;
textNodes . forEach ( function ( element ) {
collapseRules . mergeChildrenIntoParent ( element )
} ) ;
destinationParagraph = paragraphs . reduce ( function ( destination , paragraph ) {
return mergeParagraphs ( destination , paragraph , collapseRules )
} ) ;
odtDocument . fixCursorPositions ( ) ;
odtDocument . getOdfCanvas ( ) . refreshSize ( ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : destinationParagraph || paragraphElement , memberId : memberid , timeStamp : timestamp } ) ;
odtDocument . emit ( ops . OdtDocument . signalCursorMoved , odtDocument . getCursor ( memberid ) ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position , length : length }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpSplitParagraph = function OpSplitParagraph ( ) {
var self = this , optype = "SplitParagraph" , memberid , timestamp , position , odfUtils = new odf . OdfUtils ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 )
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , result = [ self ] ;
switch ( otherOptype ) {
case optype :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += 1 ;
result = null
}
}
break ;
case "AddAnnotation" :
if ( otherOpspec . position < position ) {
position += 1
}
break ;
case "InsertText" :
if ( otherOpspec . position < position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += otherOpspec . text . length ;
result = null
}
}
break ;
case "InsertTable" :
result = null ;
break ;
case "RemoveText" :
if ( otherOpspec . position + otherOpspec . length <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < position ) {
position = otherOpspec . position
}
}
break
}
return result
} ;
this . execute = function ( odtDocument ) {
var domPosition , paragraphNode , targetNode , node , splitNode , splitChildNode , keptChildNode ;
odtDocument . upgradeWhitespacesAtPosition ( position ) ;
domPosition = odtDocument . getPositionInTextNode ( position , memberid ) ;
if ( ! domPosition ) {
return false
}
paragraphNode = odtDocument . getParagraphElement ( domPosition . textNode ) ;
if ( ! paragraphNode ) {
return false
}
if ( odfUtils . isListItem ( paragraphNode . parentNode ) ) {
targetNode = paragraphNode . parentNode
} else {
targetNode = paragraphNode
}
if ( domPosition . offset === 0 ) {
keptChildNode = domPosition . textNode . previousSibling ;
splitChildNode = null
} else {
keptChildNode = domPosition . textNode ;
if ( domPosition . offset >= domPosition . textNode . length ) {
splitChildNode = null
} else {
splitChildNode = ( domPosition . textNode . splitText ( domPosition . offset ) )
}
}
node = domPosition . textNode ;
while ( node !== targetNode ) {
node = node . parentNode ;
splitNode = node . cloneNode ( false ) ;
if ( ! keptChildNode ) {
node . parentNode . insertBefore ( splitNode , node ) ;
keptChildNode = splitNode ;
splitChildNode = node
} else {
if ( splitChildNode ) {
splitNode . appendChild ( splitChildNode )
}
while ( keptChildNode . nextSibling ) {
splitNode . appendChild ( keptChildNode . nextSibling )
}
node . parentNode . insertBefore ( splitNode , node . nextSibling ) ;
keptChildNode = node ;
splitChildNode = splitNode
}
}
if ( odfUtils . isListItem ( splitChildNode ) ) {
splitChildNode = splitChildNode . childNodes [ 0 ]
}
odtDocument . fixCursorPositions ( memberid ) ;
odtDocument . getOdfCanvas ( ) . refreshSize ( ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : paragraphNode , memberId : memberid , timeStamp : timestamp } ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : splitChildNode , memberId : memberid , timeStamp : timestamp } ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpSetParagraphStyle = function OpSetParagraphStyle ( ) {
var self = this , optype = "SetParagraphStyle" , memberid , timestamp , position , styleName , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = data . position ;
styleName = data . styleName
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOpType = otherOpspec . optype , result = [ self ] ;
switch ( otherOpType ) {
case "RemoveParagraphStyle" :
if ( otherOpspec . styleName === styleName ) {
styleName = ""
}
break
}
return result
} ;
this . execute = function ( odtDocument ) {
var domPosition , paragraphNode ;
domPosition = odtDocument . getPositionInTextNode ( position ) ;
if ( domPosition ) {
paragraphNode = odtDocument . getParagraphElement ( domPosition . textNode ) ;
if ( paragraphNode ) {
if ( styleName !== "" ) {
paragraphNode . setAttributeNS ( textns , "text:style-name" , styleName )
} else {
paragraphNode . removeAttributeNS ( textns , "style-name" )
}
odtDocument . getOdfCanvas ( ) . refreshSize ( ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphChanged , { paragraphElement : paragraphNode , timeStamp : timestamp , memberId : memberid } ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
}
}
return false
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position , styleName : styleName }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpUpdateParagraphStyle = function OpUpdateParagraphStyle ( ) {
var self = this , optype = "UpdateParagraphStyle" , memberid , timestamp , styleName , setProperties , removedProperties , paragraphPropertiesName = "style:paragraph-properties" , textPropertiesName = "style:text-properties" , stylens = "urn:oasis:names:tc:opendocument:xmlns:style:1.0" , svgns = "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" ;
function removedAttributesFromStyleNode ( node , removedAttributeNames ) {
var i , attributeNameParts , attributeNameList = removedAttributeNames ? removedAttributeNames . split ( "," ) : [ ] ;
for ( i = 0 ; i < attributeNameList . length ; i += 1 ) {
attributeNameParts = attributeNameList [ i ] . split ( ":" ) ;
node . removeAttributeNS ( odf . Namespaces . resolvePrefix ( attributeNameParts [ 0 ] ) , attributeNameParts [ 1 ] )
}
}
function dropShadowedAttributes ( properties , removedProperties , shadowingProperties , shadowingRemovedProperties ) {
var value , i , name , removedPropertyNames , shadowingRemovedPropertyNames = shadowingRemovedProperties && shadowingRemovedProperties . attributes ? shadowingRemovedProperties . attributes . split ( "," ) : [ ] ;
if ( properties && ( shadowingProperties || shadowingRemovedPropertyNames . length > 0 ) ) {
Object . keys ( properties ) . forEach ( function ( key ) {
value = properties [ key ] ;
if ( shadowingProperties && shadowingProperties [ key ] !== undefined || shadowingRemovedPropertyNames && shadowingRemovedPropertyNames . indexOf ( key ) !== - 1 ) {
if ( typeof value !== "object" ) {
delete properties [ key ]
}
}
} )
}
if ( removedProperties && removedProperties . attributes && ( shadowingProperties || shadowingRemovedPropertyNames . length > 0 ) ) {
removedPropertyNames = removedProperties . attributes . split ( "," ) ;
for ( i = 0 ; i < removedPropertyNames . length ; i += 1 ) {
name = removedPropertyNames [ i ] ;
if ( shadowingProperties && shadowingProperties [ name ] !== undefined || shadowingRemovedPropertyNames && shadowingRemovedPropertyNames . indexOf ( name ) !== - 1 ) {
removedPropertyNames . splice ( i , 1 ) ;
i -= 1
}
}
if ( removedPropertyNames . length > 0 ) {
removedProperties . attributes = removedPropertyNames . join ( "," )
} else {
delete removedProperties . attributes
}
}
}
function hasProperties ( properties ) {
var key ;
for ( key in properties ) {
if ( properties . hasOwnProperty ( key ) ) {
return true
}
}
return false
}
function hasRemovedProperties ( properties ) {
var key ;
for ( key in properties ) {
if ( properties . hasOwnProperty ( key ) ) {
if ( key !== "attributes" || properties . attributes . length > 0 ) {
return true
}
}
}
return false
}
function dropShadowedProperties ( otherOpspec , propertiesName ) {
var sp = setProperties ? setProperties [ propertiesName ] : null , rp = removedProperties ? removedProperties [ propertiesName ] : null ;
dropShadowedAttributes ( sp , rp , otherOpspec . setProperties ? otherOpspec . setProperties [ propertiesName ] : null , otherOpspec . removedProperties ? otherOpspec . removedProperties [ propertiesName ] : null ) ;
if ( sp && ! hasProperties ( sp ) ) {
delete setProperties [ propertiesName ]
}
if ( rp && ! hasRemovedProperties ( rp ) ) {
delete removedProperties [ propertiesName ]
}
}
function dropStyleReferencingAttributes ( deletedStyleName ) {
if ( setProperties ) {
[ "style:parent-style-name" , "style:next-style-name" ] . forEach ( function ( attributeName ) {
if ( setProperties [ attributeName ] === deletedStyleName ) {
delete setProperties [ attributeName ]
}
} )
}
}
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
styleName = data . styleName ;
setProperties = data . setProperties ;
removedProperties = data . removedProperties
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOpType = otherOpspec . optype , result = [ self ] ;
switch ( otherOpType ) {
case optype :
if ( otherOpspec . styleName === styleName ) {
if ( ! hasPriority ) {
dropShadowedProperties ( otherOpspec , paragraphPropertiesName ) ;
dropShadowedProperties ( otherOpspec , textPropertiesName ) ;
dropShadowedAttributes ( setProperties || null , removedProperties || null , otherOpspec . setProperties || null , otherOpspec . removedProperties || null ) ;
if ( ! ( setProperties && hasProperties ( setProperties ) ) && ! ( removedProperties && hasRemovedProperties ( removedProperties ) ) ) {
result = [ ]
}
}
}
break ;
case "RemoveParagraphStyle" :
if ( otherOpspec . styleName === styleName ) {
result = [ ]
} else {
dropStyleReferencingAttributes ( otherOpspec . styleName )
}
break
}
return result
} ;
this . execute = function ( odtDocument ) {
var formatting = odtDocument . getFormatting ( ) , dom = odtDocument . getDOM ( ) , styleNode = dom . createElementNS ( stylens , "style:style" ) , paragraphPropertiesNode , textPropertiesNode , fontFaceNode , fontName , ns ;
styleNode = odtDocument . getParagraphStyleElement ( styleName ) ;
if ( styleNode ) {
paragraphPropertiesNode = styleNode . getElementsByTagNameNS ( stylens , "paragraph-properties" ) [ 0 ] ;
textPropertiesNode = styleNode . getElementsByTagNameNS ( stylens , "text-properties" ) [ 0 ] ;
if ( setProperties ) {
Object . keys ( setProperties ) . forEach ( function ( propertyName ) {
switch ( propertyName ) {
case paragraphPropertiesName :
if ( paragraphPropertiesNode === undefined ) {
paragraphPropertiesNode = dom . createElementNS ( stylens , paragraphPropertiesName ) ;
styleNode . appendChild ( paragraphPropertiesNode )
}
formatting . updateStyle ( paragraphPropertiesNode , setProperties [ paragraphPropertiesName ] ) ;
break ;
case textPropertiesName :
if ( textPropertiesNode === undefined ) {
textPropertiesNode = dom . createElementNS ( stylens , textPropertiesName ) ;
styleNode . appendChild ( textPropertiesNode )
}
fontName = setProperties [ textPropertiesName ] [ "style:font-name" ] ;
if ( fontName && ! formatting . getFontMap ( ) . hasOwnProperty ( fontName ) ) {
fontFaceNode = dom . createElementNS ( stylens , "style:font-face" ) ;
fontFaceNode . setAttributeNS ( stylens , "style:name" , fontName ) ;
fontFaceNode . setAttributeNS ( svgns , "svg:font-family" , fontName ) ;
odtDocument . getOdfCanvas ( ) . odfContainer ( ) . rootElement . fontFaceDecls . appendChild ( fontFaceNode )
}
formatting . updateStyle ( textPropertiesNode , setProperties [ textPropertiesName ] ) ;
break ;
default :
if ( typeof setProperties [ propertyName ] !== "object" ) {
ns = odf . Namespaces . resolvePrefix ( propertyName . substr ( 0 , propertyName . indexOf ( ":" ) ) ) ;
styleNode . setAttributeNS ( ns , propertyName , setProperties [ propertyName ] )
}
}
} )
}
if ( removedProperties ) {
if ( removedProperties [ paragraphPropertiesName ] ) {
removedAttributesFromStyleNode ( paragraphPropertiesNode , removedProperties [ paragraphPropertiesName ] . attributes ) ;
if ( paragraphPropertiesNode . attributes . length === 0 ) {
styleNode . removeChild ( paragraphPropertiesNode )
}
}
if ( removedProperties [ textPropertiesName ] ) {
removedAttributesFromStyleNode ( textPropertiesNode , removedProperties [ textPropertiesName ] . attributes ) ;
if ( textPropertiesNode . attributes . length === 0 ) {
styleNode . removeChild ( textPropertiesNode )
}
}
removedAttributesFromStyleNode ( styleNode , removedProperties . attributes )
}
odtDocument . getOdfCanvas ( ) . refreshCSS ( ) ;
odtDocument . emit ( ops . OdtDocument . signalParagraphStyleModified , styleName ) ;
odtDocument . getOdfCanvas ( ) . rerenderAnnotations ( ) ;
return true
}
return false
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , styleName : styleName , setProperties : setProperties , removedProperties : removedProperties }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.Namespaces" ) ;
ops . OpAddParagraphStyle = function OpAddParagraphStyle ( ) {
var self = this , memberid , timestamp , styleName , setProperties , paragraphPropertiesName = "style:paragraph-properties" , textPropertiesName = "style:text-properties" , svgns = odf . Namespaces . svgns , stylens = odf . Namespaces . stylens ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
styleName = data . styleName ;
setProperties = data . setProperties
} ;
function dropStyleReferencingAttributes ( deletedStyleName ) {
if ( setProperties ) {
[ "style:parent-style-name" , "style:next-style-name" ] . forEach ( function ( attributeName ) {
if ( setProperties [ attributeName ] === deletedStyleName ) {
delete setProperties [ attributeName ]
}
} )
}
}
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) ;
if ( otherOpspec . optype === "RemoveParagraphStyle" ) {
dropStyleReferencingAttributes ( otherOpspec . styleName )
}
return [ self ]
} ;
this . execute = function ( odtDocument ) {
var odfContainer = odtDocument . getOdfCanvas ( ) . odfContainer ( ) , formatting = odtDocument . getFormatting ( ) , dom = odtDocument . getDOM ( ) , styleNode = dom . createElementNS ( stylens , "style:style" ) , paragraphPropertiesNode , textPropertiesNode , fontFaceNode , fontName , ns ;
if ( ! styleNode ) {
return false
}
styleNode . setAttributeNS ( stylens , "style:family" , "paragraph" ) ;
styleNode . setAttributeNS ( stylens , "style:name" , styleName ) ;
if ( setProperties ) {
Object . keys ( setProperties ) . forEach ( function ( propertyName ) {
switch ( propertyName ) {
case paragraphPropertiesName :
paragraphPropertiesNode = dom . createElementNS ( stylens , paragraphPropertiesName ) ;
styleNode . appendChild ( paragraphPropertiesNode ) ;
formatting . updateStyle ( paragraphPropertiesNode , setProperties [ paragraphPropertiesName ] ) ;
break ;
case textPropertiesName :
textPropertiesNode = dom . createElementNS ( stylens , textPropertiesName ) ;
styleNode . appendChild ( textPropertiesNode ) ;
fontName = setProperties [ textPropertiesName ] [ "style:font-name" ] ;
if ( fontName && ! formatting . getFontMap ( ) . hasOwnProperty ( fontName ) ) {
fontFaceNode = dom . createElementNS ( stylens , "style:font-face" ) ;
fontFaceNode . setAttributeNS ( stylens , "style:name" , fontName ) ;
fontFaceNode . setAttributeNS ( svgns , "svg:font-family" , fontName ) ;
odfContainer . rootElement . fontFaceDecls . appendChild ( fontFaceNode )
}
formatting . updateStyle ( textPropertiesNode , setProperties [ textPropertiesName ] ) ;
break ;
default :
if ( typeof setProperties [ propertyName ] !== "object" ) {
ns = odf . Namespaces . resolvePrefix ( propertyName . substr ( 0 , propertyName . indexOf ( ":" ) ) ) ;
styleNode . setAttributeNS ( ns , propertyName , setProperties [ propertyName ] )
}
}
} )
}
odfContainer . rootElement . styles . appendChild ( styleNode ) ;
odtDocument . getOdfCanvas ( ) . refreshCSS ( ) ;
odtDocument . emit ( ops . OdtDocument . signalStyleCreated , styleName ) ;
return true
} ;
this . spec = function ( ) {
return { optype : "AddParagraphStyle" , memberid : memberid , timestamp : timestamp , styleName : styleName , setProperties : setProperties }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpRemoveParagraphStyle = function OpRemoveParagraphStyle ( ) {
var self = this , optype = "RemoveParagraphStyle" , memberid , timestamp , styleName ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
styleName = data . styleName
} ;
function getStyleReferencingAttributes ( setProperties ) {
var attributes = [ ] ;
if ( setProperties ) {
[ "style:parent-style-name" , "style:next-style-name" ] . forEach ( function ( attributeName ) {
if ( setProperties [ attributeName ] === styleName ) {
attributes . push ( attributeName )
}
} )
}
return attributes
}
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOpType = otherOpspec . optype , helperOp , setAttributes , result = [ self ] ;
switch ( otherOpType ) {
case optype :
if ( otherOpspec . styleName === styleName ) {
result = [ ]
}
break ;
case "AddParagraphStyle" :
;
case "UpdateParagraphStyle" :
setAttributes = getStyleReferencingAttributes ( otherOpspec . setProperties ) ;
if ( setAttributes . length > 0 ) {
helperOp = new ops . OpUpdateParagraphStyle ;
helperOp . init ( { styleName : otherOpspec . styleName , removedProperties : { attributes : setAttributes . join ( "," ) } } ) ;
result = [ helperOp , self ]
}
break ;
case "SetParagraphStyle" :
if ( otherOpspec . styleName === styleName ) {
otherOpspec . styleName = "" ;
helperOp = new ops . OpSetParagraphStyle ;
helperOp . init ( otherOpspec ) ;
result = [ helperOp , self ]
}
break
}
return result
} ;
this . execute = function ( odtDocument ) {
var styleNode = odtDocument . getParagraphStyleElement ( styleName ) ;
if ( ! styleNode ) {
return false
}
styleNode . parentNode . removeChild ( styleNode ) ;
odtDocument . getOdfCanvas ( ) . refreshCSS ( ) ;
odtDocument . emit ( ops . OdtDocument . signalStyleDeleted , styleName ) ;
return true
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , styleName : styleName }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OpAddAnnotation = function OpAddAnnotation ( ) {
var self = this , optype = "AddAnnotation" , memberid , timestamp , position , length , name ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = parseInt ( data . timestamp , 10 ) ;
position = parseInt ( data . position , 10 ) ;
length = parseInt ( data . length , 10 ) || 0 ;
name = data . name
} ;
this . transform = function ( otherOp , hasPriority ) {
var otherOpspec = otherOp . spec ( ) , otherOptype = otherOpspec . optype , end = position + length , result = [ self ] ;
switch ( otherOptype ) {
case optype :
if ( otherOpspec . position < position ) {
position += 1
} else {
if ( otherOpspec . position === position && ! hasPriority ) {
position += 1 ;
result = null
}
}
break ;
case "InsertText" :
if ( otherOpspec . position <= position ) {
position += otherOpspec . text . length
} else {
if ( otherOpspec . position <= end ) {
length += otherOpspec . text . length
}
}
break ;
case "SplitParagraph" :
if ( otherOpspec . position <= position ) {
position += 1
} else {
if ( otherOpspec . position <= end ) {
length += 1
}
}
break ;
case "InsertTable" :
result = null ;
break ;
case "RemoveText" :
if ( otherOpspec . position + otherOpspec . length <= position ) {
position -= otherOpspec . length
} else {
if ( otherOpspec . position < position ) {
position = otherOpspec . position
}
}
break
}
return result
} ;
function createAnnotationNode ( odtDocument , date ) {
var annotationNode , creatorNode , dateNode , listNode , listItemNode , paragraphNode , doc = odtDocument . getDOM ( ) ;
annotationNode = doc . createElementNS ( odf . Namespaces . officens , "office:annotation" ) ;
annotationNode . setAttributeNS ( odf . Namespaces . officens , "office:name" , name ) ;
creatorNode = doc . createElementNS ( odf . Namespaces . dcns , "dc:creator" ) ;
creatorNode . setAttributeNS ( odf . Namespaces . webodfns + ":names:editinfo" , "editinfo:memberid" , memberid ) ;
dateNode = doc . createElementNS ( odf . Namespaces . dcns , "dc:date" ) ;
dateNode . appendChild ( doc . createTextNode ( date . toISOString ( ) ) ) ;
listNode = doc . createElementNS ( odf . Namespaces . textns , "text:list" ) ;
listItemNode = doc . createElementNS ( odf . Namespaces . textns , "text:list-item" ) ;
paragraphNode = doc . createElementNS ( odf . Namespaces . textns , "text:p" ) ;
listItemNode . appendChild ( paragraphNode ) ;
listNode . appendChild ( listItemNode ) ;
annotationNode . appendChild ( creatorNode ) ;
annotationNode . appendChild ( dateNode ) ;
annotationNode . appendChild ( listNode ) ;
return annotationNode
}
function createAnnotationEnd ( odtDocument ) {
var annotationEnd , doc = odtDocument . getDOM ( ) ;
annotationEnd = doc . createElementNS ( odf . Namespaces . officens , "office:annotation-end" ) ;
annotationEnd . setAttributeNS ( odf . Namespaces . officens , "office:name" , name ) ;
return annotationEnd
}
function insertNodeAtPosition ( odtDocument , node , insertPosition ) {
var previousNode , domPosition = odtDocument . getPositionInTextNode ( insertPosition , memberid ) ;
if ( domPosition ) {
previousNode = domPosition . textNode ;
if ( domPosition . offset !== previousNode . length ) {
previousNode . splitText ( domPosition . offset )
}
previousNode . parentNode . insertBefore ( node , previousNode . nextSibling )
}
}
function countSteps ( number , stepCounter , positionFilter ) {
if ( number > 0 ) {
return stepCounter . countForwardSteps ( number , positionFilter )
}
if ( number < 0 ) {
return - stepCounter . countBackwardSteps ( - number , positionFilter )
}
return 0
}
this . execute = function ( odtDocument ) {
var annotation = { } , positionFilter = odtDocument . getPositionFilter ( ) , cursor = odtDocument . getCursor ( memberid ) , oldCursorPosition = odtDocument . getCursorPosition ( memberid ) , lengthToMove = position - oldCursorPosition - 1 , stepsToParagraph ;
annotation . node = createAnnotationNode ( odtDocument , new Date ( timestamp ) ) ;
if ( ! annotation . node ) {
return false
}
if ( length ) {
annotation . end = createAnnotationEnd ( odtDocument ) ;
if ( ! annotation . end ) {
return false
}
insertNodeAtPosition ( odtDocument , annotation . end , position + length )
}
insertNodeAtPosition ( odtDocument , annotation . node , position ) ;
if ( cursor ) {
stepsToParagraph = countSteps ( lengthToMove , cursor . getStepCounter ( ) , positionFilter ) ;
cursor . move ( stepsToParagraph ) ;
odtDocument . emit ( ops . OdtDocument . signalCursorMoved , cursor )
}
odtDocument . getOdfCanvas ( ) . addAnnotation ( annotation ) ;
return true
} ;
this . spec = function ( ) {
return { optype : optype , memberid : memberid , timestamp : timestamp , position : position , length : length , name : name }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "core.DomUtils" ) ;
ops . OpRemoveAnnotation = function OpRemoveAnnotation ( ) {
var memberid , timestamp , position , length , domUtils ;
this . init = function ( data ) {
memberid = data . memberid ;
timestamp = data . timestamp ;
position = parseInt ( data . position , 10 ) ;
length = parseInt ( data . length , 10 ) ;
domUtils = new core . DomUtils
} ;
this . transform = function ( otherOp , hasPriority ) {
return null
} ;
this . execute = function ( odtDocument ) {
var iterator = odtDocument . getIteratorAtPosition ( position ) , container = iterator . container ( ) , annotationName , annotationNode = null , annotationEnd = null , cursors ;
while ( ! ( container . namespaceURI === odf . Namespaces . officens && container . localName === "annotation" ) ) {
container = container . parentNode
}
if ( container === null ) {
return false
}
annotationNode = container ;
annotationName = annotationNode . getAttributeNS ( odf . Namespaces . officens , "name" ) ;
if ( annotationName ) {
annotationEnd = domUtils . getElementsByTagNameNS ( odtDocument . getRootNode ( ) , odf . Namespaces . officens , "annotation-end" ) . filter ( function ( element ) {
return annotationName === element . getAttributeNS ( odf . Namespaces . officens , "name" )
} ) [ 0 ] || null
}
odtDocument . getOdfCanvas ( ) . forgetAnnotations ( ) ;
cursors = domUtils . getElementsByTagNameNS ( annotationNode , odf . Namespaces . webodfns + ":names:cursor" , "cursor" ) ;
while ( cursors . length ) {
annotationNode . parentNode . insertBefore ( cursors . pop ( ) , annotationNode )
}
annotationNode . parentNode . removeChild ( annotationNode ) ;
if ( annotationEnd ) {
annotationEnd . parentNode . removeChild ( annotationEnd )
}
odtDocument . fixCursorPositions ( ) ;
odtDocument . getOdfCanvas ( ) . refreshAnnotations ( ) ;
return true
} ;
this . spec = function ( ) {
return { optype : "RemoveAnnotation" , memberid : memberid , timestamp : timestamp , position : position , length : length }
}
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "ops.OpAddCursor" ) ;
runtime . loadClass ( "ops.OpApplyDirectStyling" ) ;
runtime . loadClass ( "ops.OpRemoveCursor" ) ;
runtime . loadClass ( "ops.OpMoveCursor" ) ;
runtime . loadClass ( "ops.OpInsertTable" ) ;
runtime . loadClass ( "ops.OpInsertText" ) ;
runtime . loadClass ( "ops.OpRemoveText" ) ;
runtime . loadClass ( "ops.OpSplitParagraph" ) ;
runtime . loadClass ( "ops.OpSetParagraphStyle" ) ;
runtime . loadClass ( "ops.OpUpdateParagraphStyle" ) ;
runtime . loadClass ( "ops.OpAddParagraphStyle" ) ;
runtime . loadClass ( "ops.OpRemoveParagraphStyle" ) ;
runtime . loadClass ( "ops.OpAddAnnotation" ) ;
runtime . loadClass ( "ops.OpRemoveAnnotation" ) ;
ops . OperationFactory = function OperationFactory ( ) {
var specs ;
this . register = function ( specName , specConstructor ) {
specs [ specName ] = specConstructor
} ;
this . create = function ( spec ) {
var op = null , specConstructor = specs [ spec . optype ] ;
if ( specConstructor ) {
op = specConstructor ( spec ) ;
op . init ( spec )
}
return op
} ;
function constructor ( OperationType ) {
return function ( ) {
return new OperationType
}
}
function init ( ) {
specs = { AddCursor : constructor ( ops . OpAddCursor ) , ApplyDirectStyling : constructor ( ops . OpApplyDirectStyling ) , InsertTable : constructor ( ops . OpInsertTable ) , InsertText : constructor ( ops . OpInsertText ) , RemoveText : constructor ( ops . OpRemoveText ) , SplitParagraph : constructor ( ops . OpSplitParagraph ) , SetParagraphStyle : constructor ( ops . OpSetParagraphStyle ) , UpdateParagraphStyle : constructor ( ops . OpUpdateParagraphStyle ) , AddParagraphStyle : constructor ( ops . OpAddParagraphStyle ) , RemoveParagraphStyle : constructor ( ops . OpRemoveParagraphStyle ) ,
MoveCursor : constructor ( ops . OpMoveCursor ) , RemoveCursor : constructor ( ops . OpRemoveCursor ) , AddAnnotation : constructor ( ops . OpAddAnnotation ) , RemoveAnnotation : constructor ( ops . OpRemoveAnnotation ) }
}
init ( )
} ;
runtime . loadClass ( "core.Cursor" ) ;
runtime . loadClass ( "core.PositionIterator" ) ;
runtime . loadClass ( "core.PositionFilter" ) ;
runtime . loadClass ( "core.LoopWatchDog" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
gui . SelectionMover = function SelectionMover ( cursor , rootNode ) {
var odfUtils , positionIterator , cachedXOffset , timeoutHandle , FILTER _ACCEPT = core . PositionFilter . FilterResult . FILTER _ACCEPT ;
function getIteratorAtCursor ( ) {
positionIterator . setUnfilteredPosition ( cursor . getNode ( ) , 0 ) ;
return positionIterator
}
function getMaximumNodePosition ( node ) {
return node . nodeType === Node . TEXT _NODE ? node . textContent . length : node . childNodes . length
}
function getClientRect ( clientRectangles , useRightEdge ) {
var rectangle , simplifiedRectangle = null ;
if ( clientRectangles ) {
rectangle = useRightEdge ? clientRectangles [ clientRectangles . length - 1 ] : clientRectangles [ 0 ]
}
if ( rectangle ) {
simplifiedRectangle = { top : rectangle . top , left : useRightEdge ? rectangle . right : rectangle . left , bottom : rectangle . bottom }
}
return simplifiedRectangle
}
function getVisibleRect ( container , offset , range , useRightEdge ) {
var rectangle , nodeType = container . nodeType ;
range . setStart ( container , offset ) ;
range . collapse ( ! useRightEdge ) ;
rectangle = getClientRect ( range . getClientRects ( ) , useRightEdge === true ) ;
if ( ! rectangle && offset > 0 ) {
range . setStart ( container , offset - 1 ) ;
range . setEnd ( container , offset ) ;
rectangle = getClientRect ( range . getClientRects ( ) , true )
}
if ( ! rectangle ) {
if ( nodeType === Node . ELEMENT _NODE && container . childNodes [ offset - 1 ] ) {
rectangle = getVisibleRect ( container , offset - 1 , range , true )
} else {
if ( container . nodeType === Node . TEXT _NODE && offset > 0 ) {
rectangle = getVisibleRect ( container , offset - 1 , range , true )
} else {
if ( container . previousSibling ) {
rectangle = getVisibleRect ( container . previousSibling , getMaximumNodePosition ( container . previousSibling ) , range , true )
} else {
if ( container . parentNode && container . parentNode !== rootNode ) {
rectangle = getVisibleRect ( container . parentNode , 0 , range , false )
} else {
range . selectNode ( rootNode ) ;
rectangle = getClientRect ( range . getClientRects ( ) , false )
}
}
}
}
}
runtime . assert ( Boolean ( rectangle ) , "No visible rectangle found" ) ;
return ( rectangle )
}
function doMove ( steps , extend , move ) {
var left = steps , iterator = getIteratorAtCursor ( ) , initialRect , range = ( rootNode . ownerDocument . createRange ( ) ) , selectionRange = cursor . getSelectedRange ( ) ? cursor . getSelectedRange ( ) . cloneRange ( ) : rootNode . ownerDocument . createRange ( ) , newRect , horizontalMovement , o , c , isForwardSelection , window = runtime . getWindow ( ) ;
initialRect = getVisibleRect ( iterator . container ( ) , iterator . unfilteredDomOffset ( ) , range ) ;
while ( left > 0 && move ( ) ) {
left -= 1
}
if ( extend ) {
c = iterator . container ( ) ;
o = iterator . unfilteredDomOffset ( ) ;
if ( selectionRange . comparePoint ( c , o ) === - 1 ) {
selectionRange . setStart ( c , o ) ;
isForwardSelection = false
} else {
selectionRange . setEnd ( c , o )
}
} else {
selectionRange . setStart ( iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
selectionRange . collapse ( true )
}
cursor . setSelectedRange ( selectionRange , isForwardSelection ) ;
iterator = getIteratorAtCursor ( ) ;
newRect = getVisibleRect ( iterator . container ( ) , iterator . unfilteredDomOffset ( ) , range ) ;
horizontalMovement = newRect . top === initialRect . top ? true : false ;
if ( horizontalMovement || cachedXOffset === undefined ) {
cachedXOffset = newRect . left
}
window . clearTimeout ( timeoutHandle ) ;
timeoutHandle = window . setTimeout ( function ( ) {
cachedXOffset = undefined
} , 2E3 ) ;
range . detach ( ) ;
return steps - left
}
this . movePointForward = function ( steps , extend ) {
return doMove ( steps , extend , positionIterator . nextPosition )
} ;
this . movePointBackward = function ( steps , extend ) {
return doMove ( steps , extend , positionIterator . previousPosition )
} ;
function isPositionWalkable ( filter ) {
var iterator = getIteratorAtCursor ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
return true
}
return false
}
function countForwardSteps ( steps , filter ) {
var iterator = getIteratorAtCursor ( ) , watch = new core . LoopWatchDog ( 1E3 ) , stepCount = 0 , count = 0 ;
while ( steps > 0 && iterator . nextPosition ( ) ) {
stepCount += 1 ;
watch . check ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
count += stepCount ;
stepCount = 0 ;
steps -= 1
}
}
return count
}
function convertForwardStepsBetweenFilters ( steps , filter1 , filter2 ) {
var iterator = getIteratorAtCursor ( ) , watch = new core . LoopWatchDog ( 1E3 ) , stepCount = 0 , count = 0 ;
while ( steps > 0 && iterator . nextPosition ( ) ) {
watch . check ( ) ;
if ( filter2 . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
stepCount += 1 ;
if ( filter1 . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
count += stepCount ;
stepCount = 0 ;
steps -= 1
}
}
}
return count
}
function convertBackwardStepsBetweenFilters ( steps , filter1 , filter2 ) {
var iterator = getIteratorAtCursor ( ) , watch = new core . LoopWatchDog ( 1E3 ) , stepCount = 0 , count = 0 ;
while ( steps > 0 && iterator . previousPosition ( ) ) {
watch . check ( ) ;
if ( filter2 . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
stepCount += 1 ;
if ( filter1 . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
count += stepCount ;
stepCount = 0 ;
steps -= 1
}
}
}
return count
}
function countBackwardSteps ( steps , filter ) {
var iterator = getIteratorAtCursor ( ) , watch = new core . LoopWatchDog ( 1E3 ) , stepCount = 0 , count = 0 ;
while ( steps > 0 && iterator . previousPosition ( ) ) {
stepCount += 1 ;
watch . check ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
count += stepCount ;
stepCount = 0 ;
steps -= 1
}
}
return count
}
function countStepsToValidPosition ( filter ) {
var iterator = getIteratorAtCursor ( ) , paragraphNode = odfUtils . getParagraphElement ( iterator . getCurrentNode ( ) ) , count ;
count = - countBackwardSteps ( 1 , filter ) ;
if ( count === 0 || paragraphNode && paragraphNode !== odfUtils . getParagraphElement ( iterator . getCurrentNode ( ) ) ) {
count = countForwardSteps ( 1 , filter )
}
return count
}
function countLineSteps ( filter , direction , iterator ) {
var c = iterator . container ( ) , count = 0 , bestContainer = null , bestOffset , bestXDiff = 10 , xDiff , bestCount = 0 , top , left , lastTop , rect , range = ( rootNode . ownerDocument . createRange ( ) ) , watch = new core . LoopWatchDog ( 1E3 ) ;
rect = getVisibleRect ( c , iterator . unfilteredDomOffset ( ) , range ) ;
top = rect . top ;
if ( cachedXOffset === undefined ) {
left = rect . left
} else {
left = cachedXOffset
}
lastTop = top ;
while ( ( direction < 0 ? iterator . previousPosition ( ) : iterator . nextPosition ( ) ) === true ) {
watch . check ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
count += 1 ;
c = iterator . container ( ) ;
rect = getVisibleRect ( c , iterator . unfilteredDomOffset ( ) , range ) ;
if ( rect . top !== top ) {
if ( rect . top !== lastTop && lastTop !== top ) {
break
}
lastTop = rect . top ;
xDiff = Math . abs ( left - rect . left ) ;
if ( bestContainer === null || xDiff < bestXDiff ) {
bestContainer = c ;
bestOffset = iterator . unfilteredDomOffset ( ) ;
bestXDiff = xDiff ;
bestCount = count
}
}
}
}
if ( bestContainer !== null ) {
iterator . setUnfilteredPosition ( bestContainer , ( bestOffset ) ) ;
count = bestCount
} else {
count = 0
}
range . detach ( ) ;
return count
}
function countLinesSteps ( lines , filter ) {
var iterator = getIteratorAtCursor ( ) , stepCount = 0 , count = 0 , direction = lines < 0 ? - 1 : 1 ;
lines = Math . abs ( lines ) ;
while ( lines > 0 ) {
stepCount += countLineSteps ( filter , direction , iterator ) ;
if ( stepCount === 0 ) {
break
}
count += stepCount ;
lines -= 1
}
return count * direction
}
function countStepsToLineBoundary ( direction , filter ) {
var fnNextPos , increment , lastRect , rect , onSameLine , iterator = getIteratorAtCursor ( ) , paragraphNode = odfUtils . getParagraphElement ( iterator . getCurrentNode ( ) ) , count = 0 , range = ( rootNode . ownerDocument . createRange ( ) ) ;
if ( direction < 0 ) {
fnNextPos = iterator . previousPosition ;
increment = - 1
} else {
fnNextPos = iterator . nextPosition ;
increment = 1
}
lastRect = getVisibleRect ( iterator . container ( ) , iterator . unfilteredDomOffset ( ) , range ) ;
while ( fnNextPos . call ( iterator ) ) {
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
if ( odfUtils . getParagraphElement ( iterator . getCurrentNode ( ) ) !== paragraphNode ) {
break
}
rect = getVisibleRect ( iterator . container ( ) , iterator . unfilteredDomOffset ( ) , range ) ;
if ( rect . bottom !== lastRect . bottom ) {
onSameLine = rect . top >= lastRect . top && rect . bottom < lastRect . bottom || rect . top <= lastRect . top && rect . bottom > lastRect . bottom ;
if ( ! onSameLine ) {
break
}
}
count += increment ;
lastRect = rect
}
}
range . detach ( ) ;
return count
}
function getPositionInContainingNode ( node , container ) {
var offset = 0 , n ;
while ( node . parentNode !== container ) {
runtime . assert ( node . parentNode !== null , "parent is null" ) ;
node = ( node . parentNode )
}
n = container . firstChild ;
while ( n !== node ) {
offset += 1 ;
n = n . nextSibling
}
return offset
}
function comparePoints ( c1 , o1 , c2 , o2 ) {
if ( c1 === c2 ) {
return o2 - o1
}
var comparison = c1 . compareDocumentPosition ( c2 ) ;
if ( comparison === 2 ) {
comparison = - 1
} else {
if ( comparison === 4 ) {
comparison = 1
} else {
if ( comparison === 10 ) {
o1 = getPositionInContainingNode ( c1 , c2 ) ;
comparison = o1 < o2 ? 1 : - 1
} else {
o2 = getPositionInContainingNode ( c2 , c1 ) ;
comparison = o2 < o1 ? - 1 : 1
}
}
}
return comparison
}
function countStepsToPosition ( posElement , posOffset , filter ) {
runtime . assert ( posElement !== null , "SelectionMover.countStepsToPosition called with element===null" ) ;
var iterator = getIteratorAtCursor ( ) , c = iterator . container ( ) , o = iterator . unfilteredDomOffset ( ) , steps = 0 , watch = new core . LoopWatchDog ( 1E3 ) , comparison ;
iterator . setUnfilteredPosition ( posElement , posOffset ) ;
posElement = ( iterator . container ( ) ) ;
runtime . assert ( Boolean ( posElement ) , "SelectionMover.countStepsToPosition: positionIterator.container() returned null" ) ;
posOffset = iterator . unfilteredDomOffset ( ) ;
iterator . setUnfilteredPosition ( c , o ) ;
comparison = comparePoints ( posElement , posOffset , iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
if ( comparison < 0 ) {
while ( iterator . nextPosition ( ) ) {
watch . check ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
steps += 1
}
if ( iterator . container ( ) === posElement ) {
if ( iterator . unfilteredDomOffset ( ) === posOffset ) {
return steps
}
}
}
} else {
if ( comparison > 0 ) {
while ( iterator . previousPosition ( ) ) {
watch . check ( ) ;
if ( filter . acceptPosition ( iterator ) === FILTER _ACCEPT ) {
steps -= 1
}
if ( iterator . container ( ) === posElement ) {
if ( iterator . unfilteredDomOffset ( ) === posOffset ) {
return steps
}
}
}
}
}
return steps
}
this . getStepCounter = function ( ) {
return { countForwardSteps : countForwardSteps , countBackwardSteps : countBackwardSteps , convertForwardStepsBetweenFilters : convertForwardStepsBetweenFilters , convertBackwardStepsBetweenFilters : convertBackwardStepsBetweenFilters , countLinesSteps : countLinesSteps , countStepsToLineBoundary : countStepsToLineBoundary , countStepsToPosition : countStepsToPosition , isPositionWalkable : isPositionWalkable , countStepsToValidPosition : countStepsToValidPosition }
} ;
function init ( ) {
odfUtils = new odf . OdfUtils ;
positionIterator = gui . SelectionMover . createPositionIterator ( rootNode ) ;
var range = rootNode . ownerDocument . createRange ( ) ;
range . setStart ( positionIterator . container ( ) , positionIterator . unfilteredDomOffset ( ) ) ;
range . collapse ( true ) ;
cursor . setSelectedRange ( range )
}
init ( )
} ;
gui . SelectionMover . createPositionIterator = function ( rootNode ) {
function CursorFilter ( ) {
this . acceptNode = function ( node ) {
if ( node . namespaceURI === "urn:webodf:names:cursor" || node . namespaceURI === "urn:webodf:names:editinfo" ) {
return NodeFilter . FILTER _REJECT
}
return NodeFilter . FILTER _ACCEPT
}
}
var filter = new CursorFilter ;
return new core . PositionIterator ( rootNode , 5 , filter , false )
} ;
( function ( ) {
return gui . SelectionMover
} ) ( ) ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "ops.OpAddCursor" ) ;
runtime . loadClass ( "ops.OpRemoveCursor" ) ;
runtime . loadClass ( "ops.OpMoveCursor" ) ;
runtime . loadClass ( "ops.OpInsertTable" ) ;
runtime . loadClass ( "ops.OpInsertText" ) ;
runtime . loadClass ( "ops.OpRemoveText" ) ;
runtime . loadClass ( "ops.OpSplitParagraph" ) ;
runtime . loadClass ( "ops.OpSetParagraphStyle" ) ;
runtime . loadClass ( "ops.OpAddParagraphStyle" ) ;
runtime . loadClass ( "ops.OpUpdateParagraphStyle" ) ;
runtime . loadClass ( "ops.OpRemoveParagraphStyle" ) ;
ops . OperationTransformer = function OperationTransformer ( ) {
var operationFactory ;
function transformOpVsOp ( opA , opB ) {
var oldOpB , opATransformResult , opBTransformResult ;
runtime . log ( "Crosstransforming:" ) ;
runtime . log ( runtime . toJson ( opA . spec ( ) ) ) ;
runtime . log ( runtime . toJson ( opB . spec ( ) ) ) ;
oldOpB = operationFactory . create ( opB . spec ( ) ) ;
opBTransformResult = opB . transform ( opA , true ) ;
opATransformResult = opA . transform ( oldOpB , false ) ;
if ( ! opATransformResult || ! opBTransformResult ) {
return null
}
return { opsA : opATransformResult , opsB : opBTransformResult }
}
function transformOpListVsOp ( opsA , opB ) {
var b , transformResult , transformListResult , transformedOpsA = [ ] , transformedOpsB = [ ] ;
while ( opsA . length > 0 && opB ) {
transformResult = transformOpVsOp ( opsA . shift ( ) , ( opB ) ) ;
if ( ! transformResult ) {
return null
}
transformedOpsA = transformedOpsA . concat ( transformResult . opsA ) ;
if ( transformResult . opsB . length === 0 ) {
transformedOpsA = transformedOpsA . concat ( opsA ) ;
opB = null ;
break
}
if ( transformResult . opsB . length > 1 ) {
for ( b = 0 ; b < transformResult . opsB . length - 1 ; b += 1 ) {
transformListResult = transformOpListVsOp ( opsA , transformResult . opsB [ b ] ) ;
if ( ! transformListResult ) {
return null
}
transformedOpsB = transformedOpsB . concat ( transformListResult . opsB ) ;
opsA = transformListResult . opsA
}
}
opB = transformResult . opsB . pop ( )
}
if ( opB ) {
transformedOpsB . push ( opB )
}
return { opsA : transformedOpsA , opsB : transformedOpsB }
}
this . setOperationFactory = function ( f ) {
operationFactory = f
} ;
this . transform = function ( opspecsA , opspecsB ) {
var c , s , opsA = [ ] , clientOp , serverOp , transformResult , transformedOpsB = [ ] ;
for ( c = 0 ; c < opspecsA . length ; c += 1 ) {
clientOp = operationFactory . create ( opspecsA [ c ] ) ;
if ( ! clientOp ) {
return null
}
opsA . push ( clientOp )
}
for ( s = 0 ; s < opspecsB . length ; s += 1 ) {
serverOp = operationFactory . create ( opspecsB [ s ] ) ;
transformResult = transformOpListVsOp ( opsA , serverOp ) ;
if ( ! transformResult ) {
return null
}
opsA = transformResult . opsA ;
transformedOpsB = transformedOpsB . concat ( transformResult . opsB )
}
return { opsA : opsA , opsB : transformedOpsB }
}
} ;
runtime . loadClass ( "core.Cursor" ) ;
runtime . loadClass ( "gui.SelectionMover" ) ;
ops . OdtCursor = function OdtCursor ( memberId , odtDocument ) {
var self = this , selectionMover , cursor ;
this . removeFromOdtDocument = function ( ) {
cursor . remove ( )
} ;
this . move = function ( number , extend ) {
var moved = 0 ;
if ( number > 0 ) {
moved = selectionMover . movePointForward ( number , extend )
} else {
if ( number <= 0 ) {
moved = - selectionMover . movePointBackward ( - number , extend )
}
}
self . handleUpdate ( ) ;
return moved
} ;
this . handleUpdate = function ( ) {
} ;
this . getStepCounter = function ( ) {
return selectionMover . getStepCounter ( )
} ;
this . getMemberId = function ( ) {
return memberId
} ;
this . getNode = function ( ) {
return cursor . getNode ( )
} ;
this . getAnchorNode = function ( ) {
return cursor . getAnchorNode ( )
} ;
this . getSelectedRange = function ( ) {
return cursor . getSelectedRange ( )
} ;
this . getOdtDocument = function ( ) {
return odtDocument
} ;
function init ( ) {
cursor = new core . Cursor ( odtDocument . getDOM ( ) , memberId ) ;
selectionMover = new gui . SelectionMover ( cursor , odtDocument . getRootNode ( ) )
}
init ( )
} ;
/ *
Copyright ( C ) 2012 KO GmbH < aditya . bhatt @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . EditInfo = function EditInfo ( container , odtDocument ) {
var editInfoNode , editHistory = { } ;
function sortEdits ( ) {
var arr = [ ] , memberid ;
for ( memberid in editHistory ) {
if ( editHistory . hasOwnProperty ( memberid ) ) {
arr . push ( { "memberid" : memberid , "time" : editHistory [ memberid ] . time } )
}
}
arr . sort ( function ( a , b ) {
return a . time - b . time
} ) ;
return arr
}
this . getNode = function ( ) {
return editInfoNode
} ;
this . getOdtDocument = function ( ) {
return odtDocument
} ;
this . getEdits = function ( ) {
return editHistory
} ;
this . getSortedEdits = function ( ) {
return sortEdits ( )
} ;
this . addEdit = function ( memberid , timestamp ) {
editHistory [ memberid ] = { time : timestamp }
} ;
this . clearEdits = function ( ) {
editHistory = { }
} ;
function init ( ) {
var editInfons = "urn:webodf:names:editinfo" , dom = odtDocument . getDOM ( ) ;
editInfoNode = dom . createElementNS ( editInfons , "editinfo" ) ;
container . insertBefore ( editInfoNode , container . firstChild )
}
init ( )
} ;
gui . Avatar = function Avatar ( parentElement , avatarInitiallyVisible ) {
var self = this , handle , image , pendingImageUrl , displayShown = "block" , displayHidden = "none" ;
this . setColor = function ( color ) {
image . style . borderColor = color
} ;
this . setImageUrl = function ( url ) {
if ( self . isVisible ( ) ) {
image . src = url
} else {
pendingImageUrl = url
}
} ;
this . isVisible = function ( ) {
return handle . style . display === displayShown
} ;
this . show = function ( ) {
if ( pendingImageUrl ) {
image . src = pendingImageUrl ;
pendingImageUrl = undefined
}
handle . style . display = displayShown
} ;
this . hide = function ( ) {
handle . style . display = displayHidden
} ;
this . markAsFocussed = function ( isFocussed ) {
handle . className = isFocussed ? "active" : ""
} ;
function init ( ) {
var document = ( parentElement . ownerDocument ) , htmlns = document . documentElement . namespaceURI ;
handle = document . createElementNS ( htmlns , "div" ) ;
image = document . createElementNS ( htmlns , "img" ) ;
image . width = 64 ;
image . height = 64 ;
handle . appendChild ( image ) ;
handle . style . width = "64px" ;
handle . style . height = "70px" ;
handle . style . position = "absolute" ;
handle . style . top = "-80px" ;
handle . style . left = "-34px" ;
handle . style . display = avatarInitiallyVisible ? displayShown : displayHidden ;
parentElement . appendChild ( handle )
}
init ( )
} ;
runtime . loadClass ( "gui.Avatar" ) ;
runtime . loadClass ( "ops.OdtCursor" ) ;
gui . Caret = function Caret ( cursor , avatarInitiallyVisible , blinkOnRangeSelect ) {
var span , avatar , cursorNode , shouldBlink = false , blinking = false , blinkTimeout ;
function blink ( reset ) {
if ( ! shouldBlink || ! cursorNode . parentNode ) {
return
}
if ( ! blinking || reset ) {
if ( reset && blinkTimeout !== undefined ) {
runtime . clearTimeout ( blinkTimeout )
}
blinking = true ;
span . style . opacity = reset || span . style . opacity === "0" ? "1" : "0" ;
blinkTimeout = runtime . setTimeout ( function ( ) {
blinking = false ;
blink ( false )
} , 500 )
}
}
function getCaretClientRectWithMargin ( caretElement , margin ) {
var caretRect = caretElement . getBoundingClientRect ( ) ;
return { left : caretRect . left - margin . left , top : caretRect . top - margin . top , right : caretRect . right + margin . right , bottom : caretRect . bottom + margin . bottom }
}
this . refreshCursorBlinking = function ( ) {
if ( blinkOnRangeSelect || cursor . getSelectedRange ( ) . collapsed ) {
shouldBlink = true ;
blink ( true )
} else {
shouldBlink = false ;
span . style . opacity = "0"
}
} ;
this . setFocus = function ( ) {
shouldBlink = true ;
avatar . markAsFocussed ( true ) ;
blink ( true )
} ;
this . removeFocus = function ( ) {
shouldBlink = false ;
avatar . markAsFocussed ( false ) ;
span . style . opacity = "0"
} ;
this . setAvatarImageUrl = function ( url ) {
avatar . setImageUrl ( url )
} ;
this . setColor = function ( newColor ) {
span . style . borderColor = newColor ;
avatar . setColor ( newColor )
} ;
this . getCursor = function ( ) {
return cursor
} ;
this . getFocusElement = function ( ) {
return span
} ;
this . toggleHandleVisibility = function ( ) {
if ( avatar . isVisible ( ) ) {
avatar . hide ( )
} else {
avatar . show ( )
}
} ;
this . showHandle = function ( ) {
avatar . show ( )
} ;
this . hideHandle = function ( ) {
avatar . hide ( )
} ;
this . ensureVisible = function ( ) {
var canvasElement = cursor . getOdtDocument ( ) . getOdfCanvas ( ) . getElement ( ) , canvasContainerElement = canvasElement . parentNode , caretRect , canvasContainerRect , horizontalMargin = canvasContainerElement . offsetWidth - canvasContainerElement . clientWidth + 5 , verticalMargin = canvasContainerElement . offsetHeight - canvasContainerElement . clientHeight + 5 ;
caretRect = getCaretClientRectWithMargin ( span , { top : verticalMargin , left : horizontalMargin , bottom : verticalMargin , right : horizontalMargin } ) ;
canvasContainerRect = canvasContainerElement . getBoundingClientRect ( ) ;
if ( caretRect . top < canvasContainerRect . top ) {
canvasContainerElement . scrollTop -= canvasContainerRect . top - caretRect . top
} else {
if ( caretRect . bottom > canvasContainerRect . bottom ) {
canvasContainerElement . scrollTop += caretRect . bottom - canvasContainerRect . bottom
}
}
if ( caretRect . left < canvasContainerRect . left ) {
canvasContainerElement . scrollLeft -= canvasContainerRect . left - caretRect . left
} else {
if ( caretRect . right > canvasContainerRect . right ) {
canvasContainerElement . scrollLeft += caretRect . right - canvasContainerRect . right
}
}
} ;
function init ( ) {
var dom = cursor . getOdtDocument ( ) . getDOM ( ) , htmlns = dom . documentElement . namespaceURI ;
span = dom . createElementNS ( htmlns , "span" ) ;
cursorNode = cursor . getNode ( ) ;
cursorNode . appendChild ( span ) ;
avatar = new gui . Avatar ( cursorNode , avatarInitiallyVisible )
}
init ( )
} ;
runtime . loadClass ( "core.EventNotifier" ) ;
gui . ClickHandler = function ClickHandler ( ) {
var clickTimer , clickCount = 0 , clickPosition = null , eventNotifier = new core . EventNotifier ( [ gui . ClickHandler . signalSingleClick , gui . ClickHandler . signalDoubleClick , gui . ClickHandler . signalTripleClick ] ) ;
function resetClick ( ) {
clickCount = 0 ;
clickPosition = null
}
this . subscribe = function ( eventid , cb ) {
eventNotifier . subscribe ( eventid , cb )
} ;
this . handleMouseUp = function ( e ) {
var window = runtime . getWindow ( ) ;
if ( clickPosition && clickPosition . x === e . screenX && clickPosition . y === e . screenY ) {
clickCount += 1 ;
if ( clickCount === 1 ) {
eventNotifier . emit ( gui . ClickHandler . signalSingleClick , e )
} else {
if ( clickCount === 2 ) {
eventNotifier . emit ( gui . ClickHandler . signalDoubleClick , undefined )
} else {
if ( clickCount === 3 ) {
window . clearTimeout ( clickTimer ) ;
eventNotifier . emit ( gui . ClickHandler . signalTripleClick , undefined ) ;
resetClick ( )
}
}
}
} else {
eventNotifier . emit ( gui . ClickHandler . signalSingleClick , e ) ;
clickCount = 1 ;
clickPosition = { x : e . screenX , y : e . screenY } ;
window . clearTimeout ( clickTimer ) ;
clickTimer = window . setTimeout ( resetClick , 400 )
}
}
} ;
gui . ClickHandler . signalSingleClick = "click" ;
gui . ClickHandler . signalDoubleClick = "doubleClick" ;
gui . ClickHandler . signalTripleClick = "tripleClick" ;
( function ( ) {
return gui . ClickHandler
} ) ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
gui . KeyboardHandler = function KeyboardHandler ( ) {
var modifier = gui . KeyboardHandler . Modifier , defaultBinding = null , bindings = { } ;
function getModifiers ( e ) {
var modifiers = modifier . None ;
if ( e . metaKey ) {
modifiers |= modifier . Meta
}
if ( e . ctrlKey ) {
modifiers |= modifier . Ctrl
}
if ( e . altKey ) {
modifiers |= modifier . Alt
}
if ( e . shiftKey ) {
modifiers |= modifier . Shift
}
return modifiers
}
function getKeyCombo ( keyCode , modifiers ) {
if ( ! modifiers ) {
modifiers = modifier . None
}
return keyCode + ":" + modifiers
}
this . setDefault = function ( callback ) {
defaultBinding = callback
} ;
this . bind = function ( keyCode , modifiers , callback ) {
var keyCombo = getKeyCombo ( keyCode , modifiers ) ;
runtime . assert ( bindings . hasOwnProperty ( keyCombo ) === false , "tried to overwrite the callback handler of key combo: " + keyCombo ) ;
bindings [ keyCombo ] = callback
} ;
this . unbind = function ( keyCode , modifiers ) {
var keyCombo = getKeyCombo ( keyCode , modifiers ) ;
delete bindings [ keyCombo ]
} ;
this . reset = function ( ) {
defaultBinding = null ;
bindings = { }
} ;
this . handleEvent = function ( e ) {
var keyCombo = getKeyCombo ( e . keyCode , getModifiers ( e ) ) , callback = bindings [ keyCombo ] , handled = false ;
if ( callback ) {
handled = callback ( )
} else {
if ( defaultBinding !== null ) {
handled = defaultBinding ( e )
}
}
if ( handled ) {
if ( e . preventDefault ) {
e . preventDefault ( )
} else {
e . returnValue = false
}
}
}
} ;
gui . KeyboardHandler . Modifier = { None : 0 , Meta : 1 , Ctrl : 2 , Alt : 4 , Shift : 8 , MetaShift : 9 , CtrlShift : 10 , AltShift : 12 } ;
gui . KeyboardHandler . KeyCode = { Backspace : 8 , Tab : 9 , Clear : 12 , Enter : 13 , End : 35 , Home : 36 , Left : 37 , Up : 38 , Right : 39 , Down : 40 , Delete : 46 , A : 65 , B : 66 , I : 73 , U : 85 , Z : 90 } ;
( function ( ) {
return gui . KeyboardHandler
} ) ( ) ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "odf.Namespaces" ) ;
runtime . loadClass ( "xmldom.LSSerializer" ) ;
runtime . loadClass ( "odf.OdfNodeFilter" ) ;
runtime . loadClass ( "odf.TextSerializer" ) ;
gui . Clipboard = function Clipboard ( ) {
var xmlSerializer , textSerializer , filter ;
this . setDataFromRange = function ( e , range ) {
var result = true , setDataResult , clipboard = e . clipboardData , window = runtime . getWindow ( ) , document = range . startContainer . ownerDocument , fragmentContainer ;
if ( ! clipboard && window ) {
clipboard = window . clipboardData
}
if ( clipboard ) {
fragmentContainer = document . createElement ( "span" ) ;
fragmentContainer . appendChild ( range . cloneContents ( ) ) ;
setDataResult = clipboard . setData ( "text/plain" , textSerializer . writeToString ( fragmentContainer ) ) ;
result = result && setDataResult ;
setDataResult = clipboard . setData ( "text/html" , xmlSerializer . writeToString ( fragmentContainer , odf . Namespaces . namespaceMap ) ) ;
result = result && setDataResult ;
e . preventDefault ( )
} else {
result = false
}
return result
} ;
function init ( ) {
xmlSerializer = new xmldom . LSSerializer ;
textSerializer = new odf . TextSerializer ;
filter = new odf . OdfNodeFilter ;
xmlSerializer . filter = filter ;
textSerializer . filter = filter
}
init ( )
} ;
runtime . loadClass ( "core.DomUtils" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "ops.OpAddCursor" ) ;
runtime . loadClass ( "ops.OpRemoveCursor" ) ;
runtime . loadClass ( "ops.OpMoveCursor" ) ;
runtime . loadClass ( "ops.OpInsertText" ) ;
runtime . loadClass ( "ops.OpRemoveText" ) ;
runtime . loadClass ( "ops.OpSplitParagraph" ) ;
runtime . loadClass ( "ops.OpSetParagraphStyle" ) ;
runtime . loadClass ( "ops.OpRemoveAnnotation" ) ;
runtime . loadClass ( "gui.ClickHandler" ) ;
runtime . loadClass ( "gui.Clipboard" ) ;
runtime . loadClass ( "gui.KeyboardHandler" ) ;
runtime . loadClass ( "gui.StyleHelper" ) ;
gui . SessionController = function ( ) {
gui . SessionController = function SessionController ( session , inputMemberId ) {
var window = ( runtime . getWindow ( ) ) , odtDocument = session . getOdtDocument ( ) , domUtils = new core . DomUtils , odfUtils = new odf . OdfUtils , clipboard = new gui . Clipboard , clickHandler = new gui . ClickHandler , keyDownHandler = new gui . KeyboardHandler , keyPressHandler = new gui . KeyboardHandler , styleHelper = new gui . StyleHelper ( odtDocument . getFormatting ( ) ) , keyboardMovementsFilter = new core . PositionFilterChain , baseFilter = odtDocument . getPositionFilter ( ) , clickStartedWithinContainer = false , undoManager =
null ;
runtime . assert ( window !== null , "Expected to be run in an environment which has a global window, like a browser." ) ;
keyboardMovementsFilter . addFilter ( "BaseFilter" , baseFilter ) ;
keyboardMovementsFilter . addFilter ( "RootFilter" , odtDocument . createRootFilter ( inputMemberId ) ) ;
function listenEvent ( eventTarget , eventType , eventHandler , includeDirect ) {
var onVariant = "on" + eventType , bound = false ;
if ( eventTarget . attachEvent ) {
bound = eventTarget . attachEvent ( onVariant , eventHandler )
}
if ( ! bound && eventTarget . addEventListener ) {
eventTarget . addEventListener ( eventType , eventHandler , false ) ;
bound = true
}
if ( ( ! bound || includeDirect ) && eventTarget . hasOwnProperty ( onVariant ) ) {
eventTarget [ onVariant ] = eventHandler
}
}
function removeEvent ( eventTarget , eventType , eventHandler ) {
var onVariant = "on" + eventType ;
if ( eventTarget . detachEvent ) {
eventTarget . detachEvent ( onVariant , eventHandler )
}
if ( eventTarget . removeEventListener ) {
eventTarget . removeEventListener ( eventType , eventHandler , false )
}
if ( eventTarget [ onVariant ] === eventHandler ) {
eventTarget [ onVariant ] = null
}
}
function cancelEvent ( event ) {
if ( event . preventDefault ) {
event . preventDefault ( )
} else {
event . returnValue = false
}
}
function dummyHandler ( e ) {
cancelEvent ( e )
}
function createOpMoveCursor ( position , length ) {
var op = new ops . OpMoveCursor ;
op . init ( { memberid : inputMemberId , position : position , length : length || 0 } ) ;
return op
}
function countStepsToNode ( targetNode , targetOffset ) {
var iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) , canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) , node ;
node = targetNode ;
if ( ! node ) {
return null
}
while ( node !== canvasElement ) {
if ( node . namespaceURI === "urn:webodf:names:cursor" && node . localName === "cursor" || node . namespaceURI === "urn:webodf:names:editinfo" && node . localName === "editinfo" ) {
break
}
node = node . parentNode ;
if ( ! node ) {
return null
}
}
if ( node !== canvasElement && targetNode !== node ) {
targetNode = node . parentNode ;
targetOffset = Array . prototype . indexOf . call ( targetNode . childNodes , node )
}
iterator . setUnfilteredPosition ( targetNode , targetOffset ) ;
return odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) )
}
function caretPositionFromPoint ( x , y ) {
var doc = odtDocument . getDOM ( ) , result ;
if ( doc . caretRangeFromPoint ) {
result = doc . caretRangeFromPoint ( x , y ) ;
return { container : result . startContainer , offset : result . startOffset }
}
if ( doc . caretPositionFromPoint ) {
result = doc . caretPositionFromPoint ( x , y ) ;
return { container : result . offsetNode , offset : result . offset }
}
return null
}
function findClosestPosition ( node ) {
var canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) , newNode = odtDocument . getRootNode ( ) , newOffset = 0 , beforeCanvas , iterator ;
beforeCanvas = canvasElement . compareDocumentPosition ( node ) & Node . DOCUMENT _POSITION _PRECEDING ;
if ( ! beforeCanvas ) {
iterator = gui . SelectionMover . createPositionIterator ( newNode ) ;
iterator . moveToEnd ( ) ;
newNode = iterator . container ( ) ;
newOffset = iterator . unfilteredDomOffset ( )
}
return { node : newNode , offset : newOffset }
}
function getSelection ( e ) {
var canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) , selection = window . getSelection ( ) , anchorNode , anchorOffset , focusNode , focusOffset , anchorNodeInsideCanvas , focusNodeInsideCanvas , caretPos , node ;
if ( selection . anchorNode === null && selection . focusNode === null ) {
caretPos = caretPositionFromPoint ( e . clientX , e . clientY ) ;
if ( ! caretPos ) {
return null
}
anchorNode = ( caretPos . container ) ;
anchorOffset = caretPos . offset ;
focusNode = anchorNode ;
focusOffset = anchorOffset
} else {
anchorNode = ( selection . anchorNode ) ;
anchorOffset = selection . anchorOffset ;
focusNode = ( selection . focusNode ) ;
focusOffset = selection . focusOffset
}
runtime . assert ( anchorNode !== null && focusNode !== null , "anchorNode is null or focusNode is null" ) ;
anchorNodeInsideCanvas = domUtils . containsNode ( canvasElement , anchorNode ) ;
focusNodeInsideCanvas = domUtils . containsNode ( canvasElement , focusNode ) ;
if ( ! anchorNodeInsideCanvas && ! focusNodeInsideCanvas ) {
return null
}
if ( ! anchorNodeInsideCanvas ) {
node = findClosestPosition ( anchorNode ) ;
anchorNode = node . node ;
anchorOffset = node . offset
}
if ( ! focusNodeInsideCanvas ) {
node = findClosestPosition ( focusNode ) ;
focusNode = node . node ;
focusOffset = node . offset
}
canvasElement . focus ( ) ;
return { anchorNode : anchorNode , anchorOffset : anchorOffset , focusNode : focusNode , focusOffset : focusOffset }
}
function getFirstWalkablePositionInNode ( node ) {
var position = 0 , iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) , watch = new core . LoopWatchDog ( 1E3 ) , inside = false ;
while ( iterator . nextPosition ( ) ) {
watch . check ( ) ;
inside = Boolean ( node . compareDocumentPosition ( iterator . container ( ) ) & Node . DOCUMENT _POSITION _CONTAINED _BY ) ;
if ( baseFilter . acceptPosition ( iterator ) === 1 ) {
if ( inside ) {
break
}
position += 1
}
}
return position
}
function getWalkableNodeLength ( node ) {
var length = 0 , iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) , inside = false ;
iterator . setUnfilteredPosition ( node , 0 ) ;
do {
inside = Boolean ( node . compareDocumentPosition ( iterator . container ( ) ) & Node . DOCUMENT _POSITION _CONTAINED _BY ) ;
if ( ! inside && node !== iterator . container ( ) ) {
break
}
if ( baseFilter . acceptPosition ( iterator ) === 1 ) {
length += 1
}
} while ( iterator . nextPosition ( ) ) ;
return length
}
function removeAnnotation ( annotationNode ) {
var position , length , op ;
position = getFirstWalkablePositionInNode ( annotationNode ) ;
length = getWalkableNodeLength ( annotationNode ) ;
op = new ops . OpRemoveAnnotation ;
op . init ( { memberid : inputMemberId , position : position , length : length } ) ;
session . enqueue ( op )
}
function selectRange ( e ) {
if ( ! clickStartedWithinContainer ) {
return
}
runtime . setTimeout ( function ( ) {
var selection = getSelection ( e ) , oldPosition , stepsToAnchor , stepsToFocus , op ;
if ( selection === null ) {
return
}
stepsToAnchor = countStepsToNode ( selection . anchorNode , selection . anchorOffset ) ;
if ( selection . focusNode === selection . anchorNode && selection . focusOffset === selection . anchorOffset ) {
stepsToFocus = stepsToAnchor
} else {
stepsToFocus = countStepsToNode ( selection . focusNode , selection . focusOffset )
}
if ( stepsToFocus !== null && stepsToFocus !== 0 || stepsToAnchor !== null && stepsToAnchor !== 0 ) {
oldPosition = odtDocument . getCursorPosition ( inputMemberId ) ;
op = createOpMoveCursor ( oldPosition + stepsToAnchor , stepsToFocus - stepsToAnchor ) ;
session . enqueue ( op )
}
} , 0 )
}
function handleContextMenu ( e ) {
selectRange ( e )
}
function isTextSpan ( node ) {
return node . namespaceURI === odf . Namespaces . textns && node . localName === "span"
}
function selectWord ( ) {
var canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) , alphaNumeric = /[A-Za-z0-9]/ , stepsToStart = 0 , stepsToEnd = 0 , iterator , cursorNode , oldPosition , currentNode , c , op ;
if ( ! domUtils . containsNode ( canvasElement , window . getSelection ( ) . focusNode ) ) {
return
}
iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) ;
cursorNode = odtDocument . getCursor ( inputMemberId ) . getNode ( ) ;
iterator . setUnfilteredPosition ( cursorNode , 0 ) ;
while ( iterator . previousPosition ( ) ) {
currentNode = iterator . getCurrentNode ( ) ;
if ( currentNode . nodeType === Node . TEXT _NODE ) {
c = currentNode . data [ iterator . unfilteredDomOffset ( ) ] ;
if ( ! alphaNumeric . test ( c ) ) {
break
}
stepsToStart -= 1
} else {
if ( ! isTextSpan ( currentNode ) ) {
break
}
}
}
iterator . setUnfilteredPosition ( cursorNode , 0 ) ;
do {
currentNode = iterator . getCurrentNode ( ) ;
if ( currentNode . nodeType === Node . TEXT _NODE ) {
c = currentNode . data [ iterator . unfilteredDomOffset ( ) ] ;
if ( ! alphaNumeric . test ( c ) ) {
break
}
stepsToEnd += 1
} else {
if ( ! isTextSpan ( currentNode ) ) {
break
}
}
} while ( iterator . nextPosition ( ) ) ;
if ( stepsToStart !== 0 || stepsToEnd !== 0 ) {
oldPosition = odtDocument . getCursorPosition ( inputMemberId ) ;
op = createOpMoveCursor ( oldPosition + stepsToStart , Math . abs ( stepsToStart ) + Math . abs ( stepsToEnd ) ) ;
session . enqueue ( op )
}
}
function selectParagraph ( ) {
var canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) , iterator , paragraphNode , oldPosition , stepsToStart , stepsToEnd , op ;
if ( ! domUtils . containsNode ( canvasElement , window . getSelection ( ) . focusNode ) ) {
return
}
paragraphNode = odtDocument . getParagraphElement ( odtDocument . getCursor ( inputMemberId ) . getNode ( ) ) ;
stepsToStart = odtDocument . getDistanceFromCursor ( inputMemberId , paragraphNode , 0 ) ;
iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) ;
iterator . moveToEndOfNode ( paragraphNode ) ;
stepsToEnd = odtDocument . getDistanceFromCursor ( inputMemberId , paragraphNode , iterator . unfilteredDomOffset ( ) ) ;
if ( stepsToStart !== 0 || stepsToEnd !== 0 ) {
oldPosition = odtDocument . getCursorPosition ( inputMemberId ) ;
op = createOpMoveCursor ( oldPosition + stepsToStart , Math . abs ( stepsToStart ) + Math . abs ( stepsToEnd ) ) ;
session . enqueue ( op )
}
}
function extendCursorByAdjustment ( lengthAdjust ) {
var selection = odtDocument . getCursorSelection ( inputMemberId ) , stepCounter = odtDocument . getCursor ( inputMemberId ) . getStepCounter ( ) , newLength ;
if ( lengthAdjust !== 0 ) {
lengthAdjust = lengthAdjust > 0 ? stepCounter . convertForwardStepsBetweenFilters ( lengthAdjust , keyboardMovementsFilter , baseFilter ) : - stepCounter . convertBackwardStepsBetweenFilters ( - lengthAdjust , keyboardMovementsFilter , baseFilter ) ;
newLength = selection . length + lengthAdjust ;
session . enqueue ( createOpMoveCursor ( selection . position , newLength ) )
}
}
function moveCursorByAdjustment ( positionAdjust ) {
var position = odtDocument . getCursorPosition ( inputMemberId ) , stepCounter = odtDocument . getCursor ( inputMemberId ) . getStepCounter ( ) ;
if ( positionAdjust !== 0 ) {
positionAdjust = positionAdjust > 0 ? stepCounter . convertForwardStepsBetweenFilters ( positionAdjust , keyboardMovementsFilter , baseFilter ) : - stepCounter . convertBackwardStepsBetweenFilters ( - positionAdjust , keyboardMovementsFilter , baseFilter ) ;
position = position + positionAdjust ;
session . enqueue ( createOpMoveCursor ( position , 0 ) )
}
}
function moveCursorToLeft ( ) {
moveCursorByAdjustment ( - 1 ) ;
return true
}
function moveCursorToRight ( ) {
moveCursorByAdjustment ( 1 ) ;
return true
}
function extendSelectionToLeft ( ) {
extendCursorByAdjustment ( - 1 ) ;
return true
}
function extendSelectionToRight ( ) {
extendCursorByAdjustment ( 1 ) ;
return true
}
function moveCursorByLine ( direction , extend ) {
var paragraphNode = odtDocument . getParagraphElement ( odtDocument . getCursor ( inputMemberId ) . getNode ( ) ) , steps ;
runtime . assert ( Boolean ( paragraphNode ) , "SessionController: Cursor outside paragraph" ) ;
steps = odtDocument . getCursor ( inputMemberId ) . getStepCounter ( ) . countLinesSteps ( direction , keyboardMovementsFilter ) ;
if ( extend ) {
extendCursorByAdjustment ( steps )
} else {
moveCursorByAdjustment ( steps )
}
}
function moveCursorUp ( ) {
moveCursorByLine ( - 1 , false ) ;
return true
}
function moveCursorDown ( ) {
moveCursorByLine ( 1 , false ) ;
return true
}
function extendSelectionUp ( ) {
moveCursorByLine ( - 1 , true ) ;
return true
}
function extendSelectionDown ( ) {
moveCursorByLine ( 1 , true ) ;
return true
}
function moveCursorToLineBoundary ( direction , extend ) {
var steps = odtDocument . getCursor ( inputMemberId ) . getStepCounter ( ) . countStepsToLineBoundary ( direction , keyboardMovementsFilter ) ;
if ( extend ) {
extendCursorByAdjustment ( steps )
} else {
moveCursorByAdjustment ( steps )
}
}
function moveCursorToLineStart ( ) {
moveCursorToLineBoundary ( - 1 , false ) ;
return true
}
function moveCursorToLineEnd ( ) {
moveCursorToLineBoundary ( 1 , false ) ;
return true
}
function extendSelectionToLineStart ( ) {
moveCursorToLineBoundary ( - 1 , true ) ;
return true
}
function extendSelectionToLineEnd ( ) {
moveCursorToLineBoundary ( 1 , true ) ;
return true
}
function extendSelectionToParagraphStart ( ) {
var paragraphNode = odtDocument . getParagraphElement ( odtDocument . getCursor ( inputMemberId ) . getNode ( ) ) , iterator , node , steps ;
runtime . assert ( Boolean ( paragraphNode ) , "SessionController: Cursor outside paragraph" ) ;
steps = odtDocument . getDistanceFromCursor ( inputMemberId , paragraphNode , 0 ) ;
iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) ;
iterator . setUnfilteredPosition ( paragraphNode , 0 ) ;
while ( steps === 0 && iterator . previousPosition ( ) ) {
node = iterator . getCurrentNode ( ) ;
if ( odfUtils . isParagraph ( node ) ) {
steps = odtDocument . getDistanceFromCursor ( inputMemberId , node , 0 )
}
}
extendCursorByAdjustment ( steps ) ;
return true
}
function extendSelectionToParagraphEnd ( ) {
var paragraphNode = odtDocument . getParagraphElement ( odtDocument . getCursor ( inputMemberId ) . getNode ( ) ) , iterator , node , steps ;
runtime . assert ( Boolean ( paragraphNode ) , "SessionController: Cursor outside paragraph" ) ;
iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) ;
iterator . moveToEndOfNode ( paragraphNode ) ;
steps = odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
while ( steps === 0 && iterator . nextPosition ( ) ) {
node = iterator . getCurrentNode ( ) ;
if ( odfUtils . isParagraph ( node ) ) {
iterator . moveToEndOfNode ( node ) ;
steps = odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) )
}
}
extendCursorByAdjustment ( steps ) ;
return true
}
function moveCursorToDocumentBoundary ( direction , extend ) {
var iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) , steps ;
if ( direction > 0 ) {
iterator . moveToEnd ( )
}
steps = odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
if ( extend ) {
extendCursorByAdjustment ( steps )
} else {
moveCursorByAdjustment ( steps )
}
}
function moveCursorToDocumentStart ( ) {
moveCursorToDocumentBoundary ( - 1 , false ) ;
return true
}
function moveCursorToDocumentEnd ( ) {
moveCursorToDocumentBoundary ( 1 , false ) ;
return true
}
function extendSelectionToDocumentStart ( ) {
moveCursorToDocumentBoundary ( - 1 , true ) ;
return true
}
function extendSelectionToDocumentEnd ( ) {
moveCursorToDocumentBoundary ( 1 , true ) ;
return true
}
function extendSelectionToEntireDocument ( ) {
var iterator = gui . SelectionMover . createPositionIterator ( odtDocument . getRootNode ( ) ) , steps ;
steps = - odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
iterator . moveToEnd ( ) ;
steps += odtDocument . getDistanceFromCursor ( inputMemberId , iterator . container ( ) , iterator . unfilteredDomOffset ( ) ) ;
session . enqueue ( createOpMoveCursor ( 0 , steps ) ) ;
return true
}
function toForwardSelection ( selection ) {
if ( selection . length < 0 ) {
selection . position += selection . length ;
selection . length = - selection . length
}
return selection
}
function createOpRemoveSelection ( selection ) {
var op = new ops . OpRemoveText ;
op . init ( { memberid : inputMemberId , position : selection . position , length : selection . length } ) ;
return op
}
function removeTextByBackspaceKey ( ) {
var selection = toForwardSelection ( odtDocument . getCursorSelection ( inputMemberId ) ) , op = null ;
if ( selection . length === 0 ) {
if ( selection . position > 0 && odtDocument . getPositionInTextNode ( selection . position - 1 ) ) {
op = new ops . OpRemoveText ;
op . init ( { memberid : inputMemberId , position : selection . position - 1 , length : 1 } ) ;
session . enqueue ( op )
}
} else {
op = createOpRemoveSelection ( selection ) ;
session . enqueue ( op )
}
return true
}
function removeTextByDeleteKey ( ) {
var selection = toForwardSelection ( odtDocument . getCursorSelection ( inputMemberId ) ) , op = null ;
if ( selection . length === 0 ) {
if ( odtDocument . getPositionInTextNode ( selection . position + 1 ) ) {
op = new ops . OpRemoveText ;
op . init ( { memberid : inputMemberId , position : selection . position , length : 1 } ) ;
session . enqueue ( op )
}
} else {
op = createOpRemoveSelection ( selection ) ;
session . enqueue ( op )
}
return op !== null
}
function removeTextByClearKey ( ) {
var selection = toForwardSelection ( odtDocument . getCursorSelection ( inputMemberId ) ) ;
if ( selection . length !== 0 ) {
session . enqueue ( createOpRemoveSelection ( selection ) )
}
return true
}
function insertText ( text ) {
var selection = toForwardSelection ( odtDocument . getCursorSelection ( inputMemberId ) ) , op = null ;
if ( selection . length > 0 ) {
op = createOpRemoveSelection ( selection ) ;
session . enqueue ( op )
}
op = new ops . OpInsertText ;
op . init ( { memberid : inputMemberId , position : selection . position , text : text } ) ;
session . enqueue ( op )
}
function enqueueParagraphSplittingOps ( ) {
var position = odtDocument . getCursorPosition ( inputMemberId ) , op ;
op = new ops . OpSplitParagraph ;
op . init ( { memberid : inputMemberId , position : position } ) ;
session . enqueue ( op ) ;
return true
}
function maintainCursorSelection ( ) {
var cursor = odtDocument . getCursor ( inputMemberId ) , selection = window . getSelection ( ) ;
if ( cursor ) {
selection . removeAllRanges ( ) ;
selection . addRange ( cursor . getSelectedRange ( ) . cloneRange ( ) )
}
}
function stringFromKeyPress ( event ) {
if ( event . which === null ) {
return String . fromCharCode ( event . keyCode )
}
if ( event . which !== 0 && event . charCode !== 0 ) {
return String . fromCharCode ( event . which )
}
return null
}
function handleCut ( e ) {
var cursor = odtDocument . getCursor ( inputMemberId ) , selectedRange = cursor . getSelectedRange ( ) , selection , op ;
if ( selectedRange . collapsed ) {
return
}
if ( clipboard . setDataFromRange ( e , cursor . getSelectedRange ( ) ) ) {
op = new ops . OpRemoveText ;
selection = toForwardSelection ( session . getOdtDocument ( ) . getCursorSelection ( inputMemberId ) ) ;
op . init ( { memberid : inputMemberId , position : selection . position , length : selection . length } ) ;
session . enqueue ( op )
} else {
runtime . log ( "Cut operation failed" )
}
}
function handleBeforeCut ( ) {
var cursor = odtDocument . getCursor ( inputMemberId ) , selectedRange = cursor . getSelectedRange ( ) ;
return selectedRange . collapsed !== false
}
function handleCopy ( e ) {
var cursor = odtDocument . getCursor ( inputMemberId ) , selectedRange = cursor . getSelectedRange ( ) ;
if ( selectedRange . collapsed ) {
return
}
if ( ! clipboard . setDataFromRange ( e , cursor . getSelectedRange ( ) ) ) {
runtime . log ( "Cut operation failed" )
}
}
function handlePaste ( e ) {
var plainText ;
if ( window . clipboardData && window . clipboardData . getData ) {
plainText = window . clipboardData . getData ( "Text" )
} else {
if ( e . clipboardData && e . clipboardData . getData ) {
plainText = e . clipboardData . getData ( "text/plain" )
}
}
if ( plainText ) {
insertText ( plainText ) ;
cancelEvent ( e )
}
}
function handleBeforePaste ( ) {
return false
}
function updateUndoStack ( op ) {
if ( undoManager ) {
undoManager . onOperationExecuted ( op )
}
}
function forwardUndoStackChange ( e ) {
odtDocument . emit ( ops . OdtDocument . signalUndoStackChanged , e )
}
function undo ( ) {
if ( undoManager ) {
undoManager . moveBackward ( 1 ) ;
maintainCursorSelection ( ) ;
return true
}
return false
}
function redo ( ) {
if ( undoManager ) {
undoManager . moveForward ( 1 ) ;
maintainCursorSelection ( ) ;
return true
}
return false
}
function formatTextSelection ( propertyName , propertyValue ) {
var selection = odtDocument . getCursorSelection ( inputMemberId ) , op = new ops . OpApplyDirectStyling , properties = { } ;
properties [ propertyName ] = propertyValue ;
op . init ( { memberid : inputMemberId , position : selection . position , length : selection . length , setProperties : { "style:text-properties" : properties } } ) ;
session . enqueue ( op )
}
function toggleBold ( ) {
var range = odtDocument . getCursor ( inputMemberId ) . getSelectedRange ( ) , value = styleHelper . isBold ( range ) ? "normal" : "bold" ;
formatTextSelection ( "fo:font-weight" , value ) ;
return true
}
function toggleItalic ( ) {
var range = odtDocument . getCursor ( inputMemberId ) . getSelectedRange ( ) , value = styleHelper . isItalic ( range ) ? "normal" : "italic" ;
formatTextSelection ( "fo:font-style" , value ) ;
return true
}
function toggleUnderline ( ) {
var range = odtDocument . getCursor ( inputMemberId ) . getSelectedRange ( ) , value = styleHelper . hasUnderline ( range ) ? "none" : "solid" ;
formatTextSelection ( "style:text-underline-style" , value ) ;
return true
}
function filterMouseClicks ( e ) {
clickStartedWithinContainer = e . target && domUtils . containsNode ( odtDocument . getOdfCanvas ( ) . getElement ( ) , e . target )
}
this . startEditing = function ( ) {
var canvasElement , op ;
canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) ;
listenEvent ( canvasElement , "keydown" , keyDownHandler . handleEvent ) ;
listenEvent ( canvasElement , "keypress" , keyPressHandler . handleEvent ) ;
listenEvent ( canvasElement , "keyup" , dummyHandler ) ;
listenEvent ( canvasElement , "beforecut" , handleBeforeCut , true ) ;
listenEvent ( canvasElement , "cut" , handleCut ) ;
listenEvent ( canvasElement , "copy" , handleCopy ) ;
listenEvent ( canvasElement , "beforepaste" , handleBeforePaste , true ) ;
listenEvent ( canvasElement , "paste" , handlePaste ) ;
listenEvent ( window , "mousedown" , filterMouseClicks ) ;
listenEvent ( window , "mouseup" , clickHandler . handleMouseUp ) ;
listenEvent ( canvasElement , "contextmenu" , handleContextMenu ) ;
odtDocument . subscribe ( ops . OdtDocument . signalOperationExecuted , maintainCursorSelection ) ;
odtDocument . subscribe ( ops . OdtDocument . signalOperationExecuted , updateUndoStack ) ;
op = new ops . OpAddCursor ;
op . init ( { memberid : inputMemberId } ) ;
session . enqueue ( op ) ;
if ( undoManager ) {
undoManager . saveInitialState ( )
}
} ;
this . endEditing = function ( ) {
var canvasElement , op ;
odtDocument . unsubscribe ( ops . OdtDocument . signalOperationExecuted , updateUndoStack ) ;
odtDocument . unsubscribe ( ops . OdtDocument . signalOperationExecuted , maintainCursorSelection ) ;
canvasElement = odtDocument . getOdfCanvas ( ) . getElement ( ) ;
removeEvent ( canvasElement , "keydown" , keyDownHandler . handleEvent ) ;
removeEvent ( canvasElement , "keypress" , keyPressHandler . handleEvent ) ;
removeEvent ( canvasElement , "keyup" , dummyHandler ) ;
removeEvent ( canvasElement , "cut" , handleCut ) ;
removeEvent ( canvasElement , "beforecut" , handleBeforeCut ) ;
removeEvent ( canvasElement , "copy" , handleCopy ) ;
removeEvent ( canvasElement , "paste" , handlePaste ) ;
removeEvent ( canvasElement , "beforepaste" , handleBeforePaste ) ;
removeEvent ( window , "mousedown" , filterMouseClicks ) ;
removeEvent ( window , "mouseup" , clickHandler . handleMouseUp ) ;
removeEvent ( canvasElement , "contextmenu" , handleContextMenu ) ;
op = new ops . OpRemoveCursor ;
op . init ( { memberid : inputMemberId } ) ;
session . enqueue ( op ) ;
if ( undoManager ) {
undoManager . resetInitialState ( )
}
} ;
this . getInputMemberId = function ( ) {
return inputMemberId
} ;
this . getSession = function ( ) {
return session
} ;
this . setUndoManager = function ( manager ) {
if ( undoManager ) {
undoManager . unsubscribe ( gui . UndoManager . signalUndoStackChanged , forwardUndoStackChange )
}
undoManager = manager ;
if ( undoManager ) {
undoManager . setOdtDocument ( odtDocument ) ;
undoManager . setPlaybackFunction ( function ( op ) {
op . execute ( odtDocument )
} ) ;
undoManager . subscribe ( gui . UndoManager . signalUndoStackChanged , forwardUndoStackChange )
}
} ;
this . getUndoManager = function ( ) {
return undoManager
} ;
this . close = function ( callback ) {
callback ( )
} ;
function init ( ) {
var isMacOS = window . navigator . appVersion . toLowerCase ( ) . indexOf ( "mac" ) !== - 1 , modifier = gui . KeyboardHandler . Modifier , keyCode = gui . KeyboardHandler . KeyCode ;
keyDownHandler . bind ( keyCode . Tab , modifier . None , function ( ) {
insertText ( "\t" ) ;
return true
} ) ;
keyDownHandler . bind ( keyCode . Left , modifier . None , moveCursorToLeft ) ;
keyDownHandler . bind ( keyCode . Right , modifier . None , moveCursorToRight ) ;
keyDownHandler . bind ( keyCode . Up , modifier . None , moveCursorUp ) ;
keyDownHandler . bind ( keyCode . Down , modifier . None , moveCursorDown ) ;
keyDownHandler . bind ( keyCode . Backspace , modifier . None , removeTextByBackspaceKey ) ;
keyDownHandler . bind ( keyCode . Delete , modifier . None , removeTextByDeleteKey ) ;
keyDownHandler . bind ( keyCode . Left , modifier . Shift , extendSelectionToLeft ) ;
keyDownHandler . bind ( keyCode . Right , modifier . Shift , extendSelectionToRight ) ;
keyDownHandler . bind ( keyCode . Up , modifier . Shift , extendSelectionUp ) ;
keyDownHandler . bind ( keyCode . Down , modifier . Shift , extendSelectionDown ) ;
keyDownHandler . bind ( keyCode . Home , modifier . None , moveCursorToLineStart ) ;
keyDownHandler . bind ( keyCode . End , modifier . None , moveCursorToLineEnd ) ;
keyDownHandler . bind ( keyCode . Home , modifier . Ctrl , moveCursorToDocumentStart ) ;
keyDownHandler . bind ( keyCode . End , modifier . Ctrl , moveCursorToDocumentEnd ) ;
keyDownHandler . bind ( keyCode . Home , modifier . Shift , extendSelectionToLineStart ) ;
keyDownHandler . bind ( keyCode . End , modifier . Shift , extendSelectionToLineEnd ) ;
keyDownHandler . bind ( keyCode . Up , modifier . CtrlShift , extendSelectionToParagraphStart ) ;
keyDownHandler . bind ( keyCode . Down , modifier . CtrlShift , extendSelectionToParagraphEnd ) ;
keyDownHandler . bind ( keyCode . Home , modifier . CtrlShift , extendSelectionToDocumentStart ) ;
keyDownHandler . bind ( keyCode . End , modifier . CtrlShift , extendSelectionToDocumentEnd ) ;
if ( isMacOS ) {
keyDownHandler . bind ( keyCode . Clear , modifier . None , removeTextByClearKey ) ;
keyDownHandler . bind ( keyCode . Left , modifier . Meta , moveCursorToLineStart ) ;
keyDownHandler . bind ( keyCode . Right , modifier . Meta , moveCursorToLineEnd ) ;
keyDownHandler . bind ( keyCode . Home , modifier . Meta , moveCursorToDocumentStart ) ;
keyDownHandler . bind ( keyCode . End , modifier . Meta , moveCursorToDocumentEnd ) ;
keyDownHandler . bind ( keyCode . Left , modifier . MetaShift , extendSelectionToLineStart ) ;
keyDownHandler . bind ( keyCode . Right , modifier . MetaShift , extendSelectionToLineEnd ) ;
keyDownHandler . bind ( keyCode . Up , modifier . AltShift , extendSelectionToParagraphStart ) ;
keyDownHandler . bind ( keyCode . Down , modifier . AltShift , extendSelectionToParagraphEnd ) ;
keyDownHandler . bind ( keyCode . Up , modifier . MetaShift , extendSelectionToDocumentStart ) ;
keyDownHandler . bind ( keyCode . Down , modifier . MetaShift , extendSelectionToDocumentEnd ) ;
keyDownHandler . bind ( keyCode . A , modifier . Meta , extendSelectionToEntireDocument ) ;
keyDownHandler . bind ( keyCode . B , modifier . Meta , toggleBold ) ;
keyDownHandler . bind ( keyCode . I , modifier . Meta , toggleItalic ) ;
keyDownHandler . bind ( keyCode . U , modifier . Meta , toggleUnderline ) ;
keyDownHandler . bind ( keyCode . Z , modifier . Meta , undo ) ;
keyDownHandler . bind ( keyCode . Z , modifier . MetaShift , redo )
} else {
keyDownHandler . bind ( keyCode . A , modifier . Ctrl , extendSelectionToEntireDocument ) ;
keyDownHandler . bind ( keyCode . B , modifier . Ctrl , toggleBold ) ;
keyDownHandler . bind ( keyCode . I , modifier . Ctrl , toggleItalic ) ;
keyDownHandler . bind ( keyCode . U , modifier . Ctrl , toggleUnderline ) ;
keyDownHandler . bind ( keyCode . Z , modifier . Ctrl , undo ) ;
keyDownHandler . bind ( keyCode . Z , modifier . CtrlShift , redo )
}
keyPressHandler . setDefault ( function ( e ) {
var text = stringFromKeyPress ( e ) ;
if ( text && ! ( e . altKey || e . ctrlKey || e . metaKey ) ) {
insertText ( text ) ;
return true
}
return false
} ) ;
keyPressHandler . bind ( keyCode . Enter , modifier . None , enqueueParagraphSplittingOps ) ;
clickHandler . subscribe ( gui . ClickHandler . signalSingleClick , function ( event ) {
var target = event . target , annotationNode = null ;
if ( target . className === "annotationRemoveButton" ) {
annotationNode = domUtils . getElementsByTagNameNS ( target . parentNode , odf . Namespaces . officens , "annotation" ) [ 0 ] ;
removeAnnotation ( annotationNode )
} else {
selectRange ( event )
}
} ) ;
clickHandler . subscribe ( gui . ClickHandler . signalDoubleClick , selectWord ) ;
clickHandler . subscribe ( gui . ClickHandler . signalTripleClick , selectParagraph )
}
init ( )
} ;
return gui . SessionController
} ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . MemberModel = function MemberModel ( ) {
} ;
ops . MemberModel . prototype . getMemberDetailsAndUpdates = function ( memberId , subscriber ) {
} ;
ops . MemberModel . prototype . unsubscribeMemberDetailsUpdates = function ( memberId , subscriber ) {
} ;
ops . MemberModel . prototype . close = function ( callback ) {
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . TrivialMemberModel = function TrivialMemberModel ( ) {
this . getMemberDetailsAndUpdates = function ( memberId , subscriber ) {
subscriber ( memberId , null )
} ;
this . unsubscribeMemberDetailsUpdates = function ( memberId , subscriber ) {
} ;
this . close = function ( cb ) {
cb ( )
}
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . OperationRouter = function OperationRouter ( ) {
} ;
ops . OperationRouter . prototype . setOperationFactory = function ( f ) {
} ;
ops . OperationRouter . prototype . setPlaybackFunction = function ( playback _func ) {
} ;
ops . OperationRouter . prototype . push = function ( op ) {
} ;
ops . OperationRouter . prototype . close = function ( callback ) {
} ;
ops . OperationRouter . prototype . getHasLocalUnsyncedOpsAndUpdates = function ( subscriber ) {
} ;
ops . OperationRouter . prototype . unsubscribeHasLocalUnsyncedOpsUpdates = function ( subscriber ) {
} ;
/ *
Copyright ( C ) 2012 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
ops . TrivialOperationRouter = function TrivialOperationRouter ( ) {
var operationFactory , playbackFunction ;
this . setOperationFactory = function ( f ) {
operationFactory = f
} ;
this . setPlaybackFunction = function ( playback _func ) {
playbackFunction = playback _func
} ;
this . push = function ( op ) {
var timedOp , opspec = op . spec ( ) ;
opspec . timestamp = ( new Date ) . getTime ( ) ;
timedOp = operationFactory . create ( opspec ) ;
playbackFunction ( timedOp )
} ;
this . close = function ( cb ) {
cb ( )
} ;
this . getHasLocalUnsyncedOpsAndUpdates = function ( subscriber ) {
subscriber ( true )
} ;
this . unsubscribeHasLocalUnsyncedOpsUpdates = function ( subscriber ) {
}
} ;
gui . EditInfoHandle = function EditInfoHandle ( parentElement ) {
var edits = [ ] , handle , document = ( parentElement . ownerDocument ) , htmlns = document . documentElement . namespaceURI , editinfons = "urn:webodf:names:editinfo" ;
function renderEdits ( ) {
var i , infoDiv , colorSpan , authorSpan , timeSpan ;
handle . innerHTML = "" ;
for ( i = 0 ; i < edits . length ; i += 1 ) {
infoDiv = document . createElementNS ( htmlns , "div" ) ;
infoDiv . className = "editInfo" ;
colorSpan = document . createElementNS ( htmlns , "span" ) ;
colorSpan . className = "editInfoColor" ;
colorSpan . setAttributeNS ( editinfons , "editinfo:memberid" , edits [ i ] . memberid ) ;
authorSpan = document . createElementNS ( htmlns , "span" ) ;
authorSpan . className = "editInfoAuthor" ;
authorSpan . setAttributeNS ( editinfons , "editinfo:memberid" , edits [ i ] . memberid ) ;
timeSpan = document . createElementNS ( htmlns , "span" ) ;
timeSpan . className = "editInfoTime" ;
timeSpan . setAttributeNS ( editinfons , "editinfo:memberid" , edits [ i ] . memberid ) ;
timeSpan . innerHTML = edits [ i ] . time ;
infoDiv . appendChild ( colorSpan ) ;
infoDiv . appendChild ( authorSpan ) ;
infoDiv . appendChild ( timeSpan ) ;
handle . appendChild ( infoDiv )
}
}
this . setEdits = function ( editArray ) {
edits = editArray ;
renderEdits ( )
} ;
this . show = function ( ) {
handle . style . display = "block"
} ;
this . hide = function ( ) {
handle . style . display = "none"
} ;
function init ( ) {
handle = document . createElementNS ( htmlns , "div" ) ;
handle . setAttribute ( "class" , "editInfoHandle" ) ;
handle . style . display = "none" ;
parentElement . appendChild ( handle )
}
init ( )
} ;
runtime . loadClass ( "ops.EditInfo" ) ;
runtime . loadClass ( "gui.EditInfoHandle" ) ;
gui . EditInfoMarker = function EditInfoMarker ( editInfo , initialVisibility ) {
var self = this , editInfoNode , handle , marker , editinfons = "urn:webodf:names:editinfo" , decay1 , decay2 , decayTimeStep = 1E4 ;
function applyDecay ( opacity , delay ) {
return runtime . getWindow ( ) . setTimeout ( function ( ) {
marker . style . opacity = opacity
} , delay )
}
function deleteDecay ( timer ) {
runtime . getWindow ( ) . clearTimeout ( timer )
}
function setLastAuthor ( memberid ) {
marker . setAttributeNS ( editinfons , "editinfo:memberid" , memberid )
}
this . addEdit = function ( memberid , timestamp ) {
var age = Date . now ( ) - timestamp ;
editInfo . addEdit ( memberid , timestamp ) ;
handle . setEdits ( editInfo . getSortedEdits ( ) ) ;
setLastAuthor ( memberid ) ;
if ( decay1 ) {
deleteDecay ( decay1 )
}
if ( decay2 ) {
deleteDecay ( decay2 )
}
if ( age < decayTimeStep ) {
applyDecay ( 1 , 0 ) ;
decay1 = applyDecay ( 0.5 , decayTimeStep - age ) ;
decay2 = applyDecay ( 0.2 , decayTimeStep * 2 - age )
} else {
if ( age >= decayTimeStep && age < decayTimeStep * 2 ) {
applyDecay ( 0.5 , 0 ) ;
decay2 = applyDecay ( 0.2 , decayTimeStep * 2 - age )
} else {
applyDecay ( 0.2 , 0 )
}
}
} ;
this . getEdits = function ( ) {
return editInfo . getEdits ( )
} ;
this . clearEdits = function ( ) {
editInfo . clearEdits ( ) ;
handle . setEdits ( [ ] ) ;
if ( marker . hasAttributeNS ( editinfons , "editinfo:memberid" ) ) {
marker . removeAttributeNS ( editinfons , "editinfo:memberid" )
}
} ;
this . getEditInfo = function ( ) {
return editInfo
} ;
this . show = function ( ) {
marker . style . display = "block"
} ;
this . hide = function ( ) {
self . hideHandle ( ) ;
marker . style . display = "none"
} ;
this . showHandle = function ( ) {
handle . show ( )
} ;
this . hideHandle = function ( ) {
handle . hide ( )
} ;
function init ( ) {
var dom = editInfo . getOdtDocument ( ) . getDOM ( ) , htmlns = dom . documentElement . namespaceURI ;
marker = dom . createElementNS ( htmlns , "div" ) ;
marker . setAttribute ( "class" , "editInfoMarker" ) ;
marker . onmouseover = function ( ) {
self . showHandle ( )
} ;
marker . onmouseout = function ( ) {
self . hideHandle ( )
} ;
editInfoNode = editInfo . getNode ( ) ;
editInfoNode . appendChild ( marker ) ;
handle = new gui . EditInfoHandle ( editInfoNode ) ;
if ( ! initialVisibility ) {
self . hide ( )
}
}
init ( )
} ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "gui.Caret" ) ;
runtime . loadClass ( "ops.TrivialMemberModel" ) ;
runtime . loadClass ( "ops.EditInfo" ) ;
runtime . loadClass ( "gui.EditInfoMarker" ) ;
gui . SessionViewOptions = function ( ) {
this . editInfoMarkersInitiallyVisible = true ;
this . caretAvatarsInitiallyVisible = true ;
this . caretBlinksOnRangeSelect = true
} ;
gui . SessionView = function ( ) {
function configOption ( userValue , defaultValue ) {
return userValue !== undefined ? Boolean ( userValue ) : defaultValue
}
function SessionView ( viewOptions , session , caretManager ) {
var avatarInfoStyles , editInfons = "urn:webodf:names:editinfo" , editInfoMap = { } , showEditInfoMarkers = configOption ( viewOptions . editInfoMarkersInitiallyVisible , true ) , showCaretAvatars = configOption ( viewOptions . caretAvatarsInitiallyVisible , true ) , blinkOnRangeSelect = configOption ( viewOptions . caretBlinksOnRangeSelect , true ) ;
function createAvatarInfoNodeMatch ( nodeName , memberId , pseudoClass ) {
return nodeName + '[editinfo|memberid^="' + memberId + '"]' + pseudoClass
}
function getAvatarInfoStyle ( nodeName , memberId , pseudoClass ) {
var node = avatarInfoStyles . firstChild , nodeMatch = createAvatarInfoNodeMatch ( nodeName , memberId , pseudoClass ) ;
while ( node ) {
if ( node . nodeType === Node . TEXT _NODE && node . data . indexOf ( nodeMatch ) === 0 ) {
return node
}
node = node . nextSibling
}
return null
}
function setAvatarInfoStyle ( memberId , name , color ) {
function setStyle ( nodeName , rule , pseudoClass ) {
var styleRule = createAvatarInfoNodeMatch ( nodeName , memberId , pseudoClass ) + rule , styleNode = getAvatarInfoStyle ( nodeName , memberId , pseudoClass ) ;
if ( styleNode ) {
styleNode . data = styleRule
} else {
avatarInfoStyles . appendChild ( document . createTextNode ( styleRule ) )
}
}
setStyle ( "div.editInfoMarker" , "{ background-color: " + color + "; }" , "" ) ;
setStyle ( "span.editInfoColor" , "{ background-color: " + color + "; }" , "" ) ;
setStyle ( "span.editInfoAuthor" , '{ content: "' + name + '"; }' , ":before" ) ;
setStyle ( "dc|creator" , '{ content: "' + name + '"; display: none;}' , ":before" ) ;
setStyle ( "dc|creator" , "{ background-color: " + color + "; }" , "" )
}
function highlightEdit ( element , memberId , timestamp ) {
var editInfo , editInfoMarker , id = "" , editInfoNode = element . getElementsByTagNameNS ( editInfons , "editinfo" ) [ 0 ] ;
if ( editInfoNode ) {
id = editInfoNode . getAttributeNS ( editInfons , "id" ) ;
editInfoMarker = editInfoMap [ id ]
} else {
id = Math . random ( ) . toString ( ) ;
editInfo = new ops . EditInfo ( element , session . getOdtDocument ( ) ) ;
editInfoMarker = new gui . EditInfoMarker ( editInfo , showEditInfoMarkers ) ;
editInfoNode = element . getElementsByTagNameNS ( editInfons , "editinfo" ) [ 0 ] ;
editInfoNode . setAttributeNS ( editInfons , "id" , id ) ;
editInfoMap [ id ] = editInfoMarker
}
editInfoMarker . addEdit ( memberId , new Date ( timestamp ) )
}
function setEditInfoMarkerVisbility ( visible ) {
var editInfoMarker , keyname ;
for ( keyname in editInfoMap ) {
if ( editInfoMap . hasOwnProperty ( keyname ) ) {
editInfoMarker = editInfoMap [ keyname ] ;
if ( visible ) {
editInfoMarker . show ( )
} else {
editInfoMarker . hide ( )
}
}
}
}
function setCaretAvatarVisibility ( visible ) {
caretManager . getCarets ( ) . forEach ( function ( caret ) {
if ( visible ) {
caret . showHandle ( )
} else {
caret . hideHandle ( )
}
} )
}
this . showEditInfoMarkers = function ( ) {
if ( showEditInfoMarkers ) {
return
}
showEditInfoMarkers = true ;
setEditInfoMarkerVisbility ( showEditInfoMarkers )
} ;
this . hideEditInfoMarkers = function ( ) {
if ( ! showEditInfoMarkers ) {
return
}
showEditInfoMarkers = false ;
setEditInfoMarkerVisbility ( showEditInfoMarkers )
} ;
this . showCaretAvatars = function ( ) {
if ( showCaretAvatars ) {
return
}
showCaretAvatars = true ;
setCaretAvatarVisibility ( showCaretAvatars )
} ;
this . hideCaretAvatars = function ( ) {
if ( ! showCaretAvatars ) {
return
}
showCaretAvatars = false ;
setCaretAvatarVisibility ( showCaretAvatars )
} ;
this . getSession = function ( ) {
return session
} ;
this . getCaret = function ( memberid ) {
return caretManager . getCaret ( memberid )
} ;
function renderMemberData ( memberId , memberData ) {
var caret = caretManager . getCaret ( memberId ) ;
if ( memberData === undefined ) {
runtime . log ( 'MemberModel sent undefined data for member "' + memberId + '".' ) ;
return
}
if ( memberData === null ) {
memberData = { memberid : memberId , fullname : "Unknown Identity" , color : "black" , imageurl : "avatar-joe.png" }
}
if ( caret ) {
caret . setAvatarImageUrl ( memberData . imageurl ) ;
caret . setColor ( memberData . color )
}
setAvatarInfoStyle ( memberId , memberData . fullname , memberData . color )
}
function onCursorAdded ( cursor ) {
var memberId = cursor . getMemberId ( ) , memberModel = session . getMemberModel ( ) ;
caretManager . registerCursor ( cursor , showCaretAvatars , blinkOnRangeSelect ) ;
renderMemberData ( memberId , null ) ;
memberModel . getMemberDetailsAndUpdates ( memberId , renderMemberData ) ;
runtime . log ( "+++ View here +++ eagerly created an Caret for '" + memberId + "'! +++" )
}
function onCursorRemoved ( memberid ) {
var hasMemberEditInfo = false , keyname ;
for ( keyname in editInfoMap ) {
if ( editInfoMap . hasOwnProperty ( keyname ) && editInfoMap [ keyname ] . getEditInfo ( ) . getEdits ( ) . hasOwnProperty ( memberid ) ) {
hasMemberEditInfo = true ;
break
}
}
if ( ! hasMemberEditInfo ) {
session . getMemberModel ( ) . unsubscribeMemberDetailsUpdates ( memberid , renderMemberData )
}
}
this . close = function ( callback ) {
callback ( )
} ;
function init ( ) {
var odtDocument = session . getOdtDocument ( ) , head = document . getElementsByTagName ( "head" ) [ 0 ] ;
odtDocument . subscribe ( ops . OdtDocument . signalCursorAdded , onCursorAdded ) ;
odtDocument . subscribe ( ops . OdtDocument . signalCursorRemoved , onCursorRemoved ) ;
odtDocument . subscribe ( ops . OdtDocument . signalParagraphChanged , function ( info ) {
highlightEdit ( info . paragraphElement , info . memberId , info . timeStamp )
} ) ;
avatarInfoStyles = document . createElementNS ( head . namespaceURI , "style" ) ;
avatarInfoStyles . type = "text/css" ;
avatarInfoStyles . media = "screen, print, handheld, projection" ;
avatarInfoStyles . appendChild ( document . createTextNode ( "@namespace editinfo url(urn:webodf:names:editinfo);" ) ) ;
avatarInfoStyles . appendChild ( document . createTextNode ( "@namespace dc url(http://purl.org/dc/elements/1.1/);" ) ) ;
head . appendChild ( avatarInfoStyles )
}
init ( )
}
return SessionView
} ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "gui.Caret" ) ;
gui . CaretManager = function CaretManager ( sessionController ) {
var carets = { } ;
function getCaret ( memberId ) {
return carets . hasOwnProperty ( memberId ) ? carets [ memberId ] : null
}
function getCanvasElement ( ) {
return sessionController . getSession ( ) . getOdtDocument ( ) . getOdfCanvas ( ) . getElement ( )
}
function removeCaret ( memberId ) {
if ( memberId === sessionController . getInputMemberId ( ) ) {
getCanvasElement ( ) . removeAttribute ( "tabindex" )
}
delete carets [ memberId ]
}
function refreshLocalCaretBlinking ( cursor ) {
var caret , memberId = cursor . getMemberId ( ) ;
if ( memberId === sessionController . getInputMemberId ( ) ) {
caret = getCaret ( memberId ) ;
if ( caret ) {
caret . refreshCursorBlinking ( )
}
}
}
function ensureLocalCaretVisible ( info ) {
var caret ;
if ( info . memberId === sessionController . getInputMemberId ( ) ) {
caret = getCaret ( info . memberId ) ;
if ( caret ) {
caret . ensureVisible ( )
}
}
}
function focusLocalCaret ( ) {
var caret = getCaret ( sessionController . getInputMemberId ( ) ) ;
if ( caret ) {
caret . setFocus ( )
}
}
function blurLocalCaret ( ) {
var caret = getCaret ( sessionController . getInputMemberId ( ) ) ;
if ( caret ) {
caret . removeFocus ( )
}
}
this . registerCursor = function ( cursor , caretAvatarInitiallyVisible , blinkOnRangeSelect ) {
var memberid = cursor . getMemberId ( ) , canvasElement = getCanvasElement ( ) , caret = new gui . Caret ( cursor , caretAvatarInitiallyVisible , blinkOnRangeSelect ) ;
carets [ memberid ] = caret ;
if ( memberid === sessionController . getInputMemberId ( ) ) {
runtime . log ( "Starting to track input on new cursor of " + memberid ) ;
cursor . handleUpdate = caret . ensureVisible ;
canvasElement . setAttribute ( "tabindex" , 0 ) ;
canvasElement . focus ( )
}
return caret
} ;
this . getCaret = getCaret ;
this . getCarets = function ( ) {
return Object . keys ( carets ) . map ( function ( memberid ) {
return carets [ memberid ]
} )
} ;
function init ( ) {
var session = sessionController . getSession ( ) , odtDocument = session . getOdtDocument ( ) , canvasElement = getCanvasElement ( ) ;
odtDocument . subscribe ( ops . OdtDocument . signalParagraphChanged , ensureLocalCaretVisible ) ;
odtDocument . subscribe ( ops . OdtDocument . signalCursorMoved , refreshLocalCaretBlinking ) ;
odtDocument . subscribe ( ops . OdtDocument . signalCursorRemoved , removeCaret ) ;
canvasElement . onfocus = focusLocalCaret ;
canvasElement . onblur = blurLocalCaret
}
init ( )
} ;
runtime . loadClass ( "xmldom.XPath" ) ;
runtime . loadClass ( "odf.Namespaces" ) ;
gui . PresenterUI = function ( ) {
var xpath = new xmldom . XPath , window = runtime . getWindow ( ) ;
return function PresenterUI ( odf _element ) {
var self = this ;
self . setInitialSlideMode = function ( ) {
self . startSlideMode ( "single" )
} ;
self . keyDownHandler = function ( ev ) {
if ( ev . target . isContentEditable ) {
return
}
if ( ev . target . nodeName === "input" ) {
return
}
switch ( ev . keyCode ) {
case 84 :
self . toggleToolbar ( ) ;
break ;
case 37 :
;
case 8 :
self . prevSlide ( ) ;
break ;
case 39 :
;
case 32 :
self . nextSlide ( ) ;
break ;
case 36 :
self . firstSlide ( ) ;
break ;
case 35 :
self . lastSlide ( ) ;
break
}
} ;
self . root = function ( ) {
return self . odf _canvas . odfContainer ( ) . rootElement
} ;
self . firstSlide = function ( ) {
self . slideChange ( function ( old , pc ) {
return 0
} )
} ;
self . lastSlide = function ( ) {
self . slideChange ( function ( old , pc ) {
return pc - 1
} )
} ;
self . nextSlide = function ( ) {
self . slideChange ( function ( old , pc ) {
return old + 1 < pc ? old + 1 : - 1
} )
} ;
self . prevSlide = function ( ) {
self . slideChange ( function ( old , pc ) {
return old < 1 ? - 1 : old - 1
} )
} ;
self . slideChange = function ( indexChanger ) {
var pages = self . getPages ( self . odf _canvas . odfContainer ( ) . rootElement ) , last = - 1 , i = 0 , newidx , pagelist ;
pages . forEach ( function ( tuple ) {
var node = tuple [ 1 ] ;
if ( node . hasAttribute ( "slide_current" ) ) {
last = i ;
node . removeAttribute ( "slide_current" )
}
i += 1
} ) ;
newidx = indexChanger ( last , pages . length ) ;
if ( newidx === - 1 ) {
newidx = last
}
pages [ newidx ] [ 1 ] . setAttribute ( "slide_current" , "1" ) ;
pagelist = document . getElementById ( "pagelist" ) ;
pagelist . selectedIndex = newidx ;
if ( self . slide _mode === "cont" ) {
window . scrollBy ( 0 , pages [ newidx ] [ 1 ] . getBoundingClientRect ( ) . top - 30 )
}
} ;
self . selectSlide = function ( idx ) {
self . slideChange ( function ( old , pc ) {
if ( idx >= pc ) {
return - 1
}
if ( idx < 0 ) {
return - 1
}
return idx
} )
} ;
self . scrollIntoContView = function ( idx ) {
var pages = self . getPages ( self . odf _canvas . odfContainer ( ) . rootElement ) ;
if ( pages . length === 0 ) {
return
}
window . scrollBy ( 0 , pages [ idx ] [ 1 ] . getBoundingClientRect ( ) . top - 30 )
} ;
self . getPages = function ( root ) {
var pagenodes = root . getElementsByTagNameNS ( odf . Namespaces . drawns , "page" ) , pages = [ ] , i ;
for ( i = 0 ; i < pagenodes . length ; i += 1 ) {
pages . push ( [ pagenodes [ i ] . getAttribute ( "draw:name" ) , pagenodes [ i ] ] )
}
return pages
} ;
self . fillPageList = function ( odfdom _root , html _select ) {
var pages = self . getPages ( odfdom _root ) , i , html _option , res , page _denom ;
while ( html _select . firstChild ) {
html _select . removeChild ( html _select . firstChild )
}
for ( i = 0 ; i < pages . length ; i += 1 ) {
html _option = document . createElement ( "option" ) ;
res = xpath . getODFElementsWithXPath ( pages [ i ] [ 1 ] , './draw:frame[@presentation:class="title"]//draw:text-box/text:p' , xmldom . XPath ) ;
page _denom = res . length > 0 ? res [ 0 ] . textContent : pages [ i ] [ 0 ] ;
html _option . textContent = i + 1 + ": " + page _denom ;
html _select . appendChild ( html _option )
}
} ;
self . startSlideMode = function ( mode ) {
var pagelist = document . getElementById ( "pagelist" ) , css = self . odf _canvas . slidevisibilitycss ( ) . sheet ;
self . slide _mode = mode ;
while ( css . cssRules . length > 0 ) {
css . deleteRule ( 0 )
}
self . selectSlide ( 0 ) ;
if ( self . slide _mode === "single" ) {
css . insertRule ( "draw|page { position:fixed; left:0px;top:30px; z-index:1; }" , 0 ) ;
css . insertRule ( "draw|page[slide_current] { z-index:2;}" , 1 ) ;
css . insertRule ( "draw|page { -webkit-transform: scale(1);}" , 2 ) ;
self . fitToWindow ( ) ;
window . addEventListener ( "resize" , self . fitToWindow , false )
} else {
if ( self . slide _mode === "cont" ) {
window . removeEventListener ( "resize" , self . fitToWindow , false )
}
}
self . fillPageList ( self . odf _canvas . odfContainer ( ) . rootElement , pagelist )
} ;
self . toggleToolbar = function ( ) {
var css , found , i ;
css = self . odf _canvas . slidevisibilitycss ( ) . sheet ;
found = - 1 ;
for ( i = 0 ; i < css . cssRules . length ; i += 1 ) {
if ( css . cssRules [ i ] . cssText . substring ( 0 , 8 ) === ".toolbar" ) {
found = i ;
break
}
}
if ( found > - 1 ) {
css . deleteRule ( found )
} else {
css . insertRule ( ".toolbar { position:fixed; left:0px;top:-200px; z-index:0; }" , 0 )
}
} ;
self . fitToWindow = function ( ) {
function ruleByFactor ( f ) {
return "draw|page { \n" + "-moz-transform: scale(" + f + "); \n" + "-moz-transform-origin: 0% 0%; " + "-webkit-transform-origin: 0% 0%; -webkit-transform: scale(" + f + "); " + "-o-transform-origin: 0% 0%; -o-transform: scale(" + f + "); " + "-ms-transform-origin: 0% 0%; -ms-transform: scale(" + f + "); " + "}"
}
var pages = self . getPages ( self . root ( ) ) , factorVert = ( window . innerHeight - 40 ) / pages [ 0 ] [ 1 ] . clientHeight , factorHoriz = ( window . innerWidth - 10 ) / pages [ 0 ] [ 1 ] . clientWidth , factor = factorVert < factorHoriz ? factorVert : factorHoriz , css = self . odf _canvas . slidevisibilitycss ( ) . sheet ;
css . deleteRule ( 2 ) ;
css . insertRule ( ruleByFactor ( factor ) , 2 )
} ;
self . load = function ( url ) {
self . odf _canvas . load ( url )
} ;
self . odf _element = odf _element ;
self . odf _canvas = new odf . OdfCanvas ( self . odf _element ) ;
self . odf _canvas . addListener ( "statereadychange" , self . setInitialSlideMode ) ;
self . slide _mode = "undefined" ;
document . addEventListener ( "keydown" , self . keyDownHandler , false )
}
} ( ) ;
runtime . loadClass ( "core.PositionIterator" ) ;
runtime . loadClass ( "core.Cursor" ) ;
gui . XMLEdit = function XMLEdit ( element , stylesheet ) {
var simplecss , cssprefix , documentElement , walker = null ;
if ( ! element . id ) {
element . id = "xml" + String ( Math . random ( ) ) . substring ( 2 )
}
cssprefix = "#" + element . id + " " ;
simplecss = cssprefix + "*," + cssprefix + ":visited, " + cssprefix + ":link {display:block; margin: 0px; margin-left: 10px; font-size: medium; color: black; background: white; font-variant: normal; font-weight: normal; font-style: normal; font-family: sans-serif; text-decoration: none; white-space: pre-wrap; height: auto; width: auto}\n" + cssprefix + ":before {color: blue; content: '<' attr(customns_name) attr(customns_atts) '>';}\n" + cssprefix + ":after {color: blue; content: '</' attr(customns_name) '>';}\n" +
cssprefix + "{overflow: auto;}\n" ;
function listenEvent ( eventTarget , eventType , eventHandler ) {
if ( eventTarget . addEventListener ) {
eventTarget . addEventListener ( eventType , eventHandler , false )
} else {
if ( eventTarget . attachEvent ) {
eventType = "on" + eventType ;
eventTarget . attachEvent ( eventType , eventHandler )
} else {
eventTarget [ "on" + eventType ] = eventHandler
}
}
}
function cancelEvent ( event ) {
if ( event . preventDefault ) {
event . preventDefault ( )
} else {
event . returnValue = false
}
}
function isCaretMoveCommand ( charCode ) {
if ( charCode >= 16 && charCode <= 20 ) {
return true
}
if ( charCode >= 33 && charCode <= 40 ) {
return true
}
return false
}
function syncSelectionWithWalker ( ) {
var sel = element . ownerDocument . defaultView . getSelection ( ) , r ;
if ( ! sel || sel . rangeCount <= 0 || ! walker ) {
return
}
r = sel . getRangeAt ( 0 ) ;
walker . setPoint ( r . startContainer , r . startOffset )
}
function syncWalkerWithSelection ( ) {
var sel = element . ownerDocument . defaultView . getSelection ( ) , n , r ;
sel . removeAllRanges ( ) ;
if ( ! walker || ! walker . node ( ) ) {
return
}
n = walker . node ( ) ;
r = n . ownerDocument . createRange ( ) ;
r . setStart ( n , walker . position ( ) ) ;
r . collapse ( true ) ;
sel . addRange ( r )
}
function handleKeyDown ( event ) {
var charCode = event . charCode || event . keyCode ;
walker = null ;
if ( walker && charCode === 39 ) {
syncSelectionWithWalker ( ) ;
walker . stepForward ( ) ;
syncWalkerWithSelection ( )
} else {
if ( walker && charCode === 37 ) {
syncSelectionWithWalker ( ) ;
walker . stepBackward ( ) ;
syncWalkerWithSelection ( )
} else {
if ( isCaretMoveCommand ( charCode ) ) {
return
}
}
}
cancelEvent ( event )
}
function handleClick ( event ) {
cancelEvent ( event )
}
function initElement ( element ) {
listenEvent ( element , "click" , handleClick ) ;
listenEvent ( element , "keydown" , handleKeyDown ) ;
listenEvent ( element , "drop" , cancelEvent ) ;
listenEvent ( element , "dragend" , cancelEvent ) ;
listenEvent ( element , "beforepaste" , cancelEvent ) ;
listenEvent ( element , "paste" , cancelEvent )
}
function cleanWhitespace ( node ) {
var n = node . firstChild , p , re = /^\s*$/ ;
while ( n && n !== node ) {
p = n ;
n = n . nextSibling || n . parentNode ;
if ( p . nodeType === Node . TEXT _NODE && re . test ( p . nodeValue ) ) {
p . parentNode . removeChild ( p )
}
}
}
function setCssHelperAttributes ( node ) {
var atts , attsv , a , i ;
atts = node . attributes ;
attsv = "" ;
for ( i = atts . length - 1 ; i >= 0 ; i -= 1 ) {
a = atts . item ( i ) ;
attsv = attsv + " " + a . nodeName + '="' + a . nodeValue + '"'
}
node . setAttribute ( "customns_name" , node . nodeName ) ;
node . setAttribute ( "customns_atts" , attsv )
}
function addExplicitAttributes ( node ) {
var n = node . firstChild ;
while ( n && n !== node ) {
if ( n . nodeType === Node . ELEMENT _NODE ) {
addExplicitAttributes ( n )
}
n = n . nextSibling || n . parentNode
}
setCssHelperAttributes ( node ) ;
cleanWhitespace ( node )
}
function getNamespacePrefixes ( node , prefixes ) {
var n = node . firstChild , atts , att , i ;
while ( n && n !== node ) {
if ( n . nodeType === Node . ELEMENT _NODE ) {
getNamespacePrefixes ( n , prefixes ) ;
atts = n . attributes ;
for ( i = atts . length - 1 ; i >= 0 ; i -= 1 ) {
att = atts . item ( i ) ;
if ( att . namespaceURI === "http://www.w3.org/2000/xmlns/" ) {
if ( ! prefixes [ att . nodeValue ] ) {
prefixes [ att . nodeValue ] = att . localName
}
}
}
}
n = n . nextSibling || n . parentNode
}
}
function generateUniquePrefixes ( prefixes ) {
var taken = { } , ns , p , n = 0 ;
for ( ns in prefixes ) {
if ( prefixes . hasOwnProperty ( ns ) && ns ) {
p = prefixes [ ns ] ;
if ( ! p || taken . hasOwnProperty ( p ) || p === "xmlns" ) {
do {
p = "ns" + n ;
n += 1
} while ( taken . hasOwnProperty ( p ) ) ;
prefixes [ ns ] = p
}
taken [ p ] = true
}
}
}
function createCssFromXmlInstance ( node ) {
var prefixes = { } , css = "@namespace customns url(customns);\n" ;
getNamespacePrefixes ( node , prefixes ) ;
generateUniquePrefixes ( prefixes ) ;
return css
}
function updateCSS ( ) {
var css = element . ownerDocument . createElement ( "style" ) , text = createCssFromXmlInstance ( element ) ;
css . type = "text/css" ;
text = text + simplecss ;
css . appendChild ( element . ownerDocument . createTextNode ( text ) ) ;
stylesheet = stylesheet . parentNode . replaceChild ( css , stylesheet )
}
function getXML ( ) {
return documentElement
}
function setXML ( xml ) {
var node = xml . documentElement || xml ;
node = element . ownerDocument . importNode ( node , true ) ;
documentElement = node ;
addExplicitAttributes ( node ) ;
while ( element . lastChild ) {
element . removeChild ( element . lastChild )
}
element . appendChild ( node ) ;
updateCSS ( ) ;
walker = new core . PositionIterator ( node )
}
initElement ( element ) ;
this . updateCSS = updateCSS ;
this . setXML = setXML ;
this . getXML = getXML
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
gui . UndoManager = function UndoManager ( ) {
} ;
gui . UndoManager . prototype . subscribe = function ( signal , callback ) {
} ;
gui . UndoManager . prototype . unsubscribe = function ( signal , callback ) {
} ;
gui . UndoManager . prototype . setOdtDocument = function ( newDocument ) {
} ;
gui . UndoManager . prototype . saveInitialState = function ( ) {
} ;
gui . UndoManager . prototype . resetInitialState = function ( ) {
} ;
gui . UndoManager . prototype . setPlaybackFunction = function ( playback _func ) {
} ;
gui . UndoManager . prototype . hasUndoStates = function ( ) {
} ;
gui . UndoManager . prototype . hasRedoStates = function ( ) {
} ;
gui . UndoManager . prototype . moveForward = function ( states ) {
} ;
gui . UndoManager . prototype . moveBackward = function ( states ) {
} ;
gui . UndoManager . prototype . onOperationExecuted = function ( op ) {
} ;
gui . UndoManager . signalUndoStackChanged = "undoStackChanged" ;
gui . UndoManager . signalUndoStateCreated = "undoStateCreated" ;
gui . UndoManager . signalUndoStateModified = "undoStateModified" ;
( function ( ) {
return gui . UndoManager
} ) ( ) ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
gui . UndoStateRules = function UndoStateRules ( ) {
function getOpType ( op ) {
return op . spec ( ) . optype
}
this . getOpType = getOpType ;
function getOpPosition ( op ) {
return op . spec ( ) . position
}
function isEditOperation ( op ) {
switch ( getOpType ( op ) ) {
case "MoveCursor" :
;
case "AddCursor" :
;
case "RemoveCursor" :
return false ;
default :
return true
}
}
this . isEditOperation = isEditOperation ;
function canAggregateOperation ( optype ) {
switch ( optype ) {
case "RemoveText" :
;
case "InsertText" :
return true ;
default :
return false
}
}
function isSameDirectionOfTravel ( recentEditOps , thisOp ) {
var existing1 = getOpPosition ( recentEditOps [ recentEditOps . length - 2 ] ) , existing2 = getOpPosition ( recentEditOps [ recentEditOps . length - 1 ] ) , thisPos = getOpPosition ( thisOp ) , direction = existing2 - existing1 ;
return existing2 === thisPos - direction
}
function isContinuousOperation ( recentEditOps , thisOp ) {
var optype = getOpType ( thisOp ) ;
if ( canAggregateOperation ( optype ) && optype === getOpType ( recentEditOps [ 0 ] ) ) {
if ( recentEditOps . length === 1 ) {
return true
}
if ( isSameDirectionOfTravel ( recentEditOps , thisOp ) ) {
return true
}
}
return false
}
function isPartOfOperationSet ( operation , lastOperations ) {
if ( isEditOperation ( operation ) ) {
if ( lastOperations . length === 0 ) {
return true
}
return isEditOperation ( lastOperations [ lastOperations . length - 1 ] ) && isContinuousOperation ( lastOperations . filter ( isEditOperation ) , operation )
}
return true
}
this . isPartOfOperationSet = isPartOfOperationSet
} ;
/ *
Copyright ( C ) 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.DomUtils" ) ;
runtime . loadClass ( "gui.UndoManager" ) ;
runtime . loadClass ( "gui.UndoStateRules" ) ;
gui . TrivialUndoManager = function TrivialUndoManager ( defaultRules ) {
var self = this , cursorns = "urn:webodf:names:cursor" , domUtils = new core . DomUtils , initialDoc , initialState = [ ] , playFunc , odtDocument , currentUndoState = [ ] , undoStates = [ ] , redoStates = [ ] , eventNotifier = new core . EventNotifier ( [ gui . UndoManager . signalUndoStackChanged , gui . UndoManager . signalUndoStateCreated , gui . UndoManager . signalUndoStateModified , gui . TrivialUndoManager . signalDocumentRootReplaced ] ) , undoRules = defaultRules || new gui . UndoStateRules ;
function emitStackChange ( ) {
eventNotifier . emit ( gui . UndoManager . signalUndoStackChanged , { undoAvailable : self . hasUndoStates ( ) , redoAvailable : self . hasRedoStates ( ) } )
}
function mostRecentUndoState ( ) {
return undoStates [ undoStates . length - 1 ]
}
function completeCurrentUndoState ( ) {
if ( currentUndoState !== initialState && currentUndoState !== mostRecentUndoState ( ) ) {
undoStates . push ( currentUndoState )
}
}
function removeNode ( node ) {
var sibling = node . previousSibling || node . nextSibling ;
node . parentNode . removeChild ( node ) ;
domUtils . normalizeTextNodes ( sibling )
}
function removeCursors ( root ) {
domUtils . getElementsByTagNameNS ( root , cursorns , "cursor" ) . forEach ( removeNode ) ;
domUtils . getElementsByTagNameNS ( root , cursorns , "anchor" ) . forEach ( removeNode )
}
function values ( obj ) {
return Object . keys ( obj ) . map ( function ( key ) {
return obj [ key ]
} )
}
function extractCursorStates ( undoStates ) {
var addCursor = { } , moveCursor = { } , requiredAddOps = { } , remainingAddOps , operations = undoStates . pop ( ) ;
odtDocument . getCursors ( ) . forEach ( function ( cursor ) {
requiredAddOps [ cursor . getMemberId ( ) ] = true
} ) ;
remainingAddOps = Object . keys ( requiredAddOps ) . length ;
function processOp ( op ) {
var spec = op . spec ( ) ;
if ( ! requiredAddOps [ spec . memberid ] ) {
return
}
switch ( spec . optype ) {
case "AddCursor" :
if ( ! addCursor [ spec . memberid ] ) {
addCursor [ spec . memberid ] = op ;
delete requiredAddOps [ spec . memberid ] ;
remainingAddOps -= 1
}
break ;
case "MoveCursor" :
if ( ! moveCursor [ spec . memberid ] ) {
moveCursor [ spec . memberid ] = op
}
break
}
}
while ( operations && remainingAddOps > 0 ) {
operations . reverse ( ) ;
operations . forEach ( processOp ) ;
operations = undoStates . pop ( )
}
return values ( addCursor ) . concat ( values ( moveCursor ) )
}
this . subscribe = function ( signal , callback ) {
eventNotifier . subscribe ( signal , callback )
} ;
this . unsubscribe = function ( signal , callback ) {
eventNotifier . unsubscribe ( signal , callback )
} ;
this . hasUndoStates = function ( ) {
return undoStates . length > 0
} ;
this . hasRedoStates = function ( ) {
return redoStates . length > 0
} ;
this . setOdtDocument = function ( newDocument ) {
odtDocument = newDocument
} ;
this . resetInitialState = function ( ) {
undoStates . length = 0 ;
redoStates . length = 0 ;
initialState . length = 0 ;
currentUndoState . length = 0 ;
initialDoc = null ;
emitStackChange ( )
} ;
this . saveInitialState = function ( ) {
var odfContainer = odtDocument . getOdfCanvas ( ) . odfContainer ( ) , annotationManager = odtDocument . getOdfCanvas ( ) . getAnnotationManager ( ) ;
if ( annotationManager ) {
annotationManager . forgetAnnotations ( )
}
initialDoc = odfContainer . rootElement . cloneNode ( true ) ;
odtDocument . getOdfCanvas ( ) . refreshAnnotations ( ) ;
removeCursors ( initialDoc ) ;
completeCurrentUndoState ( ) ;
undoStates . unshift ( initialState ) ;
currentUndoState = initialState = extractCursorStates ( undoStates ) ;
undoStates . length = 0 ;
redoStates . length = 0 ;
emitStackChange ( )
} ;
this . setPlaybackFunction = function ( playback _func ) {
playFunc = playback _func
} ;
this . onOperationExecuted = function ( op ) {
redoStates . length = 0 ;
if ( undoRules . isEditOperation ( op ) && currentUndoState === initialState || ! undoRules . isPartOfOperationSet ( op , currentUndoState ) ) {
completeCurrentUndoState ( ) ;
currentUndoState = [ op ] ;
undoStates . push ( currentUndoState ) ;
eventNotifier . emit ( gui . UndoManager . signalUndoStateCreated , { operations : currentUndoState } ) ;
emitStackChange ( )
} else {
currentUndoState . push ( op ) ;
eventNotifier . emit ( gui . UndoManager . signalUndoStateModified , { operations : currentUndoState } )
}
} ;
this . moveForward = function ( states ) {
var moved = 0 , redoOperations ;
while ( states && redoStates . length ) {
redoOperations = redoStates . pop ( ) ;
undoStates . push ( redoOperations ) ;
redoOperations . forEach ( playFunc ) ;
states -= 1 ;
moved += 1
}
if ( moved ) {
currentUndoState = mostRecentUndoState ( ) ;
emitStackChange ( )
}
return moved
} ;
this . moveBackward = function ( states ) {
var odfCanvas = odtDocument . getOdfCanvas ( ) , odfContainer = odfCanvas . odfContainer ( ) , moved = 0 ;
while ( states && undoStates . length ) {
redoStates . push ( undoStates . pop ( ) ) ;
states -= 1 ;
moved += 1
}
if ( moved ) {
odfContainer . setRootElement ( initialDoc . cloneNode ( true ) ) ;
odfCanvas . setOdfContainer ( odfContainer , true ) ;
eventNotifier . emit ( gui . TrivialUndoManager . signalDocumentRootReplaced , { } ) ;
odtDocument . getCursors ( ) . forEach ( function ( cursor ) {
odtDocument . removeCursor ( cursor . getMemberId ( ) )
} ) ;
initialState . forEach ( playFunc ) ;
undoStates . forEach ( function ( ops ) {
ops . forEach ( playFunc )
} ) ;
odfCanvas . refreshCSS ( ) ;
currentUndoState = mostRecentUndoState ( ) || initialState ;
emitStackChange ( )
}
return moved
}
} ;
gui . TrivialUndoManager . signalDocumentRootReplaced = "documentRootReplaced" ;
( function ( ) {
return gui . TrivialUndoManager
} ) ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "core.EventNotifier" ) ;
runtime . loadClass ( "odf.OdfUtils" ) ;
runtime . loadClass ( "gui.SelectionMover" ) ;
runtime . loadClass ( "gui.StyleHelper" ) ;
runtime . loadClass ( "core.PositionFilterChain" ) ;
ops . OdtDocument = function OdtDocument ( odfCanvas ) {
var self = this , textns = "urn:oasis:names:tc:opendocument:xmlns:text:1.0" , odfUtils , cursors = { } , eventNotifier = new core . EventNotifier ( [ ops . OdtDocument . signalCursorAdded , ops . OdtDocument . signalCursorRemoved , ops . OdtDocument . signalCursorMoved , ops . OdtDocument . signalParagraphChanged , ops . OdtDocument . signalParagraphStyleModified , ops . OdtDocument . signalStyleCreated , ops . OdtDocument . signalStyleDeleted , ops . OdtDocument . signalTableAdded , ops . OdtDocument . signalOperationExecuted , ops . OdtDocument . signalUndoStackChanged ] ) ,
FILTER _ACCEPT = core . PositionFilter . FilterResult . FILTER _ACCEPT , FILTER _REJECT = core . PositionFilter . FilterResult . FILTER _REJECT , filter ;
function getRootNode ( ) {
var element = odfCanvas . odfContainer ( ) . getContentElement ( ) , localName = element && element . localName ;
runtime . assert ( localName === "text" , "Unsupported content element type '" + localName + "'for OdtDocument" ) ;
return element
}
function RootFilter ( memberId ) {
function isRoot ( node ) {
if ( node . namespaceURI === odf . Namespaces . officens && node . localName === "text" || node . namespaceURI === odf . Namespaces . officens && node . localName === "annotation" ) {
return true
}
return false
}
function getRoot ( node ) {
while ( ! isRoot ( node ) ) {
node = ( node . parentNode )
}
return node
}
this . acceptPosition = function ( iterator ) {
var node = iterator . container ( ) , cursorNode = cursors [ memberId ] . getNode ( ) ;
if ( getRoot ( node ) === getRoot ( cursorNode ) ) {
return FILTER _ACCEPT
}
return FILTER _REJECT
}
}
function TextPositionFilter ( ) {
function checkLeftRight ( container , leftNode , rightNode ) {
var r , firstPos , rightOfChar ;
if ( leftNode ) {
r = odfUtils . lookLeftForCharacter ( leftNode ) ;
if ( r === 1 ) {
return FILTER _ACCEPT
}
if ( r === 2 && ( odfUtils . scanRightForAnyCharacter ( rightNode ) || odfUtils . scanRightForAnyCharacter ( odfUtils . nextNode ( container ) ) ) ) {
return FILTER _ACCEPT
}
}
firstPos = leftNode === null && odfUtils . isParagraph ( container ) ;
rightOfChar = odfUtils . lookRightForCharacter ( rightNode ) ;
if ( firstPos ) {
if ( rightOfChar ) {
return FILTER _ACCEPT
}
return odfUtils . scanRightForAnyCharacter ( rightNode ) ? FILTER _REJECT : FILTER _ACCEPT
}
if ( ! rightOfChar ) {
return FILTER _REJECT
}
leftNode = leftNode || odfUtils . previousNode ( container ) ;
return odfUtils . scanLeftForAnyCharacter ( leftNode ) ? FILTER _REJECT : FILTER _ACCEPT
}
this . acceptPosition = function ( iterator ) {
var container = iterator . container ( ) , nodeType = container . nodeType , offset , text , leftChar , rightChar , leftNode , rightNode , r ;
if ( nodeType !== Node . ELEMENT _NODE && nodeType !== Node . TEXT _NODE ) {
return FILTER _REJECT
}
if ( nodeType === Node . TEXT _NODE ) {
if ( ! odfUtils . isGroupingElement ( container . parentNode ) || odfUtils . isWithinTrackedChanges ( container . parentNode , getRootNode ( ) ) ) {
return FILTER _REJECT
}
offset = iterator . unfilteredDomOffset ( ) ;
text = container . data ;
runtime . assert ( offset !== text . length , "Unexpected offset." ) ;
if ( offset > 0 ) {
leftChar = text . substr ( offset - 1 , 1 ) ;
if ( ! odfUtils . isODFWhitespace ( leftChar ) ) {
return FILTER _ACCEPT
}
if ( offset > 1 ) {
leftChar = text . substr ( offset - 2 , 1 ) ;
if ( ! odfUtils . isODFWhitespace ( leftChar ) ) {
r = FILTER _ACCEPT
} else {
if ( ! odfUtils . isODFWhitespace ( text . substr ( 0 , offset ) ) ) {
return FILTER _REJECT
}
}
} else {
leftNode = odfUtils . previousNode ( container ) ;
if ( odfUtils . scanLeftForNonWhitespace ( leftNode ) ) {
r = FILTER _ACCEPT
}
}
if ( r === FILTER _ACCEPT ) {
return odfUtils . isTrailingWhitespace ( container , offset ) ? FILTER _REJECT : FILTER _ACCEPT
}
rightChar = text . substr ( offset , 1 ) ;
if ( odfUtils . isODFWhitespace ( rightChar ) ) {
return FILTER _REJECT
}
return odfUtils . scanLeftForAnyCharacter ( odfUtils . previousNode ( container ) ) ? FILTER _REJECT : FILTER _ACCEPT
}
leftNode = iterator . leftNode ( ) ;
rightNode = container ;
container = ( container . parentNode ) ;
r = checkLeftRight ( container , leftNode , rightNode )
} else {
if ( ! odfUtils . isGroupingElement ( container ) || odfUtils . isWithinTrackedChanges ( container , getRootNode ( ) ) ) {
r = FILTER _REJECT
} else {
leftNode = iterator . leftNode ( ) ;
rightNode = iterator . rightNode ( ) ;
r = checkLeftRight ( container , leftNode , rightNode )
}
}
return r
}
}
function getIteratorAtPosition ( position ) {
var iterator = gui . SelectionMover . createPositionIterator ( getRootNode ( ) ) ;
position += 1 ;
while ( position > 0 && iterator . nextPosition ( ) ) {
if ( filter . acceptPosition ( iterator ) === 1 ) {
position -= 1
}
}
return iterator
}
this . getIteratorAtPosition = getIteratorAtPosition ;
function getPositionInTextNode ( position , memberid ) {
var iterator = gui . SelectionMover . createPositionIterator ( getRootNode ( ) ) , lastTextNode = null , node , nodeOffset = 0 , cursorNode = null , originalPosition = position ;
runtime . assert ( position >= 0 , "position must be >= 0" ) ;
if ( filter . acceptPosition ( iterator ) === 1 ) {
node = iterator . container ( ) ;
if ( node . nodeType === Node . TEXT _NODE ) {
lastTextNode = ( node ) ;
nodeOffset = 0
}
} else {
position += 1
}
while ( position > 0 || lastTextNode === null ) {
if ( ! iterator . nextPosition ( ) ) {
return null
}
if ( filter . acceptPosition ( iterator ) === 1 ) {
position -= 1 ;
node = iterator . container ( ) ;
if ( node . nodeType === Node . TEXT _NODE ) {
if ( node !== lastTextNode ) {
lastTextNode = ( node ) ;
nodeOffset = iterator . domOffset ( )
} else {
nodeOffset += 1
}
} else {
if ( lastTextNode !== null ) {
if ( position === 0 ) {
nodeOffset = lastTextNode . length ;
break
}
lastTextNode = null
} else {
if ( position === 0 ) {
lastTextNode = getRootNode ( ) . ownerDocument . createTextNode ( "" ) ;
node . insertBefore ( lastTextNode , iterator . rightNode ( ) ) ;
nodeOffset = 0 ;
break
}
}
}
}
}
if ( lastTextNode === null ) {
return null
}
if ( memberid && cursors [ memberid ] && self . getCursorPosition ( memberid ) === originalPosition ) {
cursorNode = cursors [ memberid ] . getNode ( ) ;
while ( nodeOffset === 0 && cursorNode . nextSibling && cursorNode . nextSibling . localName === "cursor" ) {
cursorNode . parentNode . insertBefore ( cursorNode , cursorNode . nextSibling . nextSibling )
}
if ( cursorNode && lastTextNode . length > 0 ) {
lastTextNode = getRootNode ( ) . ownerDocument . createTextNode ( "" ) ;
nodeOffset = 0 ;
cursorNode . parentNode . insertBefore ( lastTextNode , cursorNode . nextSibling )
}
}
while ( nodeOffset === 0 && lastTextNode . previousSibling && lastTextNode . previousSibling . localName === "cursor" ) {
node = lastTextNode . previousSibling ;
if ( lastTextNode . length > 0 ) {
lastTextNode = getRootNode ( ) . ownerDocument . createTextNode ( "" )
}
node . parentNode . insertBefore ( lastTextNode , node ) ;
if ( cursorNode === node ) {
break
}
}
while ( lastTextNode . previousSibling && lastTextNode . previousSibling . nodeType === Node . TEXT _NODE ) {
lastTextNode . previousSibling . appendData ( lastTextNode . data ) ;
nodeOffset = lastTextNode . length + lastTextNode . previousSibling . length ;
lastTextNode = ( lastTextNode . previousSibling ) ;
lastTextNode . parentNode . removeChild ( lastTextNode . nextSibling )
}
return { textNode : lastTextNode , offset : nodeOffset }
}
function getParagraphElement ( node ) {
return odfUtils . getParagraphElement ( node )
}
function getParagraphStyleElement ( styleName ) {
var node ;
node = odfCanvas . getFormatting ( ) . getStyleElement ( styleName , "paragraph" ) ;
return node
}
function getParagraphStyleAttributes ( styleName ) {
var node = getParagraphStyleElement ( styleName ) ;
if ( node ) {
return odfCanvas . getFormatting ( ) . getInheritedStyleAttributes ( node )
}
return null
}
function upgradeWhitespaceToElement ( textNode , offset ) {
runtime . assert ( textNode . data [ offset ] === " " , "upgradeWhitespaceToElement: textNode.data[offset] should be a literal space" ) ;
var space = textNode . ownerDocument . createElementNS ( textns , "text:s" ) ;
space . appendChild ( textNode . ownerDocument . createTextNode ( " " ) ) ;
textNode . deleteData ( offset , 1 ) ;
if ( offset > 0 ) {
textNode = ( textNode . splitText ( offset ) )
}
textNode . parentNode . insertBefore ( space , textNode ) ;
return space
}
function upgradeWhitespacesAtPosition ( position ) {
var iterator = getIteratorAtPosition ( position ) , container , offset , i ;
iterator . previousPosition ( ) ;
iterator . previousPosition ( ) ;
for ( i = - 1 ; i <= 1 ; i += 1 ) {
container = iterator . container ( ) ;
offset = iterator . unfilteredDomOffset ( ) ;
if ( container . nodeType === Node . TEXT _NODE && container . data [ offset ] === " " && odfUtils . isSignificantWhitespace ( container , offset ) ) {
container = upgradeWhitespaceToElement ( ( container ) , offset ) ;
iterator . moveToEndOfNode ( container )
}
iterator . nextPosition ( )
}
}
this . upgradeWhitespacesAtPosition = upgradeWhitespacesAtPosition ;
this . getParagraphStyleElement = getParagraphStyleElement ;
this . getParagraphElement = getParagraphElement ;
this . getParagraphStyleAttributes = getParagraphStyleAttributes ;
this . getPositionInTextNode = getPositionInTextNode ;
this . fixCursorPositions = function ( localMemberId ) {
var memberId , cursor , stepCounter , steps , rootConstrainedFilter = new core . PositionFilterChain ;
rootConstrainedFilter . addFilter ( "BaseFilter" , self . getPositionFilter ( ) ) ;
for ( memberId in cursors ) {
if ( cursors . hasOwnProperty ( memberId ) ) {
rootConstrainedFilter . addFilter ( "RootFilter" , self . createRootFilter ( memberId ) ) ;
cursor = cursors [ memberId ] ;
stepCounter = cursor . getStepCounter ( ) ;
if ( ! stepCounter . isPositionWalkable ( rootConstrainedFilter ) ) {
steps = stepCounter . countStepsToValidPosition ( rootConstrainedFilter ) ;
cursor . move ( steps ) ;
if ( memberId === localMemberId ) {
self . emit ( ops . OdtDocument . signalCursorMoved , cursor )
}
} else {
if ( self . getCursorSelection ( memberId ) . length === 0 ) {
cursor . move ( 0 )
}
}
rootConstrainedFilter . removeFilter ( "RootFilter" )
}
}
} ;
this . getWalkableParagraphLength = function ( paragraph ) {
var iterator = getIteratorAtPosition ( 0 ) , length = 0 ;
iterator . setUnfilteredPosition ( paragraph , 0 ) ;
do {
if ( getParagraphElement ( iterator . container ( ) ) !== paragraph ) {
return length
}
if ( filter . acceptPosition ( iterator ) === 1 ) {
length += 1
}
} while ( iterator . nextPosition ( ) ) ;
return length
} ;
this . getDistanceFromCursor = function ( memberid , node , offset ) {
var counter , cursor = cursors [ memberid ] , steps = 0 ;
runtime . assert ( node !== null && node !== undefined , "OdtDocument.getDistanceFromCursor called without node" ) ;
if ( cursor ) {
counter = cursor . getStepCounter ( ) . countStepsToPosition ;
steps = counter ( node , offset , filter )
}
return steps
} ;
this . getCursorPosition = function ( memberid ) {
return - self . getDistanceFromCursor ( memberid , getRootNode ( ) , 0 )
} ;
this . getCursorSelection = function ( memberid ) {
var counter , cursor = cursors [ memberid ] , focusPosition = 0 , stepsToAnchor = 0 ;
if ( cursor ) {
counter = cursor . getStepCounter ( ) . countStepsToPosition ;
focusPosition = - counter ( getRootNode ( ) , 0 , filter ) ;
stepsToAnchor = counter ( cursor . getAnchorNode ( ) , 0 , filter )
}
return { position : focusPosition + stepsToAnchor , length : - stepsToAnchor }
} ;
this . getPositionFilter = function ( ) {
return filter
} ;
this . getOdfCanvas = function ( ) {
return odfCanvas
} ;
this . getRootNode = getRootNode ;
this . getDOM = function ( ) {
return ( getRootNode ( ) . ownerDocument )
} ;
this . getCursor = function ( memberid ) {
return cursors [ memberid ]
} ;
this . getCursors = function ( ) {
var list = [ ] , i ;
for ( i in cursors ) {
if ( cursors . hasOwnProperty ( i ) ) {
list . push ( cursors [ i ] )
}
}
return list
} ;
this . addCursor = function ( cursor ) {
runtime . assert ( Boolean ( cursor ) , "OdtDocument::addCursor without cursor" ) ;
var distanceToFirstTextNode = cursor . getStepCounter ( ) . countForwardSteps ( 1 , filter ) , memberid = cursor . getMemberId ( ) ;
runtime . assert ( Boolean ( memberid ) , "OdtDocument::addCursor has cursor without memberid" ) ;
runtime . assert ( ! cursors [ memberid ] , "OdtDocument::addCursor is adding a duplicate cursor with memberid " + memberid ) ;
cursor . move ( distanceToFirstTextNode ) ;
cursors [ memberid ] = cursor
} ;
this . removeCursor = function ( memberid ) {
var cursor = cursors [ memberid ] ;
if ( cursor ) {
cursor . removeFromOdtDocument ( ) ;
delete cursors [ memberid ] ;
self . emit ( ops . OdtDocument . signalCursorRemoved , memberid ) ;
return true
}
return false
} ;
this . getMetaData = function ( metadataId ) {
var node = odfCanvas . odfContainer ( ) . rootElement . firstChild ;
while ( node && node . localName !== "meta" ) {
node = node . nextSibling
}
node = node && node . firstChild ;
while ( node && node . localName !== metadataId ) {
node = node . nextSibling
}
node = node && node . firstChild ;
while ( node && node . nodeType !== Node . TEXT _NODE ) {
node = node . nextSibling
}
return node ? node . data : null
} ;
this . getFormatting = function ( ) {
return odfCanvas . getFormatting ( )
} ;
this . getTextElements = function ( range , includeInsignificantWhitespace ) {
return odfUtils . getTextElements ( range , includeInsignificantWhitespace )
} ;
this . getParagraphElements = function ( range ) {
return odfUtils . getParagraphElements ( range )
} ;
this . emit = function ( eventid , args ) {
eventNotifier . emit ( eventid , args )
} ;
this . subscribe = function ( eventid , cb ) {
eventNotifier . subscribe ( eventid , cb )
} ;
this . unsubscribe = function ( eventid , cb ) {
eventNotifier . unsubscribe ( eventid , cb )
} ;
this . createRootFilter = function ( inputMemberId ) {
return new RootFilter ( inputMemberId )
} ;
this . close = function ( callback ) {
callback ( )
} ;
function init ( ) {
filter = new TextPositionFilter ;
odfUtils = new odf . OdfUtils
}
init ( )
} ;
ops . OdtDocument . signalCursorAdded = "cursor/added" ;
ops . OdtDocument . signalCursorRemoved = "cursor/removed" ;
ops . OdtDocument . signalCursorMoved = "cursor/moved" ;
ops . OdtDocument . signalParagraphChanged = "paragraph/changed" ;
ops . OdtDocument . signalTableAdded = "table/added" ;
ops . OdtDocument . signalStyleCreated = "style/created" ;
ops . OdtDocument . signalStyleDeleted = "style/deleted" ;
ops . OdtDocument . signalParagraphStyleModified = "paragraphstyle/modified" ;
ops . OdtDocument . signalOperationExecuted = "operation/executed" ;
ops . OdtDocument . signalUndoStackChanged = "undo/changed" ;
( function ( ) {
return ops . OdtDocument
} ) ( ) ;
/ *
Copyright ( C ) 2012 - 2013 KO GmbH < copyright @ kogmbh . com >
@ licstart
The JavaScript code in this page is free software : you can redistribute it
and / or modify it under the terms of the GNU Affero General Public License
( GNU AGPL ) 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 AGPL for more details .
As additional permission under GNU AGPL 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 .
As a special exception to the AGPL , any HTML file which merely makes function
calls to this code , and for that purpose includes it by reference shall be
deemed a separate work for copyright law purposes . In addition , the copyright
holders of this code give you permission to combine this code with free
software libraries that are released under the GNU LGPL . You may copy and
distribute such a system following the terms of the GNU AGPL for this code
and the LGPL for the libraries . If you modify this code , you may extend this
exception to your version of the code , but you are not obligated to do so .
If you do not wish to do so , delete this exception statement from your
version .
This license applies to this entire compilation .
@ licend
@ source : http : //www.webodf.org/
@ source : http : //gitorious.org/webodf/webodf/
* /
runtime . loadClass ( "ops.TrivialMemberModel" ) ;
runtime . loadClass ( "ops.TrivialOperationRouter" ) ;
runtime . loadClass ( "ops.OperationFactory" ) ;
runtime . loadClass ( "ops.OdtDocument" ) ;
ops . Session = function Session ( odfCanvas ) {
var self = this , operationFactory = new ops . OperationFactory , odtDocument = new ops . OdtDocument ( odfCanvas ) , memberModel = new ops . TrivialMemberModel , operationRouter = null ;
this . setMemberModel = function ( uModel ) {
memberModel = uModel
} ;
this . setOperationFactory = function ( opFactory ) {
operationFactory = opFactory ;
if ( operationRouter ) {
operationRouter . setOperationFactory ( operationFactory )
}
} ;
this . setOperationRouter = function ( opRouter ) {
operationRouter = opRouter ;
opRouter . setPlaybackFunction ( function ( op ) {
op . execute ( odtDocument ) ;
odtDocument . emit ( ops . OdtDocument . signalOperationExecuted , op )
} ) ;
opRouter . setOperationFactory ( operationFactory )
} ;
this . getOperationRouter = function ( ) {
return operationRouter
} ;
this . getMemberModel = function ( ) {
return memberModel
} ;
this . getOperationFactory = function ( ) {
return operationFactory
} ;
this . getOdtDocument = function ( ) {
return odtDocument
} ;
this . enqueue = function ( operation ) {
operationRouter . push ( operation )
} ;
this . close = function ( callback ) {
odtDocument . close ( function ( err ) {
if ( err ) {
callback ( err )
} else {
callback ( )
}
} )
} ;
function init ( ) {
self . setOperationRouter ( new ops . TrivialOperationRouter )
}
init ( )
} ;
var webodf _css = "@namespace draw url(urn:oasis:names:tc:opendocument:xmlns:drawing:1.0);\n@namespace fo url(urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0);\n@namespace office url(urn:oasis:names:tc:opendocument:xmlns:office:1.0);\n@namespace presentation url(urn:oasis:names:tc:opendocument:xmlns:presentation:1.0);\n@namespace style url(urn:oasis:names:tc:opendocument:xmlns:style:1.0);\n@namespace svg url(urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0);\n@namespace table url(urn:oasis:names:tc:opendocument:xmlns:table:1.0);\n@namespace text url(urn:oasis:names:tc:opendocument:xmlns:text:1.0);\n@namespace runtimens url(urn:webodf); /* namespace for runtime only */\n@namespace cursor url(urn:webodf:names:cursor);\n@namespace editinfo url(urn:webodf:names:editinfo);\n@namespace annotation url(urn:webodf:names:annotation);\n@namespace dc url(http://purl.org/dc/elements/1.1/);\n\noffice|document > *, office|document-content > * {\n display: none;\n}\noffice|body, office|document {\n display: inline-block;\n position: relative;\n}\n\ntext|p, text|h {\n display: block;\n padding: 0;\n margin: 0;\n line-height: normal;\n position: relative;\n min-height: 1.3em; /* prevent empty paragraphs and headings from collapsing if they are empty */\n}\n*[runtimens|containsparagraphanchor] {\n position: relative;\n}\ntext|s {\n white-space: pre;\n}\ntext|tab {\n display: inline;\n white-space: pre;\n}\ntext|line-break {\n content: \" \" ; \ n display : block ; \ n } \ ntext | tracked - changes { \ n /*Consumers that do not support change tracking, should ignore changes.*/ \ n display : none ; \ n } \ noffice | binary - data { \ n display : none ; \ n } \ noffice | text { \ n display : block ; \ n text - align : left ; \ n overflow : visible ; \ n word - wrap : break - word ; \ n } \ n \ noffice | text : : selection { \ n /** Let's not draw selection highlight that overflows into the office|text\n * node when selecting content across several paragraphs\n */ \ n background : transparent ; \ n } \ noffice | text * draw | text - box { \ n /** only for text documents */ \ n display : block ; \ n border : 1 px solid # d3d3d3 ; \ n } \ noffice | spreadsheet { \ n display : block ; \ n border - collapse : collapse ; \ n empty - cells : show ; \ n font - family : sans - serif ; \ n font - size : 10 pt ; \ n text - align : left ; \ n page - break - inside : avoid ; \ n overflow : hidden ; \ n } \ noffice | presentation { \ n display : inline - block ; \ n text - align : left ; \ n } \ n # shadowContent { \ n display : inline - block ; \ n text - align : left ; \ n } \ ndraw | page { \ n display : block ; \ n position : relative ; \ n overflow : hidden ; \ n } \ npresentation | notes , presentation | footer - decl , presentation | date - time - decl { \ n display : none ; \ n } \ n @ media print { \ n draw | page { \ n border : 1 pt solid black ; \ n page - break - inside : avoid ; \ n } \ n presentation | notes { \ n /*TODO*/ \ n } \ n } \ noffice | spreadsheet text | p { \ n border : 0 px ; \ n padding : 1 px ; \ n margin : 0 px ; \ n } \ noffice | spreadsheet table | table { \ n margin : 3 px ; \ n } \ noffice | spreadsheet table | table : after { \ n /* show sheet name the end of the sheet */ \ n /*content: attr(table|name);*/ /* gives parsing error in opera */ \ n } \ noffice | spreadsheet table | table - row { \ n counter - increment : row ; \ n } \ noffice | spreadsheet table | table - row : before { \ n width : 3 em ; \ n background : # cccccc ; \ n border : 1 px solid black ; \ n text - align : center ; \ n content : counter ( row ) ; \ n display : table - cell ; \ n } \ noffice | spreadsheet table | table - cell { \ n border : 1 px solid # cccccc ; \ n } \ ntable | table { \ n display : table ; \ n } \ ndraw | frame table | table { \ n width : 100 % ; \ n height : 100 % ; \ n background : white ; \ n } \ ntable | table - header - rows { \ n display : table - header - group ; \ n } \ ntable | table - row { \ n display : table - row ; \ n } \ ntable | table - column { \ n display : table - column ; \ n } \ ntable | table - cell { \ n width : 0.889 in ; \ n display : table - cell ; \ n word - break : break - all ; /* prevent long words from extending out the table cell */ \ n } \ ndraw | frame { \ n display : block ; \ n } \ ndraw | image { \ n display : block ; \ n width : 100 % ; \ n height : 100 % ; \ n top : 0 px ; \ n left : 0 px ; \ n background - repeat : no - repeat ; \ n background - size : 100 % 100 % ; \ n - moz - background - size : 100 % 100 % ; \ n } \ n / * only show the first i