forked from Botanical/BotanJS
Initial commit
This commit is contained in:
parent
f19f612fad
commit
4c93896df3
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
*~
|
||||
*.swp
|
||||
*.pyc
|
||||
__pycache__
|
||||
cache/*
|
||||
logs/*
|
30
README.md
30
README.md
@ -6,3 +6,33 @@ A working concept of Js/Css framework for web browsers
|
||||
- Python-like, class oriented syntax structure
|
||||
- Everything is merged into one file for that page
|
||||
- css class inheritance
|
||||
|
||||
### Disclaimer
|
||||
- This is a working concept. So it works on me. And may have a bunch of useless dependency. Use at your own risks!
|
||||
- It requires Python 3!
|
||||
|
||||
|
||||
### Documentation
|
||||
- Will be added later
|
||||
|
||||
### Prerequisties
|
||||
#### For Service.WebAPI
|
||||
- pip install Flask
|
||||
- pip install Celery
|
||||
- pip install redis
|
||||
- pip install compressinja
|
||||
|
||||
#### Environment varialbles
|
||||
```
|
||||
PYTHONPATH=<path to the parent of this directory>
|
||||
```
|
||||
|
||||
#### For the compressor & cache, run:
|
||||
```
|
||||
celery -A botanjs.service.jwork worker
|
||||
```
|
||||
|
||||
#### For the API Serivces, run:
|
||||
```
|
||||
./service/webapi.py
|
||||
```
|
||||
|
12
botan-rebuild.py
Executable file
12
botan-rebuild.py
Executable file
@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
import os, sys
|
||||
sys.path.append( os.path.abspath( "." ) )
|
||||
|
||||
from botanjs.service.jwork import app, JWork
|
||||
from botanjs.config import Config as config
|
||||
|
||||
bmap = os.path.join( config["Paths"]["Cache"], "botanjs", "bmap.xml" )
|
||||
|
||||
app.conf.update( BROKER_URL = config["BotanJS"]["CeleryBroker"] )
|
||||
|
||||
JWork.buildClassMap.delay( config["BotanJS"]["SrcDir"], bmap )
|
75
botan-start.py
Executable file
75
botan-start.py
Executable file
@ -0,0 +1,75 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os, pwd, grp
|
||||
from botanjs.config import Config as config
|
||||
|
||||
def drop_privileges( uid_name='nobody', gid_name='nogroup' ):
|
||||
# Get the uid/gid from the name
|
||||
running_uid = pwd.getpwnam( uid_name ).pw_uid
|
||||
running_gid = grp.getgrnam( gid_name ).gr_gid
|
||||
|
||||
current_uid = os.getuid()
|
||||
|
||||
if current_uid != 0:
|
||||
if running_uid == current_uid:
|
||||
return True
|
||||
print( "Service must be started by root" )
|
||||
return False
|
||||
|
||||
# Remove group privileges
|
||||
os.setgroups([])
|
||||
|
||||
# Try setting the new uid/gid
|
||||
os.setgid( running_gid )
|
||||
os.setuid( running_uid )
|
||||
|
||||
# Ensure a very conservative umask
|
||||
old_umask = os.umask( 0o022 )
|
||||
|
||||
return True
|
||||
|
||||
import shutil
|
||||
|
||||
# Create the lock folder for celery
|
||||
lockDir = "/var/run/celery"
|
||||
os.makedirs( lockDir, exist_ok=True )
|
||||
shutil.chown( lockDir, config["Service"]["user"] )
|
||||
|
||||
# Imediately drop the root privilege
|
||||
if drop_privileges( config["Service"]["user"], config["Service"]["group"] ) != True:
|
||||
exit()
|
||||
|
||||
import sys
|
||||
from subprocess import Popen
|
||||
|
||||
sys.path.append( os.path.abspath( "." ) )
|
||||
|
||||
from botanjs.service.webapi import WebAPI
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
jwork = "botanjs.service.jwork"
|
||||
nodeName = "botanNode1"
|
||||
|
||||
Popen([
|
||||
"celery"
|
||||
, "multi"
|
||||
, "restart"
|
||||
, nodeName
|
||||
, "-A"
|
||||
, jwork
|
||||
, "worker"
|
||||
, "--pidfile=/var/run/celery/" + jwork + ".pid"
|
||||
, "--logfile=" + os.path.join( config["Paths"]["Log"], jwork + ".log" )
|
||||
, "--workdir=" + config["Paths"]["Runtime"]
|
||||
, "beat"
|
||||
, "-l"
|
||||
, "info"
|
||||
]).communicate()
|
||||
|
||||
WebAPI(
|
||||
jsCache = config["Paths"]["Cache"]
|
||||
, jsRoot = config["BotanJS"]["SrcDir"]
|
||||
, brokerURL = config["BotanJS"]["CeleryBroker"]
|
||||
)
|
||||
|
0
botanjs/__init__.py
Normal file
0
botanjs/__init__.py
Normal file
193
botanjs/classmap.py
Normal file
193
botanjs/classmap.py
Normal file
@ -0,0 +1,193 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os;
|
||||
import re;
|
||||
import sys;
|
||||
|
||||
from xml.dom import minidom
|
||||
from collections import defaultdict
|
||||
|
||||
RegEx_N = re.compile( r"""
|
||||
.*
|
||||
__namespace
|
||||
\s*\(
|
||||
\s*(['"])([^\1]+)\1
|
||||
\s*\)
|
||||
.*
|
||||
""", re.X )
|
||||
|
||||
RegEx_I = re.compile( r"""
|
||||
.*
|
||||
__import
|
||||
\s*\(
|
||||
\s*(['"])([^\1]+)\1
|
||||
\s*\)
|
||||
.*
|
||||
""", re.X )
|
||||
|
||||
RegEx_V = re.compile( r"""
|
||||
.*
|
||||
ns
|
||||
\s*\[
|
||||
\s*NS_INVOKE
|
||||
\s*\]
|
||||
\s*\(
|
||||
\s*(['"])([^\1]+)\1
|
||||
\s*\)
|
||||
.*
|
||||
""", re.X )
|
||||
|
||||
RegEx_E = re.compile( r"""
|
||||
.*
|
||||
ns
|
||||
\s*\[
|
||||
\s*NS_EXPORT
|
||||
\s*\]
|
||||
\s*\(
|
||||
\s*EX_([A-Z_]+[A-Z])
|
||||
\s*,
|
||||
\s*(['"])([^\1]+)\2
|
||||
\s*,
|
||||
[^\)]+
|
||||
\s*\)
|
||||
.*
|
||||
""", re.X )
|
||||
|
||||
def classMeta( cf ):
|
||||
ns = ""
|
||||
imps = list()
|
||||
exps = list()
|
||||
for line in open( cf, "r" ):
|
||||
|
||||
m = RegEx_N.match( line )
|
||||
if m:
|
||||
ns = m.group(2)
|
||||
continue
|
||||
|
||||
m = RegEx_I.match( line )
|
||||
if m:
|
||||
imps.append( m.group(2) )
|
||||
continue
|
||||
|
||||
m = RegEx_V.match( line )
|
||||
if m:
|
||||
imps.append( ns + "." + m.group(2) )
|
||||
continue
|
||||
|
||||
m = RegEx_E.match( line )
|
||||
if m:
|
||||
exps.append( [ m.group(1), m.group(3) ] )
|
||||
continue
|
||||
|
||||
return [ ns, imps, exps ]
|
||||
|
||||
def className( classFile ):
|
||||
return ( os.path
|
||||
.splitext( classFile )[0]
|
||||
.replace( os.sep, "." )
|
||||
.replace( "._this", "" )
|
||||
.replace( "..BotanJS.", "" ) )
|
||||
|
||||
# __export types definition => nodeName
|
||||
EX_CLASS = "class"
|
||||
EX_FUNC = "method"
|
||||
eDef = defaultdict( lambda: 'prop', { "CLASS": EX_CLASS, "FUNC": EX_FUNC } )
|
||||
|
||||
class ClassMap:
|
||||
head = None
|
||||
DOM = None
|
||||
R = None
|
||||
|
||||
def __init__( self, BotanRoot ):
|
||||
self.R = BotanRoot
|
||||
self.DOM = minidom.parseString( "<BotanJS></BotanJS>" )
|
||||
head = os.path.join( self.R, "_this.js" )
|
||||
|
||||
def getNode( self, name, t = EX_CLASS ):
|
||||
paths = name.split( "." )
|
||||
|
||||
currentNode = self.DOM.firstChild
|
||||
|
||||
# Step down the path and create the path if necessary
|
||||
for path in paths:
|
||||
|
||||
l = currentNode.childNodes
|
||||
for i in l:
|
||||
if i.getAttribute( "name" ) == path:
|
||||
currentNode = i
|
||||
break
|
||||
|
||||
if currentNode.getAttribute( "name" ) != path:
|
||||
newNode = self.DOM.createElement( t )
|
||||
newNode.setAttribute( "name", path )
|
||||
currentNode.appendChild( newNode )
|
||||
currentNode = newNode
|
||||
|
||||
return currentNode
|
||||
|
||||
|
||||
|
||||
def skipFile( self, cf ):
|
||||
|
||||
if os.path.splitext( cf )[1] == ".js":
|
||||
if cf == self.head:
|
||||
return True
|
||||
return False
|
||||
|
||||
return True;
|
||||
|
||||
def drawMap( self, ns, ci, ce, cf ):
|
||||
nsNode = self.getNode( ns )
|
||||
|
||||
# Source every:
|
||||
# Since namespace may differ from file name
|
||||
# ns.__export may export to a different level
|
||||
# Source the exported val explicitly means
|
||||
# exports only available when source file is imported
|
||||
srcEvery = ( ns != className( cf ) )
|
||||
|
||||
cf = cf.replace( self.R, "" )
|
||||
|
||||
if not srcEvery:
|
||||
nsNode.setAttribute( "src", cf )
|
||||
|
||||
for ex in ce:
|
||||
_t = eDef[ ex[0] ]
|
||||
cNode = self.getNode( ns + "." + ex[1], t = _t )
|
||||
|
||||
if srcEvery:
|
||||
# The import is for the defined class
|
||||
if _t == EX_CLASS:
|
||||
for imp in ci:
|
||||
impNode = self.DOM.createElement( "import" )
|
||||
impNode.appendChild( self.DOM.createTextNode( imp ) )
|
||||
cNode.appendChild( impNode )
|
||||
|
||||
cNode.setAttribute( "src", cf )
|
||||
|
||||
# the file dose not export classes
|
||||
# Hence it import for itself
|
||||
if not srcEvery:
|
||||
for imp in ci:
|
||||
impNode = self.DOM.createElement( "import" )
|
||||
impNode.appendChild( self.DOM.createTextNode( imp ) )
|
||||
nsNode.appendChild( impNode )
|
||||
|
||||
|
||||
def build( self ):
|
||||
for root, dirs, files in os.walk( self.R ):
|
||||
|
||||
if root == self.R:
|
||||
dirs.remove("externs")
|
||||
|
||||
for name in files:
|
||||
classFile = os.path.join( root, name )
|
||||
|
||||
if self.skipFile( classFile ):
|
||||
continue
|
||||
|
||||
ns, ci, ce = classMeta( classFile )
|
||||
classFile = classFile.replace( self.R + os.path.sep, "" )
|
||||
self.drawMap( ns, ci, ce, classFile )
|
||||
return self.DOM.toxml()
|
||||
|
0
botanjs/compressor/__init__.py
Normal file
0
botanjs/compressor/__init__.py
Normal file
51
botanjs/compressor/closure.py
Executable file
51
botanjs/compressor/closure.py
Executable file
@ -0,0 +1,51 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
from tempfile import NamedTemporaryFile
|
||||
|
||||
COMPILER = "/opt/utils/closure.jar"
|
||||
|
||||
if not os.path.isfile( COMPILER ):
|
||||
raise Exception( "Compiler not found" )
|
||||
|
||||
|
||||
COMPILER_OPTIONS = [
|
||||
"--compilation_level ADVANCED_OPTIMIZATIONS"
|
||||
, "--output_wrapper=\"(function(){%output%})();\""
|
||||
]
|
||||
|
||||
|
||||
class Wrapper:
|
||||
|
||||
C = None
|
||||
# externs
|
||||
E = ""
|
||||
|
||||
def __init__( self ):
|
||||
self.C = "java -jar "+ COMPILER + " " + " ".join( COMPILER_OPTIONS )
|
||||
|
||||
def scanExterns( self, sdir ):
|
||||
for root, dirs, files in os.walk( sdir ):
|
||||
# Split file extensions
|
||||
files = list( os.path.splitext( x ) for x in files )
|
||||
files.sort()
|
||||
for f in files:
|
||||
files.remove( f ) if f[1] != ".js" else None
|
||||
|
||||
self.E = " --externs " + " --externs ".join(
|
||||
os.path.join( root, x )
|
||||
# join back extensions
|
||||
for x in list( "".join( x ) for x in files )
|
||||
)
|
||||
break
|
||||
|
||||
def compress( self, loc ):
|
||||
content = ""
|
||||
with open( loc, "rb" ) as f:
|
||||
content = f.read()
|
||||
|
||||
with NamedTemporaryFile() as f:
|
||||
f.write( content[12:-5] )
|
||||
os.system( self.C + self.E + " --js " + f.name + " --js_output_file " + loc[:-3] + ".c.js" )
|
||||
|
||||
|
23
botanjs/compressor/yui.py
Executable file
23
botanjs/compressor/yui.py
Executable file
@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
|
||||
COMPILER = "/opt/utils/yuicompressor.jar"
|
||||
|
||||
if not os.path.isfile( COMPILER ):
|
||||
raise Exception( "Compiler not found" )
|
||||
|
||||
COMPILER_OPTIONS = [
|
||||
"--type css"
|
||||
]
|
||||
|
||||
class Wrapper:
|
||||
|
||||
C = None
|
||||
|
||||
def __init__( self ):
|
||||
self.C = "java -jar " + COMPILER + " " + " ".join( COMPILER_OPTIONS )
|
||||
|
||||
def compress( self, loc ):
|
||||
os.system( self.C + " " + loc + " -o " + loc[:-4] + ".c.css" )
|
||||
|
5
botanjs/config.py
Executable file
5
botanjs/config.py
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
import configparser
|
||||
|
||||
Config = configparser.ConfigParser( interpolation = configparser.ExtendedInterpolation() )
|
||||
Config.read( "settings.ini" )
|
0
botanjs/service/__init__.py
Normal file
0
botanjs/service/__init__.py
Normal file
335
botanjs/service/jclassresv.py
Normal file
335
botanjs/service/jclassresv.py
Normal file
@ -0,0 +1,335 @@
|
||||
|
||||
import os
|
||||
import re
|
||||
import base64
|
||||
import zlib
|
||||
import hashlib
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
PY_SEP = os.path.sep
|
||||
|
||||
def wrapScope( src ):
|
||||
return "(function(){" + src + "})();"
|
||||
|
||||
class Resolver:
|
||||
resolved = None
|
||||
|
||||
bMap = None
|
||||
parentMap = None
|
||||
|
||||
EX_PROP = "prop"
|
||||
EX_FUNC = "method"
|
||||
EX_CLASS = "class"
|
||||
|
||||
def __init__( self, classMap ):
|
||||
self.classMap = classMap
|
||||
self._reload()
|
||||
|
||||
def _reload( self ):
|
||||
self.bMap = ET.parse( self.classMap )
|
||||
# ElementTree does not support Element.find( ".." )
|
||||
# Make a parent map to work around
|
||||
self.parentMap = { c:p for p in self.bMap.iter() for c in p }
|
||||
|
||||
self.resolved = []
|
||||
|
||||
def resource( self, elem ):
|
||||
if "src" in elem.attrib:
|
||||
return elem.attrib[ "src" ]
|
||||
|
||||
parent = self.parentMap[ elem ]
|
||||
|
||||
if parent != None:
|
||||
return self.resource( parent )
|
||||
|
||||
def resolve( self, c, classList ):
|
||||
self.resolved = []
|
||||
self.__resolve( c, classList )
|
||||
|
||||
def __resolve( self, c, classList ):
|
||||
|
||||
lista = list( "[@name=\"" + x + "\"]" for x in c.split(".") )
|
||||
|
||||
fx = "/".join( self.EX_CLASS + x for x in lista[:-1] )
|
||||
|
||||
it = lista[-1]
|
||||
# Test if class
|
||||
elem = self.bMap.find( ".//" + fx + self.EX_CLASS + it )
|
||||
|
||||
if elem == None:
|
||||
if fx != '': fx += "/"
|
||||
|
||||
# Test if prop
|
||||
elem = self.bMap.find( ".//" + fx + self.EX_PROP + it )
|
||||
|
||||
# test if func
|
||||
if elem == None:
|
||||
elem = self.bMap.find( ".//" + fx + self.EX_FUNC + it )
|
||||
|
||||
if elem == None:
|
||||
raise LookupError( "No such class: " + c )
|
||||
|
||||
imports = self.parentMap[ elem ].findall( "import" )
|
||||
|
||||
else:
|
||||
imports = elem.findall( "import" )
|
||||
|
||||
self.resolved.append( c )
|
||||
|
||||
for imp in imports:
|
||||
if imp.text not in self.resolved:
|
||||
self.__resolve( imp.text, classList )
|
||||
|
||||
classList.append([ c, elem ])
|
||||
|
||||
class BotanClassResolver:
|
||||
R = ""
|
||||
CR = None
|
||||
|
||||
classMap = ""
|
||||
flagCompress = True
|
||||
returnHash = False
|
||||
resv = None
|
||||
|
||||
def __init__( self, jwork, BotanRoot, classMap, cacheRoot ):
|
||||
|
||||
self.JWork = jwork;
|
||||
self.R = os.path.abspath( BotanRoot )
|
||||
self.CR = os.path.abspath( cacheRoot )
|
||||
|
||||
os.makedirs( self.CR, 0o755, exist_ok = True )
|
||||
|
||||
if not os.path.exists( classMap ):
|
||||
self.JWork.buildClassMap( self.R, classMap )
|
||||
|
||||
self.resv = Resolver( classMap )
|
||||
|
||||
def BotanFile( self, t ):
|
||||
content = ""
|
||||
with open( os.path.join( self.R, t ), "r" ) as f:
|
||||
content = f.read()
|
||||
|
||||
return content
|
||||
|
||||
def BotanCache( self, t ):
|
||||
content = ""
|
||||
with open( t, "r" ) as f:
|
||||
content = f.read()
|
||||
|
||||
return content
|
||||
|
||||
def cleanList( self, lista ):
|
||||
olist = []
|
||||
for i in lista:
|
||||
if i not in olist:
|
||||
olist.append( i )
|
||||
return olist
|
||||
|
||||
def jsLookup( self, classList, classFiles ):
|
||||
for c in classList:
|
||||
src = self.resv.resource( c[1] )
|
||||
|
||||
if src == None:
|
||||
raise LookupError( "Cannot find src file for: " + c[0] )
|
||||
|
||||
if src not in classFiles:
|
||||
classFiles.append( src )
|
||||
|
||||
def cssLookup( self, jsList, cssList ):
|
||||
|
||||
for f in jsList:
|
||||
possibleList = []
|
||||
|
||||
cssFile = os.path.splitext( f )[0] + ".css"
|
||||
|
||||
if cssFile not in possibleList:
|
||||
possibleList.append( cssFile )
|
||||
|
||||
f = f.split( PY_SEP )
|
||||
l = len( f )
|
||||
|
||||
for i in range( 1, l ):
|
||||
cssFile = PY_SEP.join( x for x in f[:-i] ) + PY_SEP + "@_this.css"
|
||||
if cssFile not in possibleList:
|
||||
possibleList.append( cssFile )
|
||||
|
||||
possibleList.sort()
|
||||
|
||||
for f in possibleList:
|
||||
f = f.replace( "@_this.css", "_this.css" )
|
||||
if os.path.exists( os.path.join( self.R, f ) ):
|
||||
cssList.append( f )
|
||||
|
||||
|
||||
def getCache( self, fileList, cName, mode ):
|
||||
if self.CR == None:
|
||||
return None
|
||||
|
||||
md5 = hashlib.md5( bytearray( "".join( fileList ), "utf-8" ) ).hexdigest()
|
||||
|
||||
cName[0] = oFHash = md5 + "." + mode
|
||||
cFHash = md5 + ".c." + mode
|
||||
|
||||
# Raw file
|
||||
oFile = os.path.join( self.CR, oFHash )
|
||||
# Compressed file
|
||||
cFile = os.path.join( self.CR, cFHash )
|
||||
|
||||
dates = list(
|
||||
os.path.getmtime( os.path.join( self.R, x ) )
|
||||
if os.path.exists( os.path.join( self.R, x ) ) else -1
|
||||
for x in fileList
|
||||
)
|
||||
|
||||
# Root file date
|
||||
dates.append( os.path.getmtime( os.path.join( self.R, "_this.js" ) ) );
|
||||
|
||||
if self.useCache( cFile, dates ) and self.flagCompress == True:
|
||||
return cFHash if self.returnHash else self.BotanCache( cFile )
|
||||
|
||||
elif self.useCache( oFile, dates ):
|
||||
self.JWork.saveCache.delay(
|
||||
oFile
|
||||
# Content is None to initiate a compression
|
||||
, None
|
||||
, mode
|
||||
, os.path.join( self.R, "externs" )
|
||||
)
|
||||
|
||||
return oFHash if self.returnHash else self.BotanCache( oFile )
|
||||
|
||||
def useCache( self, f, dList ):
|
||||
if not os.path.exists( f ):
|
||||
return False
|
||||
|
||||
t = os.path.getmtime( f )
|
||||
|
||||
for i in dList:
|
||||
if t < i:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def compileJs( self, cList, xList ):
|
||||
md5 = [ None ]
|
||||
|
||||
for x in xList:
|
||||
cList.remove( x ) if x in cList else None
|
||||
|
||||
cacheFile = self.getCache( cList, md5, "js" )
|
||||
|
||||
if cacheFile != None:
|
||||
return cacheFile;
|
||||
|
||||
# The root file
|
||||
outputJs = self.BotanFile( "_this.js" )
|
||||
|
||||
|
||||
for f in cList:
|
||||
path = (
|
||||
os.path.splitext( f )[0]
|
||||
.replace( PY_SEP, "." )
|
||||
.replace( "._this", "" )
|
||||
)
|
||||
struct = ";BotanJS.define( \"" + path + "\" );"
|
||||
|
||||
outputJs += struct + self.BotanFile( f )
|
||||
|
||||
outputJs = wrapScope( outputJs )
|
||||
|
||||
[ self.JWork.saveCache if self.returnHash else self.JWork.saveCache.delay ][0] (
|
||||
os.path.join( self.CR, md5[0] )
|
||||
, outputJs
|
||||
, "js"
|
||||
, os.path.join( self.R, "externs" )
|
||||
)
|
||||
|
||||
if self.returnHash:
|
||||
return md5[0]
|
||||
|
||||
return outputJs
|
||||
|
||||
def compileCss( self, cList, xList ):
|
||||
cssIList = []
|
||||
cssXList = []
|
||||
self.cssLookup( cList, cssIList )
|
||||
self.cssLookup( xList, cssXList )
|
||||
|
||||
cList = []
|
||||
xList = cssXList
|
||||
|
||||
for x in cssIList:
|
||||
cList.append( x ) if x not in xList else None
|
||||
|
||||
md5 = [ None ]
|
||||
cacheFile = self.getCache( cList, md5, "css" )
|
||||
|
||||
if cacheFile != None:
|
||||
return cacheFile;
|
||||
|
||||
outputCss = ""
|
||||
|
||||
for f in self.cleanList( cList ):
|
||||
outputCss += self.BotanFile( f )
|
||||
|
||||
[ self.JWork.saveCache if self.returnHash else self.JWork.saveCache.delay ][0] (
|
||||
os.path.join( self.CR, md5[0] ), outputCss, "css"
|
||||
)
|
||||
|
||||
if self.returnHash:
|
||||
return md5[0]
|
||||
|
||||
return outputCss
|
||||
|
||||
def getAPI( self, code, mode ):
|
||||
self.flagCompress = True
|
||||
# Should reload on debug mode only
|
||||
self.resv._reload()
|
||||
flag = mode[0]
|
||||
requestAPIs = code
|
||||
sp = "/"
|
||||
|
||||
if flag == "o":
|
||||
mode = mode[1:]
|
||||
elif flag == "r":
|
||||
mode = mode[1:]
|
||||
self.flagCompress = False
|
||||
else:
|
||||
self.returnHash = True
|
||||
requestAPIs = (
|
||||
# decode -> decompress -> split
|
||||
zlib.decompress( base64.b64decode( code, None, True ) )
|
||||
.decode( "utf-8" )
|
||||
)
|
||||
sp = ","
|
||||
|
||||
# strip malicious
|
||||
requestAPIs = (
|
||||
requestAPIs
|
||||
.replace( "[^A-Za-z\.\*" + re.escape( sp ) + " ]", "" )
|
||||
.split( sp )
|
||||
)
|
||||
|
||||
imports = []
|
||||
excludes = []
|
||||
|
||||
for apis in requestAPIs:
|
||||
|
||||
if apis == None: continue
|
||||
|
||||
classList = []
|
||||
lookupList = imports
|
||||
|
||||
if apis[0] == "-":
|
||||
apis = apis[1:]
|
||||
lookupList = excludes
|
||||
|
||||
self.resv.resolve( apis, classList )
|
||||
self.jsLookup( classList, lookupList )
|
||||
|
||||
if mode == "js":
|
||||
return self.compileJs( imports, excludes )
|
||||
elif mode == "css":
|
||||
return self.compileCss( imports, excludes )
|
||||
|
||||
raise TypeError( "Invalid mode: " + js )
|
49
botanjs/service/jwork.py
Normal file
49
botanjs/service/jwork.py
Normal file
@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
from celery import Celery
|
||||
from celery.utils.log import get_task_logger
|
||||
from botanjs.compressor.closure import Wrapper as ClosureWrapper
|
||||
from botanjs.compressor.yui import Wrapper as YUIWrapper
|
||||
from botanjs.classmap import ClassMap
|
||||
|
||||
app = Celery( "botanJWork" )
|
||||
log = get_task_logger( __name__ )
|
||||
|
||||
if os.path.exists( "settings.ini" ):
|
||||
from botanjs.config import Config
|
||||
app.conf.update( BROKER_URL = Config["BotanJS"]["CeleryBroker"] )
|
||||
|
||||
class JWork:
|
||||
|
||||
@app.task()
|
||||
def saveCache( location, content = None, mode = None, externs = "" ):
|
||||
if content != None:
|
||||
log.info( "Writing file(" + str( len( content ) ) + "): " + os.path.abspath( location ) )
|
||||
with open( location, "w" ) as f:
|
||||
f.write( content )
|
||||
|
||||
if mode == "js":
|
||||
JWork.compressJs.delay( location, externs )
|
||||
elif mode == "css":
|
||||
JWork.compressCss.delay( location )
|
||||
|
||||
@app.task()
|
||||
def compressJs( md5, externs ):
|
||||
log.info( "Compress js: " + md5 )
|
||||
w = ClosureWrapper()
|
||||
w.scanExterns( externs )
|
||||
w.compress( md5 )
|
||||
|
||||
@app.task()
|
||||
def compressCss( md5 ):
|
||||
log.info( "Compress css: " + md5 )
|
||||
w = YUIWrapper()
|
||||
w.compress( md5 )
|
||||
|
||||
@app.task()
|
||||
def buildClassMap( src, location ):
|
||||
log.info( "Building Class Map" )
|
||||
c = ClassMap( src )
|
||||
|
||||
with open( location, "w" ) as f:
|
||||
f.write( c.build() )
|
@ -0,0 +1,40 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Botan JS - Test</title>
|
||||
<script>
|
||||
var debugEnv = true;
|
||||
</script>
|
||||
|
||||
<link href="/ocss/Dandelion.CSSAnimations.MovieClip" rel="stylesheet" type="text/css" />
|
||||
<script src="/ojs/Dandelion.CSSAnimations.MovieClip"></script>
|
||||
<script>
|
||||
function load ()
|
||||
{
|
||||
var CSSAnimations = BotanJS.import( "Dandelion.CSSAnimations.*" );
|
||||
var mc = new CSSAnimations.MovieClip(
|
||||
"http://file.astropenguin.net/blog/Gothic/__A.png"
|
||||
// Row, Col
|
||||
, 6 , 7
|
||||
// wh
|
||||
, 125 , 125
|
||||
// Frame, start
|
||||
, 42 , 0
|
||||
);
|
||||
|
||||
// CSSAnimations.MouseOverMovie( mc );
|
||||
|
||||
document.body.appendChild( mc.stage );
|
||||
mc.nextFrame();
|
||||
mc.nextFrame();
|
||||
mc.nextFrame();
|
||||
mc.nextFrame();
|
||||
mc.nextFrame();
|
||||
|
||||
mc.prevFrame();
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
<body onload="load()">
|
||||
</body>
|
||||
</html>
|
25
botanjs/service/templates/test/System.Net.ClassLoader.html
Normal file
25
botanjs/service/templates/test/System.Net.ClassLoader.html
Normal file
@ -0,0 +1,25 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Botan JS - Test</title>
|
||||
<script>
|
||||
var debugEnv = true;
|
||||
var _AstConf_ = { };
|
||||
</script>
|
||||
|
||||
<link href="/ocss/System.Net.ClassLoader" rel="stylesheet" type="text/css" />
|
||||
<script src="/ojs/System.Net.ClassLoader"></script>
|
||||
<script>
|
||||
var Loader = BotanJS.import( "System.Net.ClassLoader" );
|
||||
|
||||
var makeMessagebox = function()
|
||||
{
|
||||
var MessageBox = BotanJS.import( "Components.MessageBox" );
|
||||
new MessageBox( "Title", "Message" ).show();
|
||||
};
|
||||
|
||||
var ldr = new Loader( "/" );
|
||||
ldr.load( "Components.MessageBox", makeMessagebox );
|
||||
</script>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
13
botanjs/service/templates/test/System.utils.IKey.html
Normal file
13
botanjs/service/templates/test/System.utils.IKey.html
Normal file
@ -0,0 +1,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Botan JS - Test</title>
|
||||
<script>
|
||||
var debugEnv = true;
|
||||
var _AstConf_ = { };
|
||||
</script>
|
||||
|
||||
<link href="/ocss/System.utils.IKey" rel="stylesheet" type="text/css" />
|
||||
<script src="/ojs/System.utils.IKey"></script>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
19
botanjs/service/templates/test_list.html
Normal file
19
botanjs/service/templates/test_list.html
Normal file
@ -0,0 +1,19 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Botan JS - List of Tests</title>
|
||||
<style>
|
||||
<!--
|
||||
body {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
-->
|
||||
</style>
|
||||
<body>
|
||||
<pre>
|
||||
{% for d in data %}
|
||||
<a href="/test/{{ d }}">{{ d }}</a>
|
||||
<br>
|
||||
{% endfor %}
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
72
botanjs/service/webapi.py
Executable file
72
botanjs/service/webapi.py
Executable file
@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
from flask import Flask
|
||||
from flask import Response
|
||||
from flask import render_template
|
||||
from botanjs.service.jclassresv import BotanClassResolver as JCResv
|
||||
from botanjs.service.jwork import app as CeleryApp, JWork
|
||||
import os
|
||||
|
||||
class WebAPI:
|
||||
|
||||
app = None
|
||||
|
||||
BRoot = None
|
||||
BMap = None
|
||||
BCache = None
|
||||
|
||||
def __init__( self, jsRoot = "../src", jsCache = "/tmp", brokerURL = None ):
|
||||
|
||||
self.test_templates = os.path.join(
|
||||
os.path.dirname( os.path.realpath( __file__ ) )
|
||||
, "templates"
|
||||
, "test"
|
||||
)
|
||||
|
||||
self.BRoot = os.path.abspath( jsRoot )
|
||||
self.BCache = os.path.join( jsCache, "botanjs" )
|
||||
self.BMap = os.path.join( self.BCache, "bmap.xml" )
|
||||
|
||||
if brokerURL != None:
|
||||
CeleryApp.conf.update( BROKER_URL = brokerURL )
|
||||
|
||||
self.app = Flask( __name__, static_url_path = '', static_folder = self.BCache )
|
||||
self.app.jinja_env.add_extension( "compressinja.html.HtmlCompressor" )
|
||||
|
||||
self.app.add_url_rule( "/test" , view_func = self.r_test_list )
|
||||
self.app.add_url_rule( "/test/<string:test_file>" , view_func = self.r_test )
|
||||
self.app.add_url_rule( "/<path:mode>/<path:code>" , view_func = self.api_request )
|
||||
|
||||
self.app.run( host="0.0.0.0" )
|
||||
|
||||
def r_test_list( self ):
|
||||
for root, dirs, files in os.walk( self.test_templates ):
|
||||
break
|
||||
|
||||
files.sort()
|
||||
files = ( os.path.splitext( x )[0] for x in files )
|
||||
|
||||
return render_template( "test_list.html", data = files )
|
||||
|
||||
def r_test( self, test_file ):
|
||||
return render_template( os.path.join( "test", test_file + ".html" ) )
|
||||
|
||||
|
||||
def api_request( self, mode, code ):
|
||||
try:
|
||||
t = mode[1:]
|
||||
if t == "js":
|
||||
t = "application/javascript"
|
||||
elif t == "css":
|
||||
t = "text/css"
|
||||
|
||||
srvHandler = JCResv( JWork, self.BRoot, self.BMap, self.BCache )
|
||||
return Response( srvHandler.getAPI( code, mode = mode ), mimetype = t )
|
||||
except LookupError as e:
|
||||
return str(e), 404
|
||||
# except Exception as e:
|
||||
# return str(e), 404
|
||||
|
||||
return "Invalid request", 404
|
||||
|
||||
if __name__ == "__main__":
|
||||
WebAPI()
|
71
botanjs/src/Components/Console.css
Normal file
71
botanjs/src/Components/Console.css
Normal file
@ -0,0 +1,71 @@
|
||||
.dbg_statusbar {
|
||||
}
|
||||
|
||||
.dbg_title {
|
||||
padding-bottom: 0.2em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.dbg_lastMsg {
|
||||
float: left;
|
||||
font-family: monospace;
|
||||
color: #AAA;
|
||||
font-size: 1em;
|
||||
|
||||
white-space: nowrap;
|
||||
max-width: 580px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.dbg_led {
|
||||
position: absolute;
|
||||
right: 0.5em;
|
||||
|
||||
color: coral;
|
||||
|
||||
font-size: 0.75em;
|
||||
text-shadow: 0 0 2px;
|
||||
}
|
||||
|
||||
#dbg_led[error] {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
|
||||
#time_stmp {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
font-size: 12px;
|
||||
font-family: Arial,Helvetica,sans-serif;
|
||||
padding: 0.5em;
|
||||
background-color: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
}
|
||||
|
||||
#debugCons[expanded] {
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
#debugCons{
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
#debugWrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#debugWrap textarea.response {
|
||||
line-height: 1.2;
|
||||
height: 350px;
|
||||
padding: 0.2em;
|
||||
|
||||
width: 800px;
|
||||
color: #AAA;
|
||||
background: #333;
|
||||
outline: none;
|
||||
border: none;
|
||||
|
||||
font-family: monospace;
|
||||
}
|
177
botanjs/src/Components/Console.js
Normal file
177
botanjs/src/Components/Console.js
Normal file
@ -0,0 +1,177 @@
|
||||
(function(){
|
||||
// Logger
|
||||
// log things.
|
||||
var ns = __namespace( "Components" );
|
||||
|
||||
/** @type {System.utils.Perf} */
|
||||
var Perf = __import( "System.utils.Perf" );
|
||||
/** @type {System.Cycle} */
|
||||
var Cycle = __import( "System.Cycle" );
|
||||
/** @type {System.Cycle.Tick} */
|
||||
var sTick = __import( "System.Cycle.TICK" );
|
||||
/** @type {System.Global} */
|
||||
var _global = __import( "System.Global" );
|
||||
/** @type {System.Log} */
|
||||
var Log = __import( "System.Log" );
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
/** @type {Dandelion.IDOMElement} */
|
||||
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
||||
/** @type {Components.DockPanel} */
|
||||
var DockPanel = __import( "Components.DockPanel" );
|
||||
|
||||
var objTreeView = function( obj, level, prepend )
|
||||
{
|
||||
var c = "";
|
||||
for (var p in obj)
|
||||
{
|
||||
if(typeof(obj[p]) == "object")
|
||||
{
|
||||
c +=
|
||||
prepend + Array( level + 1 ).join(" ")
|
||||
+ p + ":\n"
|
||||
+ objTreeView(
|
||||
obj[p]
|
||||
, level + 2
|
||||
, 0 < level ? prepend : Array( prepend.length ).join(" ")
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
c += prepend + Array(level + 1).join(" ") + p + ": " + obj[p] + "\n";
|
||||
}
|
||||
}
|
||||
return c;
|
||||
};
|
||||
|
||||
var Console = function ()
|
||||
{
|
||||
var stage = null
|
||||
, response_txt = null
|
||||
, lastMsg = null
|
||||
, time_txt = null
|
||||
, otop = ""
|
||||
, cycle = 0
|
||||
, sampling = 500
|
||||
, led = null
|
||||
|
||||
, ticking = function () {
|
||||
if( debugEnv )
|
||||
{
|
||||
time_txt.innerHTML = ( sTick.count - cycle ) + " cps, Sampling " + sampling + "ms";
|
||||
cycle = sTick.count;
|
||||
if(led) led.style.color = "yellowgreen";
|
||||
}
|
||||
}
|
||||
|
||||
, writeLine = function ( dat, type )
|
||||
{
|
||||
var res_txt = response_txt;
|
||||
|
||||
res_txt.value += "\n" + ( dat = ( dat != undefined ? dat.toString() : "undefined" ) );
|
||||
|
||||
lastMsg.textContent = lastMsg.innerText = dat;
|
||||
|
||||
// disabling color will make led blink since ticking is frequently setting the color to default
|
||||
led.style.color = "";
|
||||
if( otop ) stage.style.top = otop;
|
||||
res_txt.scrollTop = res_txt.scrollHeight;
|
||||
}
|
||||
|
||||
, writeError = function (dat)
|
||||
{
|
||||
writeLine( dat );
|
||||
led.setAttribute( "error", 1 );
|
||||
stage.setAttribute( "expanded", 1 );
|
||||
}
|
||||
, LogHandle = function( mesg, type )
|
||||
{
|
||||
if( type == Log.ERROR ) writeError( mesg );
|
||||
else writeLine( mesg );
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
response_txt = Dand.wrap('textarea', null, 'response');
|
||||
// Time stamp on the bottom right corner
|
||||
time_txt = Dand.wrap('span', 'time_stmp');
|
||||
|
||||
// append child
|
||||
document.body.appendChild(time_txt);
|
||||
|
||||
response_txt.readOnly = true;
|
||||
|
||||
stage = new DockPanel(
|
||||
"debugCons"
|
||||
, Dand.wrapc(
|
||||
'dbg_statusbar'
|
||||
, [
|
||||
Dand.wrapc('dbg_title', "Debug Console(Press F9)")
|
||||
, lastMsg = Dand.wrapc('dbg_lastMsg')
|
||||
, led = Dand.wrap('div', 'dbg_led', 'dbg_led', '\u25CF')
|
||||
]
|
||||
)
|
||||
, Dand.wrap( null, 'debugWrap', null, response_txt )
|
||||
, "dtop"
|
||||
);
|
||||
|
||||
var istage = IDOMElement( stage );
|
||||
|
||||
Cycle.next(
|
||||
function ()
|
||||
{
|
||||
// get otop
|
||||
otop = this.getDAttribute("top");
|
||||
}.bind( istage )
|
||||
);
|
||||
|
||||
var autoHide = function () { this.style.top = ""; }.bind(stage);
|
||||
Cycle.perma('gTicker' + Perf.uuid, ticking, sampling);
|
||||
Cycle.perma('gTicker' + Perf.uuid, autoHide, 3000);
|
||||
debugEnv = true;
|
||||
|
||||
ticking();
|
||||
|
||||
var f9Binding = function ( e )
|
||||
{
|
||||
e = e || window.event;
|
||||
if ( e.keyCode ) code = e.keyCode;
|
||||
else if ( e.which ) code = e.which;
|
||||
|
||||
if ( code == 120 )
|
||||
{
|
||||
if( this.hasAttribute( "expanded" ) )
|
||||
{
|
||||
this.removeAttribute( "expanded" );
|
||||
led.hasAttribute( "error" ) && led.removeAttribute( "error" );
|
||||
this.style.top = otop;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setAttribute( "expanded", "1" );
|
||||
}
|
||||
}
|
||||
}.bind( stage );
|
||||
|
||||
//Attach the var with the event = function
|
||||
if(document.addEventListener) document.addEventListener('keydown', f9Binding, false);
|
||||
else if(document.attachEvent) document.attachEvent('onkeydown', f9Binding);
|
||||
else document.onkeydown = f9Binding;
|
||||
|
||||
this.log = writeLine;
|
||||
this.logError = writeError;
|
||||
|
||||
Log.registerHandler( LogHandle );
|
||||
// This will output the debug info
|
||||
if( window["debug_info"] )
|
||||
{
|
||||
debug.Info( objTreeView( debug_info, 0, "[Server] " ) );
|
||||
}
|
||||
};
|
||||
|
||||
__static_method( Console, "objTreeView", objTreeView );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "Console", Console );
|
||||
})();
|
34
botanjs/src/Components/DockPanel.css
Normal file
34
botanjs/src/Components/DockPanel.css
Normal file
@ -0,0 +1,34 @@
|
||||
.right {text-align: right;}
|
||||
|
||||
.window {
|
||||
z-index: 99;
|
||||
border: 1px darkgrey solid;
|
||||
background: #222;
|
||||
}
|
||||
|
||||
.window > span {
|
||||
display:-moz-inline-block;
|
||||
display:-moz-inline-box;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
.titleBar {
|
||||
font-family: custom-sans;
|
||||
font-size: 1em;
|
||||
padding: 0.3em 0.5em;
|
||||
cursor: default;
|
||||
color: white;
|
||||
}
|
||||
|
||||
div[class^="fdock"] {
|
||||
position: fixed;
|
||||
transition: all .5s ease-in-out;
|
||||
-webkit-transition: all .5s ease-in-out;
|
||||
-moz-transition: all .5s ease-in-out;
|
||||
}
|
||||
|
||||
div.dleft { left: 0; }
|
||||
div.dtop { top: -100%; }
|
||||
div.dright { right: 0; }
|
||||
div.dbottom { bottom: 1.5em; }
|
||||
|
54
botanjs/src/Components/DockPanel.js
Normal file
54
botanjs/src/Components/DockPanel.js
Normal file
@ -0,0 +1,54 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components" );
|
||||
|
||||
/** @type {System.Cycle} */
|
||||
var Cycle = __import( "System.Cycle" );
|
||||
/** @type {System.utils.DataKey} */
|
||||
var DataKey = __import( "System.utils.DataKey" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
/** @type {Dandelion.IDOMElement} */
|
||||
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
||||
|
||||
var DockPanel = function( w_id, w_title, w_content, align )
|
||||
{
|
||||
var w_div = Dand.wrapc('window')
|
||||
, w_titleBar = Dand.wrapc('titleBar', w_title)
|
||||
;
|
||||
|
||||
if( align.indexOf('top') != -1 )
|
||||
{
|
||||
w_div.appendChild( Dand.wrapc( 'contentPanel', w_content ) );
|
||||
w_div.appendChild( w_titleBar );
|
||||
w_div.style.position = "absolute";
|
||||
|
||||
Cycle.next(function ()
|
||||
{
|
||||
w_div.style.transition = "none";
|
||||
w_div.style.top = -w_content.clientHeight + "px";
|
||||
IDOMElement( w_div ).setAttribute( new DataKey( "top", w_div.style.top ) );
|
||||
Cycle.next( function () { w_div.style.transition = ""; } );
|
||||
});
|
||||
}
|
||||
else if( align.indexOf('bottom') != -1 )
|
||||
{
|
||||
w_div.appendChild(w_titleBar);
|
||||
w_div.appendChild( Dand.wrapc( 'contentPanel', w_content ) );
|
||||
|
||||
Cycle.next(function ()
|
||||
{
|
||||
w_div.style.transition = "none";
|
||||
// w_div.style.bottom = String(w_content.clientHeight) + "px";
|
||||
// IDOMElement(w_div).addEventListeners();
|
||||
Cycle.next(function () { w_div.style.transition = ""; });
|
||||
});
|
||||
}
|
||||
|
||||
w_div = Dand.wrap( null, w_id, 'fdock ' + align, w_div );
|
||||
|
||||
document.body.appendChild( w_div );
|
||||
return w_div;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "DockPanel", DockPanel );
|
||||
})();
|
62
botanjs/src/Components/MessageBox.css
Normal file
62
botanjs/src/Components/MessageBox.css
Normal file
@ -0,0 +1,62 @@
|
||||
.mbox_mask {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.mbox_body {
|
||||
min-width: 350px;
|
||||
min-height: 100px;
|
||||
max-width: 800px;
|
||||
max-height: 600px;
|
||||
position: absolute;
|
||||
background: #222;
|
||||
|
||||
-moz-box-shadow: 0 0 10px black;
|
||||
-webkit-box-shadow: 0 0 10px black;
|
||||
box-shadow: 0 0 10px black;
|
||||
}
|
||||
|
||||
.mbox_titlebar {
|
||||
font-size: 1.2em;
|
||||
padding: 0.35em;
|
||||
color: white;
|
||||
background: #181818;
|
||||
}
|
||||
|
||||
.mbox_content {
|
||||
min-height: 80px;
|
||||
padding: 1em;
|
||||
font-family: sans-serif;
|
||||
color: white;
|
||||
|
||||
/*
|
||||
-moz-box-shadow: inset 0 10px 10px -10px black;
|
||||
-webkit-box-shadow: inset 0 10px 10px -10px black;
|
||||
box-shadow: inset 0 10px 10px -10px black;
|
||||
*/
|
||||
}
|
||||
|
||||
.mbox_buttons {
|
||||
text-align: right;
|
||||
padding: 1em 0.5em;
|
||||
}
|
||||
|
||||
.mbox_button {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.mbox_button > span {
|
||||
padding: 0.5em 1em;
|
||||
margin: 0.2em;
|
||||
color: white;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.mbox_button > span:hover {
|
||||
background: orangered;
|
||||
}
|
91
botanjs/src/Components/MessageBox.js
Normal file
91
botanjs/src/Components/MessageBox.js
Normal file
@ -0,0 +1,91 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components" );
|
||||
|
||||
/** @type {System.Cycle} */
|
||||
var Trigger = __import( "System.Cycle.Trigger" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
|
||||
// __import( "Dandelion.CSSAnimations" ); CSS_RESERVATION
|
||||
|
||||
var MessageBox = function ( title, content, yes, no, handler )
|
||||
{
|
||||
var _yes = Dand.wrap(
|
||||
"span", null
|
||||
, "mbox_button"
|
||||
, Dand.wrap( "span", null, "comp flsf", yes || "OK" )
|
||||
);
|
||||
|
||||
// left right button
|
||||
_yes.onclick = function()
|
||||
{
|
||||
// if handler is set
|
||||
if( this.clickHandler ) this.clickHandler( true );
|
||||
document.body.removeChild( this.stage );
|
||||
this.stage = null;
|
||||
}.bind( this );
|
||||
|
||||
if ( no )
|
||||
{
|
||||
var _no = Dand.wrap(
|
||||
"span", null
|
||||
, "mbox_button"
|
||||
, Dand.wrap( "span", null, "comp flsf", no )
|
||||
);
|
||||
|
||||
_no.onclick = function()
|
||||
{
|
||||
if( this.clickHandler ) this.clickHandler( false );
|
||||
document.body.removeChild( this.stage );
|
||||
this.stage = null;
|
||||
}.bind( this );
|
||||
}
|
||||
|
||||
|
||||
// set handler
|
||||
if ( handler ) this.clickHandler = handler;
|
||||
|
||||
this.stage = Dand.wrapc(
|
||||
"mbox_mask"
|
||||
, this.mbox = Dand.wrapc(
|
||||
"mbox_body cubic500"
|
||||
, [
|
||||
Dand.wrapc( "mbox_titlebar flsf", title )
|
||||
, Dand.wrapc( "mbox_content", content )
|
||||
, Dand.wrapc( "mbox_buttons", no ? [ _yes, _no ] : _yes )
|
||||
]
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
MessageBox.prototype.setHandler = function( handler ) { this.clickHandler = handler };
|
||||
|
||||
MessageBox.prototype.show = function ()
|
||||
{
|
||||
document.body.appendChild( this.stage );
|
||||
// Center the box
|
||||
var m_style = this.mbox.style;
|
||||
|
||||
m_style.transition = "none";
|
||||
m_style.top = m_style.left = "50%";
|
||||
m_style.marginLeft = String( -0.5 * this.mbox.clientWidth ) + "px";
|
||||
m_style.overflow = "hidden";
|
||||
m_style.minHeight = m_style.opacity = m_style.height = 0;
|
||||
// The interval in firefox seems independent to etablishing element style
|
||||
// using heightTriggers-hack instead
|
||||
Trigger.height(
|
||||
this.mbox, 0
|
||||
, function()
|
||||
{
|
||||
m_style.transition = m_style.minHeight = m_style.height = m_style.overflow = "";
|
||||
m_style.marginTop = String( -0.5 * this.mbox.clientHeight ) + "px";
|
||||
|
||||
m_style.opacity = 1;
|
||||
}.bind( this )
|
||||
);
|
||||
|
||||
return this.stage;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "MessageBox", MessageBox );
|
||||
})();
|
5
botanjs/src/Components/Mouse/Clipboard.css
Normal file
5
botanjs/src/Components/Mouse/Clipboard.css
Normal file
@ -0,0 +1,5 @@
|
||||
.ch_obj {
|
||||
position: fixed;
|
||||
/* 1-level higher than Context Menu*/
|
||||
z-index: 101;
|
||||
}
|
131
botanjs/src/Components/Mouse/Clipboard.js
Normal file
131
botanjs/src/Components/Mouse/Clipboard.js
Normal file
@ -0,0 +1,131 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Mouse.Clipboard" );
|
||||
|
||||
/** @type {System.Global} */
|
||||
var Global = __import( "System.Global" );
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
/** @type {System.utils.Perf} */
|
||||
var Perf = __import( "System.utils.Perf" );
|
||||
/** @type {System.Cycle} */
|
||||
var Cycle = __import( "System.Cycle" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
/** @type {Dandelion.Swf} */
|
||||
var Swf = __import( "Dandelion.Swf" );
|
||||
/** @type {Dandelion.Swf.ExtAPI} */
|
||||
var ExtAPI = __import( "Dandelion.Swf.ExtAPI" );
|
||||
|
||||
var stage
|
||||
, helperAddress = "/assets/swf/iClipboard.swf"
|
||||
, helperId
|
||||
, cCallback
|
||||
;
|
||||
|
||||
/** @type {Components.Mouse.Clipboard.SwfHelperObj */
|
||||
var clipboardHelper = null;
|
||||
|
||||
var init = function ()
|
||||
{
|
||||
if( stage ) return;
|
||||
stage = Dand.wrapc('ch_obj no_transition no_transition_recursive');
|
||||
|
||||
if( Global.IE )
|
||||
{
|
||||
document.body.appendChild(stage);
|
||||
Cycle.next(
|
||||
function (){
|
||||
stage.innerHTML = Swf.create(
|
||||
helperAddress, 20, 20, helperId = Perf.uuid, 'always', 'transparent'
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
stage.appendChild(
|
||||
Swf.create(
|
||||
helperAddress, 20, 20, helperId = Perf.uuid, 'always', 'transparent'
|
||||
)
|
||||
);
|
||||
|
||||
document.body.appendChild(stage);
|
||||
}
|
||||
|
||||
stage.style.visibility = "hidden";
|
||||
|
||||
ExtAPI.init();
|
||||
};
|
||||
|
||||
// Using onmouse<action> properties since event needs to be unique. e.g. single handler
|
||||
|
||||
// Capture mouse by trigger
|
||||
var capture = function ( trigger, callback )
|
||||
{
|
||||
cCallback = callback;
|
||||
|
||||
document.onmousemove = function (e)
|
||||
{
|
||||
if( trigger() )
|
||||
{
|
||||
Global.IE && (event || (event = e));
|
||||
stage.style.visibility = "";
|
||||
stage.style.left = ( e.pageX - 10 ) + "px";
|
||||
stage.style.top = ( e.pageY - 10 ) + "px";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var setTextToCopy = function (textToCopy)
|
||||
{
|
||||
if( clipboardHelper && clipboardHelper.copy )
|
||||
{
|
||||
clipboardHelper.copy( textToCopy );
|
||||
if( Global.debug && clipboardHelper.debug ) clipboardHelper.debug();
|
||||
}
|
||||
else
|
||||
{
|
||||
// This will loop though cycle by cycle until the movie is ready
|
||||
Cycle.next(function () {
|
||||
clipboardHelper = Swf( helperId );
|
||||
setTextToCopy( textToCopy );
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Called by swf
|
||||
var textCopied = function ()
|
||||
{
|
||||
if( cCallback ) cCallback();
|
||||
|
||||
debug.Info( "[Clipboard] Text copied" );
|
||||
stage.style.visibility = "hidden";
|
||||
|
||||
// Release the focus on swf
|
||||
clipboardHelper.blur();
|
||||
|
||||
document.onmousemove = null;
|
||||
};
|
||||
|
||||
var onMouseOver = function ( callback )
|
||||
{
|
||||
if( callback == undefined ) return stage.onmouseover;
|
||||
stage.onmouseover = callback;
|
||||
};
|
||||
|
||||
var onMouseOut = function ( callback )
|
||||
{
|
||||
if( callback == undefined ) return stage.onmouseout;
|
||||
stage.onmouseout = function () {
|
||||
stage.style.visibility = "hidden";
|
||||
this._callback();
|
||||
}.bind({_callback: callback});
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "init", init );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "setTextToCopy", setTextToCopy );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "capture", capture );
|
||||
ns[ NS_EXPORT ]( EX_VAR, "onMouseOver", onMouseOver );
|
||||
ns[ NS_EXPORT ]( EX_VAR, "onMouseOut", onMouseOut );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "_textCopied", textCopied );
|
||||
})();
|
54
botanjs/src/Components/Mouse/ContextMenu.css
Normal file
54
botanjs/src/Components/Mouse/ContextMenu.css
Normal file
@ -0,0 +1,54 @@
|
||||
.contextMenu {
|
||||
display: none;
|
||||
|
||||
cursor: default;
|
||||
position: fixed;
|
||||
/* 1 level higher than window */
|
||||
z-index: 100;
|
||||
|
||||
min-width: 135px;
|
||||
|
||||
font-size: 0.8em;
|
||||
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.contextMenu ul > li {
|
||||
padding: 0.8em 2em 0.8em 0.8em;
|
||||
background: white;
|
||||
position: relative;
|
||||
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.contextMenu ul > li:hover, .contextMenu ul > li[hover] {
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.contextMenu li > ul {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
min-width: 135px;
|
||||
max-width: 200px;
|
||||
left: 100%;
|
||||
}
|
||||
|
||||
.contextMenu li.expandable:after {
|
||||
content: '\25b6';
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 0.2em;
|
||||
height: 100%;
|
||||
|
||||
line-height: 0;
|
||||
|
||||
top: 50%;
|
||||
right: 1em;
|
||||
}
|
||||
|
||||
.contextMenu ul {
|
||||
list-style-type: none;
|
||||
background-color: white;
|
||||
border: 1px solid #DDD;
|
||||
}
|
495
botanjs/src/Components/Mouse/ContextMenu.js
Normal file
495
botanjs/src/Components/Mouse/ContextMenu.js
Normal file
@ -0,0 +1,495 @@
|
||||
(function(){
|
||||
// Usage reference refers to Astroblog.AstroEdit.SiteLibrary::buildImageCanvas
|
||||
var ns = __namespace( "Components.Mouse" );
|
||||
|
||||
/** @type {System.utils} */
|
||||
var utils = __import( "System.utils" );
|
||||
/** @type {System.utils.IKey} */
|
||||
var IKey = __import( "System.utils.IKey" );
|
||||
/** @type {System.utils.DataKey} */
|
||||
var DataKey = __import( "System.utils.DataKey" );
|
||||
/** @type {System.utils.EventKey} */
|
||||
var EventKey = __import( "System.utils.EventKey" );
|
||||
/** @type {System.Cycle} */
|
||||
var Cycle = __import( "System.Cycle" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
/** @type {Dandelion.IDOMElement} */
|
||||
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
||||
/** @type {Components.Mouse.Clipboard} */
|
||||
var Clipboard = __import( "Components.Mouse.Clipboard" );
|
||||
|
||||
|
||||
var ContextMenu = function ( target, items, whichButton, menuInsideTarget, overrides )
|
||||
{
|
||||
if ( !target.id )
|
||||
throw new Error( "[ContextMenu] target's id is missing" );
|
||||
|
||||
if( !( items instanceof Array ) )
|
||||
throw new Error( "[ContextMenu] items is not an array" );
|
||||
|
||||
var stage = null
|
||||
, mouseOnTarget = false
|
||||
, mouseOnContext = false
|
||||
, menuGroup = Dand.id("contextMenus") || (
|
||||
document.body.appendChild( Dand.wrap( null, "contextMenus", "compx" ) )
|
||||
)
|
||||
, targetParent
|
||||
, temp, i, j
|
||||
, _items = []
|
||||
|
||||
, getFuncOverride = function(prop) { return utils.objGetProp( overrides, prop, "Function" ); }
|
||||
, getStrOverride = function(prop) { return utils.objGetProp( overrides, prop, "String" ); }
|
||||
|
||||
, matchActions = function (element)
|
||||
{
|
||||
element = Dand.bubbleUp( element, isMenuItem );
|
||||
|
||||
for (i in _items)
|
||||
{
|
||||
// match attributes
|
||||
if(element == _items[i].stage)
|
||||
{
|
||||
// perform action
|
||||
return _items[i].key.handler(element);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
, isMenuItem = function(e)
|
||||
{
|
||||
if( e === document ) return false;
|
||||
return IDOMElement(e).getDAttribute("menuItem");
|
||||
}
|
||||
|
||||
, addMenuIdentifier = function(dataKey)
|
||||
{
|
||||
var d = new DataKey("menuItem", 1);
|
||||
return dataKey ? [dataKey, d] : d;
|
||||
}
|
||||
|
||||
, contextMouseDown = function(event)
|
||||
{
|
||||
// IE is evil and doesn"t pass the event object
|
||||
if (event == null)
|
||||
event = window.event;
|
||||
|
||||
// we assume we have a standards compliant browser, but check if we have IE
|
||||
var target = event.target != null ? event.target : event.srcElement;
|
||||
|
||||
// only show the context menu if the right mouse button is pressed
|
||||
// and a hyperlink has been clicked (the code can be made more selective)
|
||||
|
||||
if (event.button == 0)
|
||||
matchActions(target) || hideMenu();
|
||||
else hideMenu();
|
||||
}
|
||||
|
||||
, _chainHide = getFuncOverride("chainHide")
|
||||
, _chainShow = getFuncOverride("chainShow")
|
||||
, _hideMenu = getFuncOverride("hideMenu")
|
||||
, hideMenu
|
||||
|
||||
, _showMenu = getFuncOverride("showMenu")
|
||||
, showMenu = function (event)
|
||||
{
|
||||
if (event == null) event = window.event;
|
||||
// hide the menu first to avoid an "up-then-over" visual effect
|
||||
if(_showMenu)
|
||||
{
|
||||
_showMenu(stage, event);
|
||||
}
|
||||
else
|
||||
{
|
||||
stage.style.display = "none";
|
||||
stage.style.left = event.clientX + "px";
|
||||
stage.style.top = event.clientY + "px";
|
||||
stage.style.display = "block";
|
||||
}
|
||||
|
||||
if( hasCopyItem )
|
||||
{
|
||||
Clipboard.capture(copyTrigger, hideMenu);
|
||||
}
|
||||
}
|
||||
|
||||
, contextShow = function (event)
|
||||
{
|
||||
if(!mouseOnTarget) return false;
|
||||
|
||||
showMenu(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
,contextDelete = function ()
|
||||
{
|
||||
targetParent.removeChild(stage);
|
||||
}
|
||||
|
||||
|
||||
, menuItems = []
|
||||
|
||||
, applyHover = function( elem )
|
||||
{
|
||||
if( targetParent == elem ) return false;
|
||||
|
||||
if( elem.nodeName == "LI" )
|
||||
{
|
||||
elem.setAttribute( "hover", 1 );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
, removeHover = function( elem )
|
||||
{
|
||||
if( targetParent == elem ) return false;
|
||||
|
||||
if( elem.nodeName == "LI" )
|
||||
{
|
||||
elem.removeAttribute( "hover" );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
, itemHover = function ()
|
||||
{
|
||||
Dand.chainUpApply( this, applyHover );
|
||||
}
|
||||
, itemOut = function ()
|
||||
{
|
||||
Dand.chainUpApply( this, removeHover );
|
||||
}
|
||||
, copyTrigger = function () { return mouseOverSwitch; }
|
||||
|
||||
, mouseOverSwitch = false
|
||||
, hasCopyItem = false
|
||||
|
||||
, tryBindClipboard = function (target, evtKey)
|
||||
{
|
||||
// Event handler must return the string to copy
|
||||
|
||||
if( evtKey.keyName.toUpperCase().indexOf("COPY") != -1 )
|
||||
{
|
||||
Clipboard.init();
|
||||
// Handle clipboard events
|
||||
hasCopyItem = true;
|
||||
IDOMElement(target).addEventListeners(
|
||||
[
|
||||
new EventKey("MouseOver", function ()
|
||||
{
|
||||
mouseOverSwitch = true;
|
||||
Clipboard.setTextToCopy( this.strcpy() );
|
||||
Clipboard.onMouseOver = itemHover.bind( this.stage );
|
||||
Clipboard.onMouseOut = itemOut.bind( this.stage );
|
||||
}.bind({ strcpy: evtKey.handler, stage: target })
|
||||
)
|
||||
|
||||
, new EventKey("MouseDown", function ()
|
||||
{
|
||||
Clipboard.setTextToCopy( this.strcpy() );
|
||||
}.bind({ strcpy: evtKey.handler })
|
||||
)
|
||||
|
||||
, new EventKey("MouseOut", function ()
|
||||
{
|
||||
mouseOverSwitch = false;
|
||||
itemOut.bind(this)();
|
||||
}.bind( target )
|
||||
)
|
||||
]
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
, stepSubListeners = function (target)
|
||||
{
|
||||
var lockedOn = null, j, overedOn
|
||||
, nodes = target.childNodes
|
||||
;
|
||||
|
||||
// Collapse menu chain, each chain is a route
|
||||
// Like dominoes
|
||||
target.chainRoute = target.chainRoute || [];
|
||||
|
||||
for(var i in nodes)
|
||||
{
|
||||
j = nodes[i];
|
||||
if(!(j && j.nodeType == 1)) continue;
|
||||
|
||||
// If this item has a submenu item
|
||||
if(j.lastChild.nodeType == 1)
|
||||
{
|
||||
target.chainRoute[target.chainRoute.length] = {menu: j.lastChild, next: stepSubListeners(j.lastChild)};
|
||||
}
|
||||
|
||||
IDOMElement(j).addEventListener(
|
||||
new EventKey("MouseOver", function ()
|
||||
{
|
||||
// record "this (overed)" item
|
||||
overedOn = this;
|
||||
|
||||
var subItem = this.lastChild;
|
||||
|
||||
Cycle.delay(function ()
|
||||
{
|
||||
// Hide last displayed submenu if submenu is available
|
||||
if(lockedOn && lockedOn != subItem)
|
||||
{
|
||||
_chainHide ? _chainHide(lockedOn) : (lockedOn.style.display = "none");
|
||||
// bind the chains into chain reactor
|
||||
chainReactor.bind(lockedOn)();
|
||||
}
|
||||
|
||||
// if mouse is still on "this (overed)" item
|
||||
if(overedOn == this)
|
||||
{
|
||||
|
||||
// and if this item has sub item
|
||||
if(subItem.nodeType == 1)
|
||||
{
|
||||
lockedOn = this.lastChild;
|
||||
_chainShow ? _chainShow(subItem) : (subItem.style.display = "");
|
||||
}
|
||||
}
|
||||
}.bind(this), 300);
|
||||
}.bind(j))
|
||||
);
|
||||
}
|
||||
|
||||
return target.chainRoute.length ? chainReactor.bind(target) : null;
|
||||
}
|
||||
|
||||
, chainReactor = function ()
|
||||
{
|
||||
if(this && this.chainRoute)
|
||||
for(var i in this.chainRoute)
|
||||
{
|
||||
_chainHide ? _chainHide(this.chainRoute[i].menu) : (this.chainRoute[i].menu.style.display = "none");
|
||||
if(this.chainRoute[i].next) this.chainRoute[i].next();
|
||||
}
|
||||
}
|
||||
|
||||
, createSubMenu = function (obj)
|
||||
{
|
||||
if(!(obj.name || obj.items)) return Dand.wrapna("ul", addMenuIdentifier());
|
||||
|
||||
// Begin create submenu
|
||||
var itemroot = Dand.wrapna("ul", addMenuIdentifier())
|
||||
, j = obj.items;
|
||||
|
||||
for (var i in j)
|
||||
{
|
||||
|
||||
if(!(j[i] instanceof IKey))
|
||||
{
|
||||
// step inside level
|
||||
itemroot.appendChild(createSubMenu(j[i]));
|
||||
continue;
|
||||
}
|
||||
|
||||
// Switch inside if this key has an id-ed event
|
||||
var eKey = (j[i].keyValue instanceof EventKey) ? j[i].keyValue : j[i];
|
||||
|
||||
itemroot.appendChild( temp = Dand.wrap( "li", null, null, j[i].keyName, addMenuIdentifier(new DataKey("id", eKey.keyName))) );
|
||||
|
||||
// store EventKey & reference
|
||||
_items[_items.length] = {key: eKey, stage: temp};
|
||||
|
||||
tryBindClipboard(temp, eKey);
|
||||
}
|
||||
|
||||
|
||||
// Datakey is set for matching action
|
||||
var stage = Dand.wrap("li", null, "expandable", [ Dand.textNode(obj.name), itemroot ], addMenuIdentifier(new DataKey("id", obj.name)));
|
||||
|
||||
// Set handler if available
|
||||
if(obj.handler)
|
||||
{
|
||||
_items[_items.length] = {key: new EventKey(obj.name, obj.handler), stage: stage};
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prevent menu disappear when clicked
|
||||
_items[_items.length] = {key: new EventKey(obj.name, function() { return true; }), stage: stage};
|
||||
}
|
||||
|
||||
|
||||
_hideMenu ? _hideMenu(itemroot) : (itemroot.style.display = "none");
|
||||
|
||||
return stage;
|
||||
};
|
||||
|
||||
for ( i in items )
|
||||
{
|
||||
if ( ( j = items[i] ) )
|
||||
{
|
||||
if(!(j instanceof IKey))
|
||||
{
|
||||
menuItems[menuItems.length] = createSubMenu(j);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Switch inside if this key has an id-ed event
|
||||
var eKey = (j.keyValue instanceof EventKey) ? j.keyValue : j;
|
||||
temp = menuItems[menuItems.length] = Dand.wrapne("li", j.keyName, addMenuIdentifier(new DataKey("id", eKey.keyName)));
|
||||
|
||||
// store EventKey & reference
|
||||
_items[_items.length] = {key: eKey, stage: temp};
|
||||
|
||||
tryBindClipboard(temp, j);
|
||||
}
|
||||
}
|
||||
|
||||
stage = Dand.wrap(
|
||||
"div", null
|
||||
, getStrOverride("class") || "contextMenu"
|
||||
, temp = Dand.wrapne( "ul", menuItems, addMenuIdentifier() )
|
||||
);
|
||||
|
||||
var chain = stepSubListeners(temp);
|
||||
var hideMenu = function ()
|
||||
{
|
||||
_hideMenu ? _hideMenu( stage ) : ( stage.style.display = "none" );
|
||||
|
||||
// Root collapse chain
|
||||
if( chain ) chain();
|
||||
};
|
||||
|
||||
if( menuInsideTarget && menuInsideTarget.nodeType == 1 )
|
||||
{
|
||||
( targetParent = menuInsideTarget ).appendChild(stage);
|
||||
}
|
||||
else
|
||||
{
|
||||
( targetParent = menuGroup ).appendChild(stage);
|
||||
}
|
||||
|
||||
stage.zindex = 99;
|
||||
|
||||
// Handle which button
|
||||
i = temp = false;
|
||||
if(whichButton == "both") i = temp = true;
|
||||
else if (whichButton == "LMB") i = true;
|
||||
else if (whichButton == "RMB") temp = true;
|
||||
|
||||
if (i)
|
||||
{
|
||||
// Handle LMB
|
||||
target.onclick = function (event)
|
||||
{
|
||||
if ( Dand.id( target.id ) )
|
||||
{
|
||||
showMenu(event);
|
||||
document.body.onmousedown = contextMouseDown;
|
||||
}
|
||||
cleanUpActionList();
|
||||
}
|
||||
}
|
||||
|
||||
// Register with RMB switch
|
||||
registerBodyClickAction(contextMouseDown, contextShow, contextDelete, target.id, temp);
|
||||
|
||||
temp = IDOMElement(target);
|
||||
temp.addEventListener("MouseOver", function() { mouseOnTarget = true; });
|
||||
temp.addEventListener("MouseOut", function() { mouseOnTarget = false; });
|
||||
|
||||
temp = IDOMElement(stage);
|
||||
temp.addEventListener("MouseOver", function() { mouseOnContext = true; });
|
||||
temp.addEventListener("MouseOut", function() { mouseOnContext = false; });
|
||||
|
||||
IDOMElement(document.body).addEventListener("ContextMenu", bodyOnContext);
|
||||
|
||||
this.getItemByKey = function (key)
|
||||
{
|
||||
for (i in _items)
|
||||
{
|
||||
// match attributes
|
||||
if(IDOMElement(_items[i].stage).getDAttribute("id") == key)
|
||||
{
|
||||
return _items[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
var bodyClickPairs = [];
|
||||
|
||||
var bodyOnContext = function (event)
|
||||
{
|
||||
var i, j;
|
||||
for (i in bodyClickPairs)
|
||||
{
|
||||
if ( Dand.id( ( j = bodyClickPairs[i] )._id ) )
|
||||
{
|
||||
if(j._rmb && j._context(event))
|
||||
{
|
||||
document.body.onmousedown = j._down;
|
||||
|
||||
if( event && event.preventDefault ) event.preventDefault();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// target lost
|
||||
j._lost();
|
||||
delete bodyClickPairs[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var cleanUpActionList = function ()
|
||||
{
|
||||
var i, j;
|
||||
for ( i in bodyClickPairs )
|
||||
{
|
||||
if ( !Dand.id( ( j = bodyClickPairs[i] )._id ) )
|
||||
{
|
||||
// target lost
|
||||
j._lost();
|
||||
delete bodyClickPairs[i];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var registerBodyClickAction = function ( _mousedown, _oncontext, _targetlost, id, _useRMB )
|
||||
{
|
||||
var i = tryGetAction(id);
|
||||
if(i)
|
||||
{
|
||||
// Remove previous menu
|
||||
i._lost();
|
||||
// Perform update
|
||||
i._down = _mousedown;
|
||||
i._context = _oncontext;
|
||||
i._lost = _targetlost;
|
||||
i._rmb = _useRMB;
|
||||
}
|
||||
else
|
||||
{
|
||||
bodyClickPairs[bodyClickPairs.length] = {
|
||||
_down: _mousedown, _context: _oncontext, _lost: _targetlost, _id: id, _rmb: _useRMB
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
var tryGetAction = function (id)
|
||||
{
|
||||
for (i in bodyClickPairs)
|
||||
{
|
||||
if (bodyClickPairs[i]._id == id)
|
||||
{
|
||||
return bodyClickPairs[i];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "ContextMenu", ContextMenu );
|
||||
})();
|
3
botanjs/src/Components/Mouse/_this.js
Normal file
3
botanjs/src/Components/Mouse/_this.js
Normal file
@ -0,0 +1,3 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components.Mouse" );
|
||||
})();
|
3
botanjs/src/Components/_this.js
Normal file
3
botanjs/src/Components/_this.js
Normal file
@ -0,0 +1,3 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Components" );
|
||||
})();
|
3
botanjs/src/Dandelion/CSSAnimations/MovieClip.css
Normal file
3
botanjs/src/Dandelion/CSSAnimations/MovieClip.css
Normal file
@ -0,0 +1,3 @@
|
||||
.motion_block {
|
||||
display: inline-block;
|
||||
}
|
158
botanjs/src/Dandelion/CSSAnimations/MovieClip.js
Normal file
158
botanjs/src/Dandelion/CSSAnimations/MovieClip.js
Normal file
@ -0,0 +1,158 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion.CSSAnimations" );
|
||||
|
||||
/** @type {System.utils.EventKey} */
|
||||
var EventKey = __import( "System.utils.EventKey" );
|
||||
/** @type {System.Cycle.Trigger} */
|
||||
var Trigger = __import( "System.Cycle.Trigger" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
/** @type {Dandelion.IDOMElement} */
|
||||
var IDOMElement = __import( "Dandelion.IDOMElement" );
|
||||
|
||||
var MovieClip = function (
|
||||
__target
|
||||
, __row, __col
|
||||
, __width, __height
|
||||
, frame, start
|
||||
)
|
||||
{
|
||||
if( frame == __row * __col ) frame = 0;
|
||||
|
||||
var canvas = Dand.wrapc( "motion_block no_transition" )
|
||||
, r = __row - 1
|
||||
, c = __col - 1
|
||||
, w = __width
|
||||
, h = __height
|
||||
, i = 0, j = 0
|
||||
, k = 0, l = frame - 1
|
||||
;
|
||||
|
||||
var _next, _prev, _goto;
|
||||
|
||||
if( frame )
|
||||
{
|
||||
_next = function ()
|
||||
{
|
||||
( c < ++ i ) && ( ( i = 0 ) || ( ( r < ++ j ) && ( j = 0 ) ) );
|
||||
( l < ++ k ) && ( i = j = k = 0 );
|
||||
};
|
||||
|
||||
_prev = function ()
|
||||
{
|
||||
( -- k < 0 ) && ( k = l );
|
||||
_goto( k );
|
||||
};
|
||||
|
||||
_goto = function ( f )
|
||||
{
|
||||
for ( i = j = k = 0; 0 < f; f -- ) _next();
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
_next = function ()
|
||||
{
|
||||
( c < ++ i ) && ( ( i = 0 ) || ( ( r < ++ j ) && ( j = 0 ) ) );
|
||||
};
|
||||
|
||||
_prev = function ()
|
||||
{
|
||||
( -- i < 0 ) && ( ( i = c ) && ( ( -- j < 0 ) && ( j = r ) ) );
|
||||
};
|
||||
|
||||
_goto = function ( f )
|
||||
{
|
||||
for ( i = j = k = 0; k < f; k ++ ) _next();
|
||||
};
|
||||
}
|
||||
|
||||
canvas.style.backgroundImage = "url(" + __target + ")";
|
||||
canvas.style.width = w + "px";
|
||||
canvas.style.height = h + "px";
|
||||
canvas.style.backgroundPosition = "0px 0px";
|
||||
|
||||
var updateCanvas = function()
|
||||
{
|
||||
canvas.style.backgroundPosition = ( -i * w ) + "px " + ( -j * h ) + "px";
|
||||
};
|
||||
|
||||
// At 0 position
|
||||
var at0 = function() { return ( i == 0 && j == 0 ) };
|
||||
|
||||
var obj = {
|
||||
_next: function() { _next(); updateCanvas(); return at0(); }
|
||||
, _prev: function() { _prev(); updateCanvas(); return at0(); }
|
||||
, _goto: function( n ) { _goto( n ); updateCanvas(); }
|
||||
};
|
||||
|
||||
this["stage"] = canvas;
|
||||
this["nextFrame"] = this.nextFrame.bind( obj );
|
||||
this["prevFrame"] = this.prevFrame.bind( obj );
|
||||
this["gotoFrame"] = this.gotoFrame.bind( obj );
|
||||
};
|
||||
|
||||
MovieClip.prototype.nextFrame = function ()
|
||||
{
|
||||
return this._next();
|
||||
};
|
||||
|
||||
MovieClip.prototype.prevFrame = function ()
|
||||
{
|
||||
return this._prev();
|
||||
};
|
||||
|
||||
MovieClip.prototype.gotoFrame = function ( frameNumber )
|
||||
{
|
||||
return this._goto( frameNumber );
|
||||
};
|
||||
|
||||
MovieClip.prototype.stage = null;
|
||||
|
||||
/** @param {Dandelion.CSSAnimations.MovieClip} mc
|
||||
* @param {Boolean} whenStatic
|
||||
*/
|
||||
var MouseOverMovie = function ( mc, whenStatic )
|
||||
{
|
||||
if ( mc instanceof MovieClip )
|
||||
{
|
||||
var canRegister = true;
|
||||
var terminate = false;
|
||||
|
||||
var registrar = function () { return mc.nextFrame() || terminate; };
|
||||
|
||||
var handler = function ()
|
||||
{
|
||||
mc.gotoFrame( whenStatic );
|
||||
canRegister = true;
|
||||
terminate = false;
|
||||
};
|
||||
|
||||
var mouseOverHandler = function ( e )
|
||||
{
|
||||
if( canRegister )
|
||||
{
|
||||
canRegister = false;
|
||||
mc.gotoFrame(0);
|
||||
Trigger.register( registrar, handler, 33 );
|
||||
}
|
||||
};
|
||||
|
||||
var mouseOutHandler = function ( e )
|
||||
{
|
||||
if( !canRegister )
|
||||
terminate = true;
|
||||
};
|
||||
|
||||
mc.gotoFrame( whenStatic );
|
||||
|
||||
IDOMElement( mc.stage ).addEventListeners([
|
||||
new EventKey( "MouseOver", mouseOverHandler )
|
||||
, new EventKey( "MouseOut", mouseOutHandler )
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "MovieClip", MovieClip );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "MouseOverMovie", MouseOverMovie );
|
||||
})();
|
41
botanjs/src/Dandelion/CSSAnimations/_this.css
Normal file
41
botanjs/src/Dandelion/CSSAnimations/_this.css
Normal file
@ -0,0 +1,41 @@
|
||||
.comp, .compx * {
|
||||
-webkit-transition: all .25s ease-out;
|
||||
-moz-transition: all .25s ease-out;
|
||||
-o-transition: all .25s ease-out;
|
||||
transition: all .25s ease-out;
|
||||
}
|
||||
|
||||
.rcomp, .rcompx * {
|
||||
-webkit-transition: none;
|
||||
-moz-transition: none;
|
||||
-o-transition: none;
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.cubic500 {
|
||||
-webkit-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-moz-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-ms-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-o-transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition: all 500ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
|
||||
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
|
||||
}
|
||||
|
||||
.cubic200 {
|
||||
-webkit-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-moz-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-ms-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-o-transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition: all 200ms cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
|
||||
|
||||
-webkit-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-moz-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-ms-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
-o-transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000);
|
||||
transition-timing-function: cubic-bezier(0.215, 0.610, 0.355, 1.000); /* easeOutCubic */
|
||||
}
|
5
botanjs/src/Dandelion/CSSAnimations/_this.js
Normal file
5
botanjs/src/Dandelion/CSSAnimations/_this.js
Normal file
@ -0,0 +1,5 @@
|
||||
/*
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion.CSSAnimations" );
|
||||
})();
|
||||
*/
|
43
botanjs/src/Dandelion/CSSReset.css
Normal file
43
botanjs/src/Dandelion/CSSReset.css
Normal file
@ -0,0 +1,43 @@
|
||||
html, body, div, span, applet, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
a, abbr, acronym, address, big, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, s, samp,
|
||||
small, strike, strong, tt, var,
|
||||
b, u, i, center,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, embed,
|
||||
figure, figcaption, footer, header, hgroup,
|
||||
menu, nav, output, ruby, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
font-size: 100%;
|
||||
font: inherit;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
sup, sub {
|
||||
vertical-align: baseline;
|
||||
font-size: 80%;
|
||||
}
|
||||
article, aside, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
blockquote, q {
|
||||
quotes: none;
|
||||
}
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content: '';
|
||||
content: none;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
}
|
5
botanjs/src/Dandelion/CSSReset.js
Normal file
5
botanjs/src/Dandelion/CSSReset.js
Normal file
@ -0,0 +1,5 @@
|
||||
/*
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion.CSSReset" );
|
||||
})();
|
||||
*/
|
199
botanjs/src/Dandelion/IDOMElement.js
Normal file
199
botanjs/src/Dandelion/IDOMElement.js
Normal file
@ -0,0 +1,199 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion" );
|
||||
|
||||
/** @type {System.utils.IKey} */
|
||||
var IKey = __import( "System.utils.IKey" );
|
||||
/** @type {System.utils.Perf} */
|
||||
var Perf = __import( "System.utils.Perf" );
|
||||
|
||||
var wrap = ns[ NS_INVOKE ]( "wrap" );
|
||||
var IDOMObject = ns[ NS_INVOKE ]( "IDOMObject" );
|
||||
|
||||
// IDOMElement, augmented element wrapper utilizing IKeys
|
||||
var IDOMElement = function (element, sw)
|
||||
{
|
||||
if (element instanceof IDOMElement) return element;
|
||||
|
||||
if (sw)
|
||||
{
|
||||
IDOMObject.call( this, element, true );
|
||||
|
||||
this["getDAttribute"] = this.getDAttribute.bind(element);
|
||||
|
||||
this["lootChildren"] = this.lootChildren.bind(element);
|
||||
|
||||
this["foreach"] = this.foreach.bind(element);
|
||||
this["reverseChild"] = this.reverseChild.bind(element);
|
||||
this["first"] = this.first.bind(element);
|
||||
this["last"] = this.last.bind(element);
|
||||
this["contains"] = this.contains.bind(element);
|
||||
|
||||
// Org values
|
||||
this["style"] = element.style;
|
||||
this["hasAttribute"] = function ( key ) { this.hasAttribute( key ); }.bind( element );
|
||||
this["removeAttribute"] = function ( key ) { this.removeAttribute( key ); }.bind( element );
|
||||
this["element"] = element;
|
||||
|
||||
// Overrides
|
||||
this["setAttribute"] = this.setAttribute.bind( element );
|
||||
}
|
||||
else if ( element && element[ "nodeType" ] != undefined && element.nodeType == 1 )
|
||||
{
|
||||
return new IDOMElement( element, true );
|
||||
}
|
||||
else if( element === undefined )
|
||||
{
|
||||
return new IDOMElement( wrap(), true );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Error( "[Dandelion.IDOMElement] Invalid argument" );
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
__extends( IDOMElement, IDOMObject );
|
||||
|
||||
IDOMElement.prototype.setAttribute = function( k, v )
|
||||
{
|
||||
if( k instanceof IKey )
|
||||
{
|
||||
this.setAttribute( k.keyName, k.keyValue );
|
||||
}
|
||||
else if( k instanceof Array )
|
||||
{
|
||||
for ( var i in k )
|
||||
{
|
||||
if ( k[i] instanceof IKey )
|
||||
{
|
||||
this.setAttribute( k[i].keyName, k[i].keyValue );
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setAttribute( k, v );
|
||||
}
|
||||
};
|
||||
|
||||
IDOMElement.prototype.lootChildren = function ( element )
|
||||
{
|
||||
var _nodes = element.childNodes;
|
||||
while(_nodes.length)
|
||||
{
|
||||
this.appendChild( element.removeChild( _nodes[0] ) );
|
||||
}
|
||||
};
|
||||
|
||||
IDOMElement.prototype.getDAttribute = function(name)
|
||||
{
|
||||
var i = this.getAttribute("data-" + name);
|
||||
return i && decodeURIComponent(i);
|
||||
};
|
||||
|
||||
IDOMElement.prototype.foreach = function(type, callback)
|
||||
{
|
||||
var c = Array.apply( [], this.childNodes ), l = c.length;
|
||||
for(var i = 0; i < l; i ++)
|
||||
{
|
||||
if (c[i].nodeType == type)
|
||||
{
|
||||
callback(c[i], this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var matchNone = function() { return false; };
|
||||
var matchType = function( c, t ) { return c.nodeType == t; };
|
||||
var matchName = function( c, t ) { return c.nodeName == t; };
|
||||
|
||||
var getMatch = function( type )
|
||||
{
|
||||
type = typeof( type );
|
||||
if( type == "number" ) return matchType;
|
||||
else if( type == "string" ) return matchName;
|
||||
|
||||
return matchNone;
|
||||
};
|
||||
|
||||
IDOMElement.prototype.first = function ( type, callback )
|
||||
{
|
||||
var c = this.childNodes;
|
||||
var l = c.length;
|
||||
var elem = null;
|
||||
var tc = getMatch( type );
|
||||
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
if ( tc( c[i], type ) )
|
||||
{
|
||||
if( callback === undefined || callback( c[i], this ) )
|
||||
{
|
||||
elem = c[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
};
|
||||
|
||||
IDOMElement.prototype.last = function ( type, callback )
|
||||
{
|
||||
var c = this.childNodes;
|
||||
var l = c.length - 1;
|
||||
var elem = null;
|
||||
var tc = getMatch( type );
|
||||
|
||||
for( var i = l; -1 < i ; i -- )
|
||||
{
|
||||
if ( tc( c[i], type ) )
|
||||
{
|
||||
if( callback === undefined || callback( c[i], this ) )
|
||||
{
|
||||
elem = c[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
};
|
||||
|
||||
IDOMElement.prototype.contains = function ( target )
|
||||
{
|
||||
if( target.parentElement )
|
||||
{
|
||||
if( target == this )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return this.contains( target.parentElement );
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// attribute keys
|
||||
IDOMElement.prototype.aKeys = function()
|
||||
{
|
||||
var ikeys = [];
|
||||
var attrs = this.element.attributes;
|
||||
var l = attrs.length;
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
ikeys.push( new IKey( attrs[i].name, attrs[i].value ) );
|
||||
}
|
||||
return ikeys;
|
||||
};
|
||||
|
||||
IDOMElement.prototype.reverseChild = function()
|
||||
{
|
||||
var l = this.childNodes.length - 1;
|
||||
while( -1 < -- l )
|
||||
{
|
||||
this.appendChild( this.childNodes[l] );
|
||||
}
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "IDOMElement", IDOMElement );
|
||||
})();
|
149
botanjs/src/Dandelion/IDOMObject.js
Normal file
149
botanjs/src/Dandelion/IDOMObject.js
Normal file
@ -0,0 +1,149 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion" );
|
||||
/** @type {System.utils.EventKey} */
|
||||
var EventKey = __import( "System.utils.EventKey" );
|
||||
|
||||
var EvtsArr = function () { Array.call( this ); };
|
||||
|
||||
/** @param {System.utils.EventKey} e */
|
||||
EvtsArr.prototype.indexOf = function( e )
|
||||
{
|
||||
var l = this.length;
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
/** @type {System.utils.EventKey} */
|
||||
var evt = this[i];
|
||||
if( evt.type == e.type && evt.handler == e.handler )
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
};
|
||||
|
||||
__extends( EvtsArr, Array );
|
||||
|
||||
var IDOMObject = function ( obj, sw )
|
||||
{
|
||||
if ( obj instanceof IDOMObject ) return obj;
|
||||
|
||||
if ( sw )
|
||||
{
|
||||
this["addEventListener"] = this.addEventListener.bind(obj);
|
||||
this["addEventListeners"] = this.addEventListeners.bind(this);
|
||||
this["hasListener"] = this.hasListener.bind(obj);
|
||||
this["removeEventListener"] = this.removeEventListener.bind(obj);
|
||||
}
|
||||
else if ( obj )
|
||||
{
|
||||
return new IDOMObject( obj, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Error( "[Dandelion.IDOMObject] Invalid argument" );
|
||||
}
|
||||
}
|
||||
|
||||
IDOMObject.prototype.hasListener = function(e)
|
||||
{
|
||||
if( e instanceof EventKey
|
||||
&& this._events
|
||||
&& this._events.indexOf(e) != -1
|
||||
)
|
||||
{
|
||||
return this._events[ this._events.indexOf(e) ];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
IDOMObject.prototype.addEventListener = function (event, handler)
|
||||
{
|
||||
var e;
|
||||
if (typeof event == "string" && handler)
|
||||
{
|
||||
e = new EventKey(event, handler);
|
||||
}
|
||||
else if (event instanceof EventKey)
|
||||
{
|
||||
e = event;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( this._events )
|
||||
{
|
||||
if ( this._events.indexOf( e ) < 0 )
|
||||
{
|
||||
this._events.push( e );
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this._events = new EvtsArr();
|
||||
this._events[0] = e;
|
||||
}
|
||||
|
||||
if( this.addEventListener )
|
||||
{
|
||||
this.addEventListener( e.type, e.handler, false );
|
||||
}
|
||||
// IE
|
||||
else if( this.attachEvent )
|
||||
{
|
||||
this.attachEvent('on' + e.type, e.handler);
|
||||
}
|
||||
else
|
||||
{
|
||||
this['on' + e.type] = e.handler;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
IDOMObject.prototype.addEventListeners = function(evtKeys)
|
||||
{
|
||||
if(evtKeys instanceof Array)
|
||||
{
|
||||
for (var i in evtKeys)
|
||||
{
|
||||
this.addEventListener(evtKeys[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IDOMObject.prototype.removeEventListener = function( e, handler )
|
||||
{
|
||||
if( handler )
|
||||
{
|
||||
e = new EventKey( e, handler );
|
||||
}
|
||||
|
||||
if( this._events )
|
||||
{
|
||||
delete this._events[ this._events.indexOf(e) ];
|
||||
}
|
||||
|
||||
if( this.removeEventListener )
|
||||
{
|
||||
this.removeEventListener( e.type, e.handler );
|
||||
}
|
||||
// IE
|
||||
else if( this.detachEvent )
|
||||
{
|
||||
this.detachEvent( 'on' + e.type, e.handler );
|
||||
}
|
||||
else
|
||||
{
|
||||
this['on' + e.type] = null;
|
||||
}
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "IDOMObject", IDOMObject );
|
||||
})();
|
||||
|
7
botanjs/src/Dandelion/Swf/ExtAPI.css
Normal file
7
botanjs/src/Dandelion/Swf/ExtAPI.css
Normal file
@ -0,0 +1,7 @@
|
||||
#extAPIConsole {
|
||||
-webkit-transition: all 0s;
|
||||
-moz-transition: all 0s;
|
||||
-ms-transition: all 0s;
|
||||
-o-transition: all 0s;
|
||||
transition: all 0s;
|
||||
}
|
44
botanjs/src/Dandelion/Swf/ExtAPI.js
Normal file
44
botanjs/src/Dandelion/Swf/ExtAPI.js
Normal file
@ -0,0 +1,44 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion.Swf.ExtAPI" );
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
var jsReady = false
|
||||
, as = 0
|
||||
, cutConnection = false
|
||||
|
||||
, watchDogTime = new Date().getTime()
|
||||
, watchDogCounter = 0
|
||||
, lastCount = 0
|
||||
;
|
||||
|
||||
var ExtAPI = function ()
|
||||
{
|
||||
// TODO
|
||||
};
|
||||
|
||||
var isReady = function () { return jsReady; };
|
||||
|
||||
var init = function ()
|
||||
{
|
||||
jsReady = true;
|
||||
debug.Info( "[ExtAPI] " + new Date().toString() );
|
||||
};
|
||||
|
||||
var watch = function ()
|
||||
{
|
||||
if( watchDogCounter - lastCount < 300 )
|
||||
{
|
||||
lastCount = watchDogCounter;
|
||||
}
|
||||
else
|
||||
{
|
||||
cutConnection = true;
|
||||
debug.Warning( "[ExtAPI] Console Disabled: possible hanging dectected." )
|
||||
}
|
||||
watchDogTime = new Date().getTime();
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "init", init );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "ready", isReady );
|
||||
})();
|
56
botanjs/src/Dandelion/Swf/_this.css
Normal file
56
botanjs/src/Dandelion/Swf/_this.css
Normal file
@ -0,0 +1,56 @@
|
||||
.swf_wrapper {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.swf_wrapper > div {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.swf_inactive {
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.swf_inactive:hover {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.swf_inactive > div {
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-top: 3.5em solid transparent;
|
||||
border-bottom: 3.5em solid transparent;
|
||||
border-left: 5em solid #FFF;
|
||||
position: absolute;
|
||||
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin-top: -3.5em;
|
||||
margin-left: -1.8em;
|
||||
}
|
||||
|
||||
/* title */
|
||||
.swf_caption {
|
||||
bottom: 0;
|
||||
|
||||
position: absolute;
|
||||
|
||||
display: block;
|
||||
width: 100%;
|
||||
|
||||
color: white;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
|
||||
padding: 0.2em;
|
||||
|
||||
font-size: 2em;
|
||||
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.swf_desc {
|
||||
font-size: 60%;
|
||||
}
|
173
botanjs/src/Dandelion/Swf/_this.js
Normal file
173
botanjs/src/Dandelion/Swf/_this.js
Normal file
@ -0,0 +1,173 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion" );
|
||||
|
||||
/** @type {System.utils} */
|
||||
var utils = __import( "System.utils" );
|
||||
/** @type {System.utils.IKey} */
|
||||
var IKey = __import( "System.utils.IKey" );
|
||||
/** @type {System.Policy} */
|
||||
var Policy = __import( "System.Policy" );
|
||||
/** @type {System.Debug} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
|
||||
var IE = __import( "System.Global.IE" );
|
||||
|
||||
var s_current = {player: false, mask: false, stage: false, listener: false, sid: null};
|
||||
|
||||
var Swf = function (movieName)
|
||||
{
|
||||
if ( navigator.appName.indexOf("Microsoft") != -1 )
|
||||
{
|
||||
return window[movieName];
|
||||
}
|
||||
else
|
||||
{
|
||||
return document[movieName];
|
||||
}
|
||||
};
|
||||
|
||||
var realize = function (id)
|
||||
{
|
||||
var movieElement = Dand.id('swfWrapper_' + id)
|
||||
, swf_origin = Dand.wrap('a')
|
||||
, _src = movieElement.getAttribute("value")
|
||||
|
||||
swf_origin.href = _src;
|
||||
|
||||
if( Policy.isAllowedOrigin( stf_origin.host ) ) {
|
||||
swf_origin = "always";
|
||||
} else {
|
||||
swf_origin = "never";
|
||||
}
|
||||
|
||||
movieElement.onclick = ( IE ? createMovieIE : createMovie ).bind({
|
||||
sid: id
|
||||
, src: _src
|
||||
, width: movieElement.style.width
|
||||
, height: movieElement.style.height
|
||||
, s_stage:movieElement
|
||||
, origin: swf_origin
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
var getCurrentMovie = function (args)
|
||||
{
|
||||
if ( window.ExtAPI )
|
||||
{
|
||||
return thisMovie( s_current.sid );
|
||||
}
|
||||
return null;
|
||||
};
|
||||
*/
|
||||
|
||||
var createMovieIE = function ()
|
||||
{
|
||||
// Remove previous movie if exists
|
||||
if(s_current.stage)
|
||||
{
|
||||
s_current.stage.firstChild.className = "swf_inactive";
|
||||
s_current.stage.firstChild.innerHTML = s_current.player;
|
||||
s_current.stage.childNodes[1].style.bottom = "";
|
||||
s_current.stage.onclick = s_current.listener;
|
||||
}
|
||||
|
||||
this.s_stage.childNodes[1].style.bottom = "-2em";
|
||||
s_current.sid = "swf_" + this.sid;
|
||||
|
||||
s_current.stage = this.s_stage;
|
||||
s_current.player = this.s_stage.firstChild.innerHTML;
|
||||
|
||||
this.s_stage.firstChild.className = "swf_active";
|
||||
this.s_stage.firstChild.innerHTML = makeStageIE(this.src, this.width, this.height, s_current.sid, this.origin);
|
||||
|
||||
// Save event listener
|
||||
s_current.listener = this.s_stage.onclick;
|
||||
|
||||
// disable click event
|
||||
this.s_stage.onclick = null;
|
||||
};
|
||||
|
||||
var createMovie = function ()
|
||||
{
|
||||
|
||||
// Remove previous movie if exists
|
||||
if(s_current.stage)
|
||||
{
|
||||
s_current.stage.removeChild(s_current.player);
|
||||
s_current.stage.firstChild.style.bottom = "";
|
||||
s_current.stage.insertBefore(mask, stage.firstChild);
|
||||
s_current.stage.onclick = s_current.listener;
|
||||
}
|
||||
|
||||
|
||||
this.s_stage.childNodes[1].style.bottom = "-2em";
|
||||
s_current.sid = "swf_" + this.sid;
|
||||
|
||||
// Remove mask
|
||||
(s_current.stage = this.s_stage).removeChild(s_current.mask = this.s_stage.childNodes[0]);
|
||||
|
||||
s_current.player = makeStage(this.src, this.width, this.height, s_current.sid, this.origin);
|
||||
this.s_stage.appendChild(s_current.player);
|
||||
|
||||
// Save event listener
|
||||
s_current.listener = this.s_stage.onclick;
|
||||
|
||||
// disable click event
|
||||
this.s_stage.onclick = null;
|
||||
|
||||
};
|
||||
|
||||
var makeStage = function (src, width, height, sid, origin, wmode)
|
||||
{
|
||||
return Dand.wrapna("embed",
|
||||
[
|
||||
new IKey("src", src)
|
||||
, new IKey("quality", "high")
|
||||
, new IKey("bgcolor", "#869ca7")
|
||||
, new IKey("width", width)
|
||||
, new IKey("height", height)
|
||||
, new IKey("name", sid)
|
||||
, new IKey("align", "middle")
|
||||
, new IKey("wmode", wmode || "direct")
|
||||
, new IKey("play", "true")
|
||||
, new IKey("loop", "false")
|
||||
, new IKey("quality", "high")
|
||||
, new IKey("allowScriptAccess", origin)
|
||||
, new IKey("type", "application/x-shockwave-flash")
|
||||
, new IKey("pluginspage", "http://www.macromedia.com/go/getflashplayer")
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
var makeStageIE = function (src, width, height, sid, origin, wmode)
|
||||
{
|
||||
return Dand.wrape(
|
||||
Dand.wrapne('object',
|
||||
[
|
||||
Dand.wrapna("param", [new IKey("name", "wmode"), new IKey("value", wmode || "direct")])
|
||||
, Dand.wrapna("param", [new IKey("name", "quality"), new IKey("value", "high")])
|
||||
, Dand.wrapna("param", [new IKey("name", "movie"), new IKey("value", src)])
|
||||
, Dand.wrapna("param", [new IKey("name", "bgcolor"), new IKey("value", "#869ca7")])
|
||||
, Dand.wrapna("param", [new IKey("name", "allowScriptAccess"), new IKey("value", origin)])
|
||||
]
|
||||
,
|
||||
[
|
||||
new IKey("classid", "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000")
|
||||
, new IKey("id", sid)
|
||||
, new IKey("name", sid)
|
||||
, new IKey("width", width)
|
||||
, new IKey("height", height)
|
||||
, new IKey("data", src)
|
||||
, new IKey("type", "application/x-shockwave-flash")
|
||||
, new IKey("codebase", "http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab")
|
||||
]
|
||||
)
|
||||
).innerHTML;
|
||||
};
|
||||
|
||||
__static_method( Swf, "create", IE ? makeStageIE : makeStage );
|
||||
__static_method( Swf, "realize", realize );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "Swf", Swf );
|
||||
})();
|
10
botanjs/src/Dandelion/Window.js
Normal file
10
botanjs/src/Dandelion/Window.js
Normal file
@ -0,0 +1,10 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion.Window" );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "scrollTop" , function() { return window.pageYOffset || document.documentElement.scrollTop; } );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "scrollLeft" , function() { return window.pageXOffset || document.documentElement.scrollLeft; } );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "scrollHeight" , function() { return window.scrollHeight || document.documentElement.scrollHeight } );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "clientHeight" , function() { return window.clientHeight || document.documentElement.clientHeight; } );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "scrollWidth" , function() { return window.scrollWidth || document.documentElement.scrollWidth } );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER , "clientWidth" , function() { return window.clientWidth || document.documentElement.clientWidth; } );
|
||||
})();
|
187
botanjs/src/Dandelion/_this.js
Normal file
187
botanjs/src/Dandelion/_this.js
Normal file
@ -0,0 +1,187 @@
|
||||
(function(){
|
||||
var ns = __namespace( "Dandelion" );
|
||||
var IE = __import( "System.Global.IE" );
|
||||
|
||||
/* @type {System.utils.IKey}*/
|
||||
var IKey = __import( "System.utils.IKey" );
|
||||
|
||||
/* @type {Dandelion.IDOMElement}*/
|
||||
var IDOMElement;
|
||||
|
||||
var wrap = function ( wwith, id, wclass, elements, iKeys )
|
||||
{
|
||||
var tmp = document.createElement( wwith || "div" );
|
||||
if( id ) tmp.id = id;
|
||||
if( wclass )
|
||||
{
|
||||
if( IE )
|
||||
{
|
||||
tmp.className = wclass;
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp.setAttribute( "class", wclass );
|
||||
}
|
||||
}
|
||||
|
||||
if ( iKeys )
|
||||
{
|
||||
if ( iKeys instanceof Array )
|
||||
{
|
||||
for (var i in iKeys)
|
||||
{
|
||||
tmp.setAttribute( iKeys[i].keyName, iKeys[i].keyValue );
|
||||
}
|
||||
}
|
||||
else if ( iKeys instanceof IKey )
|
||||
{
|
||||
tmp.setAttribute( iKeys.keyName, iKeys.keyValue );
|
||||
}
|
||||
}
|
||||
|
||||
if( elements )
|
||||
{
|
||||
// is array?
|
||||
if(elements instanceof Array)
|
||||
{
|
||||
var l = elements.length;
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
elements[i] && tmp.appendChild( elements[i] );
|
||||
}
|
||||
}
|
||||
// else if string
|
||||
else if( typeof elements == "string" )
|
||||
{
|
||||
tmp.appendChild(_createTextNode(elements));
|
||||
}
|
||||
// else append child, do not do any error handling!
|
||||
else if( elements )
|
||||
{
|
||||
tmp.appendChild( elements );
|
||||
}
|
||||
}
|
||||
return tmp;
|
||||
};
|
||||
|
||||
var wrapc = function ( aClass, elements, iKeys ) {
|
||||
return wrap( false, false, aClass, elements, iKeys );
|
||||
};
|
||||
|
||||
// wrap element afters
|
||||
var wrape = function ( elements, iKeys ) {
|
||||
return wrap( false, false, false, elements, iKeys );
|
||||
};
|
||||
|
||||
// wrap name element after
|
||||
var wrapne = function ( name, elements, iKeys ) {
|
||||
return wrap(name, false, false, elements, iKeys);
|
||||
};
|
||||
|
||||
// wrap name attirbutes after
|
||||
var wrapna = function ( name, iKeys ) {
|
||||
return wrap(name, false, false, false, iKeys);
|
||||
};
|
||||
|
||||
var _createTextNode = function (s)
|
||||
{
|
||||
return document.createTextNode(s);
|
||||
};
|
||||
|
||||
// Bubble up element if <condition>
|
||||
var bubbleUp = function ( elem, condition )
|
||||
{
|
||||
if( condition( elem ) ) return elem;
|
||||
|
||||
return elem.parentNode && bubbleUp( elem.parentNode, condition );
|
||||
};
|
||||
|
||||
var chainUpApply = function( elem, func )
|
||||
{
|
||||
if( !elem ) return;
|
||||
|
||||
var chain = func( elem );
|
||||
|
||||
if( chain && elem.parentNode )
|
||||
{
|
||||
chainUpApply( elem.parentNode, func );
|
||||
}
|
||||
};
|
||||
|
||||
var id = function( name, idom )
|
||||
{
|
||||
var elem = document.getElementById( name );
|
||||
if( !elem ) return elem;
|
||||
|
||||
if( idom && runtimeImport() )
|
||||
{
|
||||
return IDOMElement( elem );
|
||||
}
|
||||
|
||||
return elem;
|
||||
};
|
||||
|
||||
var elements = function( elem, idom )
|
||||
{
|
||||
if( idom && runtimeImport() )
|
||||
{
|
||||
var l = elem.length;
|
||||
var ielem = [];
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
ielem[i] = IDOMElement( elem[i] );
|
||||
}
|
||||
return ielem;
|
||||
}
|
||||
|
||||
return elem;
|
||||
};
|
||||
|
||||
var tag = function( name, idom, target )
|
||||
{
|
||||
target = target === undefined ? document : target;
|
||||
var elem = target.getElementsByTagName( name );
|
||||
return elements( elem, idom );
|
||||
};
|
||||
|
||||
var name = function( name, idom, target )
|
||||
{
|
||||
target = target === undefined ? document : target;
|
||||
var elem = target.getElementsByName( name );
|
||||
return elements( elem, idom );
|
||||
};
|
||||
|
||||
var getClass = function( name, idom, target )
|
||||
{
|
||||
target = target === undefined ? document : target;
|
||||
var elem = target.getElementsByClassName( name );
|
||||
return elements( elem, idom );
|
||||
};
|
||||
|
||||
var runtimeImport = function()
|
||||
{
|
||||
if( IDOMElement ) return true;
|
||||
|
||||
try
|
||||
{
|
||||
var a = "Dandelion.IDOMElement";
|
||||
IDOMElement = __import( a );
|
||||
return true;
|
||||
}
|
||||
catch( e ) { }
|
||||
return false;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "wrap", wrap );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "wrapc", wrapc );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "wrape", wrape );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "wrapne", wrapne );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "wrapna", wrapna );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "textNode", _createTextNode );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "bubbleUp", bubbleUp );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "chainUpApply", chainUpApply );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "id", id );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "tag", tag );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "name", name );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "glass", getClass );
|
||||
})();
|
64
botanjs/src/README.md
Normal file
64
botanjs/src/README.md
Normal file
@ -0,0 +1,64 @@
|
||||
Goals:
|
||||
1. Scalable
|
||||
2. Compressable ( Closure compiler with ADVANCED option )
|
||||
3. Readable
|
||||
4. Only use 1 var in global scope, I.E. window.BotanJS
|
||||
5. Package like
|
||||
|
||||
Predefined programming rules:
|
||||
```
|
||||
__namespace
|
||||
__import
|
||||
__readOnly
|
||||
__static_method
|
||||
__extends
|
||||
|
||||
ns = __namespace( <package> )
|
||||
ns[ NS_INVOKE ]( <Same Level Packages> )
|
||||
ns[ NS_EXPORT ]( <TYPE>, <Name>, <Object> )
|
||||
ns[ NS_TRIGGER ]( <TYPE>, <Callback> )
|
||||
```
|
||||
|
||||
Usage:
|
||||
```
|
||||
BotanJS.import( <package> )
|
||||
```
|
||||
|
||||
BotanJS Class Map:
|
||||
```
|
||||
<BotanJS>
|
||||
<class name="System" location="/System/_this.js">
|
||||
<class name="Global" location="/System/Global.js">
|
||||
<export>ALLOWED_ORIGIN</export>
|
||||
</class>
|
||||
<class name="Debug" location="/System/Debug.js">
|
||||
<import>System.Global</import>
|
||||
</class>
|
||||
</class>
|
||||
|
||||
<class name="Dandelion" location="/Dandelion/_this.js">
|
||||
<class name="Swf" location="/Dandelion/Swf/_this.js">
|
||||
<!-- problem exists on Extern -->
|
||||
<!-- extern must follow path order -->
|
||||
<import>Dandelion.Swf.ExtAPI</import>
|
||||
<!--
|
||||
once Dandelion.Swf is imported
|
||||
Dandelion.MY_CLASS_DEPENDENT_PROP will become available
|
||||
-->
|
||||
<prop src="/Dandelion/Swf/_this.js">MY_CLASS_DEPENDENT_PROP</prop>
|
||||
<class name="ExtAPI" location="/Dandelion/Swf/ExtAPI.js">
|
||||
<import> ... </import>
|
||||
</class>
|
||||
</class>
|
||||
</class>
|
||||
</BotanJS>
|
||||
```
|
||||
|
||||
Css Inheritance:
|
||||
Unlike js, which use classes only when __import is explicitly called.
|
||||
Structure of css class are inherited by it's parent namespace
|
||||
```
|
||||
Dandelion.Swf.ExtAPI.css
|
||||
inherits from Dandelion.Swf.css
|
||||
inherits from Dandelion.css
|
||||
```
|
75
botanjs/src/System/Cycle/Trigger.js
Normal file
75
botanjs/src/System/Cycle/Trigger.js
Normal file
@ -0,0 +1,75 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Cycle.Trigger" );
|
||||
|
||||
/** @type {System.Cycle} */
|
||||
var Cycle = __import( "System.Cycle" );
|
||||
|
||||
// trigger list
|
||||
var tList = [];
|
||||
var stepperId = -1;
|
||||
|
||||
var stepper = function( args )
|
||||
{
|
||||
var thisTime = new Date().getTime();
|
||||
for ( var i in tList )
|
||||
{
|
||||
var f = tList[i];
|
||||
if( f && thisTime > f[2] )
|
||||
{
|
||||
try
|
||||
{
|
||||
if( f[0]() )
|
||||
{
|
||||
f[1]();
|
||||
delete tList[i];
|
||||
}
|
||||
else f[2] = thisTime + f[3];
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug.Error(e);
|
||||
delete tList[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var registerTrigger = function ( trigger, handler, peekInt )
|
||||
{
|
||||
tList[ tList.length ] = [ trigger, handler, new Date().getTime() + peekInt, peekInt ]
|
||||
};
|
||||
|
||||
var heightTrigger = function ( __element, value, handler )
|
||||
{
|
||||
var k = function () {
|
||||
return ( this.a.clientHeight == this.b );
|
||||
}.bind({ a: __element, b: value });
|
||||
|
||||
registerTrigger( k, handler, 50 );
|
||||
};
|
||||
|
||||
var transitionTrigger = function (__style, value, handler)
|
||||
{
|
||||
var k = function ()
|
||||
{
|
||||
return ( this.a.transition == this.b );
|
||||
}.bind({a: __style, b: value });
|
||||
registerTrigger( k, handler, 50 );
|
||||
};
|
||||
|
||||
var regTick = function( e )
|
||||
{
|
||||
if( stepperId < 0 )
|
||||
{
|
||||
stepperId = Cycle.TICK.putStepper( stepper );
|
||||
}
|
||||
};
|
||||
|
||||
ns.addEventListener( "NS_IMPORT", regTick );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "register", registerTrigger );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "transition", transitionTrigger );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "height", heightTrigger );
|
||||
|
||||
ns[ NS_TRIGGER ]( TGR_IMPORT, regTick );
|
||||
})();
|
108
botanjs/src/System/Cycle/_this.js
Normal file
108
botanjs/src/System/Cycle/_this.js
Normal file
@ -0,0 +1,108 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Cycle" );
|
||||
|
||||
/** @type {System.Tick} */
|
||||
var utils = __import( "System.utils" );
|
||||
/** @type {System.Tick} */
|
||||
var Tick = __import( "System.Tick" );
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
|
||||
var tList = [];
|
||||
|
||||
var stepper = function()
|
||||
{
|
||||
var thisTime = new Date().getTime();
|
||||
// 0: Callback
|
||||
// 1: scheduled run time
|
||||
// 2: Permanent
|
||||
// ( 3: id )
|
||||
// 4: interval
|
||||
for ( var i in tList )
|
||||
{
|
||||
var f = tList[i];
|
||||
if( f && thisTime > f[1] )
|
||||
{
|
||||
try
|
||||
{
|
||||
f[0]();
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug.Error(e);
|
||||
delete tList[i];
|
||||
continue;
|
||||
}
|
||||
|
||||
if( f[2] )
|
||||
{
|
||||
delete tList[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
f[1] = thisTime + f[4];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Should bind "func" before register
|
||||
var registerDelay = function (func, milliSec)
|
||||
{
|
||||
tList[ tList.length ] = [ func, new Date().getTime() + milliSec, true ];
|
||||
};
|
||||
|
||||
var registerPermanentTicker = function ( id, func, interval )
|
||||
{
|
||||
for ( var i in tList )
|
||||
{
|
||||
if( tList[i][3] == id )
|
||||
return false;
|
||||
}
|
||||
|
||||
tList[ tList.length ] = [ func, new Date().getTime() + interval, false, id, interval ];
|
||||
};
|
||||
|
||||
var deletePermanentTicker = function ( id )
|
||||
{
|
||||
// 3: id
|
||||
for ( var i in tList )
|
||||
{
|
||||
if( tList[i][3] == id )
|
||||
delete tList[i];
|
||||
}
|
||||
};
|
||||
|
||||
var next = function( func )
|
||||
{
|
||||
tList[ tList.length ] = [ func, 0, true ];
|
||||
};
|
||||
|
||||
var ourTick = new Tick();
|
||||
ourTick.putStepper( stepper );
|
||||
|
||||
var gTickStart = function( e )
|
||||
{
|
||||
e.target.removeEventListener( "NS_IMPORT", gTickStart );
|
||||
|
||||
var TICK = __import( "System.Cycle.TICK", true );
|
||||
|
||||
if( TICK != ourTick && TICK.started )
|
||||
{
|
||||
debug.Info( "[System.Cycle] Global Tick exists" );
|
||||
ourTick = null;
|
||||
return;
|
||||
}
|
||||
|
||||
debug.Info( "[System.Cycle] Creating global Tick" );
|
||||
ourTick.start();
|
||||
};
|
||||
|
||||
ns.addEventListener( "NS_IMPORT", gTickStart );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "next", next );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "delay", registerDelay );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "perma", registerPermanentTicker );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "permaRemove", deletePermanentTicker );
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER, "TICK", function(){ return ourTick; } );
|
||||
})();
|
46
botanjs/src/System/Debug.js
Normal file
46
botanjs/src/System/Debug.js
Normal file
@ -0,0 +1,46 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Debug" );
|
||||
/** @type {System.Log} */
|
||||
var Log = __import( "System.Log" );
|
||||
/** @type {System.Global} */
|
||||
var _global = __import( "System.Global" );
|
||||
|
||||
var st_info = _global.debug;
|
||||
var st_error = true;
|
||||
|
||||
var Error = function( e )
|
||||
{
|
||||
if( st_error )
|
||||
Log.writeLine( e.name + "\n\t" + e.message + "\n\t" + e.stack, Log.ERROR );
|
||||
};
|
||||
|
||||
var Info = function(e)
|
||||
{
|
||||
if( st_info )
|
||||
Log.writeLine( e, Log.INFO );
|
||||
};
|
||||
|
||||
var turnOff = function( what )
|
||||
{
|
||||
if( what == "info" ) st_info = false;
|
||||
else if( what == "error" ) st_error = false;
|
||||
};
|
||||
|
||||
var turnOn = function( what )
|
||||
{
|
||||
if( what == "info" ) st_info = true;
|
||||
else if( what == "error" ) st_error = true;
|
||||
};
|
||||
|
||||
/* {{{ Root log override */
|
||||
BotanJS.log.write = Info;
|
||||
|
||||
while( !BotanJS.log.end() )
|
||||
Info( BotanJS.log.read() );
|
||||
/* End Root log override }}}*/
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "Error", Error );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "Info", Info );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "turnOff", turnOff );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "turnOn", turnOn );
|
||||
})();
|
16
botanjs/src/System/Global.js
Normal file
16
botanjs/src/System/Global.js
Normal file
@ -0,0 +1,16 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Global" );
|
||||
|
||||
var debug = function()
|
||||
{
|
||||
return window[ "debugEnv" ] && window[ "debugEnv" ];
|
||||
};
|
||||
|
||||
// for IE < 10
|
||||
var IE = Boolean( document[ "all" ] );
|
||||
var ALLOWED_ORIGINS = window[ "allowed_origins" ] || [];
|
||||
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER, "debug", debug );
|
||||
ns[ NS_EXPORT ]( EX_CONST, "IE", IE );
|
||||
ns[ NS_EXPORT ]( EX_CONST, "ALLOWED_ORIGINS", ALLOWED_ORIGINS );
|
||||
})();
|
46
botanjs/src/System/Log.js
Normal file
46
botanjs/src/System/Log.js
Normal file
@ -0,0 +1,46 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Log" );
|
||||
var handler = [];
|
||||
|
||||
var SYSTEM = 1;
|
||||
var INFO = 16;
|
||||
var ERROR = 32;
|
||||
|
||||
var writeLine = function ( mesg, type )
|
||||
{
|
||||
type = ( type === undefined ) ? INFO : type;
|
||||
|
||||
var handled = false;
|
||||
for( var i in handler )
|
||||
{
|
||||
handler[i]( mesg, type );
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if( !handled
|
||||
&& window[ "console" ]
|
||||
&& console.log
|
||||
) console.log( mesg );
|
||||
};
|
||||
|
||||
var registerHandler = function( func )
|
||||
{
|
||||
var index = -1;
|
||||
handler[ index = handler.length ] = func;
|
||||
|
||||
return index;
|
||||
};
|
||||
|
||||
var removeHandler = function( index )
|
||||
{
|
||||
delete handler[ index ];
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "writeLine", writeLine );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "registerHandler", registerHandler );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "removeHandler", removeHandler );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CONST, "INFO", INFO );
|
||||
ns[ NS_EXPORT ]( EX_CONST, "ERROR", ERROR );
|
||||
ns[ NS_EXPORT ]( EX_CONST, "SYSTEM", SYSTEM );
|
||||
})();
|
75
botanjs/src/System/Net/ClassLoader.js
Normal file
75
botanjs/src/System/Net/ClassLoader.js
Normal file
@ -0,0 +1,75 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Net" );
|
||||
var className = "ClassLoader";
|
||||
|
||||
/** @type {System.utils} */
|
||||
var utils = __import( "System.utils" );
|
||||
/** @type {System.utils.IKey} */
|
||||
var IKey = __import( "System.utils.IKey" );
|
||||
/** @type {Dandelion} */
|
||||
var Dand = __import( "Dandelion" );
|
||||
|
||||
var loadFile = function ( sapi, request, mode )
|
||||
{
|
||||
var head = Dand.tag( "head" )[0];
|
||||
|
||||
// Add css
|
||||
head.appendChild(
|
||||
Dand.wrapna(
|
||||
"link"
|
||||
, IKey.quickDef(
|
||||
"rel", "stylesheet"
|
||||
, "type", "text/css"
|
||||
, "href", sapi + mode + "css/" + request
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
// Add js
|
||||
head.appendChild(
|
||||
Dand.wrapna(
|
||||
"script"
|
||||
, IKey.quickDef(
|
||||
"type", "text/javascript"
|
||||
, "src", sapi + mode + "js/" + request
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
var Loader = function( sapi, mode )
|
||||
{
|
||||
mode = ( mode === undefined ) ? "o" : mode;
|
||||
|
||||
this.load = function( classes, handler )
|
||||
{
|
||||
if( !classes.join ) classes = [ classes ];
|
||||
|
||||
var excludes = BotanJS.getDef();
|
||||
// Excludes
|
||||
utils.objMap( excludes , function( v ) { return "-" + v; } );
|
||||
|
||||
var loadc = null;
|
||||
var onLoad = function( e )
|
||||
{
|
||||
if( classes.indexOf( e.data.name ) < 0 ) return;
|
||||
handler( e.data.name );
|
||||
};
|
||||
|
||||
var sp = mode ? { 'o': '/', 'r': '/' }[ mode ] : ',';
|
||||
|
||||
loadFile(
|
||||
sapi
|
||||
, classes.join( sp ) + sp + excludes.join( sp )
|
||||
, mode
|
||||
);
|
||||
|
||||
BotanJS.addEventListener( "NS_INIT", onLoad );
|
||||
BotanJS.addEventListener( "NS_EXPORT", onLoad );
|
||||
};
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "ClassLoader", Loader );
|
||||
})();
|
||||
|
141
botanjs/src/System/Net/_this.js
Normal file
141
botanjs/src/System/Net/_this.js
Normal file
@ -0,0 +1,141 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Net" );
|
||||
/** @type {System.Debug} */
|
||||
var debug = __import( "System.Debug" );
|
||||
/** @type {Dandelion.IDOMObject} */
|
||||
var IDOMObject = __import( "Dandelion.IDOMObject" );
|
||||
|
||||
// Handles all http transfers
|
||||
var getData = function (uri, handler, failedHandler)
|
||||
{
|
||||
var request = new XMLHttpRequest();
|
||||
debug.Info("[Net] GET: " + uri);
|
||||
request.onreadystatechange = function()
|
||||
{
|
||||
/*
|
||||
0: request not initialized
|
||||
1: server connection established
|
||||
2: request received
|
||||
3: processing request
|
||||
4: request finished and response is ready
|
||||
*/
|
||||
if(request.readyState == 2)
|
||||
{
|
||||
debug.Info("[Net] GET R2:" + uri);
|
||||
}
|
||||
else if (request.readyState == 4)
|
||||
{
|
||||
debug.Info("[Net] GET R4:" + uri);
|
||||
if (request.status == 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
handler(request.responseText);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug.Error(e);
|
||||
failedHandler(null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug.Info("[Net] Status: " + request.status.toString());
|
||||
debug.Info(request.responseText);
|
||||
failedHandler && failedHandler(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
request.open("GET", uri, true);
|
||||
request.send();
|
||||
};
|
||||
|
||||
var postFile = function (uri, data, handlers)
|
||||
{
|
||||
var request = new XMLHttpRequest()
|
||||
, generalExchange = new IDOMObject( request )
|
||||
, uploadExchange = new IDOMObject( request.upload )
|
||||
;
|
||||
|
||||
if ( uploadExchange ) {
|
||||
handlers.progress && uploadExchange.addEventListener("Progress", handlers.progress);
|
||||
handlers.failed && uploadExchange.addEventListener("Error", handlers.failed);
|
||||
}
|
||||
|
||||
generalExchange.addEventListener("ReadyStateChange", function(e) {
|
||||
if ( 4 == this.readyState ) {
|
||||
handlers.complete && handlers.complete(request.responseText);
|
||||
}
|
||||
});
|
||||
|
||||
request.open("POST", uri, true);
|
||||
// request.setRequestHeader("Content-Type", "multipart/form-data");
|
||||
request.send(data);
|
||||
};
|
||||
|
||||
var postData = function (uri, data, handler, failedHandler)
|
||||
{
|
||||
var request = new XMLHttpRequest();
|
||||
// compile post string
|
||||
data = compilePostData(data);
|
||||
debug.Info("[Net] PostString: " + data);
|
||||
request.onreadystatechange = function()
|
||||
{
|
||||
/*
|
||||
0: request not initialized
|
||||
1: server connection established
|
||||
2: request received
|
||||
3: processing request
|
||||
4: request finished and response is ready
|
||||
*/
|
||||
if(request.readyState == 2)
|
||||
{
|
||||
debug.Info("[Net] POST R2:" + uri);
|
||||
}
|
||||
else if (request.readyState == 4)
|
||||
{
|
||||
debug.Info("[Net] POST R4:" + uri);
|
||||
if (request.status == 200)
|
||||
{
|
||||
try
|
||||
{
|
||||
var obj = JSON.parse(request.responseText);
|
||||
obj.status ? handler(obj): failedHandler(obj);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
debug.Error(e);
|
||||
failedHandler(null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
debug.Info("[Net] Status: " + request.status.toString());
|
||||
debug.Info(request.responseText);
|
||||
failedHandler(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.open( "POST", uri );
|
||||
request.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
|
||||
request.send( data );
|
||||
};
|
||||
|
||||
var compilePostData = function (obj)
|
||||
{
|
||||
var postdata = "timestamp=" + new Date().getTime();
|
||||
for(var name in obj)
|
||||
{
|
||||
postdata += "&" + name + "=" + encodeURIComponent(obj[name]);
|
||||
}
|
||||
|
||||
return postdata;
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "getData", getData );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "postData", postData );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "postFile", postFile );
|
||||
// ns[ NS_EXPORT ]( EX_FUNC, "compilePostData", compilePostData );
|
||||
})();
|
||||
|
13
botanjs/src/System/Policy/_this.js
Normal file
13
botanjs/src/System/Policy/_this.js
Normal file
@ -0,0 +1,13 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.Policy" );
|
||||
|
||||
/** @type {System.Global} */
|
||||
var Global = __import( "System.Global" );
|
||||
|
||||
var isOriginAllowed = function( origin )
|
||||
{
|
||||
return -1 < Global.ALLOWED_ORIGINS.indexOf( origin );
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "isOriginAllowed", isOriginAllowed );
|
||||
})();
|
50
botanjs/src/System/Tick.js
Normal file
50
botanjs/src/System/Tick.js
Normal file
@ -0,0 +1,50 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System" );
|
||||
|
||||
var Tick = function()
|
||||
{
|
||||
// cycle counter
|
||||
var nc = 0;
|
||||
this.__started = false;
|
||||
|
||||
this.loop = function()
|
||||
{
|
||||
for( var i in this.steppers )
|
||||
this.steppers[i]();
|
||||
nc ++;
|
||||
};
|
||||
|
||||
__readOnly( this, "count", function() { return nc; } );
|
||||
};
|
||||
|
||||
Tick.prototype.putStepper = function( stepperCallback )
|
||||
{
|
||||
var l = this.steppers.length;
|
||||
this.steppers[l] = stepperCallback;
|
||||
return l;
|
||||
};
|
||||
|
||||
Tick.prototype.start = function()
|
||||
{
|
||||
if( !this.__started )
|
||||
{
|
||||
this.id = setInterval( this.loop.bind( this ), 0 );
|
||||
this.__started = true;
|
||||
}
|
||||
};
|
||||
|
||||
Tick.prototype.stop = function()
|
||||
{
|
||||
if( this.__started )
|
||||
{
|
||||
this.__started = false;
|
||||
clearInterval( this.id );
|
||||
}
|
||||
};
|
||||
|
||||
Tick.prototype.steppers = [];
|
||||
|
||||
__readOnly( Tick.prototype, "started", function() { return this.__started; } );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "Tick", Tick );
|
||||
})();
|
3
botanjs/src/System/_this.js
Normal file
3
botanjs/src/System/_this.js
Normal file
@ -0,0 +1,3 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System" )
|
||||
})();
|
17
botanjs/src/System/utils/DataKey.js
Normal file
17
botanjs/src/System/utils/DataKey.js
Normal file
@ -0,0 +1,17 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.utils" );
|
||||
var IKey = ns[ NS_INVOKE ]( "IKey" );
|
||||
// Data key
|
||||
var DataKey = function ( name, value )
|
||||
{
|
||||
IKey.call(
|
||||
this
|
||||
, "data-" + name
|
||||
, value ? encodeURIComponent( String( value ) ) : ""
|
||||
);
|
||||
};
|
||||
|
||||
__extends( DataKey, IKey );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "DataKey", DataKey );
|
||||
})();
|
19
botanjs/src/System/utils/EventKey.js
Normal file
19
botanjs/src/System/utils/EventKey.js
Normal file
@ -0,0 +1,19 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.utils" );
|
||||
var IKey = ns[ NS_INVOKE ]( "IKey" );
|
||||
// Event key
|
||||
var EventKey = function ( eventType, eventHandler )
|
||||
{
|
||||
IKey.call( this, eventType, eventHandler );
|
||||
|
||||
this.type = eventType.toLowerCase();
|
||||
this.handler = eventHandler;
|
||||
}
|
||||
|
||||
__extends( EventKey, IKey );
|
||||
|
||||
EventKey.prototype.type = "";
|
||||
EventKey.prototype.handler = null;
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "EventKey", EventKey );
|
||||
})();
|
49
botanjs/src/System/utils/IKey.js
Normal file
49
botanjs/src/System/utils/IKey.js
Normal file
@ -0,0 +1,49 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.utils" );
|
||||
var ClassName = "IKey";
|
||||
|
||||
////// Class IKey
|
||||
var IKey = function (name, value)
|
||||
{
|
||||
if ( name && ( typeof name != "string" ) ) return;
|
||||
this.keyName = name;
|
||||
|
||||
if( value instanceof IKey )
|
||||
{
|
||||
this.keyValue = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.keyValue = (value != undefined) ? String(value) : "";
|
||||
}
|
||||
|
||||
this["keyName"] = this.keyName;
|
||||
this["keyValue"] = this.keyValue;
|
||||
};
|
||||
|
||||
IKey.prototype.keyName = "";
|
||||
IKey.prototype.keyValue = "";
|
||||
|
||||
var quickDef = function()
|
||||
{
|
||||
var l = arguments.length;
|
||||
|
||||
if( l % 2 != 0 )
|
||||
{
|
||||
ns[ NS_THROW ]( "Invalid Definition Count", ClassName );
|
||||
}
|
||||
|
||||
var keys = [];
|
||||
for( var i = 0; i < l; i += 2 )
|
||||
{
|
||||
keys[ keys.length ] = new IKey( arguments[i], arguments[ i + 1 ] );
|
||||
}
|
||||
|
||||
return keys;
|
||||
};
|
||||
|
||||
__static_method( IKey, "quickDef", quickDef );
|
||||
|
||||
ns[ NS_EXPORT ]( EX_CLASS, "IKey", IKey );
|
||||
|
||||
})();
|
49
botanjs/src/System/utils/Perf.js
Normal file
49
botanjs/src/System/utils/Perf.js
Normal file
@ -0,0 +1,49 @@
|
||||
(function(){
|
||||
// Performance Functions
|
||||
var ns = __namespace( "System.utils.Perf" );
|
||||
|
||||
/** {{{ Fast UUID generator, RFC4122 version 4 compliant.
|
||||
* author: Jeff Ward (jcward.com).
|
||||
* license: MIT license
|
||||
* link: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136
|
||||
**/
|
||||
var lut = [];
|
||||
for ( var i=0; i < 256; i++ )
|
||||
{
|
||||
lut[i] = ( i < 16 ? '0' : '' ) + ( i ).toString(16);
|
||||
}
|
||||
|
||||
var UUID = function()
|
||||
{
|
||||
var d0 = Math.random()*0xffffffff|0;
|
||||
var d1 = Math.random()*0xffffffff|0;
|
||||
var d2 = Math.random()*0xffffffff|0;
|
||||
var d3 = Math.random()*0xffffffff|0;
|
||||
return lut[d0&0xff]+lut[d0>>8&0xff]+lut[d0>>16&0xff]+lut[d0>>24&0xff]+'-'+
|
||||
lut[d1&0xff]+lut[d1>>8&0xff]+'-'+lut[d1>>16&0x0f|0x40]+lut[d1>>24&0xff]+'-'+
|
||||
lut[d2&0x3f|0x80]+lut[d2>>8&0xff]+'-'+lut[d2>>16&0xff]+lut[d2>>24&0xff]+
|
||||
lut[d3&0xff]+lut[d3>>8&0xff]+lut[d3>>16&0xff]+lut[d3>>24&0xff];
|
||||
};
|
||||
/* }}}*/
|
||||
|
||||
// Reverse an array using XOR swap
|
||||
var Array_Reverse = function( array )
|
||||
{
|
||||
var i = null;
|
||||
var l = array.length;
|
||||
var r = null;
|
||||
for (i = 0, r = l - 1; i < r; i += 1, r -= 1)
|
||||
{
|
||||
var left = array[i];
|
||||
var right = array[r];
|
||||
left ^= right;
|
||||
right ^= left;
|
||||
left ^= right;
|
||||
array[i] = left;
|
||||
array[r] = right;
|
||||
}
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_READONLY_GETTER, "uuid", UUID );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "ArrayReverse", Array_Reverse );
|
||||
})();
|
41
botanjs/src/System/utils/_this.js
Normal file
41
botanjs/src/System/utils/_this.js
Normal file
@ -0,0 +1,41 @@
|
||||
(function(){
|
||||
var ns = __namespace( "System.utils" );
|
||||
|
||||
// Get prop from obj if obj.<prop> is <type>
|
||||
var objGetProp = function ( obj, prop, type )
|
||||
{
|
||||
if(obj && obj[prop])
|
||||
{
|
||||
var t = obj[prop].constructor.toString().match(/function ([^\(]+)/);
|
||||
if(t && t.length == 2 && t[1].toUpperCase() == type.toUpperCase())
|
||||
{
|
||||
return obj[prop];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var objSearch = function ( obj, cond, prop )
|
||||
{
|
||||
for( var i in obj )
|
||||
{
|
||||
if( cond( obj[i] ) )
|
||||
{
|
||||
return obj[i][prop] || obj[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
var objMap = function( obj, callback )
|
||||
{
|
||||
for( var i in obj )
|
||||
{
|
||||
obj[i] = callback( obj[i] );
|
||||
}
|
||||
};
|
||||
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "objGetProp", objGetProp );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "objSearch", objSearch );
|
||||
ns[ NS_EXPORT ]( EX_FUNC, "objMap", objMap );
|
||||
})();
|
383
botanjs/src/_this.js
Normal file
383
botanjs/src/_this.js
Normal file
@ -0,0 +1,383 @@
|
||||
/*{{{ Shorthand Functions */
|
||||
var __extends = function( obj, target ) {
|
||||
obj.prototype = Object.create( target.prototype );
|
||||
obj.prototype.constructor = obj;
|
||||
};
|
||||
var __readOnly = function( prototype, name, callback )
|
||||
{
|
||||
Object.defineProperty( prototype, name, {
|
||||
get: callback
|
||||
, set: function( v ) {
|
||||
throw new Error( "Setting a read-only property: " + this.p );
|
||||
}.bind( { p: name } )
|
||||
} );
|
||||
};
|
||||
var __getter = function( obj, name, callback )
|
||||
{
|
||||
Object.defineProperty( obj, name, {
|
||||
get: callback
|
||||
, set: function( v ) {
|
||||
throw new Error( "Setting a read-only property: " + this.p );
|
||||
}.bind( { p: name } )
|
||||
} );
|
||||
};
|
||||
var __static_method = function( obj, name, callback )
|
||||
{
|
||||
Object.defineProperty( obj, name, {
|
||||
get: function(){ return callback; }
|
||||
, set: function( v ) {
|
||||
throw new Error( "Setting a read-only property: " + this.p );
|
||||
}.bind( { p: name } )
|
||||
} );
|
||||
};
|
||||
var __const = __static_method;
|
||||
/* End Shorthand Functions }}}*/
|
||||
|
||||
/*{{{ BotanEvent & EventDispatcher */
|
||||
var BotanEvent = function( name, data )
|
||||
{
|
||||
var __propagating = false;
|
||||
var __propagated = false;
|
||||
|
||||
__static_method(
|
||||
this, "propagate"
|
||||
, function()
|
||||
{
|
||||
if( !__propagated )
|
||||
{
|
||||
__propagating = true;
|
||||
}
|
||||
__propagated = true;
|
||||
}
|
||||
);
|
||||
|
||||
__static_method(
|
||||
this, "stopPropagating"
|
||||
, function()
|
||||
{
|
||||
__propagating = false;
|
||||
}
|
||||
);
|
||||
|
||||
__const( this, "type", name );
|
||||
|
||||
__getter(
|
||||
this, "propagating"
|
||||
, function()
|
||||
{
|
||||
return __propagating;
|
||||
}
|
||||
);
|
||||
|
||||
__const( this, "data", data );
|
||||
|
||||
this.setTarget = function( target )
|
||||
{
|
||||
__const( this, "target", target );
|
||||
this.setTarget = undefined;
|
||||
}.bind( this );
|
||||
};
|
||||
|
||||
/** @constructor
|
||||
* @extends EventTarget
|
||||
**/
|
||||
var EventDispatcher = function() {
|
||||
var events = {};
|
||||
var _self = this;
|
||||
|
||||
var getStack = function( name )
|
||||
{
|
||||
if( !events[ name ] ) events[ name ] = [];
|
||||
return events[ name ];
|
||||
};
|
||||
|
||||
var _dispatch = function()
|
||||
{
|
||||
this.evt.propagate();
|
||||
for( var i in this.stack )
|
||||
{
|
||||
if( this.evt.propagating )
|
||||
{
|
||||
this.stack[ i ]( this.evt );
|
||||
}
|
||||
}
|
||||
this.evt.stopPropagating();
|
||||
};
|
||||
|
||||
this.addEventListener = function( type, handler )
|
||||
{
|
||||
var stack = getStack( type );
|
||||
stack[ stack.length ] = handler;
|
||||
};
|
||||
|
||||
this.removeEventListener = function( type, handler )
|
||||
{
|
||||
var stack = getStack( type );
|
||||
var i = stack.indexOf( handler );
|
||||
if( i < 0 ) return;
|
||||
delete stack[ i ];
|
||||
};
|
||||
|
||||
/** @type {Function}
|
||||
* @param {BotanEvent} evt
|
||||
*/
|
||||
this.dispatchEvent = function( _evt )
|
||||
{
|
||||
var _stack = getStack( _evt.type );
|
||||
if( _evt.setTarget ) _evt.setTarget( _self );
|
||||
// Dispatch the event asynchronously
|
||||
setTimeout( _dispatch.bind({ evt: _evt, stack: _stack }), 0 );
|
||||
};
|
||||
};
|
||||
|
||||
/* End BotanEvent & EventDispatcher }}}*/
|
||||
|
||||
/** @type {Array}
|
||||
* @extends {EventDispatcher}
|
||||
*/
|
||||
var NamespaceObj = function() {
|
||||
EventDispatcher.call( this );
|
||||
};
|
||||
|
||||
NamespaceObj.prototype = new Array();
|
||||
|
||||
var packages = {};
|
||||
var _global = {};
|
||||
var _NSs = {};
|
||||
var _cacheIMP = {};
|
||||
|
||||
/*{{{ Constants */
|
||||
var EX_CONST = 0;
|
||||
var EX_VAR = 1;
|
||||
var EX_CLASS = 2;
|
||||
var EX_FUNC = 3;
|
||||
|
||||
var EX_READONLY_GETTER = 10;
|
||||
|
||||
var NS_INVOKE = 0;
|
||||
var NS_EXPORT = 1;
|
||||
var NS_TRIGGER = 10;
|
||||
var NS_THROW = 11;
|
||||
|
||||
var TGR_IMPORT = 0;
|
||||
/* End Constants }}}*/
|
||||
|
||||
/*{{{ Multi-instance handle */
|
||||
// Check if we are being imported 2nd time
|
||||
// If yes, we get the instance and overload
|
||||
// some core methods
|
||||
var sGarden = window["BotanJS"];
|
||||
|
||||
/** @type {BotanJS} */
|
||||
var BotanJS = null;
|
||||
var __namespace = null;
|
||||
var __import = null;
|
||||
|
||||
if( sGarden )
|
||||
{
|
||||
BotanJS = sGarden["sg"][0];
|
||||
__namespace = sGarden["sg"][1];
|
||||
__import = sGarden["sg"][2];
|
||||
}
|
||||
/* End Multi-instance handle }}}*/
|
||||
|
||||
/*{{{ Root level bug-free handlers */
|
||||
BotanJS = BotanJS || (function()
|
||||
{
|
||||
var i = 0;
|
||||
var mesg = [];
|
||||
var structures = [];
|
||||
var edp = new EventDispatcher();
|
||||
|
||||
var log = {};
|
||||
log.write = function( m ) { mesg[ mesg.length ] = m; };
|
||||
__static_method( log, "read", function() { return mesg[ i ++ ]; } );
|
||||
__static_method( log, "end", function() { return ( mesg.length <= i ); } );
|
||||
|
||||
__const( edp, "log", log );
|
||||
|
||||
__static_method( edp, "define", function( f ) { structures[ structures.length ] = f; } );
|
||||
__static_method( edp, "getDef", function() { return structures.slice(); } );
|
||||
|
||||
return edp;
|
||||
})();
|
||||
/* End Root level bug-free handlers }}}*/
|
||||
|
||||
/*{{{ Namespace declarator */
|
||||
__namespace = __namespace || function( ns )
|
||||
{
|
||||
if( _NSs[ ns ] ) return _NSs[ ns ];
|
||||
|
||||
var p = ns.split(".");
|
||||
var l = p.length;
|
||||
|
||||
var target = packages;
|
||||
for( var i = 0; i < l; i ++ ) {
|
||||
target[ p[i] ] = target[ p[i] ] || {};
|
||||
target = target[ p[i] ];
|
||||
}
|
||||
|
||||
target.__TRIGGERS = [];
|
||||
|
||||
nsObj = new NamespaceObj;
|
||||
nsObj[ NS_EXPORT ] = function( type, name, obj )
|
||||
{
|
||||
if( this.t[ name ] ) return;
|
||||
this.t[ name ] = [ type, obj ];
|
||||
|
||||
/** @type {BotanEvent} */
|
||||
var evt = new BotanEvent( "NS_EXPORT", {
|
||||
"name": this.n + "." + name
|
||||
, "type": type
|
||||
});
|
||||
|
||||
BotanJS.dispatchEvent( evt );
|
||||
|
||||
}.bind({ t: target, n: ns });
|
||||
|
||||
nsObj[ NS_INVOKE ] = function( target )
|
||||
{
|
||||
if( !this.t[ target ] )
|
||||
{
|
||||
throw new Error(
|
||||
"[" + this.n + "] "
|
||||
+ "Invoke failed: " + target + " does not exists"
|
||||
);
|
||||
}
|
||||
|
||||
return this.t[ target ][1];
|
||||
}.bind({ t: target, n: ns });
|
||||
|
||||
nsObj[ NS_TRIGGER ] = function( code, func )
|
||||
{
|
||||
this.__TRIGGERS[ code ] = func;
|
||||
}.bind( target );
|
||||
|
||||
nsObj[ NS_THROW ] = function( message, subclass )
|
||||
{
|
||||
subclass = subclass ? ( "." + subclass ) : "";
|
||||
throw new Error(
|
||||
"[" + this.n + subclass + "] " + message
|
||||
);
|
||||
}.bind({ n: ns });
|
||||
|
||||
/** @type {BotanEvent} */
|
||||
BotanJS.dispatchEvent( new BotanEvent( "NS_INIT", ns ) );
|
||||
return ( _NSs[ ns ] = nsObj );
|
||||
};
|
||||
/* End Namespace declarator }}}*/
|
||||
|
||||
/*{{{ Import operator */
|
||||
__import = __import || function( ns, noCache )
|
||||
{
|
||||
var nss = ns.replace( ".*", "" );
|
||||
if( _NSs[ nss ] )
|
||||
{
|
||||
_NSs[ nss ].dispatchEvent( new BotanEvent( "NS_IMPORT", target ) );
|
||||
}
|
||||
|
||||
// Read The Cache First
|
||||
if( !noCache && _cacheIMP[ ns ] ) return _cacheIMP[ ns ];
|
||||
|
||||
var p = ns.split(".");
|
||||
var l = p.length;
|
||||
|
||||
var target = packages;
|
||||
var wildcard = false;
|
||||
for( var i = 0; i < l; i ++ )
|
||||
{
|
||||
if( p[i] == "*" )
|
||||
{
|
||||
wildcard = true;
|
||||
break;
|
||||
}
|
||||
|
||||
target = target[ p[i] ];
|
||||
|
||||
if( !target )
|
||||
throw new Error( "No such class: " + ns );
|
||||
}
|
||||
|
||||
if( target instanceof Array && p[i] != "*" )
|
||||
{
|
||||
var rtarget = null;
|
||||
if( target[0] == EX_READONLY_GETTER )
|
||||
{
|
||||
rtarget = target[1]();
|
||||
}
|
||||
else
|
||||
{
|
||||
rtarget = target[1];
|
||||
}
|
||||
|
||||
_cacheIMP[ ns ] = rtarget;
|
||||
return rtarget;
|
||||
}
|
||||
|
||||
var nsObj = {};
|
||||
|
||||
for( var i in target )
|
||||
{
|
||||
var j = target[i];
|
||||
if( j instanceof Array )
|
||||
{
|
||||
if( wildcard && j[0] == EX_CLASS )
|
||||
{
|
||||
nsObj[ i ] = j[1];
|
||||
}
|
||||
else if( j[0] == EX_FUNC )
|
||||
{
|
||||
nsObj[ i ] = j[1];
|
||||
}
|
||||
else if( j[0] == EX_CONST )
|
||||
{
|
||||
Object.defineProperty( nsObj, i, {
|
||||
get: function() {
|
||||
return this.t[ this.p ][1];
|
||||
}.bind( { p: i, t: target } )
|
||||
, set: function( v ) {
|
||||
throw new Error( "Setting a read-only property: " + this.p );
|
||||
}.bind( { p: i } )
|
||||
});
|
||||
}
|
||||
else if( j[0] == EX_VAR )
|
||||
{
|
||||
Object.defineProperty( nsObj, i, {
|
||||
get: function() {
|
||||
return this.t[ this.p ][1]();
|
||||
}.bind( { p: i, t: target } )
|
||||
, set: function( v ) {
|
||||
this.t[ this.p ][1]( v );
|
||||
}.bind( { p: i, t: target } )
|
||||
});
|
||||
}
|
||||
else if( j[0] == EX_READONLY_GETTER )
|
||||
{
|
||||
Object.defineProperty( nsObj, i, {
|
||||
get: j[1]
|
||||
, set: function( v ) {
|
||||
throw new Error( "Setting a read-only property: " + this.p );
|
||||
}.bind( { p: i } )
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_cacheIMP[ ns ] = nsObj;
|
||||
return nsObj;
|
||||
};
|
||||
/* End Import operator }}}*/
|
||||
|
||||
window["BotanJS"] = {};
|
||||
window["BotanJS"]["version"] = "0.2";
|
||||
window["BotanJS"]["codename"] = "Botanical framework.js";
|
||||
window["BotanJS"]["import"] = function( p )
|
||||
{
|
||||
try { return __import( p ); }
|
||||
catch( e )
|
||||
{
|
||||
if( sGarden ) return sGarden["import"]( p );
|
||||
throw e;
|
||||
}
|
||||
};
|
||||
window["BotanJS"]["sg"] = [ BotanJS, __namespace, __import ];
|
16
botanjs/src/externs/BotanEvent.js
Normal file
16
botanjs/src/externs/BotanEvent.js
Normal file
@ -0,0 +1,16 @@
|
||||
/** @constructor */
|
||||
var BotanEvent = function (){};
|
||||
|
||||
/** @type {object} */
|
||||
BotanEvent.data;
|
||||
|
||||
/** @type {Function} */
|
||||
BotanEvent.propagate;
|
||||
/** @type {Function} */
|
||||
BotanEvent.stopPropagating;
|
||||
|
||||
/** @type {Boolean} */
|
||||
BotanEvent.propagating;
|
||||
|
||||
/** @type {Function} */
|
||||
BotanEvent.setTarget;
|
18
botanjs/src/externs/BotanJS.js
Normal file
18
botanjs/src/externs/BotanJS.js
Normal file
@ -0,0 +1,18 @@
|
||||
/** @constructor
|
||||
* @implements {EventTarget}
|
||||
**/
|
||||
var BotanJS = function() {};
|
||||
|
||||
/** @type {Function} */
|
||||
BotanJS.define;
|
||||
/** @type {Function} */
|
||||
BotanJS.getDef;
|
||||
|
||||
/** @type {Object} */
|
||||
BotanJS.log = {};
|
||||
/** @type {Function} */
|
||||
BotanJS.log.write;
|
||||
/** @type {Function} */
|
||||
BotanJS.log.read;
|
||||
/** @type {Function} */
|
||||
BotanJS.log.end;
|
7
botanjs/src/externs/Components.MessageBox.js
Normal file
7
botanjs/src/externs/Components.MessageBox.js
Normal file
@ -0,0 +1,7 @@
|
||||
/** @constructor */
|
||||
Components.MessageBox = function() {};
|
||||
|
||||
/** @type {Function} */
|
||||
Components.MessageBox.setHandler;
|
||||
/** @type {Function} */
|
||||
Components.MessageBox.show;
|
@ -0,0 +1,9 @@
|
||||
/** @constructor */
|
||||
Components.Mouse.Clipboard.SwfHelperObj = function() {};
|
||||
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.SwfHelperObj.dummy;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.SwfHelperObj.debug;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.SwfHelperObj.copy;
|
15
botanjs/src/externs/Components.Mouse.Clipboard.js
Normal file
15
botanjs/src/externs/Components.Mouse.Clipboard.js
Normal file
@ -0,0 +1,15 @@
|
||||
/** @constructor */
|
||||
Components.Mouse.Clipboard = function() {};
|
||||
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.init;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.setTextToCopy;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.onMouseOver;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.onMouseOut;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard._textCopied;
|
||||
/** @type {Function} */
|
||||
Components.Mouse.Clipboard.capture;
|
2
botanjs/src/externs/Components.Mouse.ContextMenu.js
Normal file
2
botanjs/src/externs/Components.Mouse.ContextMenu.js
Normal file
@ -0,0 +1,2 @@
|
||||
/** @constructor */
|
||||
Components.Mouse.ContextMenu = function() {};
|
2
botanjs/src/externs/Components.Mouse.js
Normal file
2
botanjs/src/externs/Components.Mouse.js
Normal file
@ -0,0 +1,2 @@
|
||||
/** @constructor */
|
||||
Components.Mouse = function() {};
|
2
botanjs/src/externs/Components.js
Normal file
2
botanjs/src/externs/Components.js
Normal file
@ -0,0 +1,2 @@
|
||||
/** @constructor */
|
||||
var Components = function() {};
|
14
botanjs/src/externs/Dandelion.CSSAnimations.MovieClip.js
Normal file
14
botanjs/src/externs/Dandelion.CSSAnimations.MovieClip.js
Normal file
@ -0,0 +1,14 @@
|
||||
/** @constructor */
|
||||
Dandelion.CSSAnimations.MovieClip = function (){};
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.CSSAnimations.MovieClip.gotoFrame;
|
||||
/** @type {Function} */
|
||||
Dandelion.CSSAnimations.MovieClip.prevFrame;
|
||||
/** @type {Function} */
|
||||
Dandelion.CSSAnimations.MovieClip.nextFrame;
|
||||
/** @type {Element} */
|
||||
Dandelion.CSSAnimations.MovieClip.stage;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.CSSAnimations.MouseOverMovie;
|
2
botanjs/src/externs/Dandelion.CSSAnimations.js
Normal file
2
botanjs/src/externs/Dandelion.CSSAnimations.js
Normal file
@ -0,0 +1,2 @@
|
||||
/** @constructor */
|
||||
Dandelion.CSSAnimations = function (){};
|
23
botanjs/src/externs/Dandelion.IDOMElement.js
Normal file
23
botanjs/src/externs/Dandelion.IDOMElement.js
Normal file
@ -0,0 +1,23 @@
|
||||
/** @constructor */
|
||||
Dandelion.IDOMElement = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.getDAttribute;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.setAttribute;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.lootChildren;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.foreach;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.first;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.last;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.contains;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMElement.aKeys;
|
||||
/** @type {Element} */
|
||||
Dandelion.IDOMElement.element;
|
||||
/** @type {Element} */
|
||||
Dandelion.IDOMElement.reverseChild;
|
11
botanjs/src/externs/Dandelion.IDOMObject.js
Normal file
11
botanjs/src/externs/Dandelion.IDOMObject.js
Normal file
@ -0,0 +1,11 @@
|
||||
/** @constructor */
|
||||
Dandelion.IDOMObject = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMObject.addEventListener;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMObject.addEventListeners;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMObject.hasListener;
|
||||
/** @type {Function} */
|
||||
Dandelion.IDOMObject.removeEventListener;
|
5
botanjs/src/externs/Dandelion.Swf.ExtAPI.js
Normal file
5
botanjs/src/externs/Dandelion.Swf.ExtAPI.js
Normal file
@ -0,0 +1,5 @@
|
||||
/** @constructor */
|
||||
Dandelion.Swf.ExtAPI = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.Swf.ExtAPI.ready;
|
7
botanjs/src/externs/Dandelion.Swf.js
Normal file
7
botanjs/src/externs/Dandelion.Swf.js
Normal file
@ -0,0 +1,7 @@
|
||||
/** @constructor */
|
||||
Dandelion.Swf = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.Swf.create;
|
||||
/** @type {Function} */
|
||||
Dandelion.Swf.realize;
|
38
botanjs/src/externs/Dandelion.js
Normal file
38
botanjs/src/externs/Dandelion.js
Normal file
@ -0,0 +1,38 @@
|
||||
/** @constructor */
|
||||
var Dandelion = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.wrap;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.wrapc;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.wrape;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.wrapne;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.wrapna;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.textNode;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.bubbleUp;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.chainUpApply;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.id;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.tag;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.name;
|
||||
|
||||
/** @type {Function} */
|
||||
Dandelion.glass;
|
11
botanjs/src/externs/System.Cycle.Trigger.js
Normal file
11
botanjs/src/externs/System.Cycle.Trigger.js
Normal file
@ -0,0 +1,11 @@
|
||||
/** @constructor */
|
||||
System.Cycle.Trigger = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.Trigger.register;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.Trigger.transition;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.Trigger.height;
|
17
botanjs/src/externs/System.Cycle.js
Normal file
17
botanjs/src/externs/System.Cycle.js
Normal file
@ -0,0 +1,17 @@
|
||||
/** @constructor */
|
||||
System.Cycle = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.next;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.delay;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.perma;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Cycle.permaRemove;
|
||||
|
||||
/** @type {System.Tick} */
|
||||
System.Cycle.TICK;
|
8
botanjs/src/externs/System.Debug.js
Normal file
8
botanjs/src/externs/System.Debug.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @constructor */
|
||||
System.Debug = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Debug.Info;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Debug.Error;
|
8
botanjs/src/externs/System.Global.js
Normal file
8
botanjs/src/externs/System.Global.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @constructor */
|
||||
System.Global = function (){}
|
||||
|
||||
/** @type {Boolean} */
|
||||
System.Global.debug;
|
||||
|
||||
/** @type {Boolean} */
|
||||
System.Global.IE;
|
16
botanjs/src/externs/System.Log.js
Normal file
16
botanjs/src/externs/System.Log.js
Normal file
@ -0,0 +1,16 @@
|
||||
/** @constructor */
|
||||
System.Log = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Log.writeLine;
|
||||
/** @type {Function} */
|
||||
System.Log.registerHandler;
|
||||
/** @type {Function} */
|
||||
System.Log.removeHandler;
|
||||
|
||||
/** @type {const} */
|
||||
System.Log.ERROR;
|
||||
/** @type {const} */
|
||||
System.Log.INFO;
|
||||
/** @type {const} */
|
||||
System.Log.SYSTEM;
|
11
botanjs/src/externs/System.Net.js
Normal file
11
botanjs/src/externs/System.Net.js
Normal file
@ -0,0 +1,11 @@
|
||||
/** @constructor */
|
||||
System.Net = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Net.getData;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Net.postFile;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Net.postData;
|
5
botanjs/src/externs/System.Policy.js
Normal file
5
botanjs/src/externs/System.Policy.js
Normal file
@ -0,0 +1,5 @@
|
||||
/** @constructor */
|
||||
System.Policy = function (){};
|
||||
|
||||
/** @type {Function} */
|
||||
System.Policy.isOriginAllowed;
|
13
botanjs/src/externs/System.Tick.js
Normal file
13
botanjs/src/externs/System.Tick.js
Normal file
@ -0,0 +1,13 @@
|
||||
/** @constructor */
|
||||
System.Tick = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.Tick.prototype.putStepper;
|
||||
|
||||
/** @type {Function} */
|
||||
System.Tick.prototype.start;
|
||||
/** @type {Function} */
|
||||
System.Tick.prototype.stop;
|
||||
|
||||
/** @type {Array} */
|
||||
System.Tick.prototype.steppers;
|
2
botanjs/src/externs/System.js
Normal file
2
botanjs/src/externs/System.js
Normal file
@ -0,0 +1,2 @@
|
||||
/** @constructor */
|
||||
var System = function (){}
|
4
botanjs/src/externs/System.utils.DataKey.js
Normal file
4
botanjs/src/externs/System.utils.DataKey.js
Normal file
@ -0,0 +1,4 @@
|
||||
/** @constructor
|
||||
* @extends {System.utils.IKey}
|
||||
*/
|
||||
System.utils.DataKey = function (){}
|
10
botanjs/src/externs/System.utils.EventKey.js
Normal file
10
botanjs/src/externs/System.utils.EventKey.js
Normal file
@ -0,0 +1,10 @@
|
||||
/** @constructor
|
||||
* @extends {System.utils.IKey}
|
||||
*/
|
||||
System.utils.EventKey = function (){};
|
||||
|
||||
/** @type {String} */
|
||||
System.utils.EventKey.type;
|
||||
|
||||
/** @type {Function} */
|
||||
System.utils.EventKey.handler;
|
11
botanjs/src/externs/System.utils.IKey.js
Normal file
11
botanjs/src/externs/System.utils.IKey.js
Normal file
@ -0,0 +1,11 @@
|
||||
/** @constructor */
|
||||
System.utils.IKey = function (){}
|
||||
|
||||
/** @type {string} */
|
||||
System.utils.IKey.keyName;
|
||||
|
||||
/** @type {object} */
|
||||
System.utils.IKey.keyValue;
|
||||
|
||||
/** @type {Function} */
|
||||
System.utils.IKey.quickDef;
|
8
botanjs/src/externs/System.utils.Perf.js
Normal file
8
botanjs/src/externs/System.utils.Perf.js
Normal file
@ -0,0 +1,8 @@
|
||||
/** @constructor */
|
||||
System.utils.Perf = function (){}
|
||||
|
||||
/** @type {String} */
|
||||
System.utils.Perf.uuid;
|
||||
|
||||
/** @type {Function} */
|
||||
System.utils.Perf.ArrayReverse;
|
9
botanjs/src/externs/System.utils.js
Normal file
9
botanjs/src/externs/System.utils.js
Normal file
@ -0,0 +1,9 @@
|
||||
/** @constructor */
|
||||
System.utils = function (){}
|
||||
|
||||
/** @type {Function} */
|
||||
System.utils.objGetProp;
|
||||
/** @type {Function} */
|
||||
System.utils.objSearch;
|
||||
/** @type {Function} */
|
||||
System.utils.objMap;
|
0
cache/.keep
vendored
Normal file
0
cache/.keep
vendored
Normal file
0
logs/.keep
Normal file
0
logs/.keep
Normal file
17
settings.ini
Normal file
17
settings.ini
Normal file
@ -0,0 +1,17 @@
|
||||
[Paths]
|
||||
SiteRoot = /var/www/botanjs
|
||||
Runtime = ${SiteRoot}
|
||||
Log = ${SiteRoot}/logs
|
||||
Cache = ${SiteRoot}/cache
|
||||
|
||||
[BotanJS]
|
||||
SrcDir = ${Paths:Runtime}/botanjs/src
|
||||
|
||||
REDIS_PASS = PASSWORD_FOR_REDIS_DB
|
||||
|
||||
CeleryBroker = redis://:${REDIS_PASS}@123.123.123.123:1234/9
|
||||
|
||||
|
||||
[Service]
|
||||
user = www-data
|
||||
group = www-data
|
Loading…
Reference in New Issue
Block a user