Initial commit

This commit is contained in:
斟酌 鵬兄 2015-08-14 18:12:10 +08:00
parent f19f612fad
commit 4c93896df3
93 changed files with 4724 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*~
*.swp
*.pyc
__pycache__
cache/*
logs/*

View File

@ -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
View 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
View 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
View File

193
botanjs/classmap.py Normal file
View 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()

View File

51
botanjs/compressor/closure.py Executable file
View 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
View 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
View File

@ -0,0 +1,5 @@
#!/usr/bin/env python3
import configparser
Config = configparser.ConfigParser( interpolation = configparser.ExtendedInterpolation() )
Config.read( "settings.ini" )

View File

View 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
View 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() )

View File

@ -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>

View 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>

View 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>

View 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
View 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()

View 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;
}

View 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 );
})();

View 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; }

View 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 );
})();

View 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;
}

View 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 );
})();

View File

@ -0,0 +1,5 @@
.ch_obj {
position: fixed;
/* 1-level higher than Context Menu*/
z-index: 101;
}

View 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 );
})();

View 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;
}

View 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 );
})();

View File

@ -0,0 +1,3 @@
(function(){
var ns = __namespace( "Components.Mouse" );
})();

View File

@ -0,0 +1,3 @@
(function(){
var ns = __namespace( "Components" );
})();

View File

@ -0,0 +1,3 @@
.motion_block {
display: inline-block;
}

View 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 );
})();

View 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 */
}

View File

@ -0,0 +1,5 @@
/*
(function(){
var ns = __namespace( "Dandelion.CSSAnimations" );
})();
*/

View 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;
}

View File

@ -0,0 +1,5 @@
/*
(function(){
var ns = __namespace( "Dandelion.CSSReset" );
})();
*/

View 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 );
})();

View 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 );
})();

View 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;
}

View 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 );
})();

View 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%;
}

View 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 );
})();

View 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; } );
})();

View 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
View 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
```

View 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 );
})();

View 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; } );
})();

View 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 );
})();

View 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
View 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 );
})();

View 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 );
})();

View 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 );
})();

View 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 );
})();

View 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 );
})();

View File

@ -0,0 +1,3 @@
(function(){
var ns = __namespace( "System" )
})();

View 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 );
})();

View 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 );
})();

View 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 );
})();

View 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 );
})();

View 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
View 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 ];

View 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;

View 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;

View File

@ -0,0 +1,7 @@
/** @constructor */
Components.MessageBox = function() {};
/** @type {Function} */
Components.MessageBox.setHandler;
/** @type {Function} */
Components.MessageBox.show;

View File

@ -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;

View 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;

View File

@ -0,0 +1,2 @@
/** @constructor */
Components.Mouse.ContextMenu = function() {};

View File

@ -0,0 +1,2 @@
/** @constructor */
Components.Mouse = function() {};

View File

@ -0,0 +1,2 @@
/** @constructor */
var Components = function() {};

View 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;

View File

@ -0,0 +1,2 @@
/** @constructor */
Dandelion.CSSAnimations = function (){};

View 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;

View 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;

View File

@ -0,0 +1,5 @@
/** @constructor */
Dandelion.Swf.ExtAPI = function (){}
/** @type {Function} */
Dandelion.Swf.ExtAPI.ready;

View File

@ -0,0 +1,7 @@
/** @constructor */
Dandelion.Swf = function (){}
/** @type {Function} */
Dandelion.Swf.create;
/** @type {Function} */
Dandelion.Swf.realize;

View 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;

View 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;

View 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;

View File

@ -0,0 +1,8 @@
/** @constructor */
System.Debug = function (){}
/** @type {Function} */
System.Debug.Info;
/** @type {Function} */
System.Debug.Error;

View File

@ -0,0 +1,8 @@
/** @constructor */
System.Global = function (){}
/** @type {Boolean} */
System.Global.debug;
/** @type {Boolean} */
System.Global.IE;

View 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;

View File

@ -0,0 +1,11 @@
/** @constructor */
System.Net = function (){}
/** @type {Function} */
System.Net.getData;
/** @type {Function} */
System.Net.postFile;
/** @type {Function} */
System.Net.postData;

View File

@ -0,0 +1,5 @@
/** @constructor */
System.Policy = function (){};
/** @type {Function} */
System.Policy.isOriginAllowed;

View 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;

View File

@ -0,0 +1,2 @@
/** @constructor */
var System = function (){}

View File

@ -0,0 +1,4 @@
/** @constructor
* @extends {System.utils.IKey}
*/
System.utils.DataKey = function (){}

View 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;

View 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;

View File

@ -0,0 +1,8 @@
/** @constructor */
System.utils.Perf = function (){}
/** @type {String} */
System.utils.Perf.uuid;
/** @type {Function} */
System.utils.Perf.ArrayReverse;

View 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
View File

0
logs/.keep Normal file
View File

17
settings.ini Normal file
View 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