mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-20 00:10:26 +00:00
Merge http://github.com/angular/angular.js into angular
Conflicts: .gitignore
This commit is contained in:
commit
1500e91def
140 changed files with 24534 additions and 1 deletions
9
.externalToolBuilders/JSTD_Tests.launch
Normal file
9
.externalToolBuilders/JSTD_Tests.launch
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <launchConfigurationWorkingSet editPageId="org.eclipse.ui.resourceWorkingSetPage" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1262905463390_2" label="workingSet" name="workingSet"> <item factoryID="org.eclipse.ui.internal.model.ResourceFactory" path="/angular.js/test" type="2"/> <item factoryID="org.eclipse.ui.internal.model.ResourceFactory" path="/angular.js/src" type="2"/> </launchConfigurationWorkingSet>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js}/test.sh"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
11
.gitignore
vendored
11
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
|||
<<<<<<< HEAD
|
||||
.git4_perforce_config
|
||||
blaze-eclipse
|
||||
google3/blaze-*
|
||||
|
|
@ -21,4 +22,12 @@ google3/.gwt-tmp
|
|||
google3/alloc
|
||||
google3tomcat
|
||||
google3/mbin
|
||||
google3/mgenfiles
|
||||
google3/mgenfiles
|
||||
=======
|
||||
angular-minified.map
|
||||
externs.js
|
||||
angular.js
|
||||
angular-minified.js
|
||||
angular-debug.js
|
||||
angular-scenario.js
|
||||
>>>>>>> b129a1094e6b42ed82c3ccecc2f40daaa0a6cb6a
|
||||
|
|
|
|||
1
.idea/.gitignore
vendored
Normal file
1
.idea/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
workspace.xml
|
||||
7
.idea/.rakeTasks
Normal file
7
.idea/.rakeTasks
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Settings><!--This file was automatically generated by Ruby plugin.
|
||||
You are allowed to:
|
||||
1. Remove rake task
|
||||
2. Add existing rake tasks
|
||||
To add existing rake tasks automatically delete this file and reload the project.
|
||||
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Compile JavaScript" fullCmd="compile" taksId="compile" /><RakeTask description="Generate Externs" fullCmd="compileexterns" taksId="compileexterns" /><RakeTask description="Lint" fullCmd="lint" taksId="lint" /><RakeGroup description="" fullCmd="" taksId="server"><RakeTask description="Run JsTestDriver Server" fullCmd="server:start" taksId="start" /><RakeTask description="Run JavaScript tests against the server" fullCmd="server:test" taksId="test" /></RakeGroup><RakeTask description="Run JavaScript tests" fullCmd="test" taksId="test" /><RakeTask description="" fullCmd="default" taksId="default" /></RakeGroup></Settings>
|
||||
5
.idea/encodings.xml
Normal file
5
.idea/encodings.xml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
|
||||
</project>
|
||||
|
||||
9
.idea/master.iml
Normal file
9
.idea/master.iml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="RUBY_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
14
.idea/misc.xml
Normal file
14
.idea/misc.xml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DependencyValidationManager">
|
||||
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
|
||||
</component>
|
||||
<component name="ProjectDetails">
|
||||
<option name="projectName" value="master" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Ruby SDK 1.8.7 (/usr/bin/ruby)" project-jdk-type="RUBY_SDK" />
|
||||
<component name="SvnBranchConfigurationManager">
|
||||
<option name="mySupportsUserInfoFilter" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
9
.idea/modules.xml
Normal file
9
.idea/modules.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/master.iml" filepath="$PROJECT_DIR$/.idea/master.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
|
||||
8
.idea/vcs.xml
Normal file
8
.idea/vcs.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="" />
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
27
.project
Normal file
27
.project
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>angular.js</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/JSTD_Tests.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
9
.settings/.jsdtscope
Normal file
9
.settings/.jsdtscope
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="test/" kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="src/test"/>
|
||||
<classpathentry excluding="test/" kind="src" path="test"/>
|
||||
<classpathentry kind="src" path="test/test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
||||
</classpath>
|
||||
1
.settings/org.eclipse.wst.jsdt.ui.superType.container
Normal file
1
.settings/org.eclipse.wst.jsdt.ui.superType.container
Normal file
|
|
@ -0,0 +1 @@
|
|||
org.eclipse.wst.jsdt.launching.JRE_CONTAINER
|
||||
1
.settings/org.eclipse.wst.jsdt.ui.superType.name
Normal file
1
.settings/org.eclipse.wst.jsdt.ui.superType.name
Normal file
|
|
@ -0,0 +1 @@
|
|||
Global
|
||||
22
LICENSE
Normal file
22
LICENSE
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
The MIT License
|
||||
|
||||
Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
12
README.md
Normal file
12
README.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
Angular
|
||||
======
|
||||
|
||||
Compiling
|
||||
---------
|
||||
rake compile
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
rake server:start
|
||||
rake test
|
||||
|
||||
119
Rakefile
Normal file
119
Rakefile
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
include FileUtils
|
||||
|
||||
task :default => [:compile, :test]
|
||||
|
||||
desc 'Generate Externs'
|
||||
task :compile_externs do
|
||||
out = File.new("externs.js", "w")
|
||||
|
||||
out.write("function _(){};\n")
|
||||
file = File.new("lib/underscore/underscore.js", "r")
|
||||
while (line = file.gets)
|
||||
if line =~ /^\s*_\.(\w+)\s*=.*$/
|
||||
out.write("_.#{$1}=function(){};\n")
|
||||
end
|
||||
end
|
||||
file.close
|
||||
|
||||
out.write("function jQuery(){};\n")
|
||||
file = File.new("lib/jquery/jquery-1.4.2.js", "r")
|
||||
while (line = file.gets)
|
||||
if line =~ /^\s*(\w+)\s*:\s*function.*$/
|
||||
out.write("jQuery.#{$1}=function(){};\n")
|
||||
end
|
||||
end
|
||||
file.close
|
||||
out.write("jQuery.scope=function(){};\n")
|
||||
out.write("jQuery.controller=function(){};\n")
|
||||
|
||||
out.close
|
||||
end
|
||||
|
||||
desc 'Compile Scenario'
|
||||
task :compile_scenario do
|
||||
concat = %x(cat \
|
||||
lib/underscore/underscore.js \
|
||||
lib/jquery/jquery-1.4.2.js \
|
||||
src/scenario/angular.prefix \
|
||||
src/Angular.js \
|
||||
src/JSON.js \
|
||||
src/Scope.js \
|
||||
src/Parser.js \
|
||||
src/Resource.js \
|
||||
src/Browser.js \
|
||||
src/apis.js \
|
||||
src/services.js \
|
||||
src/AngularPublic.js \
|
||||
src/scenario/Runner.js \
|
||||
src/scenario/DSL.js \
|
||||
src/scenario/angular.suffix \
|
||||
)
|
||||
css = %x(cat css/angular-scenario.css)
|
||||
f = File.new("angular-scenario.js", 'w')
|
||||
f.write(concat)
|
||||
f.write('document.write(\'<style type="text/css">\n')
|
||||
f.write(css.gsub(/'/, "\\'").gsub(/\n/, "\\n"));
|
||||
f.write('\n</style>\');')
|
||||
f.close
|
||||
end
|
||||
|
||||
desc 'Compile JavaScript'
|
||||
task :compile do
|
||||
Rake::Task['compile_externs'].execute 0
|
||||
Rake::Task['compile_scenario'].execute 0
|
||||
|
||||
concat = %x(cat \
|
||||
src/angular.prefix \
|
||||
src/Angular.js \
|
||||
src/JSON.js \
|
||||
src/Compiler.js \
|
||||
src/Scope.js \
|
||||
src/Parser.js \
|
||||
src/Resource.js \
|
||||
src/Browser.js \
|
||||
src/jqLite.js \
|
||||
src/apis.js \
|
||||
src/filters.js \
|
||||
src/formatters.js \
|
||||
src/validators.js \
|
||||
src/services.js \
|
||||
src/directives.js \
|
||||
src/markups.js \
|
||||
src/widgets.js \
|
||||
src/AngularPublic.js \
|
||||
src/angular.suffix \
|
||||
)
|
||||
f = File.new("angular-debug.js", 'w')
|
||||
f.write(concat)
|
||||
f.close
|
||||
|
||||
%x(java -jar lib/compiler-closure/compiler.jar \
|
||||
--compilation_level ADVANCED_OPTIMIZATIONS \
|
||||
--js angular-debug.js \
|
||||
--externs externs.js \
|
||||
--create_source_map ./angular-minified.map \
|
||||
--js_output_file angular-minified.js)
|
||||
end
|
||||
|
||||
namespace :server do
|
||||
desc 'Run JsTestDriver Server'
|
||||
task :start do
|
||||
sh %x(java -jar lib/jstestdriver/JsTestDriver.jar --browser open --port 9876)
|
||||
end
|
||||
|
||||
desc "Run JavaScript tests against the server"
|
||||
task :test do
|
||||
sh %(java -jar lib/jstestdriver/JsTestDriver.jar --tests all)
|
||||
end
|
||||
end
|
||||
|
||||
desc "Run JavaScript tests"
|
||||
task :test do
|
||||
sh %(java -jar lib/jstestdriver/JsTestDriver.jar --tests all --browser open --port 9876)
|
||||
end
|
||||
|
||||
desc 'Lint'
|
||||
task :lint do
|
||||
out = %x(lib/jsl/jsl -conf lib/jsl/jsl.default.conf)
|
||||
print out
|
||||
end
|
||||
6
TODO.text
Normal file
6
TODO.text
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
* move angular-bootstrap.js out of anugular.js.
|
||||
* 'angular' is the official namespace for public API
|
||||
- angular.defaults = {}
|
||||
- var scope = angular.compile(element, options);
|
||||
* angular.js is not self boot straping by default.
|
||||
* Remove SWFObject
|
||||
76
css/angular-scenario.css
Normal file
76
css/angular-scenario.css
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
@charset "UTF-8";
|
||||
/* CSS Document */
|
||||
|
||||
#runner {
|
||||
position: absolute;
|
||||
top:5px;
|
||||
left:10px;
|
||||
right:10px;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.console {
|
||||
display: block;
|
||||
overflow: scroll;
|
||||
height: 200px;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
#testView {
|
||||
position: absolute;
|
||||
bottom:10px;
|
||||
top:230px;
|
||||
left:10px;
|
||||
right:10px;
|
||||
}
|
||||
|
||||
#testView iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
li.running > span {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
#runner span {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
#runner .fail > span {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.collapsed > ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
//////
|
||||
|
||||
.run, .info, .error {
|
||||
display: block;
|
||||
padding: 0 1em;
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
.run {
|
||||
background-color: lightgrey;
|
||||
padding: 0 .2em;
|
||||
}
|
||||
|
||||
.run.pass {
|
||||
background-color: lightgreen;
|
||||
}
|
||||
|
||||
.run.fail {
|
||||
background-color: lightred;
|
||||
}
|
||||
|
||||
.name, .time, .state {
|
||||
padding-right: 2em;
|
||||
}
|
||||
|
||||
error {
|
||||
color: red;
|
||||
}
|
||||
189
css/angular.css
Normal file
189
css/angular.css
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
@charset "UTF-8";
|
||||
/* CSS Document */
|
||||
|
||||
#ng-console {
|
||||
border: thin solid black;
|
||||
font-family: 'courier';
|
||||
font-size: x-small;
|
||||
}
|
||||
|
||||
#ng-console .ng-console-error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#ng-console .ng-console-info {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.ng-upload-widget object {
|
||||
align:center;
|
||||
}
|
||||
|
||||
.ng-upload-widget a {
|
||||
margin-right: .3em;
|
||||
}
|
||||
|
||||
.ng-upload-widget span {
|
||||
color: #999999;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.ng-format-negative {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.ng-exception {
|
||||
border: 2px solid #FF0000;
|
||||
font-family: "Courier New", Courier, monospace;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.ng-validation-error {
|
||||
border: 2px solid #FF0000;
|
||||
}
|
||||
|
||||
.ng-hidden {
|
||||
display:none;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* DatePicker
|
||||
*****************/
|
||||
|
||||
div.ui-widget {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* OrderBy
|
||||
*****************/
|
||||
.ng-ascend,
|
||||
.ng-descend {
|
||||
padding-right: 20px;
|
||||
background-repeat: no-repeat;
|
||||
background-position: right;
|
||||
}
|
||||
.ng-ascend { background-image: url(angular_images/arrow_ascend.png); }
|
||||
.ng-descend { background-image: url(angular_images/arrow_descend.png); }
|
||||
|
||||
/*****************
|
||||
* TIP
|
||||
*****************/
|
||||
#ng-callout {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
outline: 0;
|
||||
font-size: 13px;
|
||||
font-weight: normal;
|
||||
font-family: Verdana, Arial, Helvetica, sans-serif;
|
||||
vertical-align: baseline;
|
||||
background: transparent;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#ng-callout .ng-arrow-left{
|
||||
background-image: url(angular_images/arrow_left.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: left top;
|
||||
position: absolute;
|
||||
z-index:101;
|
||||
left:-12px;
|
||||
height:23px;
|
||||
width:10px;
|
||||
top:-3px;
|
||||
}
|
||||
|
||||
#ng-callout .ng-arrow-right{
|
||||
background-image: url(angular_images/arrow_right.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: left top;
|
||||
position: absolute;
|
||||
z-index:101;
|
||||
height:23px;
|
||||
width:11px;
|
||||
top:-2px;
|
||||
}
|
||||
|
||||
#ng-callout {
|
||||
position: absolute;
|
||||
z-index:100;
|
||||
border: 2px solid #CCCCCC;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
#ng-callout .ng-content{
|
||||
padding:10px 10px 10px 10px;
|
||||
color:#333333;
|
||||
}
|
||||
|
||||
|
||||
#ng-callout .ng-title{
|
||||
background-color: #CCCCCC;
|
||||
text-align: left;
|
||||
padding-left: 8px;
|
||||
padding-bottom: 5px;
|
||||
padding-top: 2px;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
|
||||
#ng-spacer {
|
||||
height: 1.2em;
|
||||
}
|
||||
|
||||
#ng-loading {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
height: 1.2em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/*****************
|
||||
* Login
|
||||
*****************/
|
||||
|
||||
#ng-login {
|
||||
z-index: 2000;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
#ng-login .ng-login-container {
|
||||
width: 500px;
|
||||
height: 380px;
|
||||
margin: auto;
|
||||
border-top: 5px solid #FFF;
|
||||
border-left: 5px solid #DDD;
|
||||
border-right: 5px solid #777;
|
||||
border-bottom: 5px solid #555;
|
||||
padding: 0 3px 3px 0;
|
||||
}
|
||||
|
||||
#ng-login .ng-login-container iframe {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 2px solid black;
|
||||
}
|
||||
|
||||
|
||||
/*****************
|
||||
* indicators
|
||||
*****************/
|
||||
.ng-indicator-wait {
|
||||
display: inline-block;
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
background-image: url("angular_images/indicator-wait.png");
|
||||
}
|
||||
|
||||
.ng-input-indicator-wait {
|
||||
background-image: url("angular_images/indicator-wait.png");
|
||||
background-position: right;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
BIN
css/angular_images/arrow_ascend.png
Normal file
BIN
css/angular_images/arrow_ascend.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 KiB |
BIN
css/angular_images/arrow_descend.png
Normal file
BIN
css/angular_images/arrow_descend.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3 KiB |
BIN
css/angular_images/arrow_left.gif
Normal file
BIN
css/angular_images/arrow_left.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
BIN
css/angular_images/arrow_right.gif
Normal file
BIN
css/angular_images/arrow_right.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 102 B |
BIN
css/angular_images/indicator-wait.png
Normal file
BIN
css/angular_images/indicator-wait.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
BIN
css/angular_images/loader-bar.gif
Normal file
BIN
css/angular_images/loader-bar.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
21
example/calculator-bootstrap.html
Normal file
21
example/calculator-bootstrap.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var scope = angular.compile(document);
|
||||
scope.set('a', 3);
|
||||
scope.updateView();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Quantity: <input type="text" name="a" value="2">
|
||||
*
|
||||
Cost: <input type="text" name="b" value="3.4">
|
||||
= {{a * b | currency}}
|
||||
</body>
|
||||
</html>
|
||||
21
example/calculator-minified_init.html
Normal file
21
example/calculator-minified_init.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
||||
<script type="text/javascript" src="../angular-minified.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
scope = angular.compile(document);
|
||||
scope.set('a', 3);
|
||||
scope.updateView();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Quantity: <input type="text" name="a" value="2">
|
||||
*
|
||||
Cost: <input type="text" name="b" value="3.4">
|
||||
= {{a * b | currency}}
|
||||
</body>
|
||||
</html>
|
||||
21
example/calculator.html
Normal file
21
example/calculator.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
||||
<script type="text/javascript" src="../angular.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var scope = angular.compile(document);
|
||||
scope.set('a', 3);
|
||||
scope.updateView();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
Quantity: <input type="text" name="a" value="2">
|
||||
*
|
||||
Cost: <input type="text" name="b" value="3.4">
|
||||
= {{a * b | currency}}
|
||||
</body>
|
||||
</html>
|
||||
11
example/index.html
Normal file
11
example/index.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<li><a href="calculator-bootstrap.html">Calculator: Auto Init</a></li>
|
||||
<li><a href="calculator.html">Calculator: Manual Init</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
55
example/memoryLeak.html
Normal file
55
example/memoryLeak.html
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
var scope = angular.compile(document);
|
||||
scope.init();
|
||||
scope.set("add", function(){
|
||||
var partial = $("#partial");
|
||||
//id++;
|
||||
partial.html('<div>{{ error() }}<br/></div>');
|
||||
var scope = angular.compile(partial);
|
||||
scope.set("hello", function (){
|
||||
return 'who dat?';
|
||||
});
|
||||
scope.set("error", function (){
|
||||
this.misko.length;
|
||||
});
|
||||
function XXXXXXXXX(){};
|
||||
scope.set('xxx', new XXXXXXXXX());
|
||||
scope.set("names", ["adam", "misko", "shyam"]);
|
||||
scope.init();
|
||||
});
|
||||
scope.set("remove", function(){
|
||||
var partial = $("#partial");
|
||||
/*
|
||||
partial.find('*').andSelf().each(function(){
|
||||
var scope = $(this).data('scope');
|
||||
if (scope) {
|
||||
delete scope.state;
|
||||
delete scope.widgets;
|
||||
}
|
||||
var cntl = $(this).data('controller');
|
||||
if (cntl) {
|
||||
delete cntl.view;
|
||||
}
|
||||
$(this).removeData();
|
||||
});
|
||||
*/
|
||||
partial.removeData('scope');
|
||||
partial.children().remove();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<link rel="StyleSheet" type="text/css" href="../css/angular.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<input type="button" value="add" ng-click="add()"/>
|
||||
<input type="button" value="remove" ng-click="remove()"/>
|
||||
<div id="partial"></div>
|
||||
</body>
|
||||
</html>
|
||||
13
example/temp.html
Normal file
13
example/temp.html
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
|
||||
</head>
|
||||
<body>
|
||||
{{$location.hashSearch.order}} <br/>
|
||||
<input type="radio" name="$location.hashSearch.order" value="A"/> A <br/>
|
||||
<input type="radio" name="$location.hashSearch.order" checked value="B"/> B <br/>
|
||||
<input type="radio" name="$location.hashSearch.order" value="C"/> C <br/>
|
||||
{{$location.hashSearch.order}} <br/>
|
||||
</body>
|
||||
</html>
|
||||
98
example/tweeter/style.css
Normal file
98
example/tweeter/style.css
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
.loading {display: none;}
|
||||
.fetching .loading {display: block;}
|
||||
|
||||
a {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
h1 {
|
||||
background-color: black;
|
||||
margin: 0;
|
||||
padding: .25em;
|
||||
color: white;
|
||||
border-bottom: 5px solid gray;
|
||||
}
|
||||
|
||||
.box {
|
||||
border: 2px solid gray;
|
||||
}
|
||||
|
||||
.tweeter {
|
||||
margin-right: 360px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: .25em;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
li img {
|
||||
float: left;
|
||||
margin: 2px;
|
||||
margin-right: .5em;
|
||||
max-height: 48px;
|
||||
min-height: 48px;
|
||||
}
|
||||
|
||||
li.even {
|
||||
background-color: lightgray;
|
||||
}
|
||||
|
||||
|
||||
.addressbook {
|
||||
float: right;
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.addressbook li {
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
.clrleft {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
.notes {
|
||||
font-size: .8em;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.username, .nickname {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.editor {
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
label {
|
||||
color: gray;
|
||||
display: inline-block;
|
||||
width: 75px;
|
||||
text-align: right;
|
||||
padding: 2px;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.editor input[type=text],
|
||||
.editor textarea {
|
||||
width: 230px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
|
||||
.editor TEXTAREA {
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.debug{
|
||||
font-size: .7em;
|
||||
white-space: pre;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
80
example/tweeter/tweeter_addressbook.html
Normal file
80
example/tweeter/tweeter_addressbook.html
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../css/angular.css">
|
||||
<script type="text/javascript" src="../../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../../lib/jquery/jquery-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="../../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript" src="tweeterclient.js"></script>
|
||||
</head>
|
||||
<body ng-class="status" ng-init="mute={}" ng-watch="$anchor.user: tweets = fetchTweets($anchor.user)">
|
||||
<div class="addressbook box">
|
||||
<h1>Address Book</h1>
|
||||
[ Filter: <input type="text" name="userFilter"/>]
|
||||
<ul>
|
||||
<li ng-repeat="user in users.$filter(userFilter).$orderBy('screen_name')" ng-class-even="'even'" ng-class-odd="'odd'">
|
||||
<a href="" ng-click="$anchor.user=user.screen_name"><img src="{{user.profile_image_url}}"/></a>
|
||||
<a href="" ng-click="$anchor.user=user.screen_name">{{user.screen_name}}</a>
|
||||
as <span class="nickname">{{user.name}}</span>
|
||||
[ <a href="#" ng-click="$anchor.edituser=user.screen_name">edit</a>
|
||||
| <a href="#" ng-click="users.$remove(user)">X</a>
|
||||
| <a href="#" ng-click="mute[user.screen_name] = ! mute[user.screen_name]">mute</a>
|
||||
]
|
||||
<div class="notes">{{user.notes|linky}}</div>
|
||||
<div class="clrleft"></div>
|
||||
</li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<div ng-show="$anchor.edituser" ng-eval="user = users.$find({:$.screen_name == $anchor.edituser})">
|
||||
<div class="editor">
|
||||
<label>Username:</label>
|
||||
<input type="text" name="user.screen_name" disabled="disabled"/>
|
||||
<label>Name:</label>
|
||||
<input type="text" name="user.name"/>
|
||||
<label>Image:</label>
|
||||
<input type="text" name="user.profile_image_url"/>
|
||||
<label>Notes:</label>
|
||||
<textarea type="text" name="user.notes"></textarea>
|
||||
|
||||
<input type="button" ng-click="$anchor.edituser=undefined" value="Close"/>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="debug">
|
||||
mute={{mute|json}}
|
||||
|
||||
userFilter={{userFilter|json}}
|
||||
|
||||
tweetFilter={{tweetFilter|json}}
|
||||
|
||||
$anchor={{$anchor}}
|
||||
|
||||
users={{users}}
|
||||
|
||||
tweets={{tweets}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="tweeter box">
|
||||
<h1>Tweets: {{$anchor.user}}</h1>
|
||||
[ Filter: <input type="text" name="tweetFilter"/>
|
||||
<span ng-show="$anchor.user">| <a href="#user="><< All</a></span>
|
||||
]
|
||||
<div class="loading">Loading...</div>
|
||||
<ul>
|
||||
<li ng-repeat="tweet in tweets.$filter(tweetFilter).$filter({:!mute[$.user.screen_name]})"
|
||||
ng-class-even="'even'" ng-class-odd="'odd'"
|
||||
ng-eval="user = users.$find({: $.screen_name == tweet.user.screen_name}) || tweet.user">
|
||||
<img src="{{user.profile_image_url}}"/>
|
||||
[ <a href="" ng-click="$anchor.user=user.screen_name">{{user.nickname || user.name || user.screen_name }}</a>
|
||||
| <a href="" ng-click="users.$includeIf(user, true)">+</a>
|
||||
]:
|
||||
{{tweet.text | linky}}
|
||||
<span class="notes">{{tweet.created_at}}</span>
|
||||
<span class="notes">{{user.notes}}</span>
|
||||
<div class="clrleft"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
34
example/tweeter/tweeter_demo.html
Normal file
34
example/tweeter/tweeter_demo.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<link rel="stylesheet" type="text/css" href="../../css/angular.css">
|
||||
<script type="text/javascript" src="../../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../../lib/jquery/jquery-1.4.2.min.js"></script>
|
||||
<script type="text/javascript" src="../../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript" src="tweeterclient.js"></script>
|
||||
</head>
|
||||
<body ng-class="status" Xng-init="tweets = fetchTweets()">
|
||||
(TODO: I should fetch current tweets)
|
||||
<div class="tweeter box">
|
||||
<h1>Tweets: {{$anchor.user}}</h1>
|
||||
[ Filter: <input type="text" name="tweetFilter"/> (TODO: this should act as search box)
|
||||
<span ng-show="$anchor.user">| <a href="#user="><< All</a></span>
|
||||
]
|
||||
<div class="loading">Loading...</div>
|
||||
<ul>
|
||||
<li Xng-repeat="tweet in tweets"
|
||||
ng-class-even="'even'" ng-class-odd="'odd'">
|
||||
<img src="{{tweet.user.profile_image_url}}"/>
|
||||
[ <a href="" Xng-click="$anchor.user=tweet.user.screen_name">{{tweet.user.nickname || tweet.user.name || tweet.user.screen_name }}</a>
|
||||
]:
|
||||
{{tweet.text}} (TODO: I want urls as links)
|
||||
<span class="notes">{{tweet.created_at}}</span>
|
||||
<span class="notes">{{tweet.user.notes}}</span>
|
||||
<div class="clrleft"></div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<pre>tweets=(TODO: display me!!!)</pre>
|
||||
</body>
|
||||
</html>
|
||||
36
example/tweeter/tweeterclient.js
Normal file
36
example/tweeter/tweeterclient.js
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
function noop(){}
|
||||
$(document).ready(function(){
|
||||
function xhr(method, url, data, callback){
|
||||
jQuery.getJSON(url, function(){
|
||||
callback.apply(this, arguments);
|
||||
scope.updateView();
|
||||
});
|
||||
}
|
||||
|
||||
var resourceFactory = new ResourceFactory(xhr);
|
||||
|
||||
var Tweeter = resourceFactory.route("http://twitter.com/statuses/:service:username.json", {}, {
|
||||
home: {method:'GET', params: {service:'home_timeline'}, isArray:true },
|
||||
user: {method:'GET', params: {service:'user_timeline/'}, isArray:true }
|
||||
});
|
||||
|
||||
|
||||
var scope = window.scope = angular.compile(document, {
|
||||
location:angular.startUrlWatcher()
|
||||
});
|
||||
|
||||
function fetchTweets(username){
|
||||
return username ? Tweeter.user({username: username}) : Tweeter.home();
|
||||
}
|
||||
|
||||
scope.set('fetchTweets', fetchTweets);
|
||||
scope.set('users', [
|
||||
{screen_name:'mhevery', name:'Mi\u0161ko Hevery',
|
||||
notes:'Author of <angular/> http://www.getangular.com.',
|
||||
profile_image_url:'http://a3.twimg.com/profile_images/54360179/Me_-_Small_Banner_normal.jpg'},
|
||||
{screen_name:'abrons', name:'Adam Abrons',
|
||||
notes:'Author of <angular/> & Ruby guru see: http://www.angularjs.org.',
|
||||
profile_image_url:'http://media.linkedin.com/mpr/mpr/shrink_80_80/p/2/000/005/0a8/044278d.jpg'}
|
||||
]);
|
||||
scope.init();
|
||||
});
|
||||
24
jsTestDriver-jquery.conf
Normal file
24
jsTestDriver-jquery.conf
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
server: http://localhost:9876
|
||||
|
||||
load:
|
||||
- lib/jasmine/jasmine-0.10.3.js
|
||||
- lib/jasmine-jstd-adapter/JasmineAdapter.js
|
||||
- lib/jquery/jquery-1.4.2.js
|
||||
- test/jquery_alias.js
|
||||
- src/Angular.js
|
||||
- src/*.js
|
||||
- src/scenario/Runner.js
|
||||
- src/scenario/*.js
|
||||
- test/testabilityPatch.js
|
||||
- test/angular-mocks.js
|
||||
- test/scenario/*.js
|
||||
- test/*.js
|
||||
|
||||
exclude:
|
||||
- src/angular.prefix
|
||||
- src/angular.suffix
|
||||
- src/angular-bootstrap.js
|
||||
- src/AngularPublic.js
|
||||
- src/scenario/bootstrap.js
|
||||
- test/jquery_remove.js
|
||||
|
||||
23
jsTestDriver.conf
Normal file
23
jsTestDriver.conf
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
server: http://localhost:9876
|
||||
|
||||
load:
|
||||
- lib/jasmine/jasmine-0.10.3.js
|
||||
- lib/jasmine-jstd-adapter/JasmineAdapter.js
|
||||
- lib/jquery/jquery-1.4.2.js
|
||||
- test/jquery_remove.js
|
||||
- src/Angular.js
|
||||
- src/*.js
|
||||
- src/scenario/Runner.js
|
||||
- src/scenario/*.js
|
||||
- test/testabilityPatch.js
|
||||
- test/angular-mocks.js
|
||||
- test/scenario/*.js
|
||||
- test/*.js
|
||||
|
||||
exclude:
|
||||
- test/jquery_alias.js
|
||||
- src/angular.prefix
|
||||
- src/angular.suffix
|
||||
- src/angular-bootstrap.js
|
||||
- src/scenario/bootstrap.js
|
||||
- src/AngularPublic.js
|
||||
762
jstd.log
Normal file
762
jstd.log
Normal file
|
|
@ -0,0 +1,762 @@
|
|||
Apr 8, 2010 2:04:32 PM com.google.jstestdriver.ServerStartupAction run
|
||||
INFO: Starting server...
|
||||
Apr 8, 2010 2:04:32 PM org.mortbay.log.Slf4jLog info
|
||||
INFO: Transparent ProxyServlet @ forward to http://localhost:9876
|
||||
Apr 8, 2010 2:04:33 PM com.google.jstestdriver.BrowserHunter captureBrowser
|
||||
INFO: Browser Captured: Firefox version 3.6.3 (1)
|
||||
Apr 8, 2010 2:04:33 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1?start HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:04:33 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:04:36 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1?start HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:04:43 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:04:53 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:04 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:14 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:24 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:34 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:44 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:05:54 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:04 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:14 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:24 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:34 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:44 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:06:54 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:04 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:14 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:24 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:34 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:44 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:07:55 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:05 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:15 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:25 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:35 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:45 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:08:55 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:05 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:15 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:25 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:35 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:45 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:09:55 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:05 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:15 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:25 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:35 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:45 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:55 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1?start HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
|
||||
|
||||
Apr 8, 2010 2:10:56 PM com.google.jstestdriver.BrowserQueryResponseServlet doPost
|
||||
FINEST: POST: POST /query/1 HTTP/1.1
|
||||
Host: misko.i:9876
|
||||
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2.3) Gecko/20100401 Firefox/3.6.3
|
||||
Accept: */*
|
||||
Accept-Language: en-us,en;q=0.5
|
||||
Accept-Encoding: gzip,deflate
|
||||
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
|
||||
Keep-Alive: 115
|
||||
Connection: keep-alive
|
||||
Referer: http://misko.i:9876/slave/1/Runnerstrict.html
|
||||
Pragma: no-cache
|
||||
Cache-Control: no-cache
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
X-Requested-With: XMLHttpRequest
|
||||
Content-Length: 0
|
||||
|
||||
|
||||
202
lib/compiler-closure/COPYING
Normal file
202
lib/compiler-closure/COPYING
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
193
lib/compiler-closure/README
Normal file
193
lib/compiler-closure/README
Normal file
|
|
@ -0,0 +1,193 @@
|
|||
/*
|
||||
* Copyright 2009 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
//
|
||||
// Contents
|
||||
//
|
||||
|
||||
The Closure Compiler performs checking, instrumentation, and
|
||||
optimizations on JavaScript code. The purpose of this README is to
|
||||
explain how to build and run the Closure Compiler.
|
||||
|
||||
The Closure Compiler requires Java 6 or higher.
|
||||
http://www.java.com/
|
||||
|
||||
|
||||
//
|
||||
// Building The Closure Compiler
|
||||
//
|
||||
|
||||
There are three ways to get a Closure Compiler executable.
|
||||
|
||||
1) Use one we built for you.
|
||||
|
||||
Pre-built Closure binaries can be found at
|
||||
http://code.google.com/p/closure-compiler/downloads/list
|
||||
|
||||
|
||||
2) Check out the source and build it with Apache Ant.
|
||||
|
||||
First, check out the full source tree of the Closure Compiler. There
|
||||
are instructions on how to do this at the project site.
|
||||
http://code.google.com/p/closure-compiler/source/checkout
|
||||
|
||||
Apache Ant is a cross-platform build tool.
|
||||
http://ant.apache.org/
|
||||
|
||||
At the root of the source tree, there is an Ant file named
|
||||
build.xml. To use it, navigate to the same directory and type the
|
||||
command
|
||||
|
||||
ant jar
|
||||
|
||||
This will produce a jar file called "build/compiler.jar".
|
||||
|
||||
|
||||
3) Check out the source and build it with Eclipse.
|
||||
|
||||
Eclipse is a cross-platform IDE.
|
||||
http://www.eclipse.org/
|
||||
|
||||
Under Eclipse's File menu, click "New > Project ..." and create a
|
||||
"Java Project." You will see an options screen. Give the project a
|
||||
name, select "Create project from existing source," and choose the
|
||||
root of the checked-out source tree as the existing directory. Verify
|
||||
that you are using JRE version 6 or higher.
|
||||
|
||||
Eclipse can use the build.xml file to discover rules. When you
|
||||
navigate to the build.xml file, you will see all the build rules in
|
||||
the "Outline" pane. Run the "jar" rule to build the compiler in
|
||||
build/compiler.jar.
|
||||
|
||||
|
||||
//
|
||||
// Running The Closure Compiler
|
||||
//
|
||||
|
||||
Once you have the jar binary, running the Closure Compiler is straightforward.
|
||||
|
||||
On the command line, type
|
||||
|
||||
java -jar compiler.jar
|
||||
|
||||
This starts the compiler in interactive mode. Type
|
||||
|
||||
var x = 17 + 25;
|
||||
|
||||
then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux)
|
||||
and "Enter" again. The Compiler will respond:
|
||||
|
||||
var x=42;
|
||||
|
||||
The Closure Compiler has many options for reading input from a file,
|
||||
writing output to a file, checking your code, and running
|
||||
optimizations. To learn more, type
|
||||
|
||||
java -jar compiler.jar --help
|
||||
|
||||
You can read more detailed documentation about the many flags at
|
||||
http://code.google.com/closure/compiler/docs/gettingstarted_app.html
|
||||
|
||||
|
||||
//
|
||||
// Compiling Multiple Scripts
|
||||
//
|
||||
|
||||
If you have multiple scripts, you should compile them all together with
|
||||
one compile command.
|
||||
|
||||
java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js
|
||||
|
||||
The Closure Compiler will concatenate the files in the order they're
|
||||
passed at the command line.
|
||||
|
||||
If you need to compile many, many scripts together, you may start to
|
||||
run into problems with managing dependencies between scripts. You
|
||||
should check out the Closure Library. It contains functions for
|
||||
enforcing dependencies between scripts, and a tool called calcdeps.py
|
||||
that knows how to give scripts to the Closure Compiler in the right
|
||||
order.
|
||||
|
||||
http://code.google.com/p/closure-library/
|
||||
|
||||
//
|
||||
// Licensing
|
||||
//
|
||||
|
||||
Unless otherwise stated, all source files are licensed under
|
||||
the Apache License, Version 2.0.
|
||||
|
||||
|
||||
-----
|
||||
Code under:
|
||||
src/com/google/javascript/rhino
|
||||
test/com/google/javascript/rhino
|
||||
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: 1.5R3, with heavy modifications
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an
|
||||
implementation of JavaScript for the JVM. The JavaScript parser and
|
||||
the parse tree data structures were extracted and modified
|
||||
significantly for use by Google's JavaScript compiler.
|
||||
|
||||
Local Modifications: The packages have been renamespaced. All code not
|
||||
relavant to parsing has been removed. A JSDoc parser and static typing
|
||||
system have been added.
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/libtrunk_rhino_parser_jarjared.jar
|
||||
|
||||
URL: http://www.mozilla.org/rhino
|
||||
Version: Trunk
|
||||
License: Netscape Public License and MPL / GPL dual license
|
||||
|
||||
Description: Mozilla Rhino is an implementation of JavaScript for the JVM.
|
||||
|
||||
Local Modifications: None. We've used JarJar to renamespace the code
|
||||
post-compilation. See:
|
||||
http://code.google.com/p/jarjar/
|
||||
|
||||
|
||||
-----
|
||||
Code in:
|
||||
lib/google_common.jar
|
||||
|
||||
URL: http://code.google.com/p/guava-libraries/
|
||||
Version: Trunk
|
||||
License: Apache License 2.0
|
||||
|
||||
Description: Google's core Java libraries.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
----
|
||||
Code in:
|
||||
lib/junit.jar
|
||||
|
||||
URL: http://sourceforge.net/projects/junit/
|
||||
Version: 3.8.1
|
||||
License: Common Public License 1.0
|
||||
|
||||
Description: A framework for writing and running automated tests in Java.
|
||||
|
||||
Local Modifications: None.
|
||||
|
||||
|
||||
BIN
lib/compiler-closure/compiler.jar
Normal file
BIN
lib/compiler-closure/compiler.jar
Normal file
Binary file not shown.
111
lib/jasmine-jstd-adapter/JasmineAdapter.js
Normal file
111
lib/jasmine-jstd-adapter/JasmineAdapter.js
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* @fileoverview Jasmine JsTestDriver Adapter.
|
||||
* @author ibolmo@gmail.com (Olmo Maldonado)
|
||||
* @author misko@hevery.com (Misko Hevery)
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
function bind(_this, _function){
|
||||
return function(){
|
||||
return _function.call(_this);
|
||||
};
|
||||
}
|
||||
|
||||
var currentFrame = frame(null, null);
|
||||
|
||||
function frame(parent, name){
|
||||
var caseName = (parent && parent.caseName ? parent.caseName + " " : '') + (name ? name : '');
|
||||
var frame = {
|
||||
name: name,
|
||||
caseName: caseName,
|
||||
parent: parent,
|
||||
testCase: TestCase(caseName),
|
||||
before: [],
|
||||
after: [],
|
||||
runBefore: function(){
|
||||
if (parent) parent.runBefore.apply(this);
|
||||
for ( var i = 0; i < frame.before.length; i++) {
|
||||
frame.before[i].apply(this);
|
||||
}
|
||||
},
|
||||
runAfter: function(){
|
||||
for ( var i = 0; i < frame.after.length; i++) {
|
||||
frame.after[i].apply(this);
|
||||
}
|
||||
if (parent) parent.runAfter.apply(this);
|
||||
}
|
||||
};
|
||||
return frame;
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.describe = (function(describe){
|
||||
return function(description){
|
||||
currentFrame = frame(currentFrame, description);
|
||||
var val = describe.apply(this, arguments);
|
||||
currentFrame = currentFrame.parent;
|
||||
return val;
|
||||
};
|
||||
|
||||
})(jasmine.Env.prototype.describe);
|
||||
|
||||
var id = 0;
|
||||
|
||||
jasmine.Env.prototype.it = (function(it){
|
||||
return function(desc, itFn){
|
||||
var self = this;
|
||||
var spec = it.apply(this, arguments);
|
||||
var currentSpec = this.currentSpec;
|
||||
if (!currentSpec.$id) {
|
||||
currentSpec.$id = id++;
|
||||
}
|
||||
var frame = this.jstdFrame = currentFrame;
|
||||
var name = 'test that it ' + desc;
|
||||
if (this.jstdFrame.testCase.prototype[name])
|
||||
throw "Spec with name '" + desc + "' already exists.";
|
||||
this.jstdFrame.testCase.prototype[name] = function(){
|
||||
jasmine.getEnv().currentSpec = currentSpec;
|
||||
frame.runBefore.apply(currentSpec);
|
||||
try {
|
||||
itFn.apply(currentSpec);
|
||||
} finally {
|
||||
frame.runAfter.apply(currentSpec);
|
||||
}
|
||||
};
|
||||
return spec;
|
||||
};
|
||||
|
||||
})(jasmine.Env.prototype.it);
|
||||
|
||||
|
||||
jasmine.Env.prototype.beforeEach = (function(beforeEach){
|
||||
return function(beforeEachFunction) {
|
||||
beforeEach.apply(this, arguments);
|
||||
currentFrame.before.push(beforeEachFunction);
|
||||
};
|
||||
|
||||
})(jasmine.Env.prototype.beforeEach);
|
||||
|
||||
|
||||
jasmine.Env.prototype.afterEach = (function(afterEach){
|
||||
return function(afterEachFunction) {
|
||||
afterEach.apply(this, arguments);
|
||||
currentFrame.after.push(afterEachFunction);
|
||||
};
|
||||
|
||||
})(jasmine.Env.prototype.afterEach);
|
||||
|
||||
|
||||
jasmine.NestedResults.prototype.addResult = (function(addResult){
|
||||
return function(result) {
|
||||
addResult.call(this, result);
|
||||
if (result.type != 'MessageResult' && !result.passed()) fail(result.message);
|
||||
};
|
||||
|
||||
})(jasmine.NestedResults.prototype.addResult);
|
||||
|
||||
// Reset environment with overriden methods.
|
||||
jasmine.currentEnv_ = null;
|
||||
jasmine.getEnv();
|
||||
|
||||
})();
|
||||
2331
lib/jasmine/jasmine-0.10.3.js
Normal file
2331
lib/jasmine/jasmine-0.10.3.js
Normal file
File diff suppressed because it is too large
Load diff
6240
lib/jquery/jquery-1.4.2.js
vendored
Normal file
6240
lib/jquery/jquery-1.4.2.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
154
lib/jquery/jquery-1.4.2.min.js
vendored
Normal file
154
lib/jquery/jquery-1.4.2.min.js
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*!
|
||||
* jQuery JavaScript Library v1.4.2
|
||||
* http://jquery.com/
|
||||
*
|
||||
* Copyright 2010, John Resig
|
||||
* Dual licensed under the MIT or GPL Version 2 licenses.
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* http://sizzlejs.com/
|
||||
* Copyright 2010, The Dojo Foundation
|
||||
* Released under the MIT, BSD, and GPL Licenses.
|
||||
*
|
||||
* Date: Sat Feb 13 22:33:48 2010 -0500
|
||||
*/
|
||||
(function(A,w){function ma(){if(!c.isReady){try{s.documentElement.doScroll("left")}catch(a){setTimeout(ma,1);return}c.ready()}}function Qa(a,b){b.src?c.ajax({url:b.src,async:false,dataType:"script"}):c.globalEval(b.text||b.textContent||b.innerHTML||"");b.parentNode&&b.parentNode.removeChild(b)}function X(a,b,d,f,e,j){var i=a.length;if(typeof b==="object"){for(var o in b)X(a,o,b[o],f,e,d);return a}if(d!==w){f=!j&&f&&c.isFunction(d);for(o=0;o<i;o++)e(a[o],b,f?d.call(a[o],o,e(a[o],b)):d,j);return a}return i?
|
||||
e(a[0],b):w}function J(){return(new Date).getTime()}function Y(){return false}function Z(){return true}function na(a,b,d){d[0].type=a;return c.event.handle.apply(b,d)}function oa(a){var b,d=[],f=[],e=arguments,j,i,o,k,n,r;i=c.data(this,"events");if(!(a.liveFired===this||!i||!i.live||a.button&&a.type==="click")){a.liveFired=this;var u=i.live.slice(0);for(k=0;k<u.length;k++){i=u[k];i.origType.replace(O,"")===a.type?f.push(i.selector):u.splice(k--,1)}j=c(a.target).closest(f,a.currentTarget);n=0;for(r=
|
||||
j.length;n<r;n++)for(k=0;k<u.length;k++){i=u[k];if(j[n].selector===i.selector){o=j[n].elem;f=null;if(i.preType==="mouseenter"||i.preType==="mouseleave")f=c(a.relatedTarget).closest(i.selector)[0];if(!f||f!==o)d.push({elem:o,handleObj:i})}}n=0;for(r=d.length;n<r;n++){j=d[n];a.currentTarget=j.elem;a.data=j.handleObj.data;a.handleObj=j.handleObj;if(j.handleObj.origHandler.apply(j.elem,e)===false){b=false;break}}return b}}function pa(a,b){return"live."+(a&&a!=="*"?a+".":"")+b.replace(/\./g,"`").replace(/ /g,
|
||||
"&")}function qa(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function ra(a,b){var d=0;b.each(function(){if(this.nodeName===(a[d]&&a[d].nodeName)){var f=c.data(a[d++]),e=c.data(this,f);if(f=f&&f.events){delete e.handle;e.events={};for(var j in f)for(var i in f[j])c.event.add(this,j,f[j][i],f[j][i].data)}}})}function sa(a,b,d){var f,e,j;b=b&&b[0]?b[0].ownerDocument||b[0]:s;if(a.length===1&&typeof a[0]==="string"&&a[0].length<512&&b===s&&!ta.test(a[0])&&(c.support.checkClone||!ua.test(a[0]))){e=
|
||||
true;if(j=c.fragments[a[0]])if(j!==1)f=j}if(!f){f=b.createDocumentFragment();c.clean(a,b,f,d)}if(e)c.fragments[a[0]]=j?f:1;return{fragment:f,cacheable:e}}function K(a,b){var d={};c.each(va.concat.apply([],va.slice(0,b)),function(){d[this]=a});return d}function wa(a){return"scrollTo"in a&&a.document?a:a.nodeType===9?a.defaultView||a.parentWindow:false}var c=function(a,b){return new c.fn.init(a,b)},Ra=A.jQuery,Sa=A.$,s=A.document,T,Ta=/^[^<]*(<[\w\W]+>)[^>]*$|^#([\w-]+)$/,Ua=/^.[^:#\[\.,]*$/,Va=/\S/,
|
||||
Wa=/^(\s|\u00A0)+|(\s|\u00A0)+$/g,Xa=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,P=navigator.userAgent,xa=false,Q=[],L,$=Object.prototype.toString,aa=Object.prototype.hasOwnProperty,ba=Array.prototype.push,R=Array.prototype.slice,ya=Array.prototype.indexOf;c.fn=c.prototype={init:function(a,b){var d,f;if(!a)return this;if(a.nodeType){this.context=this[0]=a;this.length=1;return this}if(a==="body"&&!b){this.context=s;this[0]=s.body;this.selector="body";this.length=1;return this}if(typeof a==="string")if((d=Ta.exec(a))&&
|
||||
(d[1]||!b))if(d[1]){f=b?b.ownerDocument||b:s;if(a=Xa.exec(a))if(c.isPlainObject(b)){a=[s.createElement(a[1])];c.fn.attr.call(a,b,true)}else a=[f.createElement(a[1])];else{a=sa([d[1]],[f]);a=(a.cacheable?a.fragment.cloneNode(true):a.fragment).childNodes}return c.merge(this,a)}else{if(b=s.getElementById(d[2])){if(b.id!==d[2])return T.find(a);this.length=1;this[0]=b}this.context=s;this.selector=a;return this}else if(!b&&/^\w+$/.test(a)){this.selector=a;this.context=s;a=s.getElementsByTagName(a);return c.merge(this,
|
||||
a)}else return!b||b.jquery?(b||T).find(a):c(b).find(a);else if(c.isFunction(a))return T.ready(a);if(a.selector!==w){this.selector=a.selector;this.context=a.context}return c.makeArray(a,this)},selector:"",jquery:"1.4.2",length:0,size:function(){return this.length},toArray:function(){return R.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this.slice(a)[0]:this[a]},pushStack:function(a,b,d){var f=c();c.isArray(a)?ba.apply(f,a):c.merge(f,a);f.prevObject=this;f.context=this.context;if(b===
|
||||
"find")f.selector=this.selector+(this.selector?" ":"")+d;else if(b)f.selector=this.selector+"."+b+"("+d+")";return f},each:function(a,b){return c.each(this,a,b)},ready:function(a){c.bindReady();if(c.isReady)a.call(s,c);else Q&&Q.push(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(R.apply(this,arguments),"slice",R.call(arguments).join(","))},map:function(a){return this.pushStack(c.map(this,
|
||||
function(b,d){return a.call(b,d,b)}))},end:function(){return this.prevObject||c(null)},push:ba,sort:[].sort,splice:[].splice};c.fn.init.prototype=c.fn;c.extend=c.fn.extend=function(){var a=arguments[0]||{},b=1,d=arguments.length,f=false,e,j,i,o;if(typeof a==="boolean"){f=a;a=arguments[1]||{};b=2}if(typeof a!=="object"&&!c.isFunction(a))a={};if(d===b){a=this;--b}for(;b<d;b++)if((e=arguments[b])!=null)for(j in e){i=a[j];o=e[j];if(a!==o)if(f&&o&&(c.isPlainObject(o)||c.isArray(o))){i=i&&(c.isPlainObject(i)||
|
||||
c.isArray(i))?i:c.isArray(o)?[]:{};a[j]=c.extend(f,i,o)}else if(o!==w)a[j]=o}return a};c.extend({noConflict:function(a){A.$=Sa;if(a)A.jQuery=Ra;return c},isReady:false,ready:function(){if(!c.isReady){if(!s.body)return setTimeout(c.ready,13);c.isReady=true;if(Q){for(var a,b=0;a=Q[b++];)a.call(s,c);Q=null}c.fn.triggerHandler&&c(s).triggerHandler("ready")}},bindReady:function(){if(!xa){xa=true;if(s.readyState==="complete")return c.ready();if(s.addEventListener){s.addEventListener("DOMContentLoaded",
|
||||
L,false);A.addEventListener("load",c.ready,false)}else if(s.attachEvent){s.attachEvent("onreadystatechange",L);A.attachEvent("onload",c.ready);var a=false;try{a=A.frameElement==null}catch(b){}s.documentElement.doScroll&&a&&ma()}}},isFunction:function(a){return $.call(a)==="[object Function]"},isArray:function(a){return $.call(a)==="[object Array]"},isPlainObject:function(a){if(!a||$.call(a)!=="[object Object]"||a.nodeType||a.setInterval)return false;if(a.constructor&&!aa.call(a,"constructor")&&!aa.call(a.constructor.prototype,
|
||||
"isPrototypeOf"))return false;var b;for(b in a);return b===w||aa.call(a,b)},isEmptyObject:function(a){for(var b in a)return false;return true},error:function(a){throw a;},parseJSON:function(a){if(typeof a!=="string"||!a)return null;a=c.trim(a);if(/^[\],:{}\s]*$/.test(a.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return A.JSON&&A.JSON.parse?A.JSON.parse(a):(new Function("return "+
|
||||
a))();else c.error("Invalid JSON: "+a)},noop:function(){},globalEval:function(a){if(a&&Va.test(a)){var b=s.getElementsByTagName("head")[0]||s.documentElement,d=s.createElement("script");d.type="text/javascript";if(c.support.scriptEval)d.appendChild(s.createTextNode(a));else d.text=a;b.insertBefore(d,b.firstChild);b.removeChild(d)}},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,b,d){var f,e=0,j=a.length,i=j===w||c.isFunction(a);if(d)if(i)for(f in a){if(b.apply(a[f],
|
||||
d)===false)break}else for(;e<j;){if(b.apply(a[e++],d)===false)break}else if(i)for(f in a){if(b.call(a[f],f,a[f])===false)break}else for(d=a[0];e<j&&b.call(d,e,d)!==false;d=a[++e]);return a},trim:function(a){return(a||"").replace(Wa,"")},makeArray:function(a,b){b=b||[];if(a!=null)a.length==null||typeof a==="string"||c.isFunction(a)||typeof a!=="function"&&a.setInterval?ba.call(b,a):c.merge(b,a);return b},inArray:function(a,b){if(b.indexOf)return b.indexOf(a);for(var d=0,f=b.length;d<f;d++)if(b[d]===
|
||||
a)return d;return-1},merge:function(a,b){var d=a.length,f=0;if(typeof b.length==="number")for(var e=b.length;f<e;f++)a[d++]=b[f];else for(;b[f]!==w;)a[d++]=b[f++];a.length=d;return a},grep:function(a,b,d){for(var f=[],e=0,j=a.length;e<j;e++)!d!==!b(a[e],e)&&f.push(a[e]);return f},map:function(a,b,d){for(var f=[],e,j=0,i=a.length;j<i;j++){e=b(a[j],j,d);if(e!=null)f[f.length]=e}return f.concat.apply([],f)},guid:1,proxy:function(a,b,d){if(arguments.length===2)if(typeof b==="string"){d=a;a=d[b];b=w}else if(b&&
|
||||
!c.isFunction(b)){d=b;b=w}if(!b&&a)b=function(){return a.apply(d||this,arguments)};if(a)b.guid=a.guid=a.guid||b.guid||c.guid++;return b},uaMatch:function(a){a=a.toLowerCase();a=/(webkit)[ \/]([\w.]+)/.exec(a)||/(opera)(?:.*version)?[ \/]([\w.]+)/.exec(a)||/(msie) ([\w.]+)/.exec(a)||!/compatible/.test(a)&&/(mozilla)(?:.*? rv:([\w.]+))?/.exec(a)||[];return{browser:a[1]||"",version:a[2]||"0"}},browser:{}});P=c.uaMatch(P);if(P.browser){c.browser[P.browser]=true;c.browser.version=P.version}if(c.browser.webkit)c.browser.safari=
|
||||
true;if(ya)c.inArray=function(a,b){return ya.call(b,a)};T=c(s);if(s.addEventListener)L=function(){s.removeEventListener("DOMContentLoaded",L,false);c.ready()};else if(s.attachEvent)L=function(){if(s.readyState==="complete"){s.detachEvent("onreadystatechange",L);c.ready()}};(function(){c.support={};var a=s.documentElement,b=s.createElement("script"),d=s.createElement("div"),f="script"+J();d.style.display="none";d.innerHTML=" <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
|
||||
var e=d.getElementsByTagName("*"),j=d.getElementsByTagName("a")[0];if(!(!e||!e.length||!j)){c.support={leadingWhitespace:d.firstChild.nodeType===3,tbody:!d.getElementsByTagName("tbody").length,htmlSerialize:!!d.getElementsByTagName("link").length,style:/red/.test(j.getAttribute("style")),hrefNormalized:j.getAttribute("href")==="/a",opacity:/^0.55$/.test(j.style.opacity),cssFloat:!!j.style.cssFloat,checkOn:d.getElementsByTagName("input")[0].value==="on",optSelected:s.createElement("select").appendChild(s.createElement("option")).selected,
|
||||
parentNode:d.removeChild(d.appendChild(s.createElement("div"))).parentNode===null,deleteExpando:true,checkClone:false,scriptEval:false,noCloneEvent:true,boxModel:null};b.type="text/javascript";try{b.appendChild(s.createTextNode("window."+f+"=1;"))}catch(i){}a.insertBefore(b,a.firstChild);if(A[f]){c.support.scriptEval=true;delete A[f]}try{delete b.test}catch(o){c.support.deleteExpando=false}a.removeChild(b);if(d.attachEvent&&d.fireEvent){d.attachEvent("onclick",function k(){c.support.noCloneEvent=
|
||||
false;d.detachEvent("onclick",k)});d.cloneNode(true).fireEvent("onclick")}d=s.createElement("div");d.innerHTML="<input type='radio' name='radiotest' checked='checked'/>";a=s.createDocumentFragment();a.appendChild(d.firstChild);c.support.checkClone=a.cloneNode(true).cloneNode(true).lastChild.checked;c(function(){var k=s.createElement("div");k.style.width=k.style.paddingLeft="1px";s.body.appendChild(k);c.boxModel=c.support.boxModel=k.offsetWidth===2;s.body.removeChild(k).style.display="none"});a=function(k){var n=
|
||||
s.createElement("div");k="on"+k;var r=k in n;if(!r){n.setAttribute(k,"return;");r=typeof n[k]==="function"}return r};c.support.submitBubbles=a("submit");c.support.changeBubbles=a("change");a=b=d=e=j=null}})();c.props={"for":"htmlFor","class":"className",readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",colspan:"colSpan",tabindex:"tabIndex",usemap:"useMap",frameborder:"frameBorder"};var G="jQuery"+J(),Ya=0,za={};c.extend({cache:{},expando:G,noData:{embed:true,object:true,
|
||||
applet:true},data:function(a,b,d){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var f=a[G],e=c.cache;if(!f&&typeof b==="string"&&d===w)return null;f||(f=++Ya);if(typeof b==="object"){a[G]=f;e[f]=c.extend(true,{},b)}else if(!e[f]){a[G]=f;e[f]={}}a=e[f];if(d!==w)a[b]=d;return typeof b==="string"?a[b]:a}},removeData:function(a,b){if(!(a.nodeName&&c.noData[a.nodeName.toLowerCase()])){a=a==A?za:a;var d=a[G],f=c.cache,e=f[d];if(b){if(e){delete e[b];c.isEmptyObject(e)&&c.removeData(a)}}else{if(c.support.deleteExpando)delete a[c.expando];
|
||||
else a.removeAttribute&&a.removeAttribute(c.expando);delete f[d]}}}});c.fn.extend({data:function(a,b){if(typeof a==="undefined"&&this.length)return c.data(this[0]);else if(typeof a==="object")return this.each(function(){c.data(this,a)});var d=a.split(".");d[1]=d[1]?"."+d[1]:"";if(b===w){var f=this.triggerHandler("getData"+d[1]+"!",[d[0]]);if(f===w&&this.length)f=c.data(this[0],a);return f===w&&d[1]?this.data(d[0]):f}else return this.trigger("setData"+d[1]+"!",[d[0],b]).each(function(){c.data(this,
|
||||
a,b)})},removeData:function(a){return this.each(function(){c.removeData(this,a)})}});c.extend({queue:function(a,b,d){if(a){b=(b||"fx")+"queue";var f=c.data(a,b);if(!d)return f||[];if(!f||c.isArray(d))f=c.data(a,b,c.makeArray(d));else f.push(d);return f}},dequeue:function(a,b){b=b||"fx";var d=c.queue(a,b),f=d.shift();if(f==="inprogress")f=d.shift();if(f){b==="fx"&&d.unshift("inprogress");f.call(a,function(){c.dequeue(a,b)})}}});c.fn.extend({queue:function(a,b){if(typeof a!=="string"){b=a;a="fx"}if(b===
|
||||
w)return c.queue(this[0],a);return this.each(function(){var d=c.queue(this,a,b);a==="fx"&&d[0]!=="inprogress"&&c.dequeue(this,a)})},dequeue:function(a){return this.each(function(){c.dequeue(this,a)})},delay:function(a,b){a=c.fx?c.fx.speeds[a]||a:a;b=b||"fx";return this.queue(b,function(){var d=this;setTimeout(function(){c.dequeue(d,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])}});var Aa=/[\n\t]/g,ca=/\s+/,Za=/\r/g,$a=/href|src|style/,ab=/(button|input)/i,bb=/(button|input|object|select|textarea)/i,
|
||||
cb=/^(a|area)$/i,Ba=/radio|checkbox/;c.fn.extend({attr:function(a,b){return X(this,a,b,true,c.attr)},removeAttr:function(a){return this.each(function(){c.attr(this,a,"");this.nodeType===1&&this.removeAttribute(a)})},addClass:function(a){if(c.isFunction(a))return this.each(function(n){var r=c(this);r.addClass(a.call(this,n,r.attr("class")))});if(a&&typeof a==="string")for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1)if(e.className){for(var j=" "+e.className+" ",
|
||||
i=e.className,o=0,k=b.length;o<k;o++)if(j.indexOf(" "+b[o]+" ")<0)i+=" "+b[o];e.className=c.trim(i)}else e.className=a}return this},removeClass:function(a){if(c.isFunction(a))return this.each(function(k){var n=c(this);n.removeClass(a.call(this,k,n.attr("class")))});if(a&&typeof a==="string"||a===w)for(var b=(a||"").split(ca),d=0,f=this.length;d<f;d++){var e=this[d];if(e.nodeType===1&&e.className)if(a){for(var j=(" "+e.className+" ").replace(Aa," "),i=0,o=b.length;i<o;i++)j=j.replace(" "+b[i]+" ",
|
||||
" ");e.className=c.trim(j)}else e.className=""}return this},toggleClass:function(a,b){var d=typeof a,f=typeof b==="boolean";if(c.isFunction(a))return this.each(function(e){var j=c(this);j.toggleClass(a.call(this,e,j.attr("class"),b),b)});return this.each(function(){if(d==="string")for(var e,j=0,i=c(this),o=b,k=a.split(ca);e=k[j++];){o=f?o:!i.hasClass(e);i[o?"addClass":"removeClass"](e)}else if(d==="undefined"||d==="boolean"){this.className&&c.data(this,"__className__",this.className);this.className=
|
||||
this.className||a===false?"":c.data(this,"__className__")||""}})},hasClass:function(a){a=" "+a+" ";for(var b=0,d=this.length;b<d;b++)if((" "+this[b].className+" ").replace(Aa," ").indexOf(a)>-1)return true;return false},val:function(a){if(a===w){var b=this[0];if(b){if(c.nodeName(b,"option"))return(b.attributes.value||{}).specified?b.value:b.text;if(c.nodeName(b,"select")){var d=b.selectedIndex,f=[],e=b.options;b=b.type==="select-one";if(d<0)return null;var j=b?d:0;for(d=b?d+1:e.length;j<d;j++){var i=
|
||||
e[j];if(i.selected){a=c(i).val();if(b)return a;f.push(a)}}return f}if(Ba.test(b.type)&&!c.support.checkOn)return b.getAttribute("value")===null?"on":b.value;return(b.value||"").replace(Za,"")}return w}var o=c.isFunction(a);return this.each(function(k){var n=c(this),r=a;if(this.nodeType===1){if(o)r=a.call(this,k,n.val());if(typeof r==="number")r+="";if(c.isArray(r)&&Ba.test(this.type))this.checked=c.inArray(n.val(),r)>=0;else if(c.nodeName(this,"select")){var u=c.makeArray(r);c("option",this).each(function(){this.selected=
|
||||
c.inArray(c(this).val(),u)>=0});if(!u.length)this.selectedIndex=-1}else this.value=r}})}});c.extend({attrFn:{val:true,css:true,html:true,text:true,data:true,width:true,height:true,offset:true},attr:function(a,b,d,f){if(!a||a.nodeType===3||a.nodeType===8)return w;if(f&&b in c.attrFn)return c(a)[b](d);f=a.nodeType!==1||!c.isXMLDoc(a);var e=d!==w;b=f&&c.props[b]||b;if(a.nodeType===1){var j=$a.test(b);if(b in a&&f&&!j){if(e){b==="type"&&ab.test(a.nodeName)&&a.parentNode&&c.error("type property can't be changed");
|
||||
a[b]=d}if(c.nodeName(a,"form")&&a.getAttributeNode(b))return a.getAttributeNode(b).nodeValue;if(b==="tabIndex")return(b=a.getAttributeNode("tabIndex"))&&b.specified?b.value:bb.test(a.nodeName)||cb.test(a.nodeName)&&a.href?0:w;return a[b]}if(!c.support.style&&f&&b==="style"){if(e)a.style.cssText=""+d;return a.style.cssText}e&&a.setAttribute(b,""+d);a=!c.support.hrefNormalized&&f&&j?a.getAttribute(b,2):a.getAttribute(b);return a===null?w:a}return c.style(a,b,d)}});var O=/\.(.*)$/,db=function(a){return a.replace(/[^\w\s\.\|`]/g,
|
||||
function(b){return"\\"+b})};c.event={add:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){if(a.setInterval&&a!==A&&!a.frameElement)a=A;var e,j;if(d.handler){e=d;d=e.handler}if(!d.guid)d.guid=c.guid++;if(j=c.data(a)){var i=j.events=j.events||{},o=j.handle;if(!o)j.handle=o=function(){return typeof c!=="undefined"&&!c.event.triggered?c.event.handle.apply(o.elem,arguments):w};o.elem=a;b=b.split(" ");for(var k,n=0,r;k=b[n++];){j=e?c.extend({},e):{handler:d,data:f};if(k.indexOf(".")>-1){r=k.split(".");
|
||||
k=r.shift();j.namespace=r.slice(0).sort().join(".")}else{r=[];j.namespace=""}j.type=k;j.guid=d.guid;var u=i[k],z=c.event.special[k]||{};if(!u){u=i[k]=[];if(!z.setup||z.setup.call(a,f,r,o)===false)if(a.addEventListener)a.addEventListener(k,o,false);else a.attachEvent&&a.attachEvent("on"+k,o)}if(z.add){z.add.call(a,j);if(!j.handler.guid)j.handler.guid=d.guid}u.push(j);c.event.global[k]=true}a=null}}},global:{},remove:function(a,b,d,f){if(!(a.nodeType===3||a.nodeType===8)){var e,j=0,i,o,k,n,r,u,z=c.data(a),
|
||||
C=z&&z.events;if(z&&C){if(b&&b.type){d=b.handler;b=b.type}if(!b||typeof b==="string"&&b.charAt(0)==="."){b=b||"";for(e in C)c.event.remove(a,e+b)}else{for(b=b.split(" ");e=b[j++];){n=e;i=e.indexOf(".")<0;o=[];if(!i){o=e.split(".");e=o.shift();k=new RegExp("(^|\\.)"+c.map(o.slice(0).sort(),db).join("\\.(?:.*\\.)?")+"(\\.|$)")}if(r=C[e])if(d){n=c.event.special[e]||{};for(B=f||0;B<r.length;B++){u=r[B];if(d.guid===u.guid){if(i||k.test(u.namespace)){f==null&&r.splice(B--,1);n.remove&&n.remove.call(a,u)}if(f!=
|
||||
null)break}}if(r.length===0||f!=null&&r.length===1){if(!n.teardown||n.teardown.call(a,o)===false)Ca(a,e,z.handle);delete C[e]}}else for(var B=0;B<r.length;B++){u=r[B];if(i||k.test(u.namespace)){c.event.remove(a,n,u.handler,B);r.splice(B--,1)}}}if(c.isEmptyObject(C)){if(b=z.handle)b.elem=null;delete z.events;delete z.handle;c.isEmptyObject(z)&&c.removeData(a)}}}}},trigger:function(a,b,d,f){var e=a.type||a;if(!f){a=typeof a==="object"?a[G]?a:c.extend(c.Event(e),a):c.Event(e);if(e.indexOf("!")>=0){a.type=
|
||||
e=e.slice(0,-1);a.exclusive=true}if(!d){a.stopPropagation();c.event.global[e]&&c.each(c.cache,function(){this.events&&this.events[e]&&c.event.trigger(a,b,this.handle.elem)})}if(!d||d.nodeType===3||d.nodeType===8)return w;a.result=w;a.target=d;b=c.makeArray(b);b.unshift(a)}a.currentTarget=d;(f=c.data(d,"handle"))&&f.apply(d,b);f=d.parentNode||d.ownerDocument;try{if(!(d&&d.nodeName&&c.noData[d.nodeName.toLowerCase()]))if(d["on"+e]&&d["on"+e].apply(d,b)===false)a.result=false}catch(j){}if(!a.isPropagationStopped()&&
|
||||
f)c.event.trigger(a,b,f,true);else if(!a.isDefaultPrevented()){f=a.target;var i,o=c.nodeName(f,"a")&&e==="click",k=c.event.special[e]||{};if((!k._default||k._default.call(d,a)===false)&&!o&&!(f&&f.nodeName&&c.noData[f.nodeName.toLowerCase()])){try{if(f[e]){if(i=f["on"+e])f["on"+e]=null;c.event.triggered=true;f[e]()}}catch(n){}if(i)f["on"+e]=i;c.event.triggered=false}}},handle:function(a){var b,d,f,e;a=arguments[0]=c.event.fix(a||A.event);a.currentTarget=this;b=a.type.indexOf(".")<0&&!a.exclusive;
|
||||
if(!b){d=a.type.split(".");a.type=d.shift();f=new RegExp("(^|\\.)"+d.slice(0).sort().join("\\.(?:.*\\.)?")+"(\\.|$)")}e=c.data(this,"events");d=e[a.type];if(e&&d){d=d.slice(0);e=0;for(var j=d.length;e<j;e++){var i=d[e];if(b||f.test(i.namespace)){a.handler=i.handler;a.data=i.data;a.handleObj=i;i=i.handler.apply(this,arguments);if(i!==w){a.result=i;if(i===false){a.preventDefault();a.stopPropagation()}}if(a.isImmediatePropagationStopped())break}}}return a.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
|
||||
fix:function(a){if(a[G])return a;var b=a;a=c.Event(b);for(var d=this.props.length,f;d;){f=this.props[--d];a[f]=b[f]}if(!a.target)a.target=a.srcElement||s;if(a.target.nodeType===3)a.target=a.target.parentNode;if(!a.relatedTarget&&a.fromElement)a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement;if(a.pageX==null&&a.clientX!=null){b=s.documentElement;d=s.body;a.pageX=a.clientX+(b&&b.scrollLeft||d&&d.scrollLeft||0)-(b&&b.clientLeft||d&&d.clientLeft||0);a.pageY=a.clientY+(b&&b.scrollTop||
|
||||
d&&d.scrollTop||0)-(b&&b.clientTop||d&&d.clientTop||0)}if(!a.which&&(a.charCode||a.charCode===0?a.charCode:a.keyCode))a.which=a.charCode||a.keyCode;if(!a.metaKey&&a.ctrlKey)a.metaKey=a.ctrlKey;if(!a.which&&a.button!==w)a.which=a.button&1?1:a.button&2?3:a.button&4?2:0;return a},guid:1E8,proxy:c.proxy,special:{ready:{setup:c.bindReady,teardown:c.noop},live:{add:function(a){c.event.add(this,a.origType,c.extend({},a,{handler:oa}))},remove:function(a){var b=true,d=a.origType.replace(O,"");c.each(c.data(this,
|
||||
"events").live||[],function(){if(d===this.origType.replace(O,""))return b=false});b&&c.event.remove(this,a.origType,oa)}},beforeunload:{setup:function(a,b,d){if(this.setInterval)this.onbeforeunload=d;return false},teardown:function(a,b){if(this.onbeforeunload===b)this.onbeforeunload=null}}}};var Ca=s.removeEventListener?function(a,b,d){a.removeEventListener(b,d,false)}:function(a,b,d){a.detachEvent("on"+b,d)};c.Event=function(a){if(!this.preventDefault)return new c.Event(a);if(a&&a.type){this.originalEvent=
|
||||
a;this.type=a.type}else this.type=a;this.timeStamp=J();this[G]=true};c.Event.prototype={preventDefault:function(){this.isDefaultPrevented=Z;var a=this.originalEvent;if(a){a.preventDefault&&a.preventDefault();a.returnValue=false}},stopPropagation:function(){this.isPropagationStopped=Z;var a=this.originalEvent;if(a){a.stopPropagation&&a.stopPropagation();a.cancelBubble=true}},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=Z;this.stopPropagation()},isDefaultPrevented:Y,isPropagationStopped:Y,
|
||||
isImmediatePropagationStopped:Y};var Da=function(a){var b=a.relatedTarget;try{for(;b&&b!==this;)b=b.parentNode;if(b!==this){a.type=a.data;c.event.handle.apply(this,arguments)}}catch(d){}},Ea=function(a){a.type=a.data;c.event.handle.apply(this,arguments)};c.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){c.event.special[a]={setup:function(d){c.event.add(this,b,d&&d.selector?Ea:Da,a)},teardown:function(d){c.event.remove(this,b,d&&d.selector?Ea:Da)}}});if(!c.support.submitBubbles)c.event.special.submit=
|
||||
{setup:function(){if(this.nodeName.toLowerCase()!=="form"){c.event.add(this,"click.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="submit"||d==="image")&&c(b).closest("form").length)return na("submit",this,arguments)});c.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,d=b.type;if((d==="text"||d==="password")&&c(b).closest("form").length&&a.keyCode===13)return na("submit",this,arguments)})}else return false},teardown:function(){c.event.remove(this,".specialSubmit")}};
|
||||
if(!c.support.changeBubbles){var da=/textarea|input|select/i,ea,Fa=function(a){var b=a.type,d=a.value;if(b==="radio"||b==="checkbox")d=a.checked;else if(b==="select-multiple")d=a.selectedIndex>-1?c.map(a.options,function(f){return f.selected}).join("-"):"";else if(a.nodeName.toLowerCase()==="select")d=a.selectedIndex;return d},fa=function(a,b){var d=a.target,f,e;if(!(!da.test(d.nodeName)||d.readOnly)){f=c.data(d,"_change_data");e=Fa(d);if(a.type!=="focusout"||d.type!=="radio")c.data(d,"_change_data",
|
||||
e);if(!(f===w||e===f))if(f!=null||e){a.type="change";return c.event.trigger(a,b,d)}}};c.event.special.change={filters:{focusout:fa,click:function(a){var b=a.target,d=b.type;if(d==="radio"||d==="checkbox"||b.nodeName.toLowerCase()==="select")return fa.call(this,a)},keydown:function(a){var b=a.target,d=b.type;if(a.keyCode===13&&b.nodeName.toLowerCase()!=="textarea"||a.keyCode===32&&(d==="checkbox"||d==="radio")||d==="select-multiple")return fa.call(this,a)},beforeactivate:function(a){a=a.target;c.data(a,
|
||||
"_change_data",Fa(a))}},setup:function(){if(this.type==="file")return false;for(var a in ea)c.event.add(this,a+".specialChange",ea[a]);return da.test(this.nodeName)},teardown:function(){c.event.remove(this,".specialChange");return da.test(this.nodeName)}};ea=c.event.special.change.filters}s.addEventListener&&c.each({focus:"focusin",blur:"focusout"},function(a,b){function d(f){f=c.event.fix(f);f.type=b;return c.event.handle.call(this,f)}c.event.special[b]={setup:function(){this.addEventListener(a,
|
||||
d,true)},teardown:function(){this.removeEventListener(a,d,true)}}});c.each(["bind","one"],function(a,b){c.fn[b]=function(d,f,e){if(typeof d==="object"){for(var j in d)this[b](j,f,d[j],e);return this}if(c.isFunction(f)){e=f;f=w}var i=b==="one"?c.proxy(e,function(k){c(this).unbind(k,i);return e.apply(this,arguments)}):e;if(d==="unload"&&b!=="one")this.one(d,f,e);else{j=0;for(var o=this.length;j<o;j++)c.event.add(this[j],d,i,f)}return this}});c.fn.extend({unbind:function(a,b){if(typeof a==="object"&&
|
||||
!a.preventDefault)for(var d in a)this.unbind(d,a[d]);else{d=0;for(var f=this.length;d<f;d++)c.event.remove(this[d],a,b)}return this},delegate:function(a,b,d,f){return this.live(b,d,f,a)},undelegate:function(a,b,d){return arguments.length===0?this.unbind("live"):this.die(b,null,d,a)},trigger:function(a,b){return this.each(function(){c.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0]){a=c.Event(a);a.preventDefault();a.stopPropagation();c.event.trigger(a,b,this[0]);return a.result}},
|
||||
toggle:function(a){for(var b=arguments,d=1;d<b.length;)c.proxy(a,b[d++]);return this.click(c.proxy(a,function(f){var e=(c.data(this,"lastToggle"+a.guid)||0)%d;c.data(this,"lastToggle"+a.guid,e+1);f.preventDefault();return b[e].apply(this,arguments)||false}))},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var Ga={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};c.each(["live","die"],function(a,b){c.fn[b]=function(d,f,e,j){var i,o=0,k,n,r=j||this.selector,
|
||||
u=j?this:c(this.context);if(c.isFunction(f)){e=f;f=w}for(d=(d||"").split(" ");(i=d[o++])!=null;){j=O.exec(i);k="";if(j){k=j[0];i=i.replace(O,"")}if(i==="hover")d.push("mouseenter"+k,"mouseleave"+k);else{n=i;if(i==="focus"||i==="blur"){d.push(Ga[i]+k);i+=k}else i=(Ga[i]||i)+k;b==="live"?u.each(function(){c.event.add(this,pa(i,r),{data:f,selector:r,handler:e,origType:i,origHandler:e,preType:n})}):u.unbind(pa(i,r),e)}}return this}});c.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return d?this.bind(b,d):this.trigger(b)};if(c.attrFn)c.attrFn[b]=true});A.attachEvent&&!A.addEventListener&&A.attachEvent("onunload",function(){for(var a in c.cache)if(c.cache[a].handle)try{c.event.remove(c.cache[a].handle.elem)}catch(b){}});(function(){function a(g){for(var h="",l,m=0;g[m];m++){l=g[m];if(l.nodeType===3||l.nodeType===4)h+=l.nodeValue;else if(l.nodeType!==8)h+=a(l.childNodes)}return h}function b(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];
|
||||
if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1&&!p){t.sizcache=l;t.sizset=q}if(t.nodeName.toLowerCase()===h){y=t;break}t=t[g]}m[q]=y}}}function d(g,h,l,m,q,p){q=0;for(var v=m.length;q<v;q++){var t=m[q];if(t){t=t[g];for(var y=false;t;){if(t.sizcache===l){y=m[t.sizset];break}if(t.nodeType===1){if(!p){t.sizcache=l;t.sizset=q}if(typeof h!=="string"){if(t===h){y=true;break}}else if(k.filter(h,[t]).length>0){y=t;break}}t=t[g]}m[q]=y}}}var f=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
|
||||
e=0,j=Object.prototype.toString,i=false,o=true;[0,0].sort(function(){o=false;return 0});var k=function(g,h,l,m){l=l||[];var q=h=h||s;if(h.nodeType!==1&&h.nodeType!==9)return[];if(!g||typeof g!=="string")return l;for(var p=[],v,t,y,S,H=true,M=x(h),I=g;(f.exec(""),v=f.exec(I))!==null;){I=v[3];p.push(v[1]);if(v[2]){S=v[3];break}}if(p.length>1&&r.exec(g))if(p.length===2&&n.relative[p[0]])t=ga(p[0]+p[1],h);else for(t=n.relative[p[0]]?[h]:k(p.shift(),h);p.length;){g=p.shift();if(n.relative[g])g+=p.shift();
|
||||
t=ga(g,t)}else{if(!m&&p.length>1&&h.nodeType===9&&!M&&n.match.ID.test(p[0])&&!n.match.ID.test(p[p.length-1])){v=k.find(p.shift(),h,M);h=v.expr?k.filter(v.expr,v.set)[0]:v.set[0]}if(h){v=m?{expr:p.pop(),set:z(m)}:k.find(p.pop(),p.length===1&&(p[0]==="~"||p[0]==="+")&&h.parentNode?h.parentNode:h,M);t=v.expr?k.filter(v.expr,v.set):v.set;if(p.length>0)y=z(t);else H=false;for(;p.length;){var D=p.pop();v=D;if(n.relative[D])v=p.pop();else D="";if(v==null)v=h;n.relative[D](y,v,M)}}else y=[]}y||(y=t);y||k.error(D||
|
||||
g);if(j.call(y)==="[object Array]")if(H)if(h&&h.nodeType===1)for(g=0;y[g]!=null;g++){if(y[g]&&(y[g]===true||y[g].nodeType===1&&E(h,y[g])))l.push(t[g])}else for(g=0;y[g]!=null;g++)y[g]&&y[g].nodeType===1&&l.push(t[g]);else l.push.apply(l,y);else z(y,l);if(S){k(S,q,l,m);k.uniqueSort(l)}return l};k.uniqueSort=function(g){if(B){i=o;g.sort(B);if(i)for(var h=1;h<g.length;h++)g[h]===g[h-1]&&g.splice(h--,1)}return g};k.matches=function(g,h){return k(g,null,null,h)};k.find=function(g,h,l){var m,q;if(!g)return[];
|
||||
for(var p=0,v=n.order.length;p<v;p++){var t=n.order[p];if(q=n.leftMatch[t].exec(g)){var y=q[1];q.splice(1,1);if(y.substr(y.length-1)!=="\\"){q[1]=(q[1]||"").replace(/\\/g,"");m=n.find[t](q,h,l);if(m!=null){g=g.replace(n.match[t],"");break}}}}m||(m=h.getElementsByTagName("*"));return{set:m,expr:g}};k.filter=function(g,h,l,m){for(var q=g,p=[],v=h,t,y,S=h&&h[0]&&x(h[0]);g&&h.length;){for(var H in n.filter)if((t=n.leftMatch[H].exec(g))!=null&&t[2]){var M=n.filter[H],I,D;D=t[1];y=false;t.splice(1,1);if(D.substr(D.length-
|
||||
1)!=="\\"){if(v===p)p=[];if(n.preFilter[H])if(t=n.preFilter[H](t,v,l,p,m,S)){if(t===true)continue}else y=I=true;if(t)for(var U=0;(D=v[U])!=null;U++)if(D){I=M(D,t,U,v);var Ha=m^!!I;if(l&&I!=null)if(Ha)y=true;else v[U]=false;else if(Ha){p.push(D);y=true}}if(I!==w){l||(v=p);g=g.replace(n.match[H],"");if(!y)return[];break}}}if(g===q)if(y==null)k.error(g);else break;q=g}return v};k.error=function(g){throw"Syntax error, unrecognized expression: "+g;};var n=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF-]|\\.)+)/,
|
||||
CLASS:/\.((?:[\w\u00c0-\uFFFF-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(g){return g.getAttribute("href")}},
|
||||
relative:{"+":function(g,h){var l=typeof h==="string",m=l&&!/\W/.test(h);l=l&&!m;if(m)h=h.toLowerCase();m=0;for(var q=g.length,p;m<q;m++)if(p=g[m]){for(;(p=p.previousSibling)&&p.nodeType!==1;);g[m]=l||p&&p.nodeName.toLowerCase()===h?p||false:p===h}l&&k.filter(h,g,true)},">":function(g,h){var l=typeof h==="string";if(l&&!/\W/.test(h)){h=h.toLowerCase();for(var m=0,q=g.length;m<q;m++){var p=g[m];if(p){l=p.parentNode;g[m]=l.nodeName.toLowerCase()===h?l:false}}}else{m=0;for(q=g.length;m<q;m++)if(p=g[m])g[m]=
|
||||
l?p.parentNode:p.parentNode===h;l&&k.filter(h,g,true)}},"":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("parentNode",h,m,g,p,l)},"~":function(g,h,l){var m=e++,q=d;if(typeof h==="string"&&!/\W/.test(h)){var p=h=h.toLowerCase();q=b}q("previousSibling",h,m,g,p,l)}},find:{ID:function(g,h,l){if(typeof h.getElementById!=="undefined"&&!l)return(g=h.getElementById(g[1]))?[g]:[]},NAME:function(g,h){if(typeof h.getElementsByName!=="undefined"){var l=[];
|
||||
h=h.getElementsByName(g[1]);for(var m=0,q=h.length;m<q;m++)h[m].getAttribute("name")===g[1]&&l.push(h[m]);return l.length===0?null:l}},TAG:function(g,h){return h.getElementsByTagName(g[1])}},preFilter:{CLASS:function(g,h,l,m,q,p){g=" "+g[1].replace(/\\/g,"")+" ";if(p)return g;p=0;for(var v;(v=h[p])!=null;p++)if(v)if(q^(v.className&&(" "+v.className+" ").replace(/[\t\n]/g," ").indexOf(g)>=0))l||m.push(v);else if(l)h[p]=false;return false},ID:function(g){return g[1].replace(/\\/g,"")},TAG:function(g){return g[1].toLowerCase()},
|
||||
CHILD:function(g){if(g[1]==="nth"){var h=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(g[2]==="even"&&"2n"||g[2]==="odd"&&"2n+1"||!/\D/.test(g[2])&&"0n+"+g[2]||g[2]);g[2]=h[1]+(h[2]||1)-0;g[3]=h[3]-0}g[0]=e++;return g},ATTR:function(g,h,l,m,q,p){h=g[1].replace(/\\/g,"");if(!p&&n.attrMap[h])g[1]=n.attrMap[h];if(g[2]==="~=")g[4]=" "+g[4]+" ";return g},PSEUDO:function(g,h,l,m,q){if(g[1]==="not")if((f.exec(g[3])||"").length>1||/^\w/.test(g[3]))g[3]=k(g[3],null,null,h);else{g=k.filter(g[3],h,l,true^q);l||m.push.apply(m,
|
||||
g);return false}else if(n.match.POS.test(g[0])||n.match.CHILD.test(g[0]))return true;return g},POS:function(g){g.unshift(true);return g}},filters:{enabled:function(g){return g.disabled===false&&g.type!=="hidden"},disabled:function(g){return g.disabled===true},checked:function(g){return g.checked===true},selected:function(g){return g.selected===true},parent:function(g){return!!g.firstChild},empty:function(g){return!g.firstChild},has:function(g,h,l){return!!k(l[3],g).length},header:function(g){return/h\d/i.test(g.nodeName)},
|
||||
text:function(g){return"text"===g.type},radio:function(g){return"radio"===g.type},checkbox:function(g){return"checkbox"===g.type},file:function(g){return"file"===g.type},password:function(g){return"password"===g.type},submit:function(g){return"submit"===g.type},image:function(g){return"image"===g.type},reset:function(g){return"reset"===g.type},button:function(g){return"button"===g.type||g.nodeName.toLowerCase()==="button"},input:function(g){return/input|select|textarea|button/i.test(g.nodeName)}},
|
||||
setFilters:{first:function(g,h){return h===0},last:function(g,h,l,m){return h===m.length-1},even:function(g,h){return h%2===0},odd:function(g,h){return h%2===1},lt:function(g,h,l){return h<l[3]-0},gt:function(g,h,l){return h>l[3]-0},nth:function(g,h,l){return l[3]-0===h},eq:function(g,h,l){return l[3]-0===h}},filter:{PSEUDO:function(g,h,l,m){var q=h[1],p=n.filters[q];if(p)return p(g,l,h,m);else if(q==="contains")return(g.textContent||g.innerText||a([g])||"").indexOf(h[3])>=0;else if(q==="not"){h=
|
||||
h[3];l=0;for(m=h.length;l<m;l++)if(h[l]===g)return false;return true}else k.error("Syntax error, unrecognized expression: "+q)},CHILD:function(g,h){var l=h[1],m=g;switch(l){case "only":case "first":for(;m=m.previousSibling;)if(m.nodeType===1)return false;if(l==="first")return true;m=g;case "last":for(;m=m.nextSibling;)if(m.nodeType===1)return false;return true;case "nth":l=h[2];var q=h[3];if(l===1&&q===0)return true;h=h[0];var p=g.parentNode;if(p&&(p.sizcache!==h||!g.nodeIndex)){var v=0;for(m=p.firstChild;m;m=
|
||||
m.nextSibling)if(m.nodeType===1)m.nodeIndex=++v;p.sizcache=h}g=g.nodeIndex-q;return l===0?g===0:g%l===0&&g/l>=0}},ID:function(g,h){return g.nodeType===1&&g.getAttribute("id")===h},TAG:function(g,h){return h==="*"&&g.nodeType===1||g.nodeName.toLowerCase()===h},CLASS:function(g,h){return(" "+(g.className||g.getAttribute("class"))+" ").indexOf(h)>-1},ATTR:function(g,h){var l=h[1];g=n.attrHandle[l]?n.attrHandle[l](g):g[l]!=null?g[l]:g.getAttribute(l);l=g+"";var m=h[2];h=h[4];return g==null?m==="!=":m===
|
||||
"="?l===h:m==="*="?l.indexOf(h)>=0:m==="~="?(" "+l+" ").indexOf(h)>=0:!h?l&&g!==false:m==="!="?l!==h:m==="^="?l.indexOf(h)===0:m==="$="?l.substr(l.length-h.length)===h:m==="|="?l===h||l.substr(0,h.length+1)===h+"-":false},POS:function(g,h,l,m){var q=n.setFilters[h[2]];if(q)return q(g,l,h,m)}}},r=n.match.POS;for(var u in n.match){n.match[u]=new RegExp(n.match[u].source+/(?![^\[]*\])(?![^\(]*\))/.source);n.leftMatch[u]=new RegExp(/(^(?:.|\r|\n)*?)/.source+n.match[u].source.replace(/\\(\d+)/g,function(g,
|
||||
h){return"\\"+(h-0+1)}))}var z=function(g,h){g=Array.prototype.slice.call(g,0);if(h){h.push.apply(h,g);return h}return g};try{Array.prototype.slice.call(s.documentElement.childNodes,0)}catch(C){z=function(g,h){h=h||[];if(j.call(g)==="[object Array]")Array.prototype.push.apply(h,g);else if(typeof g.length==="number")for(var l=0,m=g.length;l<m;l++)h.push(g[l]);else for(l=0;g[l];l++)h.push(g[l]);return h}}var B;if(s.documentElement.compareDocumentPosition)B=function(g,h){if(!g.compareDocumentPosition||
|
||||
!h.compareDocumentPosition){if(g==h)i=true;return g.compareDocumentPosition?-1:1}g=g.compareDocumentPosition(h)&4?-1:g===h?0:1;if(g===0)i=true;return g};else if("sourceIndex"in s.documentElement)B=function(g,h){if(!g.sourceIndex||!h.sourceIndex){if(g==h)i=true;return g.sourceIndex?-1:1}g=g.sourceIndex-h.sourceIndex;if(g===0)i=true;return g};else if(s.createRange)B=function(g,h){if(!g.ownerDocument||!h.ownerDocument){if(g==h)i=true;return g.ownerDocument?-1:1}var l=g.ownerDocument.createRange(),m=
|
||||
h.ownerDocument.createRange();l.setStart(g,0);l.setEnd(g,0);m.setStart(h,0);m.setEnd(h,0);g=l.compareBoundaryPoints(Range.START_TO_END,m);if(g===0)i=true;return g};(function(){var g=s.createElement("div"),h="script"+(new Date).getTime();g.innerHTML="<a name='"+h+"'/>";var l=s.documentElement;l.insertBefore(g,l.firstChild);if(s.getElementById(h)){n.find.ID=function(m,q,p){if(typeof q.getElementById!=="undefined"&&!p)return(q=q.getElementById(m[1]))?q.id===m[1]||typeof q.getAttributeNode!=="undefined"&&
|
||||
q.getAttributeNode("id").nodeValue===m[1]?[q]:w:[]};n.filter.ID=function(m,q){var p=typeof m.getAttributeNode!=="undefined"&&m.getAttributeNode("id");return m.nodeType===1&&p&&p.nodeValue===q}}l.removeChild(g);l=g=null})();(function(){var g=s.createElement("div");g.appendChild(s.createComment(""));if(g.getElementsByTagName("*").length>0)n.find.TAG=function(h,l){l=l.getElementsByTagName(h[1]);if(h[1]==="*"){h=[];for(var m=0;l[m];m++)l[m].nodeType===1&&h.push(l[m]);l=h}return l};g.innerHTML="<a href='#'></a>";
|
||||
if(g.firstChild&&typeof g.firstChild.getAttribute!=="undefined"&&g.firstChild.getAttribute("href")!=="#")n.attrHandle.href=function(h){return h.getAttribute("href",2)};g=null})();s.querySelectorAll&&function(){var g=k,h=s.createElement("div");h.innerHTML="<p class='TEST'></p>";if(!(h.querySelectorAll&&h.querySelectorAll(".TEST").length===0)){k=function(m,q,p,v){q=q||s;if(!v&&q.nodeType===9&&!x(q))try{return z(q.querySelectorAll(m),p)}catch(t){}return g(m,q,p,v)};for(var l in g)k[l]=g[l];h=null}}();
|
||||
(function(){var g=s.createElement("div");g.innerHTML="<div class='test e'></div><div class='test'></div>";if(!(!g.getElementsByClassName||g.getElementsByClassName("e").length===0)){g.lastChild.className="e";if(g.getElementsByClassName("e").length!==1){n.order.splice(1,0,"CLASS");n.find.CLASS=function(h,l,m){if(typeof l.getElementsByClassName!=="undefined"&&!m)return l.getElementsByClassName(h[1])};g=null}}})();var E=s.compareDocumentPosition?function(g,h){return!!(g.compareDocumentPosition(h)&16)}:
|
||||
function(g,h){return g!==h&&(g.contains?g.contains(h):true)},x=function(g){return(g=(g?g.ownerDocument||g:0).documentElement)?g.nodeName!=="HTML":false},ga=function(g,h){var l=[],m="",q;for(h=h.nodeType?[h]:h;q=n.match.PSEUDO.exec(g);){m+=q[0];g=g.replace(n.match.PSEUDO,"")}g=n.relative[g]?g+"*":g;q=0;for(var p=h.length;q<p;q++)k(g,h[q],l);return k.filter(m,l)};c.find=k;c.expr=k.selectors;c.expr[":"]=c.expr.filters;c.unique=k.uniqueSort;c.text=a;c.isXMLDoc=x;c.contains=E})();var eb=/Until$/,fb=/^(?:parents|prevUntil|prevAll)/,
|
||||
gb=/,/;R=Array.prototype.slice;var Ia=function(a,b,d){if(c.isFunction(b))return c.grep(a,function(e,j){return!!b.call(e,j,e)===d});else if(b.nodeType)return c.grep(a,function(e){return e===b===d});else if(typeof b==="string"){var f=c.grep(a,function(e){return e.nodeType===1});if(Ua.test(b))return c.filter(b,f,!d);else b=c.filter(b,f)}return c.grep(a,function(e){return c.inArray(e,b)>=0===d})};c.fn.extend({find:function(a){for(var b=this.pushStack("","find",a),d=0,f=0,e=this.length;f<e;f++){d=b.length;
|
||||
c.find(a,this[f],b);if(f>0)for(var j=d;j<b.length;j++)for(var i=0;i<d;i++)if(b[i]===b[j]){b.splice(j--,1);break}}return b},has:function(a){var b=c(a);return this.filter(function(){for(var d=0,f=b.length;d<f;d++)if(c.contains(this,b[d]))return true})},not:function(a){return this.pushStack(Ia(this,a,false),"not",a)},filter:function(a){return this.pushStack(Ia(this,a,true),"filter",a)},is:function(a){return!!a&&c.filter(a,this).length>0},closest:function(a,b){if(c.isArray(a)){var d=[],f=this[0],e,j=
|
||||
{},i;if(f&&a.length){e=0;for(var o=a.length;e<o;e++){i=a[e];j[i]||(j[i]=c.expr.match.POS.test(i)?c(i,b||this.context):i)}for(;f&&f.ownerDocument&&f!==b;){for(i in j){e=j[i];if(e.jquery?e.index(f)>-1:c(f).is(e)){d.push({selector:i,elem:f});delete j[i]}}f=f.parentNode}}return d}var k=c.expr.match.POS.test(a)?c(a,b||this.context):null;return this.map(function(n,r){for(;r&&r.ownerDocument&&r!==b;){if(k?k.index(r)>-1:c(r).is(a))return r;r=r.parentNode}return null})},index:function(a){if(!a||typeof a===
|
||||
"string")return c.inArray(this[0],a?c(a):this.parent().children());return c.inArray(a.jquery?a[0]:a,this)},add:function(a,b){a=typeof a==="string"?c(a,b||this.context):c.makeArray(a);b=c.merge(this.get(),a);return this.pushStack(qa(a[0])||qa(b[0])?b:c.unique(b))},andSelf:function(){return this.add(this.prevObject)}});c.each({parent:function(a){return(a=a.parentNode)&&a.nodeType!==11?a:null},parents:function(a){return c.dir(a,"parentNode")},parentsUntil:function(a,b,d){return c.dir(a,"parentNode",
|
||||
d)},next:function(a){return c.nth(a,2,"nextSibling")},prev:function(a){return c.nth(a,2,"previousSibling")},nextAll:function(a){return c.dir(a,"nextSibling")},prevAll:function(a){return c.dir(a,"previousSibling")},nextUntil:function(a,b,d){return c.dir(a,"nextSibling",d)},prevUntil:function(a,b,d){return c.dir(a,"previousSibling",d)},siblings:function(a){return c.sibling(a.parentNode.firstChild,a)},children:function(a){return c.sibling(a.firstChild)},contents:function(a){return c.nodeName(a,"iframe")?
|
||||
a.contentDocument||a.contentWindow.document:c.makeArray(a.childNodes)}},function(a,b){c.fn[a]=function(d,f){var e=c.map(this,b,d);eb.test(a)||(f=d);if(f&&typeof f==="string")e=c.filter(f,e);e=this.length>1?c.unique(e):e;if((this.length>1||gb.test(f))&&fb.test(a))e=e.reverse();return this.pushStack(e,a,R.call(arguments).join(","))}});c.extend({filter:function(a,b,d){if(d)a=":not("+a+")";return c.find.matches(a,b)},dir:function(a,b,d){var f=[];for(a=a[b];a&&a.nodeType!==9&&(d===w||a.nodeType!==1||!c(a).is(d));){a.nodeType===
|
||||
1&&f.push(a);a=a[b]}return f},nth:function(a,b,d){b=b||1;for(var f=0;a;a=a[d])if(a.nodeType===1&&++f===b)break;return a},sibling:function(a,b){for(var d=[];a;a=a.nextSibling)a.nodeType===1&&a!==b&&d.push(a);return d}});var Ja=/ jQuery\d+="(?:\d+|null)"/g,V=/^\s+/,Ka=/(<([\w:]+)[^>]*?)\/>/g,hb=/^(?:area|br|col|embed|hr|img|input|link|meta|param)$/i,La=/<([\w:]+)/,ib=/<tbody/i,jb=/<|&#?\w+;/,ta=/<script|<object|<embed|<option|<style/i,ua=/checked\s*(?:[^=]|=\s*.checked.)/i,Ma=function(a,b,d){return hb.test(d)?
|
||||
a:b+"></"+d+">"},F={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};F.optgroup=F.option;F.tbody=F.tfoot=F.colgroup=F.caption=F.thead;F.th=F.td;if(!c.support.htmlSerialize)F._default=[1,"div<div>","</div>"];c.fn.extend({text:function(a){if(c.isFunction(a))return this.each(function(b){var d=
|
||||
c(this);d.text(a.call(this,b,d.text()))});if(typeof a!=="object"&&a!==w)return this.empty().append((this[0]&&this[0].ownerDocument||s).createTextNode(a));return c.text(this)},wrapAll:function(a){if(c.isFunction(a))return this.each(function(d){c(this).wrapAll(a.call(this,d))});if(this[0]){var b=c(a,this[0].ownerDocument).eq(0).clone(true);this[0].parentNode&&b.insertBefore(this[0]);b.map(function(){for(var d=this;d.firstChild&&d.firstChild.nodeType===1;)d=d.firstChild;return d}).append(this)}return this},
|
||||
wrapInner:function(a){if(c.isFunction(a))return this.each(function(b){c(this).wrapInner(a.call(this,b))});return this.each(function(){var b=c(this),d=b.contents();d.length?d.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){c(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){c.nodeName(this,"body")||c(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.appendChild(a)})},
|
||||
prepend:function(){return this.domManip(arguments,true,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,this)});else if(arguments.length){var a=c(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,false,function(b){this.parentNode.insertBefore(b,
|
||||
this.nextSibling)});else if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,c(arguments[0]).toArray());return a}},remove:function(a,b){for(var d=0,f;(f=this[d])!=null;d++)if(!a||c.filter(a,[f]).length){if(!b&&f.nodeType===1){c.cleanData(f.getElementsByTagName("*"));c.cleanData([f])}f.parentNode&&f.parentNode.removeChild(f)}return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++)for(b.nodeType===1&&c.cleanData(b.getElementsByTagName("*"));b.firstChild;)b.removeChild(b.firstChild);
|
||||
return this},clone:function(a){var b=this.map(function(){if(!c.support.noCloneEvent&&!c.isXMLDoc(this)){var d=this.outerHTML,f=this.ownerDocument;if(!d){d=f.createElement("div");d.appendChild(this.cloneNode(true));d=d.innerHTML}return c.clean([d.replace(Ja,"").replace(/=([^="'>\s]+\/)>/g,'="$1">').replace(V,"")],f)[0]}else return this.cloneNode(true)});if(a===true){ra(this,b);ra(this.find("*"),b.find("*"))}return b},html:function(a){if(a===w)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(Ja,
|
||||
""):null;else if(typeof a==="string"&&!ta.test(a)&&(c.support.leadingWhitespace||!V.test(a))&&!F[(La.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Ka,Ma);try{for(var b=0,d=this.length;b<d;b++)if(this[b].nodeType===1){c.cleanData(this[b].getElementsByTagName("*"));this[b].innerHTML=a}}catch(f){this.empty().append(a)}}else c.isFunction(a)?this.each(function(e){var j=c(this),i=j.html();j.empty().append(function(){return a.call(this,e,i)})}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&
|
||||
this[0].parentNode){if(c.isFunction(a))return this.each(function(b){var d=c(this),f=d.html();d.replaceWith(a.call(this,b,f))});if(typeof a!=="string")a=c(a).detach();return this.each(function(){var b=this.nextSibling,d=this.parentNode;c(this).remove();b?c(b).before(a):c(d).append(a)})}else return this.pushStack(c(c.isFunction(a)?a():a),"replaceWith",a)},detach:function(a){return this.remove(a,true)},domManip:function(a,b,d){function f(u){return c.nodeName(u,"table")?u.getElementsByTagName("tbody")[0]||
|
||||
u.appendChild(u.ownerDocument.createElement("tbody")):u}var e,j,i=a[0],o=[],k;if(!c.support.checkClone&&arguments.length===3&&typeof i==="string"&&ua.test(i))return this.each(function(){c(this).domManip(a,b,d,true)});if(c.isFunction(i))return this.each(function(u){var z=c(this);a[0]=i.call(this,u,b?z.html():w);z.domManip(a,b,d)});if(this[0]){e=i&&i.parentNode;e=c.support.parentNode&&e&&e.nodeType===11&&e.childNodes.length===this.length?{fragment:e}:sa(a,this,o);k=e.fragment;if(j=k.childNodes.length===
|
||||
1?(k=k.firstChild):k.firstChild){b=b&&c.nodeName(j,"tr");for(var n=0,r=this.length;n<r;n++)d.call(b?f(this[n],j):this[n],n>0||e.cacheable||this.length>1?k.cloneNode(true):k)}o.length&&c.each(o,Qa)}return this}});c.fragments={};c.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){c.fn[a]=function(d){var f=[];d=c(d);var e=this.length===1&&this[0].parentNode;if(e&&e.nodeType===11&&e.childNodes.length===1&&d.length===1){d[b](this[0]);
|
||||
return this}else{e=0;for(var j=d.length;e<j;e++){var i=(e>0?this.clone(true):this).get();c.fn[b].apply(c(d[e]),i);f=f.concat(i)}return this.pushStack(f,a,d.selector)}}});c.extend({clean:function(a,b,d,f){b=b||s;if(typeof b.createElement==="undefined")b=b.ownerDocument||b[0]&&b[0].ownerDocument||s;for(var e=[],j=0,i;(i=a[j])!=null;j++){if(typeof i==="number")i+="";if(i){if(typeof i==="string"&&!jb.test(i))i=b.createTextNode(i);else if(typeof i==="string"){i=i.replace(Ka,Ma);var o=(La.exec(i)||["",
|
||||
""])[1].toLowerCase(),k=F[o]||F._default,n=k[0],r=b.createElement("div");for(r.innerHTML=k[1]+i+k[2];n--;)r=r.lastChild;if(!c.support.tbody){n=ib.test(i);o=o==="table"&&!n?r.firstChild&&r.firstChild.childNodes:k[1]==="<table>"&&!n?r.childNodes:[];for(k=o.length-1;k>=0;--k)c.nodeName(o[k],"tbody")&&!o[k].childNodes.length&&o[k].parentNode.removeChild(o[k])}!c.support.leadingWhitespace&&V.test(i)&&r.insertBefore(b.createTextNode(V.exec(i)[0]),r.firstChild);i=r.childNodes}if(i.nodeType)e.push(i);else e=
|
||||
c.merge(e,i)}}if(d)for(j=0;e[j];j++)if(f&&c.nodeName(e[j],"script")&&(!e[j].type||e[j].type.toLowerCase()==="text/javascript"))f.push(e[j].parentNode?e[j].parentNode.removeChild(e[j]):e[j]);else{e[j].nodeType===1&&e.splice.apply(e,[j+1,0].concat(c.makeArray(e[j].getElementsByTagName("script"))));d.appendChild(e[j])}return e},cleanData:function(a){for(var b,d,f=c.cache,e=c.event.special,j=c.support.deleteExpando,i=0,o;(o=a[i])!=null;i++)if(d=o[c.expando]){b=f[d];if(b.events)for(var k in b.events)e[k]?
|
||||
c.event.remove(o,k):Ca(o,k,b.handle);if(j)delete o[c.expando];else o.removeAttribute&&o.removeAttribute(c.expando);delete f[d]}}});var kb=/z-?index|font-?weight|opacity|zoom|line-?height/i,Na=/alpha\([^)]*\)/,Oa=/opacity=([^)]*)/,ha=/float/i,ia=/-([a-z])/ig,lb=/([A-Z])/g,mb=/^-?\d+(?:px)?$/i,nb=/^-?\d/,ob={position:"absolute",visibility:"hidden",display:"block"},pb=["Left","Right"],qb=["Top","Bottom"],rb=s.defaultView&&s.defaultView.getComputedStyle,Pa=c.support.cssFloat?"cssFloat":"styleFloat",ja=
|
||||
function(a,b){return b.toUpperCase()};c.fn.css=function(a,b){return X(this,a,b,true,function(d,f,e){if(e===w)return c.curCSS(d,f);if(typeof e==="number"&&!kb.test(f))e+="px";c.style(d,f,e)})};c.extend({style:function(a,b,d){if(!a||a.nodeType===3||a.nodeType===8)return w;if((b==="width"||b==="height")&&parseFloat(d)<0)d=w;var f=a.style||a,e=d!==w;if(!c.support.opacity&&b==="opacity"){if(e){f.zoom=1;b=parseInt(d,10)+""==="NaN"?"":"alpha(opacity="+d*100+")";a=f.filter||c.curCSS(a,"filter")||"";f.filter=
|
||||
Na.test(a)?a.replace(Na,b):b}return f.filter&&f.filter.indexOf("opacity=")>=0?parseFloat(Oa.exec(f.filter)[1])/100+"":""}if(ha.test(b))b=Pa;b=b.replace(ia,ja);if(e)f[b]=d;return f[b]},css:function(a,b,d,f){if(b==="width"||b==="height"){var e,j=b==="width"?pb:qb;function i(){e=b==="width"?a.offsetWidth:a.offsetHeight;f!=="border"&&c.each(j,function(){f||(e-=parseFloat(c.curCSS(a,"padding"+this,true))||0);if(f==="margin")e+=parseFloat(c.curCSS(a,"margin"+this,true))||0;else e-=parseFloat(c.curCSS(a,
|
||||
"border"+this+"Width",true))||0})}a.offsetWidth!==0?i():c.swap(a,ob,i);return Math.max(0,Math.round(e))}return c.curCSS(a,b,d)},curCSS:function(a,b,d){var f,e=a.style;if(!c.support.opacity&&b==="opacity"&&a.currentStyle){f=Oa.test(a.currentStyle.filter||"")?parseFloat(RegExp.$1)/100+"":"";return f===""?"1":f}if(ha.test(b))b=Pa;if(!d&&e&&e[b])f=e[b];else if(rb){if(ha.test(b))b="float";b=b.replace(lb,"-$1").toLowerCase();e=a.ownerDocument.defaultView;if(!e)return null;if(a=e.getComputedStyle(a,null))f=
|
||||
a.getPropertyValue(b);if(b==="opacity"&&f==="")f="1"}else if(a.currentStyle){d=b.replace(ia,ja);f=a.currentStyle[b]||a.currentStyle[d];if(!mb.test(f)&&nb.test(f)){b=e.left;var j=a.runtimeStyle.left;a.runtimeStyle.left=a.currentStyle.left;e.left=d==="fontSize"?"1em":f||0;f=e.pixelLeft+"px";e.left=b;a.runtimeStyle.left=j}}return f},swap:function(a,b,d){var f={};for(var e in b){f[e]=a.style[e];a.style[e]=b[e]}d.call(a);for(e in b)a.style[e]=f[e]}});if(c.expr&&c.expr.filters){c.expr.filters.hidden=function(a){var b=
|
||||
a.offsetWidth,d=a.offsetHeight,f=a.nodeName.toLowerCase()==="tr";return b===0&&d===0&&!f?true:b>0&&d>0&&!f?false:c.curCSS(a,"display")==="none"};c.expr.filters.visible=function(a){return!c.expr.filters.hidden(a)}}var sb=J(),tb=/<script(.|\s)*?\/script>/gi,ub=/select|textarea/i,vb=/color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week/i,N=/=\?(&|$)/,ka=/\?/,wb=/(\?|&)_=.*?(&|$)/,xb=/^(\w+:)?\/\/([^\/?#]+)/,yb=/%20/g,zb=c.fn.load;c.fn.extend({load:function(a,b,d){if(typeof a!==
|
||||
"string")return zb.call(this,a);else if(!this.length)return this;var f=a.indexOf(" ");if(f>=0){var e=a.slice(f,a.length);a=a.slice(0,f)}f="GET";if(b)if(c.isFunction(b)){d=b;b=null}else if(typeof b==="object"){b=c.param(b,c.ajaxSettings.traditional);f="POST"}var j=this;c.ajax({url:a,type:f,dataType:"html",data:b,complete:function(i,o){if(o==="success"||o==="notmodified")j.html(e?c("<div />").append(i.responseText.replace(tb,"")).find(e):i.responseText);d&&j.each(d,[i.responseText,o,i])}});return this},
|
||||
serialize:function(){return c.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?c.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||ub.test(this.nodeName)||vb.test(this.type))}).map(function(a,b){a=c(this).val();return a==null?null:c.isArray(a)?c.map(a,function(d){return{name:b.name,value:d}}):{name:b.name,value:a}}).get()}});c.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),
|
||||
function(a,b){c.fn[b]=function(d){return this.bind(b,d)}});c.extend({get:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b=null}return c.ajax({type:"GET",url:a,data:b,success:d,dataType:f})},getScript:function(a,b){return c.get(a,null,b,"script")},getJSON:function(a,b,d){return c.get(a,b,d,"json")},post:function(a,b,d,f){if(c.isFunction(b)){f=f||d;d=b;b={}}return c.ajax({type:"POST",url:a,data:b,success:d,dataType:f})},ajaxSetup:function(a){c.extend(c.ajaxSettings,a)},ajaxSettings:{url:location.href,
|
||||
global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:A.XMLHttpRequest&&(A.location.protocol!=="file:"||!A.ActiveXObject)?function(){return new A.XMLHttpRequest}:function(){try{return new A.ActiveXObject("Microsoft.XMLHTTP")}catch(a){}},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},etag:{},ajax:function(a){function b(){e.success&&
|
||||
e.success.call(k,o,i,x);e.global&&f("ajaxSuccess",[x,e])}function d(){e.complete&&e.complete.call(k,x,i);e.global&&f("ajaxComplete",[x,e]);e.global&&!--c.active&&c.event.trigger("ajaxStop")}function f(q,p){(e.context?c(e.context):c.event).trigger(q,p)}var e=c.extend(true,{},c.ajaxSettings,a),j,i,o,k=a&&a.context||e,n=e.type.toUpperCase();if(e.data&&e.processData&&typeof e.data!=="string")e.data=c.param(e.data,e.traditional);if(e.dataType==="jsonp"){if(n==="GET")N.test(e.url)||(e.url+=(ka.test(e.url)?
|
||||
"&":"?")+(e.jsonp||"callback")+"=?");else if(!e.data||!N.test(e.data))e.data=(e.data?e.data+"&":"")+(e.jsonp||"callback")+"=?";e.dataType="json"}if(e.dataType==="json"&&(e.data&&N.test(e.data)||N.test(e.url))){j=e.jsonpCallback||"jsonp"+sb++;if(e.data)e.data=(e.data+"").replace(N,"="+j+"$1");e.url=e.url.replace(N,"="+j+"$1");e.dataType="script";A[j]=A[j]||function(q){o=q;b();d();A[j]=w;try{delete A[j]}catch(p){}z&&z.removeChild(C)}}if(e.dataType==="script"&&e.cache===null)e.cache=false;if(e.cache===
|
||||
false&&n==="GET"){var r=J(),u=e.url.replace(wb,"$1_="+r+"$2");e.url=u+(u===e.url?(ka.test(e.url)?"&":"?")+"_="+r:"")}if(e.data&&n==="GET")e.url+=(ka.test(e.url)?"&":"?")+e.data;e.global&&!c.active++&&c.event.trigger("ajaxStart");r=(r=xb.exec(e.url))&&(r[1]&&r[1]!==location.protocol||r[2]!==location.host);if(e.dataType==="script"&&n==="GET"&&r){var z=s.getElementsByTagName("head")[0]||s.documentElement,C=s.createElement("script");C.src=e.url;if(e.scriptCharset)C.charset=e.scriptCharset;if(!j){var B=
|
||||
false;C.onload=C.onreadystatechange=function(){if(!B&&(!this.readyState||this.readyState==="loaded"||this.readyState==="complete")){B=true;b();d();C.onload=C.onreadystatechange=null;z&&C.parentNode&&z.removeChild(C)}}}z.insertBefore(C,z.firstChild);return w}var E=false,x=e.xhr();if(x){e.username?x.open(n,e.url,e.async,e.username,e.password):x.open(n,e.url,e.async);try{if(e.data||a&&a.contentType)x.setRequestHeader("Content-Type",e.contentType);if(e.ifModified){c.lastModified[e.url]&&x.setRequestHeader("If-Modified-Since",
|
||||
c.lastModified[e.url]);c.etag[e.url]&&x.setRequestHeader("If-None-Match",c.etag[e.url])}r||x.setRequestHeader("X-Requested-With","XMLHttpRequest");x.setRequestHeader("Accept",e.dataType&&e.accepts[e.dataType]?e.accepts[e.dataType]+", */*":e.accepts._default)}catch(ga){}if(e.beforeSend&&e.beforeSend.call(k,x,e)===false){e.global&&!--c.active&&c.event.trigger("ajaxStop");x.abort();return false}e.global&&f("ajaxSend",[x,e]);var g=x.onreadystatechange=function(q){if(!x||x.readyState===0||q==="abort"){E||
|
||||
d();E=true;if(x)x.onreadystatechange=c.noop}else if(!E&&x&&(x.readyState===4||q==="timeout")){E=true;x.onreadystatechange=c.noop;i=q==="timeout"?"timeout":!c.httpSuccess(x)?"error":e.ifModified&&c.httpNotModified(x,e.url)?"notmodified":"success";var p;if(i==="success")try{o=c.httpData(x,e.dataType,e)}catch(v){i="parsererror";p=v}if(i==="success"||i==="notmodified")j||b();else c.handleError(e,x,i,p);d();q==="timeout"&&x.abort();if(e.async)x=null}};try{var h=x.abort;x.abort=function(){x&&h.call(x);
|
||||
g("abort")}}catch(l){}e.async&&e.timeout>0&&setTimeout(function(){x&&!E&&g("timeout")},e.timeout);try{x.send(n==="POST"||n==="PUT"||n==="DELETE"?e.data:null)}catch(m){c.handleError(e,x,null,m);d()}e.async||g();return x}},handleError:function(a,b,d,f){if(a.error)a.error.call(a.context||a,b,d,f);if(a.global)(a.context?c(a.context):c.event).trigger("ajaxError",[b,a,f])},active:0,httpSuccess:function(a){try{return!a.status&&location.protocol==="file:"||a.status>=200&&a.status<300||a.status===304||a.status===
|
||||
1223||a.status===0}catch(b){}return false},httpNotModified:function(a,b){var d=a.getResponseHeader("Last-Modified"),f=a.getResponseHeader("Etag");if(d)c.lastModified[b]=d;if(f)c.etag[b]=f;return a.status===304||a.status===0},httpData:function(a,b,d){var f=a.getResponseHeader("content-type")||"",e=b==="xml"||!b&&f.indexOf("xml")>=0;a=e?a.responseXML:a.responseText;e&&a.documentElement.nodeName==="parsererror"&&c.error("parsererror");if(d&&d.dataFilter)a=d.dataFilter(a,b);if(typeof a==="string")if(b===
|
||||
"json"||!b&&f.indexOf("json")>=0)a=c.parseJSON(a);else if(b==="script"||!b&&f.indexOf("javascript")>=0)c.globalEval(a);return a},param:function(a,b){function d(i,o){if(c.isArray(o))c.each(o,function(k,n){b||/\[\]$/.test(i)?f(i,n):d(i+"["+(typeof n==="object"||c.isArray(n)?k:"")+"]",n)});else!b&&o!=null&&typeof o==="object"?c.each(o,function(k,n){d(i+"["+k+"]",n)}):f(i,o)}function f(i,o){o=c.isFunction(o)?o():o;e[e.length]=encodeURIComponent(i)+"="+encodeURIComponent(o)}var e=[];if(b===w)b=c.ajaxSettings.traditional;
|
||||
if(c.isArray(a)||a.jquery)c.each(a,function(){f(this.name,this.value)});else for(var j in a)d(j,a[j]);return e.join("&").replace(yb,"+")}});var la={},Ab=/toggle|show|hide/,Bb=/^([+-]=)?([\d+-.]+)(.*)$/,W,va=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];c.fn.extend({show:function(a,b){if(a||a===0)return this.animate(K("show",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");
|
||||
this[a].style.display=d||"";if(c.css(this[a],"display")==="none"){d=this[a].nodeName;var f;if(la[d])f=la[d];else{var e=c("<"+d+" />").appendTo("body");f=e.css("display");if(f==="none")f="block";e.remove();la[d]=f}c.data(this[a],"olddisplay",f)}}a=0;for(b=this.length;a<b;a++)this[a].style.display=c.data(this[a],"olddisplay")||"";return this}},hide:function(a,b){if(a||a===0)return this.animate(K("hide",3),a,b);else{a=0;for(b=this.length;a<b;a++){var d=c.data(this[a],"olddisplay");!d&&d!=="none"&&c.data(this[a],
|
||||
"olddisplay",c.css(this[a],"display"))}a=0;for(b=this.length;a<b;a++)this[a].style.display="none";return this}},_toggle:c.fn.toggle,toggle:function(a,b){var d=typeof a==="boolean";if(c.isFunction(a)&&c.isFunction(b))this._toggle.apply(this,arguments);else a==null||d?this.each(function(){var f=d?a:c(this).is(":hidden");c(this)[f?"show":"hide"]()}):this.animate(K("toggle",3),a,b);return this},fadeTo:function(a,b,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,d)},
|
||||
animate:function(a,b,d,f){var e=c.speed(b,d,f);if(c.isEmptyObject(a))return this.each(e.complete);return this[e.queue===false?"each":"queue"](function(){var j=c.extend({},e),i,o=this.nodeType===1&&c(this).is(":hidden"),k=this;for(i in a){var n=i.replace(ia,ja);if(i!==n){a[n]=a[i];delete a[i];i=n}if(a[i]==="hide"&&o||a[i]==="show"&&!o)return j.complete.call(this);if((i==="height"||i==="width")&&this.style){j.display=c.css(this,"display");j.overflow=this.style.overflow}if(c.isArray(a[i])){(j.specialEasing=
|
||||
j.specialEasing||{})[i]=a[i][1];a[i]=a[i][0]}}if(j.overflow!=null)this.style.overflow="hidden";j.curAnim=c.extend({},a);c.each(a,function(r,u){var z=new c.fx(k,j,r);if(Ab.test(u))z[u==="toggle"?o?"show":"hide":u](a);else{var C=Bb.exec(u),B=z.cur(true)||0;if(C){u=parseFloat(C[2]);var E=C[3]||"px";if(E!=="px"){k.style[r]=(u||1)+E;B=(u||1)/z.cur(true)*B;k.style[r]=B+E}if(C[1])u=(C[1]==="-="?-1:1)*u+B;z.custom(B,u,E)}else z.custom(B,u,"")}});return true})},stop:function(a,b){var d=c.timers;a&&this.queue([]);
|
||||
this.each(function(){for(var f=d.length-1;f>=0;f--)if(d[f].elem===this){b&&d[f](true);d.splice(f,1)}});b||this.dequeue();return this}});c.each({slideDown:K("show",1),slideUp:K("hide",1),slideToggle:K("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(a,b){c.fn[a]=function(d,f){return this.animate(b,d,f)}});c.extend({speed:function(a,b,d){var f=a&&typeof a==="object"?a:{complete:d||!d&&b||c.isFunction(a)&&a,duration:a,easing:d&&b||b&&!c.isFunction(b)&&b};f.duration=c.fx.off?0:typeof f.duration===
|
||||
"number"?f.duration:c.fx.speeds[f.duration]||c.fx.speeds._default;f.old=f.complete;f.complete=function(){f.queue!==false&&c(this).dequeue();c.isFunction(f.old)&&f.old.call(this)};return f},easing:{linear:function(a,b,d,f){return d+f*a},swing:function(a,b,d,f){return(-Math.cos(a*Math.PI)/2+0.5)*f+d}},timers:[],fx:function(a,b,d){this.options=b;this.elem=a;this.prop=d;if(!b.orig)b.orig={}}});c.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this);(c.fx.step[this.prop]||
|
||||
c.fx.step._default)(this);if((this.prop==="height"||this.prop==="width")&&this.elem.style)this.elem.style.display="block"},cur:function(a){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];return(a=parseFloat(c.css(this.elem,this.prop,a)))&&a>-10000?a:parseFloat(c.curCSS(this.elem,this.prop))||0},custom:function(a,b,d){function f(j){return e.step(j)}this.startTime=J();this.start=a;this.end=b;this.unit=d||this.unit||"px";this.now=this.start;
|
||||
this.pos=this.state=0;var e=this;f.elem=this.elem;if(f()&&c.timers.push(f)&&!W)W=setInterval(c.fx.tick,13)},show:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.show=true;this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur());c(this.elem).show()},hide:function(){this.options.orig[this.prop]=c.style(this.elem,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(a){var b=J(),d=true;if(a||b>=this.options.duration+this.startTime){this.now=
|
||||
this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;for(var f in this.options.curAnim)if(this.options.curAnim[f]!==true)d=false;if(d){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;a=c.data(this.elem,"olddisplay");this.elem.style.display=a?a:this.options.display;if(c.css(this.elem,"display")==="none")this.elem.style.display="block"}this.options.hide&&c(this.elem).hide();if(this.options.hide||this.options.show)for(var e in this.options.curAnim)c.style(this.elem,
|
||||
e,this.options.orig[e]);this.options.complete.call(this.elem)}return false}else{e=b-this.startTime;this.state=e/this.options.duration;a=this.options.easing||(c.easing.swing?"swing":"linear");this.pos=c.easing[this.options.specialEasing&&this.options.specialEasing[this.prop]||a](this.state,e,0,1,this.options.duration);this.now=this.start+(this.end-this.start)*this.pos;this.update()}return true}};c.extend(c.fx,{tick:function(){for(var a=c.timers,b=0;b<a.length;b++)a[b]()||a.splice(b--,1);a.length||
|
||||
c.fx.stop()},stop:function(){clearInterval(W);W=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){c.style(a.elem,"opacity",a.now)},_default:function(a){if(a.elem.style&&a.elem.style[a.prop]!=null)a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit;else a.elem[a.prop]=a.now}}});if(c.expr&&c.expr.filters)c.expr.filters.animated=function(a){return c.grep(c.timers,function(b){return a===b.elem}).length};c.fn.offset="getBoundingClientRect"in s.documentElement?
|
||||
function(a){var b=this[0];if(a)return this.each(function(e){c.offset.setOffset(this,a,e)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);var d=b.getBoundingClientRect(),f=b.ownerDocument;b=f.body;f=f.documentElement;return{top:d.top+(self.pageYOffset||c.support.boxModel&&f.scrollTop||b.scrollTop)-(f.clientTop||b.clientTop||0),left:d.left+(self.pageXOffset||c.support.boxModel&&f.scrollLeft||b.scrollLeft)-(f.clientLeft||b.clientLeft||0)}}:function(a){var b=
|
||||
this[0];if(a)return this.each(function(r){c.offset.setOffset(this,a,r)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return c.offset.bodyOffset(b);c.offset.initialize();var d=b.offsetParent,f=b,e=b.ownerDocument,j,i=e.documentElement,o=e.body;f=(e=e.defaultView)?e.getComputedStyle(b,null):b.currentStyle;for(var k=b.offsetTop,n=b.offsetLeft;(b=b.parentNode)&&b!==o&&b!==i;){if(c.offset.supportsFixedPosition&&f.position==="fixed")break;j=e?e.getComputedStyle(b,null):b.currentStyle;
|
||||
k-=b.scrollTop;n-=b.scrollLeft;if(b===d){k+=b.offsetTop;n+=b.offsetLeft;if(c.offset.doesNotAddBorder&&!(c.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(b.nodeName))){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=d;d=b.offsetParent}if(c.offset.subtractsBorderForOverflowNotVisible&&j.overflow!=="visible"){k+=parseFloat(j.borderTopWidth)||0;n+=parseFloat(j.borderLeftWidth)||0}f=j}if(f.position==="relative"||f.position==="static"){k+=o.offsetTop;n+=o.offsetLeft}if(c.offset.supportsFixedPosition&&
|
||||
f.position==="fixed"){k+=Math.max(i.scrollTop,o.scrollTop);n+=Math.max(i.scrollLeft,o.scrollLeft)}return{top:k,left:n}};c.offset={initialize:function(){var a=s.body,b=s.createElement("div"),d,f,e,j=parseFloat(c.curCSS(a,"marginTop",true))||0;c.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"});b.innerHTML="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
|
||||
a.insertBefore(b,a.firstChild);d=b.firstChild;f=d.firstChild;e=d.nextSibling.firstChild.firstChild;this.doesNotAddBorder=f.offsetTop!==5;this.doesAddBorderForTableAndCells=e.offsetTop===5;f.style.position="fixed";f.style.top="20px";this.supportsFixedPosition=f.offsetTop===20||f.offsetTop===15;f.style.position=f.style.top="";d.style.overflow="hidden";d.style.position="relative";this.subtractsBorderForOverflowNotVisible=f.offsetTop===-5;this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==j;a.removeChild(b);
|
||||
c.offset.initialize=c.noop},bodyOffset:function(a){var b=a.offsetTop,d=a.offsetLeft;c.offset.initialize();if(c.offset.doesNotIncludeMarginInBodyOffset){b+=parseFloat(c.curCSS(a,"marginTop",true))||0;d+=parseFloat(c.curCSS(a,"marginLeft",true))||0}return{top:b,left:d}},setOffset:function(a,b,d){if(/static/.test(c.curCSS(a,"position")))a.style.position="relative";var f=c(a),e=f.offset(),j=parseInt(c.curCSS(a,"top",true),10)||0,i=parseInt(c.curCSS(a,"left",true),10)||0;if(c.isFunction(b))b=b.call(a,
|
||||
d,e);d={top:b.top-e.top+j,left:b.left-e.left+i};"using"in b?b.using.call(a,d):f.css(d)}};c.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),d=this.offset(),f=/^body|html$/i.test(b[0].nodeName)?{top:0,left:0}:b.offset();d.top-=parseFloat(c.curCSS(a,"marginTop",true))||0;d.left-=parseFloat(c.curCSS(a,"marginLeft",true))||0;f.top+=parseFloat(c.curCSS(b[0],"borderTopWidth",true))||0;f.left+=parseFloat(c.curCSS(b[0],"borderLeftWidth",true))||0;return{top:d.top-
|
||||
f.top,left:d.left-f.left}},offsetParent:function(){return this.map(function(){for(var a=this.offsetParent||s.body;a&&!/^body|html$/i.test(a.nodeName)&&c.css(a,"position")==="static";)a=a.offsetParent;return a})}});c.each(["Left","Top"],function(a,b){var d="scroll"+b;c.fn[d]=function(f){var e=this[0],j;if(!e)return null;if(f!==w)return this.each(function(){if(j=wa(this))j.scrollTo(!a?f:c(j).scrollLeft(),a?f:c(j).scrollTop());else this[d]=f});else return(j=wa(e))?"pageXOffset"in j?j[a?"pageYOffset":
|
||||
"pageXOffset"]:c.support.boxModel&&j.document.documentElement[d]||j.document.body[d]:e[d]}});c.each(["Height","Width"],function(a,b){var d=b.toLowerCase();c.fn["inner"+b]=function(){return this[0]?c.css(this[0],d,false,"padding"):null};c.fn["outer"+b]=function(f){return this[0]?c.css(this[0],d,false,f?"margin":"border"):null};c.fn[d]=function(f){var e=this[0];if(!e)return f==null?null:this;if(c.isFunction(f))return this.each(function(j){var i=c(this);i[d](f.call(this,j,i[d]()))});return"scrollTo"in
|
||||
e&&e.document?e.document.compatMode==="CSS1Compat"&&e.document.documentElement["client"+b]||e.document.body["client"+b]:e.nodeType===9?Math.max(e.documentElement["client"+b],e.body["scroll"+b],e.documentElement["scroll"+b],e.body["offset"+b],e.documentElement["offset"+b]):f===w?c.css(e,d):this.css(d,typeof f==="string"?f:f+"px")}});A.jQuery=A.$=c})(window);
|
||||
77
lib/jquery/jquery-ui-1.7.1.custom.min.js
vendored
Normal file
77
lib/jquery/jquery-ui-1.7.1.custom.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
lib/jsl/jsl
Executable file
BIN
lib/jsl/jsl
Executable file
Binary file not shown.
128
lib/jsl/jsl.default.conf
Executable file
128
lib/jsl/jsl.default.conf
Executable file
|
|
@ -0,0 +1,128 @@
|
|||
#
|
||||
# Configuration File for JavaScript Lint 0.3.0
|
||||
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
|
||||
#
|
||||
# This configuration file can be used to lint a collection of scripts, or to enable
|
||||
# or disable warnings for scripts that are linted via the command line.
|
||||
#
|
||||
|
||||
### Warnings
|
||||
# Enable or disable warnings based on requirements.
|
||||
# Use "+WarningName" to display or "-WarningName" to suppress.
|
||||
#
|
||||
-no_return_value # function {0} does not always return a value
|
||||
+duplicate_formal # duplicate formal argument {0}
|
||||
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
|
||||
+var_hides_arg # variable {0} hides argument
|
||||
+redeclared_var # redeclaration of {0} {1}
|
||||
-anon_no_return_value # anonymous function does not always return a value
|
||||
+missing_semicolon # missing semicolon
|
||||
+meaningless_block # meaningless block; curly braces have no impact
|
||||
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
||||
+unreachable_code # unreachable code
|
||||
-missing_break # missing break statement
|
||||
+missing_break_for_last_case # missing break statement for last case in switch
|
||||
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
||||
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
||||
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
||||
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
||||
+use_of_label # use of label
|
||||
-block_without_braces # block statement without curly braces
|
||||
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
||||
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
||||
+octal_number # leading zeros make an octal number
|
||||
+nested_comment # nested comment
|
||||
-misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
||||
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
||||
+empty_statement # empty statement or extra semicolon
|
||||
-missing_option_explicit # the "option explicit" control comment is missing
|
||||
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
||||
+dup_option_explicit # duplicate "option explicit" control comment
|
||||
+useless_assign # useless assignment
|
||||
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
||||
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
|
||||
-missing_default_case # missing default case in switch statement
|
||||
+duplicate_case_in_switch # duplicate case in switch statements
|
||||
+default_not_at_end # the default case is not at the end of the switch statement
|
||||
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
||||
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
||||
+useless_comparison # useless comparison; comparing identical expressions
|
||||
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
||||
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
||||
+assign_to_function_call # assignment to a function call
|
||||
+parseint_missing_radix # parseInt missing radix parameter
|
||||
|
||||
|
||||
### Output format
|
||||
# Customize the format of the error message.
|
||||
# __FILE__ indicates current file path
|
||||
# __FILENAME__ indicates current file name
|
||||
# __LINE__ indicates current line
|
||||
# __ERROR__ indicates error message
|
||||
#
|
||||
# Visual Studio syntax (default):
|
||||
+output-format __FILE__(__LINE__): __ERROR__
|
||||
# Alternative syntax:
|
||||
#+output-format __FILE__:__LINE__: __ERROR__
|
||||
|
||||
|
||||
### Context
|
||||
# Show the in-line position of the error.
|
||||
# Use "+context" to display or "-context" to suppress.
|
||||
#
|
||||
+context
|
||||
|
||||
|
||||
### Semicolons
|
||||
# By default, assignments of an anonymous function to a variable or
|
||||
# property (such as a function prototype) must be followed by a semicolon.
|
||||
#
|
||||
+lambda_assign_requires_semicolon
|
||||
|
||||
|
||||
### Control Comments
|
||||
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
|
||||
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
|
||||
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
|
||||
# although legacy control comments are enabled by default for backward compatibility.
|
||||
#
|
||||
+legacy_control_comments
|
||||
|
||||
|
||||
### JScript Function Extensions
|
||||
# JScript allows member functions to be defined like this:
|
||||
# function MyObj() { /*constructor*/ }
|
||||
# function MyObj.prototype.go() { /*member function*/ }
|
||||
#
|
||||
# It also allows events to be attached like this:
|
||||
# function window::onload() { /*init page*/ }
|
||||
#
|
||||
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
|
||||
#
|
||||
-jscript_function_extensions
|
||||
|
||||
|
||||
### Defining identifiers
|
||||
# By default, "option explicit" is enabled on a per-file basis.
|
||||
# To enable this for all files, use "+always_use_option_explicit"
|
||||
-always_use_option_explicit
|
||||
|
||||
# Define certain identifiers of which the lint is not aware.
|
||||
# (Use this in conjunction with the "undeclared identifier" warning.)
|
||||
#
|
||||
# Common uses for webpages might be:
|
||||
#+define window
|
||||
#+define document
|
||||
|
||||
|
||||
### Files
|
||||
# Specify which files to lint
|
||||
# Use "+recurse" to enable recursion (disabled by default).
|
||||
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
|
||||
# or "+process Folder\Path\*.htm".
|
||||
#
|
||||
+process src/*.js
|
||||
+process src/scenario/*.js
|
||||
+process test/*.js
|
||||
+process test/scenario/*.js
|
||||
|
||||
BIN
lib/jstestdriver/JsTestDriver.jar
Normal file
BIN
lib/jstestdriver/JsTestDriver.jar
Normal file
Binary file not shown.
22
lib/nodeserver/server.js
Normal file
22
lib/nodeserver/server.js
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
var sys = require('sys'),
|
||||
http = require('http'),
|
||||
fs = require('fs');
|
||||
|
||||
http.createServer(function (req, res) {
|
||||
res.writeHead(200, {});
|
||||
sys.p('GET ' + req.url);
|
||||
var file = fs.createReadStream('.' + req.url);
|
||||
file.addListener('data', bind(res, res.write));
|
||||
file.addListener('error', function( error ){
|
||||
sys.p(error);
|
||||
res.end();
|
||||
});
|
||||
file.addListener('close', bind(res, res.end));
|
||||
}).listen(8000);
|
||||
sys.puts('Server running at http://127.0.0.1:8000/');
|
||||
|
||||
function bind(_this, _fn) {
|
||||
return function(){
|
||||
return _fn.apply(_this, arguments);
|
||||
};
|
||||
}
|
||||
4
lib/swfobject/swfobject.js
Normal file
4
lib/swfobject/swfobject.js
Normal file
File diff suppressed because one or more lines are too long
17
lib/underscore/underscore-min.js
vendored
Normal file
17
lib/underscore/underscore-min.js
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
(function(){var j=this,n=j._,i=function(a){this._wrapped=a},m=typeof StopIteration!=="undefined"?StopIteration:"__break__",b=j._=function(a){return new i(a)};if(typeof exports!=="undefined")exports._=b;var k=Array.prototype.slice,o=Array.prototype.unshift,p=Object.prototype.toString,q=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;b.VERSION="0.5.8";b.each=function(a,c,d){try{if(a.forEach)a.forEach(c,d);else if(b.isNumber(a.length))for(var e=0,f=a.length;e<f;e++)c.call(d,a[e],
|
||||
e,a);else{var g=b.keys(a);f=g.length;for(e=0;e<f;e++)c.call(d,a[g[e]],g[e],a)}}catch(h){if(h!=m)throw h;}return a};b.map=function(a,c,d){if(a&&b.isFunction(a.map))return a.map(c,d);var e=[];b.each(a,function(f,g,h){e.push(c.call(d,f,g,h))});return e};b.reduce=function(a,c,d,e){if(a&&b.isFunction(a.reduce))return a.reduce(b.bind(d,e),c);b.each(a,function(f,g,h){c=d.call(e,c,f,g,h)});return c};b.reduceRight=function(a,c,d,e){if(a&&b.isFunction(a.reduceRight))return a.reduceRight(b.bind(d,e),c);var f=
|
||||
b.clone(b.toArray(a)).reverse();b.each(f,function(g,h){c=d.call(e,c,g,h,a)});return c};b.detect=function(a,c,d){var e;b.each(a,function(f,g,h){if(c.call(d,f,g,h)){e=f;b.breakLoop()}});return e};b.select=function(a,c,d){if(a&&b.isFunction(a.filter))return a.filter(c,d);var e=[];b.each(a,function(f,g,h){c.call(d,f,g,h)&&e.push(f)});return e};b.reject=function(a,c,d){var e=[];b.each(a,function(f,g,h){!c.call(d,f,g,h)&&e.push(f)});return e};b.all=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.every))return a.every(c,
|
||||
d);var e=true;b.each(a,function(f,g,h){(e=e&&c.call(d,f,g,h))||b.breakLoop()});return e};b.any=function(a,c,d){c=c||b.identity;if(a&&b.isFunction(a.some))return a.some(c,d);var e=false;b.each(a,function(f,g,h){if(e=c.call(d,f,g,h))b.breakLoop()});return e};b.include=function(a,c){if(a&&b.isFunction(a.indexOf))return b.indexOf(a,c)!=-1;var d=false;b.each(a,function(e){if(d=e===c)b.breakLoop()});return d};b.invoke=function(a,c){var d=b.rest(arguments,2);return b.map(a,function(e){return(c?e[c]:e).apply(e,
|
||||
d)})};b.pluck=function(a,c){return b.map(a,function(d){return d[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a))return Math.max.apply(Math,a);var e={computed:-Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g>=e.computed&&(e={value:f,computed:g})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};b.each(a,function(f,g,h){g=c?c.call(d,f,g,h):f;g<e.computed&&(e={value:f,computed:g})});return e.value};b.sortBy=function(a,c,d){return b.pluck(b.map(a,
|
||||
function(e,f,g){return{value:e,criteria:c.call(d,e,f,g)}}).sort(function(e,f){e=e.criteria;f=f.criteria;return e<f?-1:e>f?1:0}),"value")};b.sortedIndex=function(a,c,d){d=d||b.identity;for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?(e=g+1):(f=g)}return e};b.toArray=function(a){if(!a)return[];if(a.toArray)return a.toArray();if(b.isArray(a))return a;if(b.isArguments(a))return k.call(a);return b.values(a)};b.size=function(a){return b.toArray(a).length};b.first=function(a,c,d){return c&&!d?k.call(a,
|
||||
0,c):a[0]};b.rest=function(a,c,d){return k.call(a,b.isUndefined(c)||d?1:c)};b.last=function(a){return a[a.length-1]};b.compact=function(a){return b.select(a,function(c){return!!c})};b.flatten=function(a){return b.reduce(a,[],function(c,d){if(b.isArray(d))return c.concat(b.flatten(d));c.push(d);return c})};b.without=function(a){var c=b.rest(arguments);return b.select(a,function(d){return!b.include(c,d)})};b.uniq=function(a,c){return b.reduce(a,[],function(d,e,f){if(0==f||(c===true?b.last(d)!=e:!b.include(d,
|
||||
e)))d.push(e);return d})};b.intersect=function(a){var c=b.rest(arguments);return b.select(b.uniq(a),function(d){return b.all(c,function(e){return b.indexOf(e,d)>=0})})};b.zip=function(){for(var a=b.toArray(arguments),c=b.max(b.pluck(a,"length")),d=new Array(c),e=0;e<c;e++)d[e]=b.pluck(a,String(e));return d};b.indexOf=function(a,c){if(a.indexOf)return a.indexOf(c);for(var d=0,e=a.length;d<e;d++)if(a[d]===c)return d;return-1};b.lastIndexOf=function(a,c){if(a.lastIndexOf)return a.lastIndexOf(c);for(var d=
|
||||
a.length;d--;)if(a[d]===c)return d;return-1};b.range=function(a,c,d){var e=b.toArray(arguments),f=e.length<=1;a=f?0:e[0];c=f?e[0]:e[1];d=e[2]||1;e=Math.ceil((c-a)/d);if(e<=0)return[];e=new Array(e);f=a;for(var g=0;;f+=d){if((d>0?f-c:c-f)>=0)return e;e[g++]=f}};b.bind=function(a,c){var d=b.rest(arguments,2);return function(){return a.apply(c||j,d.concat(b.toArray(arguments)))}};b.bindAll=function(a){var c=b.rest(arguments);if(c.length==0)c=b.functions(a);b.each(c,function(d){a[d]=b.bind(a[d],a)});
|
||||
return a};b.delay=function(a,c){var d=b.rest(arguments,2);return setTimeout(function(){return a.apply(a,d)},c)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(b.rest(arguments)))};b.wrap=function(a,c){return function(){var d=[a].concat(b.toArray(arguments));return c.apply(c,d)}};b.compose=function(){var a=b.toArray(arguments);return function(){for(var c=b.toArray(arguments),d=a.length-1;d>=0;d--)c=[a[d].apply(this,c)];return c[0]}};b.keys=function(a){if(b.isArray(a))return b.range(0,a.length);
|
||||
var c=[];for(var d in a)q.call(a,d)&&c.push(d);return c};b.values=function(a){return b.map(a,b.identity)};b.functions=function(a){return b.select(b.keys(a),function(c){return b.isFunction(a[c])}).sort()};b.extend=function(a,c){for(var d in c)a[d]=c[d];return a};b.clone=function(a){if(b.isArray(a))return a.slice(0);return b.extend({},a)};b.tap=function(a,c){c(a);return a};b.isEqual=function(a,c){if(a===c)return true;var d=typeof a;if(d!=typeof c)return false;if(a==c)return true;if(!a&&c||a&&!c)return false;
|
||||
if(a.isEqual)return a.isEqual(c);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return true;if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return false;if(a.length&&a.length!==c.length)return false;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return false;for(var f in a)if(!b.isEqual(a[f],c[f]))return false;return true};b.isEmpty=function(a){return b.keys(a).length==
|
||||
0};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=function(a){return!!(a&&a.concat&&a.unshift)};b.isArguments=function(a){return a&&b.isNumber(a.length)&&!a.concat&&!a.substr&&!a.apply&&!r.call(a,"length")};b.isFunction=function(a){return!!(a&&a.constructor&&a.call&&a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return a===+a||p.call(a)==="[object Number]"};b.isDate=function(a){return!!(a&&a.getTimezoneOffset&&a.setUTCFullYear)};
|
||||
b.isRegExp=function(a){return!!(a&&a.test&&a.exec&&(a.ignoreCase||a.ignoreCase===false))};b.isNaN=function(a){return b.isNumber(a)&&isNaN(a)};b.isNull=function(a){return a===null};b.isUndefined=function(a){return typeof a=="undefined"};b.noConflict=function(){j._=n;return this};b.identity=function(a){return a};b.breakLoop=function(){throw m;};var s=0;b.uniqueId=function(a){var c=s++;return a?a+c:c};b.templateSettings={start:"<%",end:"%>",interpolate:/<%=(.+?)%>/g};b.template=function(a,c){var d=b.templateSettings;
|
||||
a=new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+a.replace(/[\r\t\n]/g," ").replace(new RegExp("'(?=[^"+d.end[0]+"]*"+d.end+")","g"),"\t").split("'").join("\\'").split("\t").join("'").replace(d.interpolate,"',$1,'").split(d.start).join("');").split(d.end).join("p.push('")+"');}return p.join('');");return c?a(c):a};b.forEach=b.each;b.foldl=b.inject=b.reduce;b.foldr=b.reduceRight;b.filter=b.select;b.every=b.all;b.some=b.any;b.head=b.first;b.tail=b.rest;
|
||||
b.methods=b.functions;var l=function(a,c){return c?b(a).chain():a};b.each(b.functions(b),function(a){var c=b[a];i.prototype[a]=function(){var d=b.toArray(arguments);o.call(d,this._wrapped);return l(c.apply(b,d),this._chain)}});b.each(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var c=Array.prototype[a];i.prototype[a]=function(){c.apply(this._wrapped,arguments);return l(this._wrapped,this._chain)}});b.each(["concat","join","slice"],function(a){var c=Array.prototype[a];i.prototype[a]=
|
||||
function(){return l(c.apply(this._wrapped,arguments),this._chain)}});i.prototype.chain=function(){this._chain=true;return this};i.prototype.value=function(){return this._wrapped}})();
|
||||
646
lib/underscore/underscore.js
Normal file
646
lib/underscore/underscore.js
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
// Underscore.js
|
||||
// (c) 2010 Jeremy Ashkenas, DocumentCloud Inc.
|
||||
// Underscore is freely distributable under the terms of the MIT license.
|
||||
// Portions of Underscore are inspired by or borrowed from Prototype.js,
|
||||
// Oliver Steele's Functional, and John Resig's Micro-Templating.
|
||||
// For all details and documentation:
|
||||
// http://documentcloud.github.com/underscore
|
||||
|
||||
(function() {
|
||||
|
||||
// ------------------------- Baseline setup ---------------------------------
|
||||
|
||||
// Establish the root object, "window" in the browser, or "global" on the server.
|
||||
var root = this;
|
||||
|
||||
// Save the previous value of the "_" variable.
|
||||
var previousUnderscore = root._;
|
||||
|
||||
// If Underscore is called as a function, it returns a wrapped object that
|
||||
// can be used OO-style. This wrapper holds altered versions of all the
|
||||
// underscore functions. Wrapped objects may be chained.
|
||||
var wrapper = function(obj) { this._wrapped = obj; };
|
||||
|
||||
// Establish the object that gets thrown to break out of a loop iteration.
|
||||
var breaker = typeof StopIteration !== 'undefined' ? StopIteration : '__break__';
|
||||
|
||||
// Create a safe reference to the Underscore object for reference below.
|
||||
var _ = root._ = function(obj) { return new wrapper(obj); };
|
||||
|
||||
// Export the Underscore object for CommonJS.
|
||||
if (typeof exports !== 'undefined') exports._ = _;
|
||||
|
||||
// Create quick reference variables for speed access to core prototypes.
|
||||
var slice = Array.prototype.slice,
|
||||
unshift = Array.prototype.unshift,
|
||||
toString = Object.prototype.toString,
|
||||
hasOwnProperty = Object.prototype.hasOwnProperty,
|
||||
propertyIsEnumerable = Object.prototype.propertyIsEnumerable;
|
||||
|
||||
// Current version.
|
||||
_.VERSION = '0.5.8';
|
||||
|
||||
// ------------------------ Collection Functions: ---------------------------
|
||||
|
||||
// The cornerstone, an each implementation.
|
||||
// Handles objects implementing forEach, arrays, and raw objects.
|
||||
_.each = function(obj, iterator, context) {
|
||||
var index = 0;
|
||||
try {
|
||||
if (obj.forEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (_.isNumber(obj.length)) {
|
||||
for (var i=0, l=obj.length; i<l; i++) iterator.call(context, obj[i], i, obj);
|
||||
} else {
|
||||
var keys = _.keys(obj), l = keys.length;
|
||||
for (var i=0; i<l; i++) iterator.call(context, obj[keys[i]], keys[i], obj);
|
||||
}
|
||||
} catch(e) {
|
||||
if (e != breaker) throw e;
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Return the results of applying the iterator to each element. Use JavaScript
|
||||
// 1.6's version of map, if possible.
|
||||
_.map = function(obj, iterator, context) {
|
||||
if (obj && _.isFunction(obj.map)) return obj.map(iterator, context);
|
||||
var results = [];
|
||||
_.each(obj, function(value, index, list) {
|
||||
results.push(iterator.call(context, value, index, list));
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Reduce builds up a single result from a list of values. Also known as
|
||||
// inject, or foldl. Uses JavaScript 1.8's version of reduce, if possible.
|
||||
_.reduce = function(obj, memo, iterator, context) {
|
||||
if (obj && _.isFunction(obj.reduce)) return obj.reduce(_.bind(iterator, context), memo);
|
||||
_.each(obj, function(value, index, list) {
|
||||
memo = iterator.call(context, memo, value, index, list);
|
||||
});
|
||||
return memo;
|
||||
};
|
||||
|
||||
// The right-associative version of reduce, also known as foldr. Uses
|
||||
// JavaScript 1.8's version of reduceRight, if available.
|
||||
_.reduceRight = function(obj, memo, iterator, context) {
|
||||
if (obj && _.isFunction(obj.reduceRight)) return obj.reduceRight(_.bind(iterator, context), memo);
|
||||
var reversed = _.clone(_.toArray(obj)).reverse();
|
||||
_.each(reversed, function(value, index) {
|
||||
memo = iterator.call(context, memo, value, index, obj);
|
||||
});
|
||||
return memo;
|
||||
};
|
||||
|
||||
// Return the first value which passes a truth test.
|
||||
_.detect = function(obj, iterator, context) {
|
||||
var result;
|
||||
_.each(obj, function(value, index, list) {
|
||||
if (iterator.call(context, value, index, list)) {
|
||||
result = value;
|
||||
_.breakLoop();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Return all the elements that pass a truth test. Use JavaScript 1.6's
|
||||
// filter(), if it exists.
|
||||
_.select = function(obj, iterator, context) {
|
||||
if (obj && _.isFunction(obj.filter)) return obj.filter(iterator, context);
|
||||
var results = [];
|
||||
_.each(obj, function(value, index, list) {
|
||||
iterator.call(context, value, index, list) && results.push(value);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Return all the elements for which a truth test fails.
|
||||
_.reject = function(obj, iterator, context) {
|
||||
var results = [];
|
||||
_.each(obj, function(value, index, list) {
|
||||
!iterator.call(context, value, index, list) && results.push(value);
|
||||
});
|
||||
return results;
|
||||
};
|
||||
|
||||
// Determine whether all of the elements match a truth test. Delegate to
|
||||
// JavaScript 1.6's every(), if it is present.
|
||||
_.all = function(obj, iterator, context) {
|
||||
iterator = iterator || _.identity;
|
||||
if (obj && _.isFunction(obj.every)) return obj.every(iterator, context);
|
||||
var result = true;
|
||||
_.each(obj, function(value, index, list) {
|
||||
if (!(result = result && iterator.call(context, value, index, list))) _.breakLoop();
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Determine if at least one element in the object matches a truth test. Use
|
||||
// JavaScript 1.6's some(), if it exists.
|
||||
_.any = function(obj, iterator, context) {
|
||||
iterator = iterator || _.identity;
|
||||
if (obj && _.isFunction(obj.some)) return obj.some(iterator, context);
|
||||
var result = false;
|
||||
_.each(obj, function(value, index, list) {
|
||||
if (result = iterator.call(context, value, index, list)) _.breakLoop();
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
// Determine if a given value is included in the array or object,
|
||||
// based on '==='.
|
||||
_.include = function(obj, target) {
|
||||
if (obj && _.isFunction(obj.indexOf)) return _.indexOf(obj, target) != -1;
|
||||
var found = false;
|
||||
_.each(obj, function(value) {
|
||||
if (found = value === target) _.breakLoop();
|
||||
});
|
||||
return found;
|
||||
};
|
||||
|
||||
// Invoke a method with arguments on every item in a collection.
|
||||
_.invoke = function(obj, method) {
|
||||
var args = _.rest(arguments, 2);
|
||||
return _.map(obj, function(value) {
|
||||
return (method ? value[method] : value).apply(value, args);
|
||||
});
|
||||
};
|
||||
|
||||
// Convenience version of a common use case of map: fetching a property.
|
||||
_.pluck = function(obj, key) {
|
||||
return _.map(obj, function(value){ return value[key]; });
|
||||
};
|
||||
|
||||
// Return the maximum item or (item-based computation).
|
||||
_.max = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
|
||||
var result = {computed : -Infinity};
|
||||
_.each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed >= result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Return the minimum element (or element-based computation).
|
||||
_.min = function(obj, iterator, context) {
|
||||
if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
|
||||
var result = {computed : Infinity};
|
||||
_.each(obj, function(value, index, list) {
|
||||
var computed = iterator ? iterator.call(context, value, index, list) : value;
|
||||
computed < result.computed && (result = {value : value, computed : computed});
|
||||
});
|
||||
return result.value;
|
||||
};
|
||||
|
||||
// Sort the object's values by a criteria produced by an iterator.
|
||||
_.sortBy = function(obj, iterator, context) {
|
||||
return _.pluck(_.map(obj, function(value, index, list) {
|
||||
return {
|
||||
value : value,
|
||||
criteria : iterator.call(context, value, index, list)
|
||||
};
|
||||
}).sort(function(left, right) {
|
||||
var a = left.criteria, b = right.criteria;
|
||||
return a < b ? -1 : a > b ? 1 : 0;
|
||||
}), 'value');
|
||||
};
|
||||
|
||||
// Use a comparator function to figure out at what index an object should
|
||||
// be inserted so as to maintain order. Uses binary search.
|
||||
_.sortedIndex = function(array, obj, iterator) {
|
||||
iterator = iterator || _.identity;
|
||||
var low = 0, high = array.length;
|
||||
while (low < high) {
|
||||
var mid = (low + high) >> 1;
|
||||
iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
|
||||
}
|
||||
return low;
|
||||
};
|
||||
|
||||
// Convert anything iterable into a real, live array.
|
||||
_.toArray = function(iterable) {
|
||||
if (!iterable) return [];
|
||||
if (iterable.toArray) return iterable.toArray();
|
||||
if (_.isArray(iterable)) return iterable;
|
||||
if (_.isArguments(iterable)) return slice.call(iterable);
|
||||
return _.values(iterable);
|
||||
};
|
||||
|
||||
// Return the number of elements in an object.
|
||||
_.size = function(obj) {
|
||||
return _.toArray(obj).length;
|
||||
};
|
||||
|
||||
// -------------------------- Array Functions: ------------------------------
|
||||
|
||||
// Get the first element of an array. Passing "n" will return the first N
|
||||
// values in the array. Aliased as "head". The "guard" check allows it to work
|
||||
// with _.map.
|
||||
_.first = function(array, n, guard) {
|
||||
return n && !guard ? slice.call(array, 0, n) : array[0];
|
||||
};
|
||||
|
||||
// Returns everything but the first entry of the array. Aliased as "tail".
|
||||
// Especially useful on the arguments object. Passing an "index" will return
|
||||
// the rest of the values in the array from that index onward. The "guard"
|
||||
//check allows it to work with _.map.
|
||||
_.rest = function(array, index, guard) {
|
||||
return slice.call(array, _.isUndefined(index) || guard ? 1 : index);
|
||||
};
|
||||
|
||||
// Get the last element of an array.
|
||||
_.last = function(array) {
|
||||
return array[array.length - 1];
|
||||
};
|
||||
|
||||
// Trim out all falsy values from an array.
|
||||
_.compact = function(array) {
|
||||
return _.select(array, function(value){ return !!value; });
|
||||
};
|
||||
|
||||
// Return a completely flattened version of an array.
|
||||
_.flatten = function(array) {
|
||||
return _.reduce(array, [], function(memo, value) {
|
||||
if (_.isArray(value)) return memo.concat(_.flatten(value));
|
||||
memo.push(value);
|
||||
return memo;
|
||||
});
|
||||
};
|
||||
|
||||
// Return a version of the array that does not contain the specified value(s).
|
||||
_.without = function(array) {
|
||||
var values = _.rest(arguments);
|
||||
return _.select(array, function(value){ return !_.include(values, value); });
|
||||
};
|
||||
|
||||
// Produce a duplicate-free version of the array. If the array has already
|
||||
// been sorted, you have the option of using a faster algorithm.
|
||||
_.uniq = function(array, isSorted) {
|
||||
return _.reduce(array, [], function(memo, el, i) {
|
||||
if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) memo.push(el);
|
||||
return memo;
|
||||
});
|
||||
};
|
||||
|
||||
// Produce an array that contains every item shared between all the
|
||||
// passed-in arrays.
|
||||
_.intersect = function(array) {
|
||||
var rest = _.rest(arguments);
|
||||
return _.select(_.uniq(array), function(item) {
|
||||
return _.all(rest, function(other) {
|
||||
return _.indexOf(other, item) >= 0;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Zip together multiple lists into a single array -- elements that share
|
||||
// an index go together.
|
||||
_.zip = function() {
|
||||
var args = _.toArray(arguments);
|
||||
var length = _.max(_.pluck(args, 'length'));
|
||||
var results = new Array(length);
|
||||
for (var i=0; i<length; i++) results[i] = _.pluck(args, String(i));
|
||||
return results;
|
||||
};
|
||||
|
||||
// If the browser doesn't supply us with indexOf (I'm looking at you, MSIE),
|
||||
// we need this function. Return the position of the first occurence of an
|
||||
// item in an array, or -1 if the item is not included in the array.
|
||||
_.indexOf = function(array, item) {
|
||||
if (array.indexOf) return array.indexOf(item);
|
||||
for (var i=0, l=array.length; i<l; i++) if (array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Provide JavaScript 1.6's lastIndexOf, delegating to the native function,
|
||||
// if possible.
|
||||
_.lastIndexOf = function(array, item) {
|
||||
if (array.lastIndexOf) return array.lastIndexOf(item);
|
||||
var i = array.length;
|
||||
while (i--) if (array[i] === item) return i;
|
||||
return -1;
|
||||
};
|
||||
|
||||
// Generate an integer Array containing an arithmetic progression. A port of
|
||||
// the native Python range() function. See:
|
||||
// http://docs.python.org/library/functions.html#range
|
||||
_.range = function(start, stop, step) {
|
||||
var a = _.toArray(arguments);
|
||||
var solo = a.length <= 1;
|
||||
var start = solo ? 0 : a[0], stop = solo ? a[0] : a[1], step = a[2] || 1;
|
||||
var len = Math.ceil((stop - start) / step);
|
||||
if (len <= 0) return [];
|
||||
var range = new Array(len);
|
||||
for (var i = start, idx = 0; true; i += step) {
|
||||
if ((step > 0 ? i - stop : stop - i) >= 0) return range;
|
||||
range[idx++] = i;
|
||||
}
|
||||
};
|
||||
|
||||
// ----------------------- Function Functions: ------------------------------
|
||||
|
||||
// Create a function bound to a given object (assigning 'this', and arguments,
|
||||
// optionally). Binding with arguments is also known as 'curry'.
|
||||
_.bind = function(func, obj) {
|
||||
var args = _.rest(arguments, 2);
|
||||
return function() {
|
||||
return func.apply(obj || root, args.concat(_.toArray(arguments)));
|
||||
};
|
||||
};
|
||||
|
||||
// Bind all of an object's methods to that object. Useful for ensuring that
|
||||
// all callbacks defined on an object belong to it.
|
||||
_.bindAll = function(obj) {
|
||||
var funcs = _.rest(arguments);
|
||||
if (funcs.length == 0) funcs = _.functions(obj);
|
||||
_.each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Delays a function for the given number of milliseconds, and then calls
|
||||
// it with the arguments supplied.
|
||||
_.delay = function(func, wait) {
|
||||
var args = _.rest(arguments, 2);
|
||||
return setTimeout(function(){ return func.apply(func, args); }, wait);
|
||||
};
|
||||
|
||||
// Defers a function, scheduling it to run after the current call stack has
|
||||
// cleared.
|
||||
_.defer = function(func) {
|
||||
return _.delay.apply(_, [func, 1].concat(_.rest(arguments)));
|
||||
};
|
||||
|
||||
// Returns the first function passed as an argument to the second,
|
||||
// allowing you to adjust arguments, run code before and after, and
|
||||
// conditionally execute the original function.
|
||||
_.wrap = function(func, wrapper) {
|
||||
return function() {
|
||||
var args = [func].concat(_.toArray(arguments));
|
||||
return wrapper.apply(wrapper, args);
|
||||
};
|
||||
};
|
||||
|
||||
// Returns a function that is the composition of a list of functions, each
|
||||
// consuming the return value of the function that follows.
|
||||
_.compose = function() {
|
||||
var funcs = _.toArray(arguments);
|
||||
return function() {
|
||||
var args = _.toArray(arguments);
|
||||
for (var i=funcs.length-1; i >= 0; i--) {
|
||||
args = [funcs[i].apply(this, args)];
|
||||
}
|
||||
return args[0];
|
||||
};
|
||||
};
|
||||
|
||||
// ------------------------- Object Functions: ------------------------------
|
||||
|
||||
// Retrieve the names of an object's properties.
|
||||
_.keys = function(obj) {
|
||||
if (_.isArray(obj)) return _.range(0, obj.length);
|
||||
var keys = [];
|
||||
for (var key in obj) if (hasOwnProperty.call(obj, key)) keys.push(key);
|
||||
return keys;
|
||||
};
|
||||
|
||||
// Retrieve the values of an object's properties.
|
||||
_.values = function(obj) {
|
||||
return _.map(obj, _.identity);
|
||||
};
|
||||
|
||||
// Return a sorted list of the function names available in Underscore.
|
||||
_.functions = function(obj) {
|
||||
return _.select(_.keys(obj), function(key){ return _.isFunction(obj[key]); }).sort();
|
||||
};
|
||||
|
||||
// Extend a given object with all of the properties in a source object.
|
||||
_.extend = function(destination, source) {
|
||||
for (var property in source) destination[property] = source[property];
|
||||
return destination;
|
||||
};
|
||||
|
||||
// Create a (shallow-cloned) duplicate of an object.
|
||||
_.clone = function(obj) {
|
||||
if (_.isArray(obj)) return obj.slice(0);
|
||||
return _.extend({}, obj);
|
||||
};
|
||||
|
||||
// Invokes interceptor with the obj, and then returns obj.
|
||||
// The primary purpose of this method is to "tap into" a method chain, in order to perform operations on intermediate results within the chain.
|
||||
_.tap = function(obj, interceptor) {
|
||||
interceptor(obj);
|
||||
return obj;
|
||||
};
|
||||
|
||||
// Perform a deep comparison to check if two objects are equal.
|
||||
_.isEqual = function(a, b) {
|
||||
// Check object identity.
|
||||
if (a === b) return true;
|
||||
// Different types?
|
||||
var atype = typeof(a), btype = typeof(b);
|
||||
if (atype != btype) return false;
|
||||
// Basic equality test (watch out for coercions).
|
||||
if (a == b) return true;
|
||||
// One is falsy and the other truthy.
|
||||
if ((!a && b) || (a && !b)) return false;
|
||||
// One of them implements an isEqual()?
|
||||
if (a.isEqual) return a.isEqual(b);
|
||||
// Check dates' integer values.
|
||||
if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
|
||||
// Both are NaN?
|
||||
if (_.isNaN(a) && _.isNaN(b)) return true;
|
||||
// Compare regular expressions.
|
||||
if (_.isRegExp(a) && _.isRegExp(b))
|
||||
return a.source === b.source &&
|
||||
a.global === b.global &&
|
||||
a.ignoreCase === b.ignoreCase &&
|
||||
a.multiline === b.multiline;
|
||||
// If a is not an object by this point, we can't handle it.
|
||||
if (atype !== 'object') return false;
|
||||
// Check for different array lengths before comparing contents.
|
||||
if (a.length && (a.length !== b.length)) return false;
|
||||
// Nothing else worked, deep compare the contents.
|
||||
var aKeys = _.keys(a), bKeys = _.keys(b);
|
||||
// Different object sizes?
|
||||
if (aKeys.length != bKeys.length) return false;
|
||||
// Recursive comparison of contents.
|
||||
for (var key in a) if (!_.isEqual(a[key], b[key])) return false;
|
||||
return true;
|
||||
};
|
||||
|
||||
// Is a given array or object empty?
|
||||
_.isEmpty = function(obj) {
|
||||
return _.keys(obj).length == 0;
|
||||
};
|
||||
|
||||
// Is a given value a DOM element?
|
||||
_.isElement = function(obj) {
|
||||
return !!(obj && obj.nodeType == 1);
|
||||
};
|
||||
|
||||
// Is a given value an array?
|
||||
_.isArray = function(obj) {
|
||||
return !!(obj && obj.concat && obj.unshift);
|
||||
};
|
||||
|
||||
// Is a given variable an arguments object?
|
||||
_.isArguments = function(obj) {
|
||||
return obj && _.isNumber(obj.length) && !obj.concat && !obj.substr && !obj.apply && !propertyIsEnumerable.call(obj, 'length');
|
||||
};
|
||||
|
||||
// Is a given value a function?
|
||||
_.isFunction = function(obj) {
|
||||
return !!(obj && obj.constructor && obj.call && obj.apply);
|
||||
};
|
||||
|
||||
// Is a given value a string?
|
||||
_.isString = function(obj) {
|
||||
return !!(obj === '' || (obj && obj.charCodeAt && obj.substr));
|
||||
};
|
||||
|
||||
// Is a given value a number?
|
||||
_.isNumber = function(obj) {
|
||||
return (obj === +obj) || (toString.call(obj) === '[object Number]');
|
||||
};
|
||||
|
||||
// Is a given value a date?
|
||||
_.isDate = function(obj) {
|
||||
return !!(obj && obj.getTimezoneOffset && obj.setUTCFullYear);
|
||||
};
|
||||
|
||||
// Is the given value a regular expression?
|
||||
_.isRegExp = function(obj) {
|
||||
return !!(obj && obj.test && obj.exec && (obj.ignoreCase || obj.ignoreCase === false));
|
||||
};
|
||||
|
||||
// Is the given value NaN -- this one is interesting. NaN != NaN, and
|
||||
// isNaN(undefined) == true, so we make sure it's a number first.
|
||||
_.isNaN = function(obj) {
|
||||
return _.isNumber(obj) && isNaN(obj);
|
||||
};
|
||||
|
||||
// Is a given value equal to null?
|
||||
_.isNull = function(obj) {
|
||||
return obj === null;
|
||||
};
|
||||
|
||||
// Is a given variable undefined?
|
||||
_.isUndefined = function(obj) {
|
||||
return typeof obj == 'undefined';
|
||||
};
|
||||
|
||||
// -------------------------- Utility Functions: ----------------------------
|
||||
|
||||
// Run Underscore.js in noConflict mode, returning the '_' variable to its
|
||||
// previous owner. Returns a reference to the Underscore object.
|
||||
_.noConflict = function() {
|
||||
root._ = previousUnderscore;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Keep the identity function around for default iterators.
|
||||
_.identity = function(value) {
|
||||
return value;
|
||||
};
|
||||
|
||||
// Break out of the middle of an iteration.
|
||||
_.breakLoop = function() {
|
||||
throw breaker;
|
||||
};
|
||||
|
||||
// Generate a unique integer id (unique within the entire client session).
|
||||
// Useful for temporary DOM ids.
|
||||
var idCounter = 0;
|
||||
_.uniqueId = function(prefix) {
|
||||
var id = idCounter++;
|
||||
return prefix ? prefix + id : id;
|
||||
};
|
||||
|
||||
// By default, Underscore uses ERB-style template delimiters, change the
|
||||
// following template settings to use alternative delimiters.
|
||||
_.templateSettings = {
|
||||
start : '<%',
|
||||
end : '%>',
|
||||
interpolate : /<%=(.+?)%>/g
|
||||
};
|
||||
|
||||
// JavaScript templating a-la ERB, pilfered from John Resig's
|
||||
// "Secrets of the JavaScript Ninja", page 83.
|
||||
// Single-quote fix from Rick Strahl's version.
|
||||
_.template = function(str, data) {
|
||||
var c = _.templateSettings;
|
||||
var fn = new Function('obj',
|
||||
'var p=[],print=function(){p.push.apply(p,arguments);};' +
|
||||
'with(obj){p.push(\'' +
|
||||
str.replace(/[\r\t\n]/g, " ")
|
||||
.replace(new RegExp("'(?=[^"+c.end[0]+"]*"+c.end+")","g"),"\t")
|
||||
.split("'").join("\\'")
|
||||
.split("\t").join("'")
|
||||
.replace(c.interpolate, "',$1,'")
|
||||
.split(c.start).join("');")
|
||||
.split(c.end).join("p.push('")
|
||||
+ "');}return p.join('');");
|
||||
return data ? fn(data) : fn;
|
||||
};
|
||||
|
||||
// ------------------------------- Aliases ----------------------------------
|
||||
|
||||
_.forEach = _.each;
|
||||
_.foldl = _.inject = _.reduce;
|
||||
_.foldr = _.reduceRight;
|
||||
_.filter = _.select;
|
||||
_.every = _.all;
|
||||
_.some = _.any;
|
||||
_.head = _.first;
|
||||
_.tail = _.rest;
|
||||
_.methods = _.functions;
|
||||
|
||||
// ------------------------ Setup the OOP Wrapper: --------------------------
|
||||
|
||||
// Helper function to continue chaining intermediate results.
|
||||
var result = function(obj, chain) {
|
||||
return chain ? _(obj).chain() : obj;
|
||||
};
|
||||
|
||||
// Add all of the Underscore functions to the wrapper object.
|
||||
_.each(_.functions(_), function(name) {
|
||||
var method = _[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
var args = _.toArray(arguments);
|
||||
unshift.call(args, this._wrapped);
|
||||
return result(method.apply(_, args), this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Add all mutator Array functions to the wrapper.
|
||||
_.each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
|
||||
var method = Array.prototype[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
method.apply(this._wrapped, arguments);
|
||||
return result(this._wrapped, this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Add all accessor Array functions to the wrapper.
|
||||
_.each(['concat', 'join', 'slice'], function(name) {
|
||||
var method = Array.prototype[name];
|
||||
wrapper.prototype[name] = function() {
|
||||
return result(method.apply(this._wrapped, arguments), this._chain);
|
||||
};
|
||||
});
|
||||
|
||||
// Start chaining a wrapped Underscore object.
|
||||
wrapper.prototype.chain = function() {
|
||||
this._chain = true;
|
||||
return this;
|
||||
};
|
||||
|
||||
// Extracts the result from a wrapped and chained object.
|
||||
wrapper.prototype.value = function() {
|
||||
return this._wrapped;
|
||||
};
|
||||
|
||||
})();
|
||||
7
lib/underscore/update.sh
Executable file
7
lib/underscore/update.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
underscore=$(dirname $0)
|
||||
github='http://github.com/documentcloud/underscore/raw/master'
|
||||
|
||||
wget $github/underscore-min.js -O $underscore/underscore-min.js
|
||||
wget $github/underscore.js -O $underscore/underscore.js
|
||||
142
lib/webtoolkit/webtoolkit.base64.js
Normal file
142
lib/webtoolkit/webtoolkit.base64.js
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
*
|
||||
* Base64 encode / decode
|
||||
* http://www.webtoolkit.info/
|
||||
*
|
||||
**/
|
||||
|
||||
var Base64 = {
|
||||
|
||||
// private property
|
||||
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=",
|
||||
|
||||
// public method for encoding
|
||||
encode : function (input) {
|
||||
var output = "";
|
||||
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
|
||||
input = Base64._utf8_encode(input);
|
||||
|
||||
while (i < input.length) {
|
||||
|
||||
chr1 = input.charCodeAt(i++);
|
||||
chr2 = input.charCodeAt(i++);
|
||||
chr3 = input.charCodeAt(i++);
|
||||
|
||||
enc1 = chr1 >> 2;
|
||||
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||
enc4 = chr3 & 63;
|
||||
|
||||
if (isNaN(chr2)) {
|
||||
enc3 = enc4 = 64;
|
||||
} else if (isNaN(chr3)) {
|
||||
enc4 = 64;
|
||||
}
|
||||
|
||||
output = output +
|
||||
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
|
||||
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
||||
|
||||
}
|
||||
|
||||
return output;
|
||||
},
|
||||
|
||||
// public method for decoding
|
||||
decode : function (input) {
|
||||
var output = "";
|
||||
var chr1, chr2, chr3;
|
||||
var enc1, enc2, enc3, enc4;
|
||||
var i = 0;
|
||||
|
||||
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||
|
||||
while (i < input.length) {
|
||||
|
||||
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||
|
||||
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||
|
||||
output = output + String.fromCharCode(chr1);
|
||||
|
||||
if (enc3 != 64) {
|
||||
output = output + String.fromCharCode(chr2);
|
||||
}
|
||||
if (enc4 != 64) {
|
||||
output = output + String.fromCharCode(chr3);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
output = Base64._utf8_decode(output);
|
||||
|
||||
return output;
|
||||
|
||||
},
|
||||
|
||||
// private method for UTF-8 encoding
|
||||
_utf8_encode : function (string) {
|
||||
string = string.replace(/\r\n/g,"\n");
|
||||
var utftext = "";
|
||||
|
||||
for (var n = 0; n < string.length; n++) {
|
||||
|
||||
var c = string.charCodeAt(n);
|
||||
|
||||
if (c < 128) {
|
||||
utftext += String.fromCharCode(c);
|
||||
}
|
||||
else if((c > 127) && (c < 2048)) {
|
||||
utftext += String.fromCharCode((c >> 6) | 192);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
}
|
||||
else {
|
||||
utftext += String.fromCharCode((c >> 12) | 224);
|
||||
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||
utftext += String.fromCharCode((c & 63) | 128);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return utftext;
|
||||
},
|
||||
|
||||
// private method for UTF-8 decoding
|
||||
_utf8_decode : function (utftext) {
|
||||
var string = "";
|
||||
var i = 0;
|
||||
var c = c1 = c2 = 0;
|
||||
|
||||
while ( i < utftext.length ) {
|
||||
|
||||
c = utftext.charCodeAt(i);
|
||||
|
||||
if (c < 128) {
|
||||
string += String.fromCharCode(c);
|
||||
i++;
|
||||
}
|
||||
else if((c > 191) && (c < 224)) {
|
||||
c2 = utftext.charCodeAt(i+1);
|
||||
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||
i += 2;
|
||||
}
|
||||
else {
|
||||
c2 = utftext.charCodeAt(i+1);
|
||||
c3 = utftext.charCodeAt(i+2);
|
||||
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||
i += 3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
};
|
||||
1
nodeserver.sh
Executable file
1
nodeserver.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
node lib/nodeserver/server.js
|
||||
9
scenario/Runner-compiled.html
Normal file
9
scenario/Runner-compiled.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../angular-scenario.js"></script>
|
||||
<script type="text/javascript" src="widgets-scenario.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
9
scenario/Runner.html
Normal file
9
scenario/Runner.html
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../src/scenario/bootstrap.js"></script>
|
||||
<script type="text/javascript" src="widgets-scenario.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
6
scenario/application-account.html
Normal file
6
scenario/application-account.html
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
<div ng-controller="AccountController">
|
||||
account page goes here!
|
||||
<input type="text" name="name" value="misko"/>
|
||||
<button ng-click="hello()">hello</button>
|
||||
</div>
|
||||
|
||||
34
scenario/application.html
Normal file
34
scenario/application.html
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"></link>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
|
||||
<script>
|
||||
function AccountController(){
|
||||
}
|
||||
|
||||
AccountController.prototype = {
|
||||
hello: function(){
|
||||
alert(this.name);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body ng-init="$window.$scope = this">
|
||||
[ <a href="#login">login</a>
|
||||
| <a href="#account">account</a>
|
||||
]
|
||||
|
||||
<ng:switch on="$location.hashPath">
|
||||
<div ng-switch-when="login">login screen</div>
|
||||
<ng:include ng-switch-when="account" src="'application-account.html'"></ng:include>
|
||||
</ng:switch>
|
||||
|
||||
|
||||
(( input name ))
|
||||
|
||||
<pre>$location={{$location}}</pre>
|
||||
</body>
|
||||
</html>
|
||||
4
scenario/cross-site-post/People.json
Normal file
4
scenario/cross-site-post/People.json
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[
|
||||
{ name: 'Misko', favorite: ['water melon', 'persimmon', 'passion fruit'] },
|
||||
{ name: 'Lenka', favorite: ['strawberry'] }
|
||||
]
|
||||
10
scenario/cross-site-post/index.html
Normal file
10
scenario/cross-site-post/index.html
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../../src/angular-bootstrap.js#autobind"></script>
|
||||
</head>
|
||||
<body ng:init="$window.$scope = this; People = $resource('People.json')">
|
||||
<button ng-click="people = People.query()">Load People</button>
|
||||
<pre>people = {{people}}</pre>
|
||||
</body>
|
||||
</html>
|
||||
19
scenario/datastore-scenarios.js
Normal file
19
scenario/datastore-scenarios.js
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
angular.scenarioDef.datastore = {
|
||||
$before:[
|
||||
{Given:"dataset",
|
||||
dataset:{
|
||||
Book:[{$id:'moby', name:"Moby Dick"},
|
||||
{$id:'gadsby', name:'Great Gadsby'}]
|
||||
}
|
||||
},
|
||||
{Given:"browser", at:"datastore.html#book=moby"},
|
||||
],
|
||||
checkLoadBook:[
|
||||
{Then:"drainRequestQueue"},
|
||||
|
||||
{Then:"text", at:"{{book.$id}}", should_be:"moby"},
|
||||
{Then:"text", at:"li[$index=0] {{book.name}}", should_be:"Great Gahdsby"},
|
||||
{Then:"text", at:"li[$index=0] {{book.name}}", should_be:"Moby Dick"},
|
||||
|
||||
]
|
||||
};
|
||||
17
scenario/datastore.html
Normal file
17
scenario/datastore.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<script type="text/javascript" src="../lib/underscore/underscore.js"></script>
|
||||
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.js"></script>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){angular.compile(document).init();});
|
||||
</script>
|
||||
</head>
|
||||
<body ng-entity="book=Book" ng-init="books=Book.all()">
|
||||
<p>{{book.$id}}</p>
|
||||
<li ng-repeat="book in books.$orderBy('name')">
|
||||
<li>{{book.name}}</li>
|
||||
</li>
|
||||
</body>
|
||||
</html>
|
||||
33
scenario/perf.html
Normal file
33
scenario/perf.html
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
|
||||
<script type="text/javascript">
|
||||
function PerfCntl(){}
|
||||
PerfCntl.prototype = {
|
||||
createItems: function(){
|
||||
var items = [];
|
||||
for ( var i = 0; i < 1000; i++) {
|
||||
var item = {
|
||||
name: "" + Math.random(),
|
||||
parts: [Math.random(), Math.random()]
|
||||
};
|
||||
items.push(item);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body ng:init="$window.$scope = this; items = createItems()" ng-controller="PerfCntl">
|
||||
<input type="text" name="text"/>
|
||||
<hr/>
|
||||
<ul>
|
||||
<li Xng-repeat="item in items.$filter('').$orderBy('name')"
|
||||
ng-repeat="item in items">
|
||||
{{item.name}} <a href="#{{item.name}}">{{item.parts.join(', ')}}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
7
scenario/style.css
Normal file
7
scenario/style.css
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
tr {
|
||||
border: 1px solid black;
|
||||
}
|
||||
25
scenario/widgets-scenario.js
Normal file
25
scenario/widgets-scenario.js
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
describe('widgets', function(){
|
||||
it('should verify that basic widgets work', function(){
|
||||
browser.navigateTo('widgets.html');
|
||||
|
||||
expect('{{text.basic}}').toEqual('');
|
||||
input('text.basic').enter('John');
|
||||
expect('{{text.basic}}').toEqual('John');
|
||||
|
||||
expect('{{text.password}}').toEqual('');
|
||||
input('text.password').enter('secret');
|
||||
expect('{{text.password}}').toEqual('secret');
|
||||
|
||||
expect('{{text.hidden}}').toEqual('hiddenValue');
|
||||
|
||||
expect('{{gender}}').toEqual('male');
|
||||
input('gender').select('female');
|
||||
input('gender').isChecked('female');
|
||||
expect('{{gender}}').toEqual('female');
|
||||
|
||||
// expect('{{tea}}').toBeChecked();
|
||||
// input('gender').select('female');
|
||||
// expect('{{gender}}').toEqual('female');
|
||||
|
||||
});
|
||||
});
|
||||
49
scenario/widgets-scenarios.old
Normal file
49
scenario/widgets-scenarios.old
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
angular.scenarioDef.widgets = {
|
||||
$before:[
|
||||
{Given:"browser", at:"widgets.html"}
|
||||
],
|
||||
checkWidgetBinding:[
|
||||
{Then:"text", at:"{{text.basic}}", should_be:""},
|
||||
{When:"enter", text:"John", at:":input[name=text.basic]"},
|
||||
{Then:"text", at:"{{text.basic}}", should_be:"John"},
|
||||
|
||||
{Then:"text", at:"{{gender}}", should_be:"male"},
|
||||
{When:"click", at:"input:radio[value=female]"},
|
||||
{Then:"text", at:"{{gender}}", should_be:"female"},
|
||||
|
||||
{Then:"text", at:"{{tea}}", should_be:"on"},
|
||||
{When:"click", at:"input[name=tea]"},
|
||||
{Then:"text", at:"{{tea}}", should_be:""},
|
||||
|
||||
{Then:"text", at:"{{coffee}}", should_be:""},
|
||||
{When:"click", at:"input[name=coffee]"},
|
||||
{Then:"text", at:"{{coffee}}", should_be:"on"},
|
||||
|
||||
{Then:"text", at:"{{count}}", should_be:0},
|
||||
{When:"click", at:"form :button"},
|
||||
{When:"click", at:"form :submit"},
|
||||
{When:"click", at:"form :image"},
|
||||
{Then:"text", at:"{{count}}", should_be:3},
|
||||
|
||||
{Then:"text", at:"{{select}}", should_be:"A"},
|
||||
{When:"select", at:"select[name=select]", option:"B"},
|
||||
{Then:"text", at:"{{select}}", should_be:"B"},
|
||||
|
||||
{Then:"text", at:"{{multiple}}", should_be:"[]"},
|
||||
{When:"select", at:"select[name=multiple]", option:"A"},
|
||||
{Then:"text", at:"{{multiple}}", should_be:["A"]},
|
||||
{When:"select", at:"select[name=multiple]", option:"B"},
|
||||
{Then:"text", at:"{{multiple}}", should_be:["A", "B"]},
|
||||
{When:"select", at:"select[name=multiple]", option:"A"},
|
||||
{Then:"text", at:"{{multiple}}", should_be:["B"]},
|
||||
|
||||
{Then:"text", at:"{{hidden}}", should_be:"hiddenValue"},
|
||||
|
||||
{Then:"text", at:"{{password}}", should_be:"passwordValue"},
|
||||
{When:"enter", text:"reset", at:":input[name=password]"},
|
||||
{Then:"text", at:"{{password}}", should_be:"reset"},
|
||||
],
|
||||
checkNewWidgetEmpty:[
|
||||
{Then:"text", at:"{{name}}", should_be:""},
|
||||
]
|
||||
};
|
||||
98
scenario/widgets.html
Normal file
98
scenario/widgets.html
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css"/>
|
||||
<script type="text/javascript" src="../src/angular-bootstrap.js#autobind"></script>
|
||||
</head>
|
||||
<body ng:init="$window.$scope = this">
|
||||
<table>
|
||||
<tr>
|
||||
<th width="330">Description</th>
|
||||
<th>Test</th>
|
||||
<th>Result</th>
|
||||
</tr>
|
||||
<tr><th colspan="3">Input text field</th></tr>
|
||||
<tr>
|
||||
<td>basic</td>
|
||||
<td>
|
||||
<input type="text" name="text.basic"/>
|
||||
</td>
|
||||
<td>text.basic={{text.basic}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>password</td>
|
||||
<td><input type="password" name="text.password" /></td>
|
||||
<td>text.password={{text.password}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>hidden</td>
|
||||
<td><input type="hidden" name="text.hidden" value="hiddenValue" /></td>
|
||||
<td>text.hidden={{text.hidden}}</td>
|
||||
</tr>
|
||||
<tr><th colspan="3">Input selection field</th></tr>
|
||||
<tr>
|
||||
<td>radio</td>
|
||||
<td>
|
||||
<input type="radio" name="gender" value="female"/> Female <br/>
|
||||
<input type="radio" name="gender" value="male" checked="checked"/> Male
|
||||
</td>
|
||||
<td>gender={{gender}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>checkbox</td>
|
||||
<td>
|
||||
<input type="checkbox" name="checkbox.tea" checked value="on"/> Tea<br/>
|
||||
<input type="checkbox" name="checkbox.coffee" value="on"/> Coffe
|
||||
</td>
|
||||
<td>
|
||||
<pre>checkbox={{checkbox}}</pre>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>select</td>
|
||||
<td>
|
||||
<select name="select">
|
||||
<option>A</option>
|
||||
<option>B</option>
|
||||
<option>C</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>select={{select}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>multiselect</td>
|
||||
<td>
|
||||
<select name="multiselect" multiple>
|
||||
<option>A</option>
|
||||
<option>B</option>
|
||||
<option>C</option>
|
||||
</select>
|
||||
</td>
|
||||
<td>multiselect={{multiselect}}</td>
|
||||
</tr>
|
||||
<tr><th colspan="3">Buttons</th></tr>
|
||||
<tr>
|
||||
<td>ng-change<br/>ng-click</td>
|
||||
<td ng:init="button.count = 0">
|
||||
<form>
|
||||
<input type="button" value="button" ng-change="button.count = button.count + 1"/> <br/>
|
||||
<input type="submit" value="submit" ng-change="button.count = button.count + 1"/><br/>
|
||||
<input type="image" src="" ng-change="button.count = button.count + 1"/><br/>
|
||||
<a href="" ng:click="button.count = button.count + 1">action</a>
|
||||
</form>
|
||||
</td>
|
||||
<td>button={{button}}</td>
|
||||
</tr>
|
||||
<tr><th colspan="3">Repeaters</th></tr>
|
||||
<tr>
|
||||
<td>ng-repeat</td>
|
||||
<td>
|
||||
<ul>
|
||||
<li ng-repeat="name in ['misko', 'adam']">{{name}}</li>
|
||||
</ul>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
1
server.sh
Executable file
1
server.sh
Executable file
|
|
@ -0,0 +1 @@
|
|||
java -jar lib/jstestdriver/JsTestDriver.jar --port 9876
|
||||
401
src/Angular.js
Normal file
401
src/Angular.js
Normal file
|
|
@ -0,0 +1,401 @@
|
|||
////////////////////////////////////
|
||||
|
||||
if (typeof document.getAttribute == 'undefined')
|
||||
document.getAttribute = function() {};
|
||||
|
||||
if (!window['console']) window['console']={'log':noop, 'error':noop};
|
||||
|
||||
var consoleNode,
|
||||
PRIORITY_FIRST = -99999,
|
||||
PRIORITY_WATCH = -1000,
|
||||
PRIORITY_LAST = 99999,
|
||||
PRIORITY = {'FIRST': PRIORITY_FIRST, 'LAST': PRIORITY_LAST, 'WATCH':PRIORITY_WATCH},
|
||||
NOOP = 'noop',
|
||||
NG_EXCEPTION = 'ng-exception',
|
||||
NG_VALIDATION_ERROR = 'ng-validation-error',
|
||||
jQuery = window['jQuery'] || window['$'], // weirdness to make IE happy
|
||||
_ = window['_'],
|
||||
msie = !!/(msie) ([\w.]+)/.exec(lowercase(navigator.userAgent)),
|
||||
jqLite = jQuery || jqLiteWrap,
|
||||
slice = Array.prototype.slice,
|
||||
angular = window['angular'] || (window['angular'] = {}),
|
||||
angularTextMarkup = extensionMap(angular, 'textMarkup'),
|
||||
angularAttrMarkup = extensionMap(angular, 'attrMarkup'),
|
||||
angularDirective = extensionMap(angular, 'directive'),
|
||||
angularWidget = extensionMap(angular, 'widget'),
|
||||
angularValidator = extensionMap(angular, 'validator'),
|
||||
angularFilter = extensionMap(angular, 'filter'),
|
||||
angularFormatter = extensionMap(angular, 'formatter'),
|
||||
angularService = extensionMap(angular, 'service'),
|
||||
angularCallbacks = extensionMap(angular, 'callbacks'),
|
||||
nodeName;
|
||||
|
||||
function angularAlert(){
|
||||
log(arguments); window.alert.apply(window, arguments);
|
||||
}
|
||||
|
||||
function foreach(obj, iterator, context) {
|
||||
var key;
|
||||
if (obj) {
|
||||
if (isFunction(obj)){
|
||||
for (key in obj) {
|
||||
if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
|
||||
iterator.call(context, obj[key], key);
|
||||
}
|
||||
}
|
||||
} else if (obj.forEach) {
|
||||
obj.forEach(iterator, context);
|
||||
} else if (isObject(obj) && isNumber(obj.length)) {
|
||||
for (key = 0; key < obj.length; key++)
|
||||
iterator.call(context, obj[key], key);
|
||||
} else {
|
||||
for (key in obj)
|
||||
iterator.call(context, obj[key], key);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
function foreachSorted(obj, iterator, context) {
|
||||
var keys = [];
|
||||
for (var key in obj) keys.push(key);
|
||||
keys.sort();
|
||||
for ( var i = 0; i < keys.length; i++) {
|
||||
iterator.call(context, obj[keys[i]], keys[i]);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
function extend(dst) {
|
||||
foreach(arguments, function(obj){
|
||||
if (obj !== dst) {
|
||||
foreach(obj, function(value, key){
|
||||
dst[key] = value;
|
||||
});
|
||||
}
|
||||
});
|
||||
return dst;
|
||||
}
|
||||
|
||||
function noop() {}
|
||||
function identity($) {return $;}
|
||||
function extensionMap(angular, name) {
|
||||
var extPoint;
|
||||
return angular[name] || (extPoint = angular[name] = function (name, fn, prop){
|
||||
if (isDefined(fn)) {
|
||||
extPoint[name] = extend(fn, prop || {});
|
||||
}
|
||||
return extPoint[name];
|
||||
});
|
||||
}
|
||||
|
||||
function jqLiteWrap(element) {
|
||||
// for some reasons the parentNode of an orphan looks like null but its typeof is object.
|
||||
if (element) {
|
||||
if (isString(element)) {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = element;
|
||||
element = new JQLite(div.childNodes);
|
||||
} else if (!(element instanceof JQLite) && isElement(element)) {
|
||||
element = new JQLite(element);
|
||||
}
|
||||
}
|
||||
return element;
|
||||
}
|
||||
function isUndefined(value){ return typeof value == 'undefined'; }
|
||||
function isDefined(value){ return typeof value != 'undefined'; }
|
||||
function isObject(value){ return typeof value == 'object';}
|
||||
function isString(value){ return typeof value == 'string';}
|
||||
function isNumber(value){ return typeof value == 'number';}
|
||||
function isArray(value) { return value instanceof Array; }
|
||||
function isFunction(value){ return typeof value == 'function';}
|
||||
function isTextNode(node) { return nodeName(node) == '#text'; }
|
||||
function lowercase(value){ return isString(value) ? value.toLowerCase() : value; }
|
||||
function uppercase(value){ return isString(value) ? value.toUpperCase() : value; }
|
||||
function trim(value) { return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; }
|
||||
function isElement(node) {
|
||||
return node && (node.nodeName || node instanceof JQLite || (jQuery && node instanceof jQuery));
|
||||
}
|
||||
|
||||
function HTML(html) {
|
||||
this.html = html;
|
||||
}
|
||||
|
||||
if (msie) {
|
||||
nodeName = function(element) {
|
||||
element = element[0] || element;
|
||||
return (element.scopeName && element.scopeName != 'HTML' ) ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName;
|
||||
};
|
||||
} else {
|
||||
nodeName = function(element) {
|
||||
return (element[0] || element).nodeName;
|
||||
};
|
||||
}
|
||||
|
||||
function isVisible(element) {
|
||||
var rect = element[0].getBoundingClientRect(),
|
||||
width = (rect.width || (rect.right||0 - rect.left||0)),
|
||||
height = (rect.height || (rect.bottom||0 - rect.top||0));
|
||||
return width>0 && height>0;
|
||||
}
|
||||
|
||||
function map(obj, iterator, context) {
|
||||
var results = [];
|
||||
foreach(obj, function(value, index, list) {
|
||||
results.push(iterator.call(context, value, index, list));
|
||||
});
|
||||
return results;
|
||||
}
|
||||
function size(obj) {
|
||||
var size = 0;
|
||||
if (obj) {
|
||||
if (isNumber(obj.length)) {
|
||||
return obj.length;
|
||||
} else if (isObject(obj)){
|
||||
for (key in obj)
|
||||
size++;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
function includes(array, obj) {
|
||||
for ( var i = 0; i < array.length; i++) {
|
||||
if (obj === array[i]) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function indexOf(array, obj) {
|
||||
for ( var i = 0; i < array.length; i++) {
|
||||
if (obj === array[i]) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function log(a, b, c){
|
||||
var console = window['console'];
|
||||
switch(arguments.length) {
|
||||
case 1:
|
||||
console['log'](a);
|
||||
break;
|
||||
case 2:
|
||||
console['log'](a, b);
|
||||
break;
|
||||
default:
|
||||
console['log'](a, b, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function error(a, b, c){
|
||||
var console = window['console'];
|
||||
switch(arguments.length) {
|
||||
case 1:
|
||||
console['error'](a);
|
||||
break;
|
||||
case 2:
|
||||
console['error'](a, b);
|
||||
break;
|
||||
default:
|
||||
console['error'](a, b, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function consoleLog(level, objs) {
|
||||
var log = document.createElement("div");
|
||||
log.className = level;
|
||||
var msg = "";
|
||||
var sep = "";
|
||||
for ( var i = 0; i < objs.length; i++) {
|
||||
var obj = objs[i];
|
||||
msg += sep + (typeof obj == 'string' ? obj : toJson(obj));
|
||||
sep = " ";
|
||||
}
|
||||
log.appendChild(document.createTextNode(msg));
|
||||
consoleNode.appendChild(log);
|
||||
}
|
||||
|
||||
function isLeafNode (node) {
|
||||
if (node) {
|
||||
switch (node.nodeName) {
|
||||
case "OPTION":
|
||||
case "PRE":
|
||||
case "TITLE":
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function copy(source, destination){
|
||||
if (!destination) {
|
||||
if (source) {
|
||||
if (isArray(source)) {
|
||||
return copy(source, []);
|
||||
} else if (isObject(source)) {
|
||||
return copy(source, {});
|
||||
}
|
||||
}
|
||||
return source;
|
||||
} else {
|
||||
if (isArray(source)) {
|
||||
while(destination.length) {
|
||||
destination.pop();
|
||||
}
|
||||
for ( var i = 0; i < source.length; i++) {
|
||||
destination.push(copy(source[i]));
|
||||
}
|
||||
} else {
|
||||
foreach(destination, function(value, key){
|
||||
delete destination[key];
|
||||
});
|
||||
for ( var key in source) {
|
||||
destination[key] = copy(source[key]);
|
||||
}
|
||||
}
|
||||
return destination;
|
||||
}
|
||||
}
|
||||
|
||||
function setHtml(node, html) {
|
||||
if (isLeafNode(node)) {
|
||||
if (msie) {
|
||||
node.innerText = html;
|
||||
} else {
|
||||
node.textContent = html;
|
||||
}
|
||||
} else {
|
||||
node.innerHTML = html;
|
||||
}
|
||||
}
|
||||
|
||||
function escapeHtml(html) {
|
||||
if (!html || !html.replace)
|
||||
return html;
|
||||
return html.
|
||||
replace(/&/g, '&').
|
||||
replace(/</g, '<').
|
||||
replace(/>/g, '>');
|
||||
}
|
||||
|
||||
|
||||
function isRenderableElement(element) {
|
||||
var name = element && element[0] && element[0].nodeName;
|
||||
return name && name.charAt(0) != '#' &&
|
||||
!includes(['TR', 'COL', 'COLGROUP', 'TBODY', 'THEAD', 'TFOOT'], name);
|
||||
}
|
||||
function elementError(element, type, error) {
|
||||
while (!isRenderableElement(element)) {
|
||||
element = element.parent() || jqLite(document.body);
|
||||
}
|
||||
if (element[0]['$NG_ERROR'] !== error) {
|
||||
element[0]['$NG_ERROR'] = error;
|
||||
if (error) {
|
||||
element.addClass(type);
|
||||
element.attr(type, error);
|
||||
} else {
|
||||
element.removeClass(type);
|
||||
element.removeAttr(type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function escapeAttr(html) {
|
||||
if (!html || !html.replace)
|
||||
return html;
|
||||
return html.replace(/</g, '<').replace(/>/g, '>').replace(/\"/g,
|
||||
'"');
|
||||
}
|
||||
|
||||
function bind(_this, _function) {
|
||||
if (!isFunction(_function))
|
||||
throw "Not a function!";
|
||||
var curryArgs = slice.call(arguments, 2, arguments.length);
|
||||
return function() {
|
||||
return _function.apply(_this, curryArgs.concat(slice.call(arguments, 0, arguments.length)));
|
||||
};
|
||||
}
|
||||
|
||||
function outerHTML(node) {
|
||||
var temp = document.createElement('div');
|
||||
temp.appendChild(node);
|
||||
var outerHTML = temp.innerHTML;
|
||||
temp.removeChild(node);
|
||||
return outerHTML;
|
||||
}
|
||||
|
||||
function toBoolean(value) {
|
||||
if (value && value.length !== 0) {
|
||||
var v = lowercase("" + value);
|
||||
value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == '[]');
|
||||
} else {
|
||||
value = false;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
function merge(src, dst) {
|
||||
for ( var key in src) {
|
||||
var value = dst[key];
|
||||
var type = typeof value;
|
||||
if (type == 'undefined') {
|
||||
dst[key] = fromJson(toJson(src[key]));
|
||||
} else if (type == 'object' && value.constructor != array &&
|
||||
key.substring(0, 1) != "$") {
|
||||
merge(src[key], value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function compile(element, parentScope, overrides) {
|
||||
var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget),
|
||||
$element = jqLite(element),
|
||||
parent = extend({}, parentScope);
|
||||
parent.$element = $element;
|
||||
return compiler.compile($element)($element, parent, overrides);
|
||||
}
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
function parseKeyValue(keyValue) {
|
||||
var obj = {}, key_value, key;
|
||||
foreach((keyValue || "").split('&'), function(keyValue){
|
||||
if (keyValue) {
|
||||
key_value = keyValue.split('=');
|
||||
key = decodeURIComponent(key_value[0]);
|
||||
obj[key] = key_value[1] ? decodeURIComponent(key_value[1]) : true;
|
||||
}
|
||||
});
|
||||
return obj;
|
||||
}
|
||||
|
||||
function toKeyValue(obj) {
|
||||
var parts = [];
|
||||
foreach(obj, function(value, key){
|
||||
parts.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
|
||||
});
|
||||
return parts.length ? parts.join('&') : '';
|
||||
}
|
||||
|
||||
function angularInit(config){
|
||||
if (config.autobind) {
|
||||
var scope = compile(window.document, null, {'$config':config});
|
||||
// TODO default to the source of angular.js
|
||||
scope.$browser.addCss('css/angular.css');
|
||||
scope.$init();
|
||||
}
|
||||
}
|
||||
|
||||
function angularJsConfig(document) {
|
||||
var filename = /(.*)\/angular(-(.*))?.js(#(.*))?/,
|
||||
scripts = document.getElementsByTagName("SCRIPT"),
|
||||
match;
|
||||
for(var j = 0; j < scripts.length; j++) {
|
||||
match = (scripts[j].src || "").match(filename);
|
||||
if (match) {
|
||||
return match[5];
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
29
src/AngularPublic.js
Normal file
29
src/AngularPublic.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
var browserSingleton;
|
||||
angularService('$browser', function browserFactory(){
|
||||
if (!browserSingleton) {
|
||||
browserSingleton = new Browser(window.location, window.document);
|
||||
browserSingleton.startUrlWatcher();
|
||||
browserSingleton.bind();
|
||||
}
|
||||
return browserSingleton;
|
||||
});
|
||||
|
||||
extend(angular, {
|
||||
'element': jqLite,
|
||||
'compile': compile,
|
||||
'scope': createScope,
|
||||
'copy': copy,
|
||||
'extend': extend,
|
||||
'foreach': foreach,
|
||||
'noop':noop,
|
||||
'bind':bind,
|
||||
'identity':identity,
|
||||
'isUndefined': isUndefined,
|
||||
'isDefined': isDefined,
|
||||
'isString': isString,
|
||||
'isFunction': isFunction,
|
||||
'isObject': isObject,
|
||||
'isNumber': isNumber,
|
||||
'isArray': isArray
|
||||
});
|
||||
|
||||
130
src/Browser.js
Normal file
130
src/Browser.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
//////////////////////////////
|
||||
// Browser
|
||||
//////////////////////////////
|
||||
|
||||
function Browser(location, document) {
|
||||
this.delay = 50;
|
||||
this.expectedUrl = location.href;
|
||||
this.urlListeners = [];
|
||||
this.hoverListener = noop;
|
||||
this.isMock = false;
|
||||
this.outstandingRequests = { count: 0, callbacks:[]};
|
||||
|
||||
this.XHR = window.XMLHttpRequest || function () {
|
||||
try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {}
|
||||
try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {}
|
||||
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {}
|
||||
throw new Error("This browser does not support XMLHttpRequest.");
|
||||
};
|
||||
this.setTimeout = function(fn, delay) {
|
||||
window.setTimeout(fn, delay);
|
||||
};
|
||||
|
||||
this.location = location;
|
||||
this.document = jqLite(document);
|
||||
this.body = jqLite(document.body);
|
||||
}
|
||||
|
||||
Browser.prototype = {
|
||||
|
||||
bind: function() {
|
||||
var self = this;
|
||||
self.document.bind("mouseover", function(event){
|
||||
self.hoverListener(jqLite(msie ? event.srcElement : event.target), true);
|
||||
return true;
|
||||
});
|
||||
self.document.bind("mouseleave mouseout click dblclick keypress keyup", function(event){
|
||||
self.hoverListener(jqLite(event.target), false);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
|
||||
hover: function(hoverListener) {
|
||||
this.hoverListener = hoverListener;
|
||||
},
|
||||
|
||||
addCss: function(url) {
|
||||
var doc = this.document[0],
|
||||
head = jqLite(doc.getElementsByTagName('head')[0]),
|
||||
link = jqLite(doc.createElement('link'));
|
||||
link.attr('rel', 'stylesheet');
|
||||
link.attr('type', 'text/css');
|
||||
link.attr('href', url);
|
||||
head.append(link);
|
||||
},
|
||||
|
||||
xhr: function(method, url, post, callback){
|
||||
if (isFunction(post)) {
|
||||
callback = post;
|
||||
post = null;
|
||||
}
|
||||
var xhr = new this.XHR(),
|
||||
self = this;
|
||||
xhr.open(method, url, true);
|
||||
this.outstandingRequests.count ++;
|
||||
xhr.onreadystatechange = function() {
|
||||
if (xhr.readyState == 4) {
|
||||
try {
|
||||
callback(xhr.status || 200, xhr.responseText);
|
||||
} finally {
|
||||
self.outstandingRequests.count--;
|
||||
self.processRequestCallbacks();
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send(post || '');
|
||||
},
|
||||
|
||||
processRequestCallbacks: function(){
|
||||
if (this.outstandingRequests.count === 0) {
|
||||
while(this.outstandingRequests.callbacks.length) {
|
||||
try {
|
||||
this.outstandingRequests.callbacks.pop()();
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
notifyWhenNoOutstandingRequests: function(callback){
|
||||
if (this.outstandingRequests.count === 0) {
|
||||
callback();
|
||||
} else {
|
||||
this.outstandingRequests.callbacks.push(callback);
|
||||
}
|
||||
},
|
||||
|
||||
watchUrl: function(fn){
|
||||
this.urlListeners.push(fn);
|
||||
},
|
||||
|
||||
startUrlWatcher: function() {
|
||||
var self = this;
|
||||
(function pull () {
|
||||
if (self.expectedUrl !== self.location.href) {
|
||||
foreach(self.urlListeners, function(listener){
|
||||
try {
|
||||
listener(self.location.href);
|
||||
} catch (e) {
|
||||
error(e);
|
||||
}
|
||||
});
|
||||
self.expectedUrl = self.location.href;
|
||||
}
|
||||
self.setTimeout(pull, self.delay);
|
||||
})();
|
||||
},
|
||||
|
||||
setUrl: function(url) {
|
||||
var existingURL = this.location.href;
|
||||
if (!existingURL.match(/#/)) existingURL += '#';
|
||||
if (!url.match(/#/)) url += '#';
|
||||
if (existingURL != url) {
|
||||
this.location.href = this.expectedUrl = url;
|
||||
}
|
||||
},
|
||||
|
||||
getUrl: function() {
|
||||
return this.location.href;
|
||||
}
|
||||
};
|
||||
212
src/Compiler.js
Normal file
212
src/Compiler.js
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/**
|
||||
* Template provides directions an how to bind to a given element.
|
||||
* It contains a list of init functions which need to be called to
|
||||
* bind to a new instance of elements. It also provides a list
|
||||
* of child paths which contain child templates
|
||||
*/
|
||||
function Template(priority) {
|
||||
this.paths = [];
|
||||
this.children = [];
|
||||
this.inits = [];
|
||||
this.priority = priority || 0;
|
||||
}
|
||||
|
||||
Template.prototype = {
|
||||
init: function(element, scope) {
|
||||
var inits = {};
|
||||
this.collectInits(element, inits);
|
||||
foreachSorted(inits, function(queue){
|
||||
foreach(queue, function(fn){
|
||||
fn(scope);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
collectInits: function(element, inits) {
|
||||
var queue = inits[this.priority];
|
||||
if (!queue) {
|
||||
inits[this.priority] = queue = [];
|
||||
}
|
||||
element = jqLite(element);
|
||||
foreach(this.inits, function(fn) {
|
||||
queue.push(function(scope) {
|
||||
scope.$tryEval(fn, element, element);
|
||||
});
|
||||
});
|
||||
|
||||
var i,
|
||||
childNodes = element[0].childNodes,
|
||||
children = this.children,
|
||||
paths = this.paths,
|
||||
length = paths.length;
|
||||
for (i = 0; i < length; i++) {
|
||||
children[i].collectInits(childNodes[paths[i]], inits);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
addInit:function(init) {
|
||||
if (init) {
|
||||
this.inits.push(init);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
addChild: function(index, template) {
|
||||
if (template) {
|
||||
this.paths.push(index);
|
||||
this.children.push(template);
|
||||
}
|
||||
},
|
||||
|
||||
empty: function() {
|
||||
return this.inits.length === 0 && this.paths.length === 0;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////////////
|
||||
//Compiler
|
||||
//////////////////////////////////
|
||||
function Compiler(textMarkup, attrMarkup, directives, widgets){
|
||||
this.textMarkup = textMarkup;
|
||||
this.attrMarkup = attrMarkup;
|
||||
this.directives = directives;
|
||||
this.widgets = widgets;
|
||||
}
|
||||
|
||||
Compiler.prototype = {
|
||||
compile: function(rawElement) {
|
||||
rawElement = jqLite(rawElement);
|
||||
var index = 0,
|
||||
template,
|
||||
parent = rawElement.parent();
|
||||
if (parent && parent[0]) {
|
||||
parent = parent[0];
|
||||
for(var i = 0; i < parent.childNodes.length; i++) {
|
||||
if (parent.childNodes[i] == rawElement[0]) {
|
||||
index = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
template = this.templatize(rawElement, index, 0) || new Template();
|
||||
return function(element, parentScope){
|
||||
element = jqLite(element);
|
||||
var scope = parentScope && parentScope.$eval ?
|
||||
parentScope :
|
||||
createScope(parentScope || {}, angularService);
|
||||
return extend(scope, {
|
||||
$element:element,
|
||||
$init: function() {
|
||||
template.init(element, scope);
|
||||
scope.$eval();
|
||||
delete scope.$init;
|
||||
return scope;
|
||||
}
|
||||
});
|
||||
};
|
||||
},
|
||||
|
||||
templatize: function(element, elementIndex, priority){
|
||||
var self = this,
|
||||
widget,
|
||||
directiveFns = self.directives,
|
||||
descend = true,
|
||||
directives = true,
|
||||
template,
|
||||
selfApi = {
|
||||
compile: bind(self, self.compile),
|
||||
comment:function(text) {return jqLite(document.createComment(text));},
|
||||
element:function(type) {return jqLite(document.createElement(type));},
|
||||
text:function(text) {return jqLite(document.createTextNode(text));},
|
||||
descend: function(value){ if(isDefined(value)) descend = value; return descend;},
|
||||
directives: function(value){ if(isDefined(value)) directives = value; return directives;}
|
||||
};
|
||||
priority = element.attr('ng-eval-order') || priority || 0;
|
||||
if (isString(priority)) {
|
||||
priority = PRIORITY[uppercase(priority)] || 0;
|
||||
}
|
||||
template = new Template(priority);
|
||||
eachAttribute(element, function(value, name){
|
||||
if (!widget) {
|
||||
if (widget = self.widgets['@' + name]) {
|
||||
widget = bind(selfApi, widget, value, element);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (!widget) {
|
||||
if (widget = self.widgets[nodeName(element)]) {
|
||||
widget = bind(selfApi, widget, element);
|
||||
}
|
||||
}
|
||||
if (widget) {
|
||||
descend = false;
|
||||
directives = false;
|
||||
var parent = element.parent();
|
||||
template.addInit(widget.call(selfApi, element));
|
||||
if (parent && parent[0]) {
|
||||
element = jqLite(parent[0].childNodes[elementIndex]);
|
||||
}
|
||||
}
|
||||
if (descend){
|
||||
// process markup for text nodes only
|
||||
eachTextNode(element, function(textNode){
|
||||
var text = textNode.text();
|
||||
foreach(self.textMarkup, function(markup){
|
||||
markup.call(selfApi, text, textNode, element);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (directives) {
|
||||
// Process attributes/directives
|
||||
eachAttribute(element, function(value, name){
|
||||
foreach(self.attrMarkup, function(markup){
|
||||
markup.call(selfApi, value, name, element);
|
||||
});
|
||||
});
|
||||
eachAttribute(element, function(value, name){
|
||||
template.addInit((directiveFns[name]||noop).call(selfApi, value, element));
|
||||
});
|
||||
}
|
||||
// Process non text child nodes
|
||||
if (descend) {
|
||||
eachNode(element, function(child, i){
|
||||
template.addChild(i, self.templatize(child, i, priority));
|
||||
});
|
||||
}
|
||||
return template.empty() ? null : template;
|
||||
}
|
||||
};
|
||||
|
||||
function eachTextNode(element, fn){
|
||||
var i, chldNodes = element[0].childNodes || [], chld;
|
||||
for (i = 0; i < chldNodes.length; i++) {
|
||||
if(isTextNode(chld = chldNodes[i])) {
|
||||
fn(jqLite(chld), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eachNode(element, fn){
|
||||
var i, chldNodes = element[0].childNodes || [], chld;
|
||||
for (i = 0; i < chldNodes.length; i++) {
|
||||
if(!isTextNode(chld = chldNodes[i])) {
|
||||
fn(jqLite(chld), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function eachAttribute(element, fn){
|
||||
var i, attrs = element[0].attributes || [], chld, attr, name, value, attrValue = {};
|
||||
for (i = 0; i < attrs.length; i++) {
|
||||
attr = attrs[i];
|
||||
name = attr.name.replace(':', '-');
|
||||
value = attr.value;
|
||||
if (msie && name == 'href') {
|
||||
value = decodeURIComponent(element[0].getAttribute(name, 2));
|
||||
}
|
||||
attrValue[name] = value;
|
||||
}
|
||||
foreachSorted(attrValue, fn);
|
||||
}
|
||||
|
||||
105
src/JSON.js
Normal file
105
src/JSON.js
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
array = [].constructor;
|
||||
|
||||
function toJson(obj, pretty){
|
||||
var buf = [];
|
||||
toJsonArray(buf, obj, pretty ? "\n " : null, []);
|
||||
return buf.join('');
|
||||
}
|
||||
|
||||
function toPrettyJson(obj) {
|
||||
return toJson(obj, true);
|
||||
}
|
||||
|
||||
function fromJson(json) {
|
||||
if (!json) return json;
|
||||
try {
|
||||
var parser = new Parser(json, true);
|
||||
var expression = parser.primary();
|
||||
parser.assertAllConsumed();
|
||||
return expression();
|
||||
} catch (e) {
|
||||
error("fromJson error: ", json, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
angular['toJson'] = toJson;
|
||||
angular['fromJson'] = fromJson;
|
||||
|
||||
function toJsonArray(buf, obj, pretty, stack){
|
||||
if (typeof obj == "object") {
|
||||
if (includes(stack, obj)) {
|
||||
buf.push("RECURSION");
|
||||
return;
|
||||
}
|
||||
stack.push(obj);
|
||||
}
|
||||
var type = typeof obj;
|
||||
if (obj === null) {
|
||||
buf.push("null");
|
||||
} else if (type === 'function') {
|
||||
return;
|
||||
} else if (type === 'boolean') {
|
||||
buf.push('' + obj);
|
||||
} else if (type === 'number') {
|
||||
if (isNaN(obj)) {
|
||||
buf.push('null');
|
||||
} else {
|
||||
buf.push('' + obj);
|
||||
}
|
||||
} else if (type === 'string') {
|
||||
return buf.push(angular['String']['quoteUnicode'](obj));
|
||||
} else if (type === 'object') {
|
||||
if (obj instanceof Array) {
|
||||
buf.push("[");
|
||||
var len = obj.length;
|
||||
var sep = false;
|
||||
for(var i=0; i<len; i++) {
|
||||
var item = obj[i];
|
||||
if (sep) buf.push(",");
|
||||
if (typeof item == 'function' || typeof item == 'undefined') {
|
||||
buf.push("null");
|
||||
} else {
|
||||
toJsonArray(buf, item, pretty, stack);
|
||||
}
|
||||
sep = true;
|
||||
}
|
||||
buf.push("]");
|
||||
} else if (obj instanceof Date) {
|
||||
buf.push(angular['String']['quoteUnicode'](angular['Date']['toString'](obj)));
|
||||
} else {
|
||||
buf.push("{");
|
||||
if (pretty) buf.push(pretty);
|
||||
var comma = false;
|
||||
var childPretty = pretty ? pretty + " " : false;
|
||||
var keys = [];
|
||||
for(var k in obj) {
|
||||
if (k.indexOf('$$') === 0 || obj[k] === undefined)
|
||||
continue;
|
||||
keys.push(k);
|
||||
}
|
||||
keys.sort();
|
||||
for ( var keyIndex = 0; keyIndex < keys.length; keyIndex++) {
|
||||
var key = keys[keyIndex];
|
||||
try {
|
||||
var value = obj[key];
|
||||
if (typeof value != 'function') {
|
||||
if (comma) {
|
||||
buf.push(",");
|
||||
if (pretty) buf.push(pretty);
|
||||
}
|
||||
buf.push(angular['String']['quote'](key));
|
||||
buf.push(":");
|
||||
toJsonArray(buf, value, childPretty, stack);
|
||||
comma = true;
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
buf.push("}");
|
||||
}
|
||||
}
|
||||
if (typeof obj == "object") {
|
||||
stack.pop();
|
||||
}
|
||||
}
|
||||
730
src/Parser.js
Normal file
730
src/Parser.js
Normal file
|
|
@ -0,0 +1,730 @@
|
|||
function Lexer(text, parsStrings){
|
||||
this.text = text;
|
||||
// UTC dates have 20 characters, we send them through parser
|
||||
this.dateParseLength = parsStrings ? 20 : -1;
|
||||
this.tokens = [];
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
Lexer.OPERATORS = {
|
||||
'null':function(self){return null;},
|
||||
'true':function(self){return true;},
|
||||
'false':function(self){return false;},
|
||||
'undefined':noop,
|
||||
'+':function(self, a,b){return (isDefined(a)?a:0)+(isDefined(b)?b:0);},
|
||||
'-':function(self, a,b){return (isDefined(a)?a:0)-(isDefined(b)?b:0);},
|
||||
'*':function(self, a,b){return a*b;},
|
||||
'/':function(self, a,b){return a/b;},
|
||||
'%':function(self, a,b){return a%b;},
|
||||
'^':function(self, a,b){return a^b;},
|
||||
'=':function(self, a,b){return setter(self, a, b);},
|
||||
'==':function(self, a,b){return a==b;},
|
||||
'!=':function(self, a,b){return a!=b;},
|
||||
'<':function(self, a,b){return a<b;},
|
||||
'>':function(self, a,b){return a>b;},
|
||||
'<=':function(self, a,b){return a<=b;},
|
||||
'>=':function(self, a,b){return a>=b;},
|
||||
'&&':function(self, a,b){return a&&b;},
|
||||
'||':function(self, a,b){return a||b;},
|
||||
'&':function(self, a,b){return a&b;},
|
||||
// '|':function(self, a,b){return a|b;},
|
||||
'|':function(self, a,b){return b(self, a);},
|
||||
'!':function(self, a){return !a;}
|
||||
};
|
||||
Lexer.ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'};
|
||||
|
||||
Lexer.prototype = {
|
||||
peek: function() {
|
||||
if (this.index + 1 < this.text.length) {
|
||||
return this.text.charAt(this.index + 1);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
parse: function() {
|
||||
var tokens = this.tokens;
|
||||
var OPERATORS = Lexer.OPERATORS;
|
||||
var canStartRegExp = true;
|
||||
while (this.index < this.text.length) {
|
||||
var ch = this.text.charAt(this.index);
|
||||
if (ch == '"' || ch == "'") {
|
||||
this.readString(ch);
|
||||
canStartRegExp = true;
|
||||
} else if (ch == '(' || ch == '[') {
|
||||
tokens.push({index:this.index, text:ch});
|
||||
this.index++;
|
||||
} else if (ch == '{' ) {
|
||||
var peekCh = this.peek();
|
||||
if (peekCh == ':' || peekCh == '(') {
|
||||
tokens.push({index:this.index, text:ch + peekCh});
|
||||
this.index++;
|
||||
} else {
|
||||
tokens.push({index:this.index, text:ch});
|
||||
}
|
||||
this.index++;
|
||||
canStartRegExp = true;
|
||||
} else if (ch == ')' || ch == ']' || ch == '}' ) {
|
||||
tokens.push({index:this.index, text:ch});
|
||||
this.index++;
|
||||
canStartRegExp = false;
|
||||
} else if ( ch == ':' || ch == '.' || ch == ',' || ch == ';') {
|
||||
tokens.push({index:this.index, text:ch});
|
||||
this.index++;
|
||||
canStartRegExp = true;
|
||||
} else if ( canStartRegExp && ch == '/' ) {
|
||||
this.readRegexp();
|
||||
canStartRegExp = false;
|
||||
} else if ( this.isNumber(ch) ) {
|
||||
this.readNumber();
|
||||
canStartRegExp = false;
|
||||
} else if (this.isIdent(ch)) {
|
||||
this.readIdent();
|
||||
canStartRegExp = false;
|
||||
} else if (this.isWhitespace(ch)) {
|
||||
this.index++;
|
||||
} else {
|
||||
var ch2 = ch + this.peek();
|
||||
var fn = OPERATORS[ch];
|
||||
var fn2 = OPERATORS[ch2];
|
||||
if (fn2) {
|
||||
tokens.push({index:this.index, text:ch2, fn:fn2});
|
||||
this.index += 2;
|
||||
} else if (fn) {
|
||||
tokens.push({index:this.index, text:ch, fn:fn});
|
||||
this.index += 1;
|
||||
} else {
|
||||
throw "Lexer Error: Unexpected next character [" +
|
||||
this.text.substring(this.index) +
|
||||
"] in expression '" + this.text +
|
||||
"' at column '" + (this.index+1) + "'.";
|
||||
}
|
||||
canStartRegExp = true;
|
||||
}
|
||||
}
|
||||
return tokens;
|
||||
},
|
||||
|
||||
isNumber: function(ch) {
|
||||
return '0' <= ch && ch <= '9';
|
||||
},
|
||||
|
||||
isWhitespace: function(ch) {
|
||||
return ch == ' ' || ch == '\r' || ch == '\t' ||
|
||||
ch == '\n' || ch == '\v';
|
||||
},
|
||||
|
||||
isIdent: function(ch) {
|
||||
return 'a' <= ch && ch <= 'z' ||
|
||||
'A' <= ch && ch <= 'Z' ||
|
||||
'_' == ch || ch == '$';
|
||||
},
|
||||
|
||||
readNumber: function() {
|
||||
var number = "";
|
||||
var start = this.index;
|
||||
while (this.index < this.text.length) {
|
||||
var ch = this.text.charAt(this.index);
|
||||
if (ch == '.' || this.isNumber(ch)) {
|
||||
number += ch;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
this.index++;
|
||||
}
|
||||
number = 1 * number;
|
||||
this.tokens.push({index:start, text:number,
|
||||
fn:function(){return number;}});
|
||||
},
|
||||
|
||||
readIdent: function() {
|
||||
var ident = "";
|
||||
var start = this.index;
|
||||
while (this.index < this.text.length) {
|
||||
var ch = this.text.charAt(this.index);
|
||||
if (ch == '.' || this.isIdent(ch) || this.isNumber(ch)) {
|
||||
ident += ch;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
this.index++;
|
||||
}
|
||||
var fn = Lexer.OPERATORS[ident];
|
||||
if (!fn) {
|
||||
fn = getterFn(ident);
|
||||
fn.isAssignable = ident;
|
||||
}
|
||||
this.tokens.push({index:start, text:ident, fn:fn});
|
||||
},
|
||||
|
||||
readString: function(quote) {
|
||||
var start = this.index;
|
||||
var dateParseLength = this.dateParseLength;
|
||||
this.index++;
|
||||
var string = "";
|
||||
var rawString = quote;
|
||||
var escape = false;
|
||||
while (this.index < this.text.length) {
|
||||
var ch = this.text.charAt(this.index);
|
||||
rawString += ch;
|
||||
if (escape) {
|
||||
if (ch == 'u') {
|
||||
var hex = this.text.substring(this.index + 1, this.index + 5);
|
||||
this.index += 4;
|
||||
string += String.fromCharCode(parseInt(hex, 16));
|
||||
} else {
|
||||
var rep = Lexer.ESCAPE[ch];
|
||||
if (rep) {
|
||||
string += rep;
|
||||
} else {
|
||||
string += ch;
|
||||
}
|
||||
}
|
||||
escape = false;
|
||||
} else if (ch == '\\') {
|
||||
escape = true;
|
||||
} else if (ch == quote) {
|
||||
this.index++;
|
||||
this.tokens.push({index:start, text:rawString, string:string,
|
||||
fn:function(){
|
||||
return (string.length == dateParseLength) ?
|
||||
angular['String']['toDate'](string) : string;
|
||||
}});
|
||||
return;
|
||||
} else {
|
||||
string += ch;
|
||||
}
|
||||
this.index++;
|
||||
}
|
||||
throw "Lexer Error: Unterminated quote [" +
|
||||
this.text.substring(start) + "] starting at column '" +
|
||||
(start+1) + "' in expression '" + this.text + "'.";
|
||||
},
|
||||
|
||||
readRegexp: function(quote) {
|
||||
var start = this.index;
|
||||
this.index++;
|
||||
var regexp = "";
|
||||
var escape = false;
|
||||
while (this.index < this.text.length) {
|
||||
var ch = this.text.charAt(this.index);
|
||||
if (escape) {
|
||||
regexp += ch;
|
||||
escape = false;
|
||||
} else if (ch === '\\') {
|
||||
regexp += ch;
|
||||
escape = true;
|
||||
} else if (ch === '/') {
|
||||
this.index++;
|
||||
var flags = "";
|
||||
if (this.isIdent(this.text.charAt(this.index))) {
|
||||
this.readIdent();
|
||||
flags = this.tokens.pop().text;
|
||||
}
|
||||
var compiledRegexp = new RegExp(regexp, flags);
|
||||
this.tokens.push({index:start, text:regexp, flags:flags,
|
||||
fn:function(){return compiledRegexp;}});
|
||||
return;
|
||||
} else {
|
||||
regexp += ch;
|
||||
}
|
||||
this.index++;
|
||||
}
|
||||
throw "Lexer Error: Unterminated RegExp [" +
|
||||
this.text.substring(start) + "] starting at column '" +
|
||||
(start+1) + "' in expression '" + this.text + "'.";
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////
|
||||
|
||||
function Parser(text, parseStrings){
|
||||
this.text = text;
|
||||
this.tokens = new Lexer(text, parseStrings).parse();
|
||||
this.index = 0;
|
||||
}
|
||||
|
||||
Parser.ZERO = function(){
|
||||
return 0;
|
||||
};
|
||||
|
||||
Parser.prototype = {
|
||||
error: function(msg, token) {
|
||||
throw "Token '" + token.text +
|
||||
"' is " + msg + " at column='" +
|
||||
(token.index + 1) + "' of expression '" +
|
||||
this.text + "' starting at '" + this.text.substring(token.index) + "'.";
|
||||
},
|
||||
|
||||
peekToken: function() {
|
||||
if (this.tokens.length === 0)
|
||||
throw "Unexpected end of expression: " + this.text;
|
||||
return this.tokens[0];
|
||||
},
|
||||
|
||||
peek: function(e1, e2, e3, e4) {
|
||||
var tokens = this.tokens;
|
||||
if (tokens.length > 0) {
|
||||
var token = tokens[0];
|
||||
var t = token.text;
|
||||
if (t==e1 || t==e2 || t==e3 || t==e4 ||
|
||||
(!e1 && !e2 && !e3 && !e4)) {
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
expect: function(e1, e2, e3, e4){
|
||||
var token = this.peek(e1, e2, e3, e4);
|
||||
if (token) {
|
||||
this.tokens.shift();
|
||||
this.currentToken = token;
|
||||
return token;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
consume: function(e1){
|
||||
if (!this.expect(e1)) {
|
||||
var token = this.peek();
|
||||
throw "Expecting '" + e1 + "' at column '" +
|
||||
(token.index+1) + "' in '" +
|
||||
this.text + "' got '" +
|
||||
this.text.substring(token.index) + "'.";
|
||||
}
|
||||
},
|
||||
|
||||
_unary: function(fn, right) {
|
||||
return function(self) {
|
||||
return fn(self, right(self));
|
||||
};
|
||||
},
|
||||
|
||||
_binary: function(left, fn, right) {
|
||||
return function(self) {
|
||||
return fn(self, left(self), right(self));
|
||||
};
|
||||
},
|
||||
|
||||
hasTokens: function () {
|
||||
return this.tokens.length > 0;
|
||||
},
|
||||
|
||||
assertAllConsumed: function(){
|
||||
if (this.tokens.length !== 0) {
|
||||
throw "Did not understand '" + this.text.substring(this.tokens[0].index) +
|
||||
"' while evaluating '" + this.text + "'.";
|
||||
}
|
||||
},
|
||||
|
||||
statements: function(){
|
||||
var statements = [];
|
||||
while(true) {
|
||||
if (this.tokens.length > 0 && !this.peek('}', ')', ';', ']'))
|
||||
statements.push(this.filterChain());
|
||||
if (!this.expect(';')) {
|
||||
return function (self){
|
||||
var value;
|
||||
for ( var i = 0; i < statements.length; i++) {
|
||||
var statement = statements[i];
|
||||
if (statement)
|
||||
value = statement(self);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
filterChain: function(){
|
||||
var left = this.expression();
|
||||
var token;
|
||||
while(true) {
|
||||
if ((token = this.expect('|'))) {
|
||||
left = this._binary(left, token.fn, this.filter());
|
||||
} else {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
filter: function(){
|
||||
return this._pipeFunction(angularFilter);
|
||||
},
|
||||
|
||||
validator: function(){
|
||||
return this._pipeFunction(angularValidator);
|
||||
},
|
||||
|
||||
_pipeFunction: function(fnScope){
|
||||
var fn = this.functionIdent(fnScope);
|
||||
var argsFn = [];
|
||||
var token;
|
||||
while(true) {
|
||||
if ((token = this.expect(':'))) {
|
||||
argsFn.push(this.expression());
|
||||
} else {
|
||||
var fnInvoke = function(self, input){
|
||||
var args = [input];
|
||||
for ( var i = 0; i < argsFn.length; i++) {
|
||||
args.push(argsFn[i](self));
|
||||
}
|
||||
return fn.apply(self, args);
|
||||
};
|
||||
return function(){
|
||||
return fnInvoke;
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
expression: function(){
|
||||
return this.throwStmt();
|
||||
},
|
||||
|
||||
throwStmt: function(){
|
||||
if (this.expect('throw')) {
|
||||
var throwExp = this.assignment();
|
||||
return function (self) {
|
||||
throw throwExp(self);
|
||||
};
|
||||
} else {
|
||||
return this.assignment();
|
||||
}
|
||||
},
|
||||
|
||||
assignment: function(){
|
||||
var left = this.logicalOR();
|
||||
var token;
|
||||
if (token = this.expect('=')) {
|
||||
if (!left.isAssignable) {
|
||||
throw "Left hand side '" +
|
||||
this.text.substring(0, token.index) + "' of assignment '" +
|
||||
this.text.substring(token.index) + "' is not assignable.";
|
||||
}
|
||||
var ident = function(){return left.isAssignable;};
|
||||
return this._binary(ident, token.fn, this.logicalOR());
|
||||
} else {
|
||||
return left;
|
||||
}
|
||||
},
|
||||
|
||||
logicalOR: function(){
|
||||
var left = this.logicalAND();
|
||||
var token;
|
||||
while(true) {
|
||||
if ((token = this.expect('||'))) {
|
||||
left = this._binary(left, token.fn, this.logicalAND());
|
||||
} else {
|
||||
return left;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
logicalAND: function(){
|
||||
var left = this.equality();
|
||||
var token;
|
||||
if ((token = this.expect('&&'))) {
|
||||
left = this._binary(left, token.fn, this.logicalAND());
|
||||
}
|
||||
return left;
|
||||
},
|
||||
|
||||
equality: function(){
|
||||
var left = this.relational();
|
||||
var token;
|
||||
if ((token = this.expect('==','!='))) {
|
||||
left = this._binary(left, token.fn, this.equality());
|
||||
}
|
||||
return left;
|
||||
},
|
||||
|
||||
relational: function(){
|
||||
var left = this.additive();
|
||||
var token;
|
||||
if (token = this.expect('<', '>', '<=', '>=')) {
|
||||
left = this._binary(left, token.fn, this.relational());
|
||||
}
|
||||
return left;
|
||||
},
|
||||
|
||||
additive: function(){
|
||||
var left = this.multiplicative();
|
||||
var token;
|
||||
while(token = this.expect('+','-')) {
|
||||
left = this._binary(left, token.fn, this.multiplicative());
|
||||
}
|
||||
return left;
|
||||
},
|
||||
|
||||
multiplicative: function(){
|
||||
var left = this.unary();
|
||||
var token;
|
||||
while(token = this.expect('*','/','%')) {
|
||||
left = this._binary(left, token.fn, this.unary());
|
||||
}
|
||||
return left;
|
||||
},
|
||||
|
||||
unary: function(){
|
||||
var token;
|
||||
if (this.expect('+')) {
|
||||
return this.primary();
|
||||
} else if (token = this.expect('-')) {
|
||||
return this._binary(Parser.ZERO, token.fn, this.unary());
|
||||
} else if (token = this.expect('!')) {
|
||||
return this._unary(token.fn, this.unary());
|
||||
} else {
|
||||
return this.primary();
|
||||
}
|
||||
},
|
||||
|
||||
functionIdent: function(fnScope) {
|
||||
var token = this.expect();
|
||||
var element = token.text.split('.');
|
||||
var instance = fnScope;
|
||||
var key;
|
||||
for ( var i = 0; i < element.length; i++) {
|
||||
key = element[i];
|
||||
if (instance)
|
||||
instance = instance[key];
|
||||
}
|
||||
if (typeof instance != 'function') {
|
||||
throw "Function '" + token.text + "' at column '" +
|
||||
(token.index+1) + "' in '" + this.text + "' is not defined.";
|
||||
}
|
||||
return instance;
|
||||
},
|
||||
|
||||
primary: function() {
|
||||
var primary;
|
||||
if (this.expect('(')) {
|
||||
var expression = this.filterChain();
|
||||
this.consume(')');
|
||||
primary = expression;
|
||||
} else if (this.expect('[')) {
|
||||
primary = this.arrayDeclaration();
|
||||
} else if (this.expect('{')) {
|
||||
primary = this.object();
|
||||
} else if (this.expect('{:')) {
|
||||
primary = this.closure(false);
|
||||
} else if (this.expect('{(')) {
|
||||
primary = this.closure(true);
|
||||
} else {
|
||||
var token = this.expect();
|
||||
primary = token.fn;
|
||||
if (!primary) {
|
||||
this.error("not a primary expression", token);
|
||||
}
|
||||
}
|
||||
var next;
|
||||
while (next = this.expect('(', '[', '.')) {
|
||||
if (next.text === '(') {
|
||||
primary = this.functionCall(primary);
|
||||
} else if (next.text === '[') {
|
||||
primary = this.objectIndex(primary);
|
||||
} else if (next.text === '.') {
|
||||
primary = this.fieldAccess(primary);
|
||||
} else {
|
||||
throw "IMPOSSIBLE";
|
||||
}
|
||||
}
|
||||
return primary;
|
||||
},
|
||||
|
||||
closure: function(hasArgs) {
|
||||
var args = [];
|
||||
if (hasArgs) {
|
||||
if (!this.expect(')')) {
|
||||
args.push(this.expect().text);
|
||||
while(this.expect(',')) {
|
||||
args.push(this.expect().text);
|
||||
}
|
||||
this.consume(')');
|
||||
}
|
||||
this.consume(":");
|
||||
}
|
||||
var statements = this.statements();
|
||||
this.consume("}");
|
||||
return function(self) {
|
||||
return function($){
|
||||
var scope = createScope(self);
|
||||
scope['$'] = $;
|
||||
for ( var i = 0; i < args.length; i++) {
|
||||
setter(scope, args[i], arguments[i]);
|
||||
}
|
||||
return statements(scope);
|
||||
};
|
||||
};
|
||||
},
|
||||
|
||||
fieldAccess: function(object) {
|
||||
var field = this.expect().text;
|
||||
var getter = getterFn(field);
|
||||
var fn = function (self){
|
||||
return getter(object(self));
|
||||
};
|
||||
fn.isAssignable = field;
|
||||
return fn;
|
||||
},
|
||||
|
||||
objectIndex: function(obj) {
|
||||
var indexFn = this.expression();
|
||||
this.consume(']');
|
||||
if (this.expect('=')) {
|
||||
var rhs = this.expression();
|
||||
return function (self){
|
||||
return obj(self)[indexFn(self)] = rhs(self);
|
||||
};
|
||||
} else {
|
||||
return function (self){
|
||||
var o = obj(self);
|
||||
var i = indexFn(self);
|
||||
return (o) ? o[i] : undefined;
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
functionCall: function(fn) {
|
||||
var argsFn = [];
|
||||
if (this.peekToken().text != ')') {
|
||||
do {
|
||||
argsFn.push(this.expression());
|
||||
} while (this.expect(','));
|
||||
}
|
||||
this.consume(')');
|
||||
return function (self){
|
||||
var args = [];
|
||||
for ( var i = 0; i < argsFn.length; i++) {
|
||||
args.push(argsFn[i](self));
|
||||
}
|
||||
var fnPtr = fn(self);
|
||||
if (typeof fnPtr === 'function') {
|
||||
return fnPtr.apply(self, args);
|
||||
} else {
|
||||
throw "Expression '" + fn.isAssignable + "' is not a function.";
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
// This is used with json array declaration
|
||||
arrayDeclaration: function () {
|
||||
var elementFns = [];
|
||||
if (this.peekToken().text != ']') {
|
||||
do {
|
||||
elementFns.push(this.expression());
|
||||
} while (this.expect(','));
|
||||
}
|
||||
this.consume(']');
|
||||
return function (self){
|
||||
var array = [];
|
||||
for ( var i = 0; i < elementFns.length; i++) {
|
||||
array.push(elementFns[i](self));
|
||||
}
|
||||
return array;
|
||||
};
|
||||
},
|
||||
|
||||
object: function () {
|
||||
var keyValues = [];
|
||||
if (this.peekToken().text != '}') {
|
||||
do {
|
||||
var token = this.expect(),
|
||||
key = token.string || token.text;
|
||||
this.consume(":");
|
||||
var value = this.expression();
|
||||
keyValues.push({key:key, value:value});
|
||||
} while (this.expect(','));
|
||||
}
|
||||
this.consume('}');
|
||||
return function (self){
|
||||
var object = {};
|
||||
for ( var i = 0; i < keyValues.length; i++) {
|
||||
var keyValue = keyValues[i];
|
||||
var value = keyValue.value(self);
|
||||
object[keyValue.key] = value;
|
||||
}
|
||||
return object;
|
||||
};
|
||||
},
|
||||
|
||||
entityDeclaration: function () {
|
||||
var decl = [];
|
||||
while(this.hasTokens()) {
|
||||
decl.push(this.entityDecl());
|
||||
if (!this.expect(';')) {
|
||||
this.assertAllConsumed();
|
||||
}
|
||||
}
|
||||
return function (self){
|
||||
var code = "";
|
||||
for ( var i = 0; i < decl.length; i++) {
|
||||
code += decl[i](self);
|
||||
}
|
||||
return code;
|
||||
};
|
||||
},
|
||||
|
||||
entityDecl: function () {
|
||||
var entity = this.expect().text;
|
||||
var instance;
|
||||
var defaults;
|
||||
if (this.expect('=')) {
|
||||
instance = entity;
|
||||
entity = this.expect().text;
|
||||
}
|
||||
if (this.expect(':')) {
|
||||
defaults = this.primary()(null);
|
||||
}
|
||||
return function(self) {
|
||||
var Entity = self.datastore.entity(entity, defaults);
|
||||
setter(self, entity, Entity);
|
||||
if (instance) {
|
||||
var document = Entity();
|
||||
document['$$anchor'] = instance;
|
||||
setter(self, instance, document);
|
||||
return "$anchor." + instance + ":{" +
|
||||
instance + "=" + entity + ".load($anchor." + instance + ");" +
|
||||
instance + ".$$anchor=" + angular['String']['quote'](instance) + ";" +
|
||||
"};";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
watch: function () {
|
||||
var decl = [];
|
||||
while(this.hasTokens()) {
|
||||
decl.push(this.watchDecl());
|
||||
if (!this.expect(';')) {
|
||||
this.assertAllConsumed();
|
||||
}
|
||||
}
|
||||
this.assertAllConsumed();
|
||||
return function (self){
|
||||
for ( var i = 0; i < decl.length; i++) {
|
||||
var d = decl[i](self);
|
||||
self.addListener(d.name, d.fn);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
watchDecl: function () {
|
||||
var anchorName = this.expect().text;
|
||||
this.consume(":");
|
||||
var expression;
|
||||
if (this.peekToken().text == '{') {
|
||||
this.consume("{");
|
||||
expression = this.statements();
|
||||
this.consume("}");
|
||||
} else {
|
||||
expression = this.expression();
|
||||
}
|
||||
return function(self) {
|
||||
return {name:anchorName, fn:expression};
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
140
src/Resource.js
Normal file
140
src/Resource.js
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
function Route(template, defaults) {
|
||||
this.template = template = template + '#';
|
||||
this.defaults = defaults || {};
|
||||
var urlParams = this.urlParams = {};
|
||||
foreach(template.split(/\W/), function(param){
|
||||
if (param && template.match(new RegExp(":" + param + "\\W"))) {
|
||||
urlParams[param] = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Route.prototype = {
|
||||
url: function(params) {
|
||||
var path = [];
|
||||
var self = this;
|
||||
var url = this.template;
|
||||
params = params || {};
|
||||
foreach(this.urlParams, function(_, urlParam){
|
||||
var value = params[urlParam] || self.defaults[urlParam] || "";
|
||||
url = url.replace(new RegExp(":" + urlParam + "(\\W)"), value + "$1");
|
||||
});
|
||||
url = url.replace(/\/?#$/, '');
|
||||
var query = [];
|
||||
foreachSorted(params, function(value, key){
|
||||
if (!self.urlParams[key]) {
|
||||
query.push(encodeURI(key) + '=' + encodeURI(value));
|
||||
}
|
||||
});
|
||||
return url + (query.length ? '?' + query.join('&') : '');
|
||||
}
|
||||
};
|
||||
|
||||
function ResourceFactory(xhr) {
|
||||
this.xhr = xhr;
|
||||
}
|
||||
|
||||
ResourceFactory.DEFAULT_ACTIONS = {
|
||||
'get': {method:'GET'},
|
||||
'save': {method:'POST'},
|
||||
'query': {method:'GET', isArray:true},
|
||||
'remove': {method:'DELETE'},
|
||||
'delete': {method:'DELETE'}
|
||||
};
|
||||
|
||||
ResourceFactory.prototype = {
|
||||
route: function(url, paramDefaults, actions){
|
||||
var self = this;
|
||||
var route = new Route(url);
|
||||
actions = extend({}, ResourceFactory.DEFAULT_ACTIONS, actions);
|
||||
function extractParams(data){
|
||||
var ids = {};
|
||||
foreach(paramDefaults || {}, function(value, key){
|
||||
ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
|
||||
});
|
||||
return ids;
|
||||
}
|
||||
|
||||
function Resource(value){
|
||||
copy(value || {}, this);
|
||||
}
|
||||
|
||||
foreach(actions, function(action, name){
|
||||
var isGet = action.method == 'GET';
|
||||
var isPost = action.method == 'POST';
|
||||
Resource[name] = function (a1, a2, a3) {
|
||||
var params = {};
|
||||
var data;
|
||||
var callback = noop;
|
||||
switch(arguments.length) {
|
||||
case 3: callback = a3;
|
||||
case 2:
|
||||
if (isFunction(a2)) {
|
||||
callback = a2;
|
||||
} else {
|
||||
params = a1;
|
||||
data = a2;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
if (isFunction(a1)) callback = a1;
|
||||
else if (isPost) data = a1;
|
||||
else params = a1;
|
||||
break;
|
||||
case 0: break;
|
||||
default:
|
||||
throw "Expected between 0-3 arguments [params, data, callback], got " + arguments.length + " arguments.";
|
||||
}
|
||||
|
||||
var value = action.isArray ? [] : new Resource(data;)
|
||||
self.xhr(
|
||||
action.method,
|
||||
route.url(extend({}, action.params || {}, extractParams(data), params)),
|
||||
data,
|
||||
function(status, response, clear) {
|
||||
if (status == 200) {
|
||||
if (action.isArray) {
|
||||
if (action.cacheThenRetrieve)
|
||||
value = [];
|
||||
foreach(response, function(item){
|
||||
value.push(new Resource(item));
|
||||
});
|
||||
} else {
|
||||
copy(response, value);
|
||||
}
|
||||
(callback||noop)(value);
|
||||
} else {
|
||||
throw {status: status, response:response, message: status + ": " + response};
|
||||
}
|
||||
},
|
||||
action.cacheThenRetrieve
|
||||
);
|
||||
return value;
|
||||
};
|
||||
|
||||
Resource.bind = function(additionalParamDefaults){
|
||||
return self.route(url, extend({}, paramDefaults, additionalParamDefaults), actions);
|
||||
};
|
||||
|
||||
if (!isGet) {
|
||||
Resource.prototype['$' + name] = function(a1, a2){
|
||||
var params = {};
|
||||
var callback = noop;
|
||||
switch(arguments.length) {
|
||||
case 2: params = a1; callback = a2;
|
||||
case 1: if (typeof a1 == 'function') callback = a1; else params = a1;
|
||||
case 0: break;
|
||||
default:
|
||||
throw "Expected between 1-2 arguments [params, callback], got " + arguments.length + " arguments.";
|
||||
}
|
||||
var self = this;
|
||||
Resource[name](params, this, function(response){
|
||||
copy(response, self);
|
||||
callback(self);
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
return Resource;
|
||||
}
|
||||
};
|
||||
224
src/Scope.js
Normal file
224
src/Scope.js
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
function getter(instance, path, unboundFn) {
|
||||
if (!path) return instance;
|
||||
var element = path.split('.');
|
||||
var key;
|
||||
var lastInstance = instance;
|
||||
var len = element.length;
|
||||
for ( var i = 0; i < len; i++) {
|
||||
key = element[i];
|
||||
if (!key.match(/^[\$\w][\$\w\d]*$/))
|
||||
throw "Expression '" + path + "' is not a valid expression for accesing variables.";
|
||||
if (instance) {
|
||||
lastInstance = instance;
|
||||
instance = instance[key];
|
||||
}
|
||||
if (isUndefined(instance) && key.charAt(0) == '$') {
|
||||
var type = angular['Global']['typeOf'](lastInstance);
|
||||
type = angular[type.charAt(0).toUpperCase()+type.substring(1)];
|
||||
var fn = type ? type[[key.substring(1)]] : undefined;
|
||||
if (fn) {
|
||||
instance = bind(lastInstance, fn, lastInstance);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!unboundFn && isFunction(instance) && !instance['$$factory']) {
|
||||
return bind(lastInstance, instance);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
function setter(instance, path, value){
|
||||
var element = path.split('.');
|
||||
for ( var i = 0; element.length > 1; i++) {
|
||||
var key = element.shift();
|
||||
var newInstance = instance[key];
|
||||
if (!newInstance) {
|
||||
newInstance = {};
|
||||
instance[key] = newInstance;
|
||||
}
|
||||
instance = newInstance;
|
||||
}
|
||||
instance[element.shift()] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
var getterFnCache = {};
|
||||
function getterFn(path){
|
||||
var fn = getterFnCache[path];
|
||||
if (fn) return fn;
|
||||
|
||||
var code = 'function (self){\n';
|
||||
code += ' var last, fn, type;\n';
|
||||
foreach(path.split('.'), function(key) {
|
||||
key = (key == 'this') ? '["this"]' : '.' + key;
|
||||
code += ' if(!self) return self;\n';
|
||||
code += ' last = self;\n';
|
||||
code += ' self = self' + key + ';\n';
|
||||
code += ' if(typeof self == "function") \n';
|
||||
code += ' self = function(){ return last'+key+'.apply(last, arguments); };\n';
|
||||
if (key.charAt(1) == '$') {
|
||||
// special code for super-imposed functions
|
||||
var name = key.substr(2);
|
||||
code += ' if(!self) {\n';
|
||||
code += ' type = angular.Global.typeOf(last);\n';
|
||||
code += ' fn = (angular[type.charAt(0).toUpperCase() + type.substring(1)]||{})["' + name + '"];\n';
|
||||
code += ' if (fn)\n';
|
||||
code += ' self = function(){ return fn.apply(last, [last].concat(slice.call(arguments, 0, arguments.length))); };\n';
|
||||
code += ' }\n';
|
||||
}
|
||||
});
|
||||
code += ' return self;\n}';
|
||||
fn = eval('(' + code + ')');
|
||||
fn.toString = function(){ return code; };
|
||||
|
||||
return getterFnCache[path] = fn;
|
||||
}
|
||||
|
||||
///////////////////////////////////
|
||||
|
||||
var compileCache = {};
|
||||
function expressionCompile(exp){
|
||||
if (isFunction(exp)) return exp;
|
||||
var fn = compileCache[exp];
|
||||
if (!fn) {
|
||||
var parser = new Parser(exp);
|
||||
var fnSelf = parser.statements();
|
||||
parser.assertAllConsumed();
|
||||
fn = compileCache[exp] = extend(
|
||||
function(){ return fnSelf(this);},
|
||||
{fnSelf: fnSelf});
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
|
||||
function rethrow(e) { throw e; }
|
||||
function errorHandlerFor(element, error) {
|
||||
elementError(element, NG_EXCEPTION, isDefined(error) ? toJson(error) : error);
|
||||
}
|
||||
|
||||
var scopeId = 0;
|
||||
function createScope(parent, services, existing) {
|
||||
function Parent(){}
|
||||
function API(){}
|
||||
function Behavior(){}
|
||||
|
||||
var instance, behavior, api, evalLists = {sorted:[]}, servicesCache = extend({}, existing);
|
||||
|
||||
parent = Parent.prototype = (parent || {});
|
||||
api = API.prototype = new Parent();
|
||||
behavior = Behavior.prototype = new API();
|
||||
instance = new Behavior();
|
||||
|
||||
extend(api, {
|
||||
'this': instance,
|
||||
$id: (scopeId++),
|
||||
$parent: parent,
|
||||
$bind: bind(instance, bind, instance),
|
||||
$get: bind(instance, getter, instance),
|
||||
$set: bind(instance, setter, instance),
|
||||
|
||||
$eval: function $eval(exp) {
|
||||
if (exp !== undefined) {
|
||||
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
|
||||
} else {
|
||||
for ( var i = 0, iSize = evalLists.sorted.length; i < iSize; i++) {
|
||||
for ( var queue = evalLists.sorted[i],
|
||||
jSize = queue.length,
|
||||
j= 0; j < jSize; j++) {
|
||||
instance.$tryEval(queue[j].fn, queue[j].handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
$tryEval: function (expression, exceptionHandler) {
|
||||
try {
|
||||
return expressionCompile(expression).apply(instance, slice.call(arguments, 2, arguments.length));
|
||||
} catch (e) {
|
||||
error(e);
|
||||
if (isFunction(exceptionHandler)) {
|
||||
exceptionHandler(e);
|
||||
} else if (exceptionHandler) {
|
||||
errorHandlerFor(exceptionHandler, e);
|
||||
} else if (isFunction(instance.$exceptionHandler)) {
|
||||
instance.$exceptionHandler(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
$watch: function(watchExp, listener, exceptionHandler) {
|
||||
var watch = expressionCompile(watchExp),
|
||||
last;
|
||||
function watcher(){
|
||||
var value = watch.call(instance),
|
||||
lastValue = last;
|
||||
if (last !== value) {
|
||||
last = value;
|
||||
instance.$tryEval(listener, exceptionHandler, value, lastValue);
|
||||
}
|
||||
}
|
||||
instance.$onEval(PRIORITY_WATCH, watcher);
|
||||
watcher();
|
||||
},
|
||||
|
||||
$onEval: function(priority, expr, exceptionHandler){
|
||||
if (!isNumber(priority)) {
|
||||
exceptionHandler = expr;
|
||||
expr = priority;
|
||||
priority = 0;
|
||||
}
|
||||
var evalList = evalLists[priority];
|
||||
if (!evalList) {
|
||||
evalList = evalLists[priority] = [];
|
||||
evalList.priority = priority;
|
||||
evalLists.sorted.push(evalList);
|
||||
evalLists.sorted.sort(function(a,b){return a.priority-b.priority;});
|
||||
}
|
||||
evalList.push({
|
||||
fn: expressionCompile(expr),
|
||||
handler: exceptionHandler
|
||||
});
|
||||
},
|
||||
|
||||
$become: function(Class) {
|
||||
// remove existing
|
||||
foreach(behavior, function(value, key){ delete behavior[key]; });
|
||||
foreach((Class || noop).prototype, function(fn, name){
|
||||
behavior[name] = bind(instance, fn);
|
||||
});
|
||||
(Class || noop).call(instance);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (!parent.$root) {
|
||||
api.$root = instance;
|
||||
api.$parent = instance;
|
||||
}
|
||||
|
||||
function inject(name){
|
||||
var service = servicesCache[name], factory, args = [];
|
||||
if (isUndefined(service)) {
|
||||
factory = services[name];
|
||||
if (!isFunction(factory))
|
||||
throw "Don't know how to inject '" + name + "'.";
|
||||
foreach(factory.inject, function(dependency){
|
||||
args.push(inject(dependency));
|
||||
});
|
||||
servicesCache[name] = service = factory.apply(instance, args);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
foreach(services, function(_, name){
|
||||
var service = inject(name);
|
||||
if (service) {
|
||||
setter(instance, name, service);
|
||||
}
|
||||
});
|
||||
|
||||
return instance;
|
||||
}
|
||||
70
src/angular-bootstrap.js
vendored
Normal file
70
src/angular-bootstrap.js
vendored
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
(function(previousOnLoad){
|
||||
var filename = /(.*)\/angular-(.*).js(#(.*))?/,
|
||||
scripts = document.getElementsByTagName("SCRIPT"),
|
||||
serverPath,
|
||||
config,
|
||||
match;
|
||||
for(var j = 0; j < scripts.length; j++) {
|
||||
match = (scripts[j].src || "").match(filename);
|
||||
if (match) {
|
||||
serverPath = match[1];
|
||||
config = match[4];
|
||||
}
|
||||
}
|
||||
|
||||
function addScript(file){
|
||||
document.write('<script type="text/javascript" src="' + serverPath + file +'"></script>');
|
||||
}
|
||||
|
||||
addScript("/Angular.js");
|
||||
addScript("/JSON.js");
|
||||
addScript("/Compiler.js");
|
||||
addScript("/Scope.js");
|
||||
addScript("/jqLite.js");
|
||||
addScript("/Parser.js");
|
||||
addScript("/Resource.js");
|
||||
addScript("/Browser.js");
|
||||
addScript("/AngularPublic.js");
|
||||
|
||||
// Extension points
|
||||
addScript("/services.js");
|
||||
addScript("/apis.js");
|
||||
addScript("/filters.js");
|
||||
addScript("/formatters.js");
|
||||
addScript("/validators.js");
|
||||
addScript("/directives.js");
|
||||
addScript("/markups.js");
|
||||
addScript("/widgets.js");
|
||||
|
||||
window.onload = function(){
|
||||
try {
|
||||
if (previousOnLoad) previousOnLoad();
|
||||
} catch(e) {}
|
||||
angularInit(parseKeyValue(config));
|
||||
};
|
||||
|
||||
})(window.onload);
|
||||
|
||||
24
src/angular.prefix
Normal file
24
src/angular.prefix
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
(function(window, document, previousOnLoad){
|
||||
9
src/angular.suffix
Normal file
9
src/angular.suffix
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
window.onload = function(){
|
||||
try {
|
||||
if (previousOnLoad) previousOnLoad();
|
||||
} catch(e) {}
|
||||
angularInit(parseKeyValue(angularJsConfig(document)));
|
||||
};
|
||||
|
||||
})(window, document, window.onload);
|
||||
338
src/apis.js
Normal file
338
src/apis.js
Normal file
|
|
@ -0,0 +1,338 @@
|
|||
var angularGlobal = {
|
||||
'typeOf':function(obj){
|
||||
if (obj === null) return "null";
|
||||
var type = typeof obj;
|
||||
if (type == "object") {
|
||||
if (obj instanceof Array) return "array";
|
||||
if (obj instanceof Date) return "date";
|
||||
if (obj.nodeType == 1) return "element";
|
||||
}
|
||||
return type;
|
||||
}
|
||||
};
|
||||
|
||||
var angularCollection = {
|
||||
'size': size
|
||||
};
|
||||
var angularObject = {
|
||||
'extend': extend
|
||||
};
|
||||
var angularArray = {
|
||||
'indexOf': indexOf,
|
||||
'include': includes,
|
||||
'includeIf':function(array, value, condition) {
|
||||
var index = indexOf(array, value);
|
||||
if (condition) {
|
||||
if (index == -1)
|
||||
array.push(value);
|
||||
} else {
|
||||
array.splice(index, 1);
|
||||
}
|
||||
return array;
|
||||
},
|
||||
'sum':function(array, expression) {
|
||||
var fn = angular['Function']['compile'](expression);
|
||||
var sum = 0;
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
var value = 1 * fn(array[i]);
|
||||
if (!isNaN(value)){
|
||||
sum += value;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
},
|
||||
'remove':function(array, value) {
|
||||
var index = indexOf(array, value);
|
||||
if (index >=0)
|
||||
array.splice(index, 1);
|
||||
return value;
|
||||
},
|
||||
'find':function(array, condition, defaultValue) {
|
||||
if (!condition) return undefined;
|
||||
var fn = angular['Function']['compile'](condition);
|
||||
foreach(array, function($){
|
||||
if (fn($)){
|
||||
defaultValue = $;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
return defaultValue;
|
||||
},
|
||||
'findById':function(array, id) {
|
||||
return angular.Array.find(array, function($){return $.$id == id;}, null);
|
||||
},
|
||||
'filter':function(array, expression) {
|
||||
var predicates = [];
|
||||
predicates.check = function(value) {
|
||||
for (var j = 0; j < predicates.length; j++) {
|
||||
if(!predicates[j](value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
var search = function(obj, text){
|
||||
if (text.charAt(0) === '!') {
|
||||
return !search(obj, text.substr(1));
|
||||
}
|
||||
switch (typeof obj) {
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "string":
|
||||
return ('' + obj).toLowerCase().indexOf(text) > -1;
|
||||
case "object":
|
||||
for ( var objKey in obj) {
|
||||
if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case "array":
|
||||
for ( var i = 0; i < obj.length; i++) {
|
||||
if (search(obj[i], text)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
};
|
||||
switch (typeof expression) {
|
||||
case "boolean":
|
||||
case "number":
|
||||
case "string":
|
||||
expression = {$:expression};
|
||||
case "object":
|
||||
for (var key in expression) {
|
||||
if (key == '$') {
|
||||
(function(){
|
||||
var text = (''+expression[key]).toLowerCase();
|
||||
if (!text) return;
|
||||
predicates.push(function(value) {
|
||||
return search(value, text);
|
||||
});
|
||||
})();
|
||||
} else {
|
||||
(function(){
|
||||
var path = key;
|
||||
var text = (''+expression[key]).toLowerCase();
|
||||
if (!text) return;
|
||||
predicates.push(function(value) {
|
||||
return search(getter(value, path), text);
|
||||
});
|
||||
})();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "function":
|
||||
predicates.push(expression);
|
||||
break;
|
||||
default:
|
||||
return array;
|
||||
}
|
||||
var filtered = [];
|
||||
for ( var j = 0; j < array.length; j++) {
|
||||
var value = array[j];
|
||||
if (predicates.check(value)) {
|
||||
filtered.push(value);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
},
|
||||
'add':function(array, value) {
|
||||
array.push(isUndefined(value)? {} : value);
|
||||
return array;
|
||||
},
|
||||
'count':function(array, condition) {
|
||||
if (!condition) return array.length;
|
||||
var fn = angular['Function']['compile'](condition), count = 0;
|
||||
foreach(array, function(value){
|
||||
if (fn(value)) {
|
||||
count ++;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
},
|
||||
'orderBy':function(array, expression, descend) {
|
||||
function reverse(comp, descending) {
|
||||
return toBoolean(descending) ?
|
||||
function(a,b){return comp(b,a);} : comp;
|
||||
}
|
||||
function compare(v1, v2){
|
||||
var t1 = typeof v1;
|
||||
var t2 = typeof v2;
|
||||
if (t1 == t2) {
|
||||
if (t1 == "string") v1 = v1.toLowerCase();
|
||||
if (t1 == "string") v2 = v2.toLowerCase();
|
||||
if (v1 === v2) return 0;
|
||||
return v1 < v2 ? -1 : 1;
|
||||
} else {
|
||||
return t1 < t2 ? -1 : 1;
|
||||
}
|
||||
}
|
||||
expression = isArray(expression) ? expression: [expression];
|
||||
expression = map(expression, function($){
|
||||
var descending = false;
|
||||
if (typeof $ == "string" && ($.charAt(0) == '+' || $.charAt(0) == '-')) {
|
||||
descending = $.charAt(0) == '-';
|
||||
$ = $.substring(1);
|
||||
}
|
||||
var get = $ ? expressionCompile($).fnSelf : identity;
|
||||
return reverse(function(a,b){
|
||||
return compare(get(a),get(b));
|
||||
}, descending);
|
||||
});
|
||||
var comparator = function(o1, o2){
|
||||
for ( var i = 0; i < expression.length; i++) {
|
||||
var comp = expression[i](o1, o2);
|
||||
if (comp !== 0) return comp;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
var arrayCopy = [];
|
||||
for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); }
|
||||
return arrayCopy.sort(reverse(comparator, descend));
|
||||
},
|
||||
'orderByToggle':function(predicate, attribute) {
|
||||
var STRIP = /^([+|-])?(.*)/;
|
||||
var ascending = false;
|
||||
var index = -1;
|
||||
foreach(predicate, function($, i){
|
||||
if (index == -1) {
|
||||
if ($ == attribute) {
|
||||
ascending = true;
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
if (($.charAt(0)=='+'||$.charAt(0)=='-') && $.substring(1) == attribute) {
|
||||
ascending = $.charAt(0) == '+';
|
||||
index = i;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (index >= 0) {
|
||||
predicate.splice(index, 1);
|
||||
}
|
||||
predicate.unshift((ascending ? "-" : "+") + attribute);
|
||||
return predicate;
|
||||
},
|
||||
'orderByDirection':function(predicate, attribute, ascend, descend) {
|
||||
ascend = ascend || 'ng-ascend';
|
||||
descend = descend || 'ng-descend';
|
||||
var att = predicate[0] || '';
|
||||
var direction = true;
|
||||
if (att.charAt(0) == '-') {
|
||||
att = att.substring(1);
|
||||
direction = false;
|
||||
} else if(att.charAt(0) == '+') {
|
||||
att = att.substring(1);
|
||||
}
|
||||
return att == attribute ? (direction ? ascend : descend) : "";
|
||||
},
|
||||
'merge':function(array, index, mergeValue) {
|
||||
var value = array[index];
|
||||
if (!value) {
|
||||
value = {};
|
||||
array[index] = value;
|
||||
}
|
||||
merge(mergeValue, value);
|
||||
return array;
|
||||
}
|
||||
};
|
||||
|
||||
var angularString = {
|
||||
'quote':function(string) {
|
||||
return '"' + string.replace(/\\/g, '\\\\').
|
||||
replace(/"/g, '\\"').
|
||||
replace(/\n/g, '\\n').
|
||||
replace(/\f/g, '\\f').
|
||||
replace(/\r/g, '\\r').
|
||||
replace(/\t/g, '\\t').
|
||||
replace(/\v/g, '\\v') +
|
||||
'"';
|
||||
},
|
||||
'quoteUnicode':function(string) {
|
||||
var str = angular['String']['quote'](string);
|
||||
var chars = [];
|
||||
for ( var i = 0; i < str.length; i++) {
|
||||
var ch = str.charCodeAt(i);
|
||||
if (ch < 128) {
|
||||
chars.push(str.charAt(i));
|
||||
} else {
|
||||
var encode = "000" + ch.toString(16);
|
||||
chars.push("\\u" + encode.substring(encode.length - 4));
|
||||
}
|
||||
}
|
||||
return chars.join('');
|
||||
},
|
||||
'toDate':function(string){
|
||||
var match;
|
||||
if (typeof string == 'string' &&
|
||||
(match = string.match(/^(\d\d\d\d)-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)Z$/))){
|
||||
var date = new Date(0);
|
||||
date.setUTCFullYear(match[1], match[2] - 1, match[3]);
|
||||
date.setUTCHours(match[4], match[5], match[6], 0);
|
||||
return date;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
};
|
||||
|
||||
var angularDate = {
|
||||
'toString':function(date){
|
||||
function pad(n) { return n < 10 ? "0" + n : n; }
|
||||
return !date ? date :
|
||||
date.getUTCFullYear() + '-' +
|
||||
pad(date.getUTCMonth() + 1) + '-' +
|
||||
pad(date.getUTCDate()) + 'T' +
|
||||
pad(date.getUTCHours()) + ':' +
|
||||
pad(date.getUTCMinutes()) + ':' +
|
||||
pad(date.getUTCSeconds()) + 'Z' ;
|
||||
}
|
||||
};
|
||||
|
||||
var angularFunction = {
|
||||
'compile':function(expression) {
|
||||
if (isFunction(expression)){
|
||||
return expression;
|
||||
} else if (expression){
|
||||
return expressionCompile(expression).fnSelf;
|
||||
} else {
|
||||
return identity;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function defineApi(dst, chain, underscoreNames){
|
||||
if (_) {
|
||||
var lastChain = _.last(chain);
|
||||
foreach(underscoreNames, function(name){
|
||||
lastChain[name] = _[name];
|
||||
});
|
||||
}
|
||||
angular[dst] = angular[dst] || {};
|
||||
foreach(chain, function(parent){
|
||||
extend(angular[dst], parent);
|
||||
});
|
||||
}
|
||||
defineApi('Global', [angularGlobal],
|
||||
['extend', 'clone','isEqual',
|
||||
'isElement', 'isArray', 'isFunction', 'isUndefined']);
|
||||
defineApi('Collection', [angularGlobal, angularCollection],
|
||||
['each', 'map', 'reduce', 'reduceRight', 'detect',
|
||||
'select', 'reject', 'all', 'any', 'include',
|
||||
'invoke', 'pluck', 'max', 'min', 'sortBy',
|
||||
'sortedIndex', 'toArray', 'size']);
|
||||
defineApi('Array', [angularGlobal, angularCollection, angularArray],
|
||||
['first', 'last', 'compact', 'flatten', 'without',
|
||||
'uniq', 'intersect', 'zip', 'indexOf', 'lastIndexOf']);
|
||||
defineApi('Object', [angularGlobal, angularCollection, angularObject],
|
||||
['keys', 'values']);
|
||||
defineApi('String', [angularGlobal, angularString], []);
|
||||
defineApi('Date', [angularGlobal, angularDate], []);
|
||||
//IE bug
|
||||
angular['Date']['toString'] = angularDate['toString'];
|
||||
defineApi('Function', [angularGlobal, angularCollection, angularFunction],
|
||||
['bind', 'bindAll', 'delay', 'defer', 'wrap', 'compose']);
|
||||
356
src/delete/Binder.js
Normal file
356
src/delete/Binder.js
Normal file
|
|
@ -0,0 +1,356 @@
|
|||
function Binder(doc, widgetFactory, datastore, location, config) {
|
||||
this.doc = doc;
|
||||
this.location = location;
|
||||
this.datastore = datastore;
|
||||
this.anchor = {};
|
||||
this.widgetFactory = widgetFactory;
|
||||
this.config = config || {};
|
||||
this.updateListeners = [];
|
||||
}
|
||||
|
||||
Binder.parseBindings = function(string) {
|
||||
var results = [];
|
||||
var lastIndex = 0;
|
||||
var index;
|
||||
while((index = string.indexOf('{{', lastIndex)) > -1) {
|
||||
if (lastIndex < index)
|
||||
results.push(string.substr(lastIndex, index - lastIndex));
|
||||
lastIndex = index;
|
||||
|
||||
index = string.indexOf('}}', index);
|
||||
index = index < 0 ? string.length : index + 2;
|
||||
|
||||
results.push(string.substr(lastIndex, index - lastIndex));
|
||||
lastIndex = index;
|
||||
}
|
||||
if (lastIndex != string.length)
|
||||
results.push(string.substr(lastIndex, string.length - lastIndex));
|
||||
return results.length === 0 ? [ string ] : results;
|
||||
};
|
||||
|
||||
Binder.hasBinding = function(string) {
|
||||
var bindings = Binder.parseBindings(string);
|
||||
return bindings.length > 1 || Binder.binding(bindings[0]) !== null;
|
||||
};
|
||||
|
||||
Binder.binding = function(string) {
|
||||
var binding = string.replace(/\n/gm, ' ').match(/^\{\{(.*)\}\}$/);
|
||||
return binding ? binding[1] : null;
|
||||
};
|
||||
|
||||
|
||||
Binder.prototype = {
|
||||
parseQueryString: function(query) {
|
||||
var params = {};
|
||||
query.replace(/(?:^|&)([^&=]*)=?([^&]*)/g,
|
||||
function (match, left, right) {
|
||||
if (left) params[decodeURIComponent(left)] = decodeURIComponent(right);
|
||||
});
|
||||
return params;
|
||||
},
|
||||
|
||||
parseAnchor: function() {
|
||||
var self = this, url = this.location['get']() || "";
|
||||
|
||||
var anchorIndex = url.indexOf('#');
|
||||
if (anchorIndex < 0) return;
|
||||
var anchor = url.substring(anchorIndex + 1);
|
||||
|
||||
var anchorQuery = this.parseQueryString(anchor);
|
||||
foreach(self.anchor, function(newValue, key) {
|
||||
delete self.anchor[key];
|
||||
});
|
||||
foreach(anchorQuery, function(newValue, key) {
|
||||
self.anchor[key] = newValue;
|
||||
});
|
||||
},
|
||||
|
||||
onUrlChange: function() {
|
||||
this.parseAnchor();
|
||||
this.updateView();
|
||||
},
|
||||
|
||||
updateAnchor: function() {
|
||||
var url = this.location['get']() || "";
|
||||
var anchorIndex = url.indexOf('#');
|
||||
if (anchorIndex > -1)
|
||||
url = url.substring(0, anchorIndex);
|
||||
url += "#";
|
||||
var sep = '';
|
||||
for (var key in this.anchor) {
|
||||
var value = this.anchor[key];
|
||||
if (typeof value === 'undefined' || value === null) {
|
||||
delete this.anchor[key];
|
||||
} else {
|
||||
url += sep + encodeURIComponent(key);
|
||||
if (value !== true)
|
||||
url += "=" + encodeURIComponent(value);
|
||||
sep = '&';
|
||||
}
|
||||
}
|
||||
this.location['set'](url);
|
||||
return url;
|
||||
},
|
||||
|
||||
updateView: function() {
|
||||
var start = new Date().getTime();
|
||||
var scope = jQuery(this.doc).scope();
|
||||
scope.clearInvalid();
|
||||
scope.updateView();
|
||||
var end = new Date().getTime();
|
||||
this.updateAnchor();
|
||||
foreach(this.updateListeners, function(fn) {fn();});
|
||||
},
|
||||
|
||||
docFindWithSelf: function(exp){
|
||||
var doc = jQuery(this.doc);
|
||||
var selection = doc.find(exp);
|
||||
if (doc.is(exp)){
|
||||
selection = selection.andSelf();
|
||||
}
|
||||
return selection;
|
||||
},
|
||||
|
||||
executeInit: function() {
|
||||
this.docFindWithSelf("[ng-init]").each(function() {
|
||||
var jThis = jQuery(this);
|
||||
var scope = jThis.scope();
|
||||
try {
|
||||
scope.eval(jThis.attr('ng-init'));
|
||||
} catch (e) {
|
||||
alert("EVAL ERROR:\n" + jThis.attr('ng-init') + '\n' + toJson(e, true));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
entity: function (scope) {
|
||||
var self = this;
|
||||
this.docFindWithSelf("[ng-entity]").attr("ng-watch", function() {
|
||||
try {
|
||||
var jNode = jQuery(this);
|
||||
var decl = scope.entity(jNode.attr("ng-entity"), self.datastore);
|
||||
return decl + (jNode.attr('ng-watch') || "");
|
||||
} catch (e) {
|
||||
log(e);
|
||||
alert(e);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
compile: function() {
|
||||
var jNode = jQuery(this.doc);
|
||||
if (this.config['autoSubmit']) {
|
||||
var submits = this.docFindWithSelf(":submit").not("[ng-action]");
|
||||
submits.attr("ng-action", "$save()");
|
||||
submits.not(":disabled").not("ng-bind-attr").attr("ng-bind-attr", '{disabled:"{{$invalidWidgets}}"}');
|
||||
}
|
||||
this.precompile(this.doc)(this.doc, jNode.scope(), "");
|
||||
this.docFindWithSelf("a[ng-action]").live('click', function (event) {
|
||||
var jNode = jQuery(this);
|
||||
var scope = jNode.scope();
|
||||
try {
|
||||
scope.eval(jNode.attr('ng-action'));
|
||||
jNode.removeAttr('ng-error');
|
||||
jNode.removeClass("ng-exception");
|
||||
} catch (e) {
|
||||
jNode.addClass("ng-exception");
|
||||
jNode.attr('ng-error', toJson(e, true));
|
||||
}
|
||||
scope.get('$updateView')();
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
translateBinding: function(node, parentPath, factories) {
|
||||
var path = parentPath.concat();
|
||||
var offset = path.pop();
|
||||
var parts = Binder.parseBindings(node.nodeValue);
|
||||
if (parts.length > 1 || Binder.binding(parts[0])) {
|
||||
var parent = node.parentNode;
|
||||
if (isLeafNode(parent)) {
|
||||
parent.setAttribute('ng-bind-template', node.nodeValue);
|
||||
factories.push({path:path, fn:function(node, scope, prefix) {
|
||||
return new BindUpdater(node, node.getAttribute('ng-bind-template'));
|
||||
}});
|
||||
} else {
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
var binding = Binder.binding(part);
|
||||
var newNode;
|
||||
if (binding) {
|
||||
newNode = document.createElement("span");
|
||||
var jNewNode = jQuery(newNode);
|
||||
jNewNode.attr("ng-bind", binding);
|
||||
if (i === 0) {
|
||||
factories.push({path:path.concat(offset + i), fn:this.ng_bind});
|
||||
}
|
||||
} else if (msie && part.charAt(0) == ' ') {
|
||||
newNode = document.createElement("span");
|
||||
newNode.innerHTML = ' ' + part.substring(1);
|
||||
} else {
|
||||
newNode = document.createTextNode(part);
|
||||
}
|
||||
parent.insertBefore(newNode, node);
|
||||
}
|
||||
}
|
||||
parent.removeChild(node);
|
||||
}
|
||||
},
|
||||
|
||||
precompile: function(root) {
|
||||
var factories = [];
|
||||
this.precompileNode(root, [], factories);
|
||||
return function (template, scope, prefix) {
|
||||
var len = factories.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
var factory = factories[i];
|
||||
var node = template;
|
||||
var path = factory.path;
|
||||
for (var j = 0; j < path.length; j++) {
|
||||
node = node.childNodes[path[j]];
|
||||
}
|
||||
try {
|
||||
scope.addWidget(factory.fn(node, scope, prefix));
|
||||
} catch (e) {
|
||||
alert(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
precompileNode: function(node, path, factories) {
|
||||
var nodeType = node.nodeType;
|
||||
if (nodeType == Node.TEXT_NODE) {
|
||||
this.translateBinding(node, path, factories);
|
||||
return;
|
||||
} else if (nodeType != Node.ELEMENT_NODE && nodeType != Node.DOCUMENT_NODE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!node.getAttribute) return;
|
||||
var nonBindable = node.getAttribute('ng-non-bindable');
|
||||
if (nonBindable || nonBindable === "") return;
|
||||
|
||||
var attributes = node.attributes;
|
||||
if (attributes) {
|
||||
var bindings = node.getAttribute('ng-bind-attr');
|
||||
node.removeAttribute('ng-bind-attr');
|
||||
bindings = bindings ? fromJson(bindings) : {};
|
||||
var attrLen = attributes.length;
|
||||
for (var i = 0; i < attrLen; i++) {
|
||||
var attr = attributes[i];
|
||||
var attrName = attr.name;
|
||||
// http://www.glennjones.net/Post/809/getAttributehrefbug.htm
|
||||
var attrValue = msie && attrName == 'href' ?
|
||||
decodeURI(node.getAttribute(attrName, 2)) : attr.value;
|
||||
if (Binder.hasBinding(attrValue)) {
|
||||
bindings[attrName] = attrValue;
|
||||
}
|
||||
}
|
||||
var json = toJson(bindings);
|
||||
if (json.length > 2) {
|
||||
node.setAttribute("ng-bind-attr", json);
|
||||
}
|
||||
}
|
||||
|
||||
if (!node.getAttribute) log(node);
|
||||
var repeaterExpression = node.getAttribute('ng-repeat');
|
||||
if (repeaterExpression) {
|
||||
node.removeAttribute('ng-repeat');
|
||||
var precompiled = this.precompile(node);
|
||||
var view = document.createComment("ng-repeat: " + repeaterExpression);
|
||||
var parentNode = node.parentNode;
|
||||
parentNode.insertBefore(view, node);
|
||||
parentNode.removeChild(node);
|
||||
function template(childScope, prefix, i) {
|
||||
var clone = jQuery(node).clone();
|
||||
clone.css('display', '');
|
||||
clone.attr('ng-repeat-index', "" + i);
|
||||
clone.data('scope', childScope);
|
||||
precompiled(clone[0], childScope, prefix + i + ":");
|
||||
return clone;
|
||||
}
|
||||
factories.push({path:path, fn:function(node, scope, prefix) {
|
||||
return new RepeaterUpdater(jQuery(node), repeaterExpression, template, prefix);
|
||||
}});
|
||||
return;
|
||||
}
|
||||
|
||||
if (node.getAttribute('ng-eval')) factories.push({path:path, fn:this.ng_eval});
|
||||
if (node.getAttribute('ng-bind')) factories.push({path:path, fn:this.ng_bind});
|
||||
if (node.getAttribute('ng-bind-attr')) factories.push({path:path, fn:this.ng_bind_attr});
|
||||
if (node.getAttribute('ng-hide')) factories.push({path:path, fn:this.ng_hide});
|
||||
if (node.getAttribute('ng-show')) factories.push({path:path, fn:this.ng_show});
|
||||
if (node.getAttribute('ng-class')) factories.push({path:path, fn:this.ng_class});
|
||||
if (node.getAttribute('ng-class-odd')) factories.push({path:path, fn:this.ng_class_odd});
|
||||
if (node.getAttribute('ng-class-even')) factories.push({path:path, fn:this.ng_class_even});
|
||||
if (node.getAttribute('ng-style')) factories.push({path:path, fn:this.ng_style});
|
||||
if (node.getAttribute('ng-watch')) factories.push({path:path, fn:this.ng_watch});
|
||||
var nodeName = node.nodeName;
|
||||
if ((nodeName == 'INPUT' ) ||
|
||||
nodeName == 'TEXTAREA' ||
|
||||
nodeName == 'SELECT' ||
|
||||
nodeName == 'BUTTON') {
|
||||
var self = this;
|
||||
factories.push({path:path, fn:function(node, scope, prefix) {
|
||||
node.name = prefix + node.name.split(":").pop();
|
||||
return self.widgetFactory.createController(jQuery(node), scope);
|
||||
}});
|
||||
}
|
||||
if (nodeName == 'OPTION') {
|
||||
var html = jQuery('<select/>').append(jQuery(node).clone()).html();
|
||||
if (!html.match(/<option(\s.*\s|\s)value\s*=\s*.*>.*<\/\s*option\s*>/gi)) {
|
||||
if (Binder.hasBinding(node.text)) {
|
||||
jQuery(node).attr('ng-bind-attr', angular.toJson({'value':node.text}));
|
||||
} else {
|
||||
node.value = node.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var children = node.childNodes;
|
||||
for (var k = 0; k < children.length; k++) {
|
||||
this.precompileNode(children[k], path.concat(k), factories);
|
||||
}
|
||||
},
|
||||
|
||||
ng_eval: function(node) {
|
||||
return new EvalUpdater(node, node.getAttribute('ng-eval'));
|
||||
},
|
||||
|
||||
ng_bind: function(node) {
|
||||
return new BindUpdater(node, "{{" + node.getAttribute('ng-bind') + "}}");
|
||||
},
|
||||
|
||||
ng_bind_attr: function(node) {
|
||||
return new BindAttrUpdater(node, fromJson(node.getAttribute('ng-bind-attr')));
|
||||
},
|
||||
|
||||
ng_hide: function(node) {
|
||||
return new HideUpdater(node, node.getAttribute('ng-hide'));
|
||||
},
|
||||
|
||||
ng_show: function(node) {
|
||||
return new ShowUpdater(node, node.getAttribute('ng-show'));
|
||||
},
|
||||
|
||||
ng_class: function(node) {
|
||||
return new ClassUpdater(node, node.getAttribute('ng-class'));
|
||||
},
|
||||
|
||||
ng_class_even: function(node) {
|
||||
return new ClassEvenUpdater(node, node.getAttribute('ng-class-even'));
|
||||
},
|
||||
|
||||
ng_class_odd: function(node) {
|
||||
return new ClassOddUpdater(node, node.getAttribute('ng-class-odd'));
|
||||
},
|
||||
|
||||
ng_style: function(node) {
|
||||
return new StyleUpdater(node, node.getAttribute('ng-style'));
|
||||
},
|
||||
|
||||
ng_watch: function(node, scope) {
|
||||
scope.watch(node.getAttribute('ng-watch'));
|
||||
}
|
||||
};
|
||||
65
src/delete/Model.js
Normal file
65
src/delete/Model.js
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
// Single $ is special and does not get searched
|
||||
// Double $$ is special an is client only (does not get sent to server)
|
||||
|
||||
function Model(entity, initial) {
|
||||
this['$$entity'] = entity;
|
||||
this['$loadFrom'](initial||{});
|
||||
this['$entity'] = entity['title'];
|
||||
this['$migrate']();
|
||||
};
|
||||
|
||||
Model.copyDirectFields = function(src, dst) {
|
||||
if (src === dst || !src || !dst) return;
|
||||
var isDataField = function(src, dst, field) {
|
||||
return (field.substring(0,2) !== '$$') &&
|
||||
(typeof src[field] !== 'function') &&
|
||||
(typeof dst[field] !== 'function');
|
||||
};
|
||||
for (var field in dst) {
|
||||
if (isDataField(src, dst, field))
|
||||
delete dst[field];
|
||||
}
|
||||
for (field in src) {
|
||||
if (isDataField(src, dst, field))
|
||||
dst[field] = src[field];
|
||||
}
|
||||
};
|
||||
|
||||
extend(Model.prototype, {
|
||||
'$migrate': function() {
|
||||
merge(this['$$entity']['defaults'], this);
|
||||
return this;
|
||||
},
|
||||
|
||||
'$merge': function(other) {
|
||||
merge(other, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
'$save': function(callback) {
|
||||
this['$$entity'].datastore.save(this, callback === true ? undefined : callback);
|
||||
if (callback === true) this['$$entity'].datastore.flush();
|
||||
return this;
|
||||
},
|
||||
|
||||
'$delete': function(callback) {
|
||||
this['$$entity'].datastore.remove(this, callback === true ? undefined : callback);
|
||||
if (callback === true) this['$$entity'].datastore.flush();
|
||||
return this;
|
||||
},
|
||||
|
||||
'$loadById': function(id, callback) {
|
||||
this['$$entity'].datastore.load(this, id, callback);
|
||||
return this;
|
||||
},
|
||||
|
||||
'$loadFrom': function(other) {
|
||||
Model.copyDirectFields(other, this);
|
||||
return this;
|
||||
},
|
||||
|
||||
'$saveTo': function(other) {
|
||||
Model.copyDirectFields(this, other);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
407
src/delete/Scope.js
Normal file
407
src/delete/Scope.js
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
function Scope(initialState, name) {
|
||||
var self = this;
|
||||
self.widgets = [];
|
||||
self.evals = [];
|
||||
self.watchListeners = {};
|
||||
self.name = name;
|
||||
initialState = initialState || {};
|
||||
var State = function(){};
|
||||
State.prototype = initialState;
|
||||
self.state = new State();
|
||||
extend(self.state, {
|
||||
'$parent': initialState,
|
||||
'$watch': bind(self, self.addWatchListener),
|
||||
'$eval': bind(self, self.eval),
|
||||
'$bind': bind(self, bind, self),
|
||||
// change name to autoEval?
|
||||
'$addEval': bind(self, self.addEval),
|
||||
'$updateView': bind(self, self.updateView)
|
||||
});
|
||||
if (name == "ROOT") {
|
||||
self.state['$root'] = self.state;
|
||||
}
|
||||
};
|
||||
|
||||
Scope.expressionCache = {};
|
||||
Scope.getter = function(instance, path) {
|
||||
if (!path) return instance;
|
||||
var element = path.split('.');
|
||||
var key;
|
||||
var lastInstance = instance;
|
||||
var len = element.length;
|
||||
for ( var i = 0; i < len; i++) {
|
||||
key = element[i];
|
||||
if (!key.match(/^[\$\w][\$\w\d]*$/))
|
||||
throw "Expression '" + path + "' is not a valid expression for accesing variables.";
|
||||
if (instance) {
|
||||
lastInstance = instance;
|
||||
instance = instance[key];
|
||||
}
|
||||
if (_.isUndefined(instance) && key.charAt(0) == '$') {
|
||||
var type = angular['Global']['typeOf'](lastInstance);
|
||||
type = angular[type.charAt(0).toUpperCase()+type.substring(1)];
|
||||
var fn = type ? type[[key.substring(1)]] : undefined;
|
||||
if (fn) {
|
||||
instance = _.bind(fn, lastInstance, lastInstance);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof instance === 'function' && !instance['$$factory']) {
|
||||
return bind(lastInstance, instance);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
Scope.setter = function(instance, path, value){
|
||||
var element = path.split('.');
|
||||
for ( var i = 0; element.length > 1; i++) {
|
||||
var key = element.shift();
|
||||
var newInstance = instance[key];
|
||||
if (!newInstance) {
|
||||
newInstance = {};
|
||||
instance[key] = newInstance;
|
||||
}
|
||||
instance = newInstance;
|
||||
}
|
||||
instance[element.shift()] = value;
|
||||
return value;
|
||||
};
|
||||
|
||||
Scope.prototype = {
|
||||
// TODO: rename to update? or eval?
|
||||
updateView: function() {
|
||||
var self = this;
|
||||
this.fireWatchers();
|
||||
foreach(this.widgets, function(widget){
|
||||
self.evalWidget(widget, "", {}, function(){
|
||||
this.updateView(self);
|
||||
});
|
||||
});
|
||||
foreach(this.evals, bind(this, this.apply));
|
||||
},
|
||||
|
||||
addWidget: function(controller) {
|
||||
if (controller) this.widgets.push(controller);
|
||||
},
|
||||
|
||||
addEval: function(fn, listener) {
|
||||
// todo: this should take a function/string and a listener
|
||||
// todo: this is a hack, which will need to be cleaned up.
|
||||
var self = this,
|
||||
listenFn = listener || noop,
|
||||
expr = self.compile(fn);
|
||||
this.evals.push(function(){
|
||||
self.apply(listenFn, expr());
|
||||
});
|
||||
},
|
||||
|
||||
isProperty: function(exp) {
|
||||
for ( var i = 0; i < exp.length; i++) {
|
||||
var ch = exp.charAt(i);
|
||||
if (ch!='.' && !Lexer.prototype.isIdent(ch)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
get: function(path) {
|
||||
// log('SCOPE.get', path, Scope.getter(this.state, path));
|
||||
return Scope.getter(this.state, path);
|
||||
},
|
||||
|
||||
set: function(path, value) {
|
||||
// log('SCOPE.set', path, value);
|
||||
var instance = this.state;
|
||||
return Scope.setter(instance, path, value);
|
||||
},
|
||||
|
||||
setEval: function(expressionText, value) {
|
||||
this.eval(expressionText + "=" + toJson(value));
|
||||
},
|
||||
|
||||
compile: function(exp) {
|
||||
if (isFunction(exp)) return bind(this.state, exp);
|
||||
var expFn = Scope.expressionCache[exp], self = this;
|
||||
if (!expFn) {
|
||||
var parser = new Parser(exp);
|
||||
expFn = parser.statements();
|
||||
parser.assertAllConsumed();
|
||||
Scope.expressionCache[exp] = expFn;
|
||||
}
|
||||
return function(context){
|
||||
context = context || {};
|
||||
context.self = self.state;
|
||||
context.scope = self;
|
||||
return expFn.call(self, context);
|
||||
};
|
||||
},
|
||||
|
||||
eval: function(exp, context) {
|
||||
// log('Scope.eval', expressionText);
|
||||
return this.compile(exp)(context);
|
||||
},
|
||||
|
||||
//TODO: Refactor. This function needs to be an execution closure for widgets
|
||||
// move to widgets
|
||||
// remove expression, just have inner closure.
|
||||
evalWidget: function(widget, expression, context, onSuccess, onFailure) {
|
||||
try {
|
||||
var value = this.eval(expression, context);
|
||||
if (widget.hasError) {
|
||||
widget.hasError = false;
|
||||
jQuery(widget.view).
|
||||
removeClass('ng-exception').
|
||||
removeAttr('ng-error');
|
||||
}
|
||||
if (onSuccess) {
|
||||
value = onSuccess.apply(widget, [value]);
|
||||
}
|
||||
return true;
|
||||
} catch (e){
|
||||
var jsonError = toJson(e, true);
|
||||
error('Eval Widget Error:', jsonError);
|
||||
widget.hasError = true;
|
||||
jQuery(widget.view).
|
||||
addClass('ng-exception').
|
||||
attr('ng-error', jsonError);
|
||||
if (onFailure) {
|
||||
onFailure.apply(widget, [e, jsonError]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
validate: function(expressionText, value, element) {
|
||||
var expression = Scope.expressionCache[expressionText];
|
||||
if (!expression) {
|
||||
expression = new Parser(expressionText).validator();
|
||||
Scope.expressionCache[expressionText] = expression;
|
||||
}
|
||||
var self = {scope:this, self:this.state, '$element':element};
|
||||
return expression(self)(self, value);
|
||||
},
|
||||
|
||||
entity: function(entityDeclaration, datastore) {
|
||||
var expression = new Parser(entityDeclaration).entityDeclaration();
|
||||
return expression({scope:this, datastore:datastore});
|
||||
},
|
||||
|
||||
clearInvalid: function() {
|
||||
var invalid = this.state['$invalidWidgets'];
|
||||
while(invalid.length > 0) {invalid.pop();}
|
||||
},
|
||||
|
||||
markInvalid: function(widget) {
|
||||
this.state['$invalidWidgets'].push(widget);
|
||||
},
|
||||
|
||||
watch: function(declaration) {
|
||||
var self = this;
|
||||
new Parser(declaration).watch()({
|
||||
scope:this,
|
||||
addListener:function(watch, exp){
|
||||
self.addWatchListener(watch, function(n,o){
|
||||
try {
|
||||
return exp({scope:self}, n, o);
|
||||
} catch(e) {
|
||||
alert(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
addWatchListener: function(watchExpression, listener) {
|
||||
// TODO: clean me up!
|
||||
if (!isFunction(listener)) {
|
||||
listener = this.compile(listener);
|
||||
}
|
||||
var watcher = this.watchListeners[watchExpression];
|
||||
if (!watcher) {
|
||||
watcher = {listeners:[], expression:watchExpression};
|
||||
this.watchListeners[watchExpression] = watcher;
|
||||
}
|
||||
watcher.listeners.push(listener);
|
||||
},
|
||||
|
||||
fireWatchers: function() {
|
||||
var self = this, fired = false;
|
||||
foreach(this.watchListeners, function(watcher) {
|
||||
var value = self.eval(watcher.expression);
|
||||
if (value !== watcher.lastValue) {
|
||||
foreach(watcher.listeners, function(listener){
|
||||
listener(value, watcher.lastValue);
|
||||
fired = true;
|
||||
});
|
||||
watcher.lastValue = value;
|
||||
}
|
||||
});
|
||||
return fired;
|
||||
},
|
||||
|
||||
apply: function(fn) {
|
||||
fn.apply(this.state, slice.call(arguments, 1, arguments.length));
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
function getter(instance, path) {
|
||||
if (!path) return instance;
|
||||
var element = path.split('.');
|
||||
var key;
|
||||
var lastInstance = instance;
|
||||
var len = element.length;
|
||||
for ( var i = 0; i < len; i++) {
|
||||
key = element[i];
|
||||
if (!key.match(/^[\$\w][\$\w\d]*$/))
|
||||
throw "Expression '" + path + "' is not a valid expression for accesing variables.";
|
||||
if (instance) {
|
||||
lastInstance = instance;
|
||||
instance = instance[key];
|
||||
}
|
||||
if (_.isUndefined(instance) && key.charAt(0) == '$') {
|
||||
var type = angular['Global']['typeOf'](lastInstance);
|
||||
type = angular[type.charAt(0).toUpperCase()+type.substring(1)];
|
||||
var fn = type ? type[[key.substring(1)]] : undefined;
|
||||
if (fn) {
|
||||
instance = _.bind(fn, lastInstance, lastInstance);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof instance === 'function' && !instance['$$factory']) {
|
||||
return bind(lastInstance, instance);
|
||||
}
|
||||
return instance;
|
||||
};
|
||||
|
||||
function setter(instance, path, value){
|
||||
var element = path.split('.');
|
||||
for ( var i = 0; element.length > 1; i++) {
|
||||
var key = element.shift();
|
||||
var newInstance = instance[key];
|
||||
if (!newInstance) {
|
||||
newInstance = {};
|
||||
instance[key] = newInstance;
|
||||
}
|
||||
instance = newInstance;
|
||||
}
|
||||
instance[element.shift()] = value;
|
||||
return value;
|
||||
};
|
||||
|
||||
var compileCache = {};
|
||||
function expressionCompile(exp){
|
||||
if (isFunction(exp)) return exp;
|
||||
var expFn = compileCache[exp];
|
||||
if (!expFn) {
|
||||
var parser = new Parser(exp);
|
||||
expFn = parser.statements();
|
||||
parser.assertAllConsumed();
|
||||
compileCache[exp] = expFn;
|
||||
}
|
||||
// return expFn
|
||||
// TODO(remove this hack)
|
||||
return function(){
|
||||
return expFn({
|
||||
scope: {
|
||||
set: this.$set,
|
||||
get: this.$get
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var NON_RENDERABLE_ELEMENTS = {
|
||||
'#text': 1, '#comment':1, 'TR':1, 'TH':1
|
||||
};
|
||||
|
||||
function isRenderableElement(element){
|
||||
return element && element[0] && !NON_RENDERABLE_ELEMENTS[element[0].nodeName];
|
||||
}
|
||||
|
||||
function rethrow(e) { throw e; }
|
||||
function errorHandlerFor(element) {
|
||||
while (!isRenderableElement(element)) {
|
||||
element = element.parent() || jqLite(document.body);
|
||||
}
|
||||
return function(error) {
|
||||
element.attr('ng-error', angular.toJson(error));
|
||||
element.addClass('ng-exception');
|
||||
};
|
||||
}
|
||||
|
||||
function createScope(parent, Class) {
|
||||
function Parent(){}
|
||||
function API(){}
|
||||
function Behavior(){}
|
||||
|
||||
var instance, behavior, api, watchList = [], evalList = [];
|
||||
|
||||
Class = Class || noop;
|
||||
parent = Parent.prototype = parent || {};
|
||||
api = API.prototype = new Parent();
|
||||
behavior = Behavior.prototype = extend(new API(), Class.prototype);
|
||||
instance = new Behavior();
|
||||
|
||||
extend(api, {
|
||||
$parent: parent,
|
||||
$bind: bind(instance, bind, instance),
|
||||
$get: bind(instance, getter, instance),
|
||||
$set: bind(instance, setter, instance),
|
||||
|
||||
$eval: function(exp) {
|
||||
if (isDefined(exp)) {
|
||||
return expressionCompile(exp).apply(instance, slice.call(arguments, 1, arguments.length));
|
||||
} else {
|
||||
foreach(evalList, function(eval) {
|
||||
instance.$tryEval(eval.fn, eval.handler);
|
||||
});
|
||||
foreach(watchList, function(watch) {
|
||||
var value = instance.$tryEval(watch.watch, watch.handler);
|
||||
if (watch.last !== value) {
|
||||
instance.$tryEval(watch.listener, watch.handler, value, watch.last);
|
||||
watch.last = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
$tryEval: function (expression, exceptionHandler) {
|
||||
try {
|
||||
return expressionCompile(expression).apply(instance, slice.call(arguments, 2, arguments.length));
|
||||
} catch (e) {
|
||||
error(e);
|
||||
if (isFunction(exceptionHandler)) {
|
||||
exceptionHandler(e);
|
||||
} else if (exceptionHandler) {
|
||||
errorHandlerFor(exceptionHandler)(e);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
$watch: function(watchExp, listener, exceptionHandler) {
|
||||
var watch = expressionCompile(watchExp);
|
||||
watchList.push({
|
||||
watch: watch,
|
||||
last: watch.call(instance),
|
||||
handler: exceptionHandler,
|
||||
listener:expressionCompile(listener)
|
||||
});
|
||||
},
|
||||
|
||||
$onEval: function(expr, exceptionHandler){
|
||||
evalList.push({
|
||||
fn: expressionCompile(expr),
|
||||
handler: exceptionHandler
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Class.apply(instance, slice.call(arguments, 2, arguments.length));
|
||||
|
||||
return instance;
|
||||
}
|
||||
806
src/delete/Widgets.js
Normal file
806
src/delete/Widgets.js
Normal file
|
|
@ -0,0 +1,806 @@
|
|||
function WidgetFactory(serverUrl, database) {
|
||||
this.nextUploadId = 0;
|
||||
this.serverUrl = serverUrl;
|
||||
this.database = database;
|
||||
if (window['swfobject']) {
|
||||
this.createSWF = window['swfobject']['createSWF'];
|
||||
} else {
|
||||
this.createSWF = function(){
|
||||
alert("ERROR: swfobject not loaded!");
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
WidgetFactory.prototype = {
|
||||
createController: function(input, scope) {
|
||||
var controller;
|
||||
var type = input.attr('type').toLowerCase();
|
||||
var exp = input.attr('name');
|
||||
if (exp) exp = exp.split(':').pop();
|
||||
var event = "change";
|
||||
var bubbleEvent = true;
|
||||
var formatter = angularFormatter[input.attr('ng-format')] || angularFormatter['noop'];
|
||||
if (type == 'button' || type == 'submit' || type == 'reset' || type == 'image') {
|
||||
controller = new ButtonController(input[0], exp, formatter);
|
||||
event = "click";
|
||||
bubbleEvent = false;
|
||||
} else if (type == 'text' || type == 'textarea' || type == 'hidden' || type == 'password') {
|
||||
controller = new TextController(input[0], exp, formatter);
|
||||
event = "keyup change";
|
||||
} else if (type == 'checkbox') {
|
||||
controller = new CheckboxController(input[0], exp, formatter);
|
||||
event = "click";
|
||||
} else if (type == 'radio') {
|
||||
controller = new RadioController(input[0], exp, formatter);
|
||||
event="click";
|
||||
} else if (type == 'select-one') {
|
||||
controller = new SelectController(input[0], exp, formatter);
|
||||
} else if (type == 'select-multiple') {
|
||||
controller = new MultiSelectController(input[0], exp, formatter);
|
||||
} else if (type == 'file') {
|
||||
controller = this.createFileController(input, exp, formatter);
|
||||
} else {
|
||||
throw 'Unknown type: ' + type;
|
||||
}
|
||||
input.data('controller', controller);
|
||||
var updateView = scope.get('$updateView');
|
||||
var action = function() {
|
||||
if (controller.updateModel(scope)) {
|
||||
var action = jQuery(controller.view).attr('ng-action') || "";
|
||||
if (scope.evalWidget(controller, action)) {
|
||||
updateView(scope);
|
||||
}
|
||||
}
|
||||
return bubbleEvent;
|
||||
};
|
||||
jQuery(controller.view, ":input").
|
||||
bind(event, action);
|
||||
return controller;
|
||||
},
|
||||
|
||||
createFileController: function(fileInput) {
|
||||
var uploadId = '__uploadWidget_' + (this.nextUploadId++);
|
||||
var view = FileController.template(uploadId);
|
||||
fileInput.after(view);
|
||||
var att = {
|
||||
'data':this.serverUrl + "/admin/ServerAPI.swf",
|
||||
'width':"95", 'height':"20", 'align':"top",
|
||||
'wmode':"transparent"};
|
||||
var par = {
|
||||
'flashvars':"uploadWidgetId=" + uploadId,
|
||||
'allowScriptAccess':"always"};
|
||||
var swfNode = this.createSWF(att, par, uploadId);
|
||||
fileInput.remove();
|
||||
var cntl = new FileController(view, fileInput[0].name, swfNode, this.serverUrl + "/data/" + this.database);
|
||||
jQuery(swfNode).parent().data('controller', cntl);
|
||||
return cntl;
|
||||
}
|
||||
};
|
||||
/////////////////////
|
||||
// FileController
|
||||
///////////////////////
|
||||
|
||||
function FileController(view, scopeName, uploader, databaseUrl) {
|
||||
this.view = view;
|
||||
this.uploader = uploader;
|
||||
this.scopeName = scopeName;
|
||||
this.attachmentsPath = databaseUrl + '/_attachments';
|
||||
this.value = null;
|
||||
this.lastValue = undefined;
|
||||
};
|
||||
|
||||
angularCallbacks['flashEvent'] = function(id, event, args) {
|
||||
var object = document.getElementById(id);
|
||||
var jobject = jQuery(object);
|
||||
var controller = jobject.parent().data("controller");
|
||||
FileController.prototype[event].apply(controller, args);
|
||||
_.defer(jobject.scope().get('$updateView'));
|
||||
};
|
||||
|
||||
FileController.template = function(id) {
|
||||
return jQuery('<span class="ng-upload-widget">' +
|
||||
'<input type="checkbox" ng-non-bindable="true"/>' +
|
||||
'<object id="' + id + '" />' +
|
||||
'<a></a>' +
|
||||
'<span/>' +
|
||||
'</span>');
|
||||
};
|
||||
|
||||
extend(FileController.prototype, {
|
||||
'cancel': noop,
|
||||
'complete': noop,
|
||||
'httpStatus': function(status) {
|
||||
alert("httpStatus:" + this.scopeName + " status:" + status);
|
||||
},
|
||||
'ioError': function() {
|
||||
alert("ioError:" + this.scopeName);
|
||||
},
|
||||
'open': function() {
|
||||
alert("open:" + this.scopeName);
|
||||
},
|
||||
'progress':noop,
|
||||
'securityError': function() {
|
||||
alert("securityError:" + this.scopeName);
|
||||
},
|
||||
'uploadCompleteData': function(data) {
|
||||
var value = fromJson(data);
|
||||
value.url = this.attachmentsPath + '/' + value.id + '/' + value.text;
|
||||
this.view.find("input").attr('checked', true);
|
||||
var scope = this.view.scope();
|
||||
this.value = value;
|
||||
this.updateModel(scope);
|
||||
this.value = null;
|
||||
},
|
||||
'select': function(name, size, type) {
|
||||
this.name = name;
|
||||
this.view.find("a").text(name).attr('href', name);
|
||||
this.view.find("span").text(angular['filter']['bytes'](size));
|
||||
this.upload();
|
||||
},
|
||||
|
||||
updateModel: function(scope) {
|
||||
var isChecked = this.view.find("input").attr('checked');
|
||||
var value = isChecked ? this.value : null;
|
||||
if (this.lastValue === value) {
|
||||
return false;
|
||||
} else {
|
||||
scope.set(this.scopeName, value);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var modelValue = scope.get(this.scopeName);
|
||||
if (modelValue && this.value !== modelValue) {
|
||||
this.value = modelValue;
|
||||
this.view.find("a").
|
||||
attr("href", this.value.url).
|
||||
text(this.value.text);
|
||||
this.view.find("span").text(angular['filter']['bytes'](this.value.size));
|
||||
}
|
||||
this.view.find("input").attr('checked', !!modelValue);
|
||||
},
|
||||
|
||||
upload: function() {
|
||||
if (this.name) {
|
||||
this.uploader['uploadFile'](this.attachmentsPath);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
///////////////////////
|
||||
// NullController
|
||||
///////////////////////
|
||||
function NullController(view) {this.view = view;};
|
||||
NullController.prototype = {
|
||||
updateModel: function() { return true; },
|
||||
updateView: noop
|
||||
};
|
||||
NullController.instance = new NullController();
|
||||
|
||||
|
||||
///////////////////////
|
||||
// ButtonController
|
||||
///////////////////////
|
||||
var ButtonController = NullController;
|
||||
|
||||
///////////////////////
|
||||
// TextController
|
||||
///////////////////////
|
||||
function TextController(view, exp, formatter) {
|
||||
this.view = view;
|
||||
this.formatter = formatter;
|
||||
this.exp = exp;
|
||||
this.validator = view.getAttribute('ng-validate');
|
||||
this.required = typeof view.attributes['ng-required'] != "undefined";
|
||||
this.lastErrorText = null;
|
||||
this.lastValue = undefined;
|
||||
this.initialValue = this.formatter['parse'](view.value);
|
||||
var widget = view.getAttribute('ng-widget');
|
||||
if (widget === 'datepicker') {
|
||||
jQuery(view).datepicker();
|
||||
}
|
||||
};
|
||||
|
||||
TextController.prototype = {
|
||||
updateModel: function(scope) {
|
||||
var value = this.formatter['parse'](this.view.value);
|
||||
if (this.lastValue === value) {
|
||||
return false;
|
||||
} else {
|
||||
scope.setEval(this.exp, value);
|
||||
this.lastValue = value;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var view = this.view;
|
||||
var value = scope.get(this.exp);
|
||||
if (typeof value === "undefined") {
|
||||
value = this.initialValue;
|
||||
scope.setEval(this.exp, value);
|
||||
}
|
||||
value = value ? value : '';
|
||||
if (!_(this.lastValue).isEqual(value)) {
|
||||
view.value = this.formatter['format'](value);
|
||||
this.lastValue = value;
|
||||
}
|
||||
|
||||
var isValidationError = false;
|
||||
view.removeAttribute('ng-error');
|
||||
if (this.required) {
|
||||
isValidationError = !(value && $.trim("" + value).length > 0);
|
||||
}
|
||||
var errorText = isValidationError ? "Required Value" : null;
|
||||
if (!isValidationError && this.validator && value) {
|
||||
errorText = scope.validate(this.validator, value, view);
|
||||
isValidationError = !!errorText;
|
||||
}
|
||||
if (this.lastErrorText !== errorText) {
|
||||
this.lastErrorText = isValidationError;
|
||||
if (errorText && isVisible(view)) {
|
||||
view.setAttribute('ng-error', errorText);
|
||||
scope.markInvalid(this);
|
||||
}
|
||||
jQuery(view).toggleClass('ng-validation-error', isValidationError);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
// CheckboxController
|
||||
///////////////////////
|
||||
function CheckboxController(view, exp, formatter) {
|
||||
this.view = view;
|
||||
this.exp = exp;
|
||||
this.lastValue = undefined;
|
||||
this.formatter = formatter;
|
||||
this.initialValue = this.formatter['parse'](view.checked ? view.value : "");
|
||||
};
|
||||
|
||||
CheckboxController.prototype = {
|
||||
updateModel: function(scope) {
|
||||
var input = this.view;
|
||||
var value = input.checked ? input.value : '';
|
||||
value = this.formatter['parse'](value);
|
||||
value = this.formatter['format'](value);
|
||||
if (this.lastValue === value) {
|
||||
return false;
|
||||
} else {
|
||||
scope.setEval(this.exp, this.formatter['parse'](value));
|
||||
this.lastValue = value;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var input = this.view;
|
||||
var value = scope.eval(this.exp);
|
||||
if (typeof value === "undefined") {
|
||||
value = this.initialValue;
|
||||
scope.setEval(this.exp, value);
|
||||
}
|
||||
input.checked = this.formatter['parse'](input.value) == value;
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
// SelectController
|
||||
///////////////////////
|
||||
function SelectController(view, exp) {
|
||||
this.view = view;
|
||||
this.exp = exp;
|
||||
this.lastValue = undefined;
|
||||
this.initialValue = view.value;
|
||||
};
|
||||
|
||||
SelectController.prototype = {
|
||||
updateModel: function(scope) {
|
||||
var input = this.view;
|
||||
if (input.selectedIndex < 0) {
|
||||
scope.setEval(this.exp, null);
|
||||
} else {
|
||||
var value = this.view.value;
|
||||
if (this.lastValue === value) {
|
||||
return false;
|
||||
} else {
|
||||
scope.setEval(this.exp, value);
|
||||
this.lastValue = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var input = this.view;
|
||||
var value = scope.get(this.exp);
|
||||
if (typeof value === 'undefined') {
|
||||
value = this.initialValue;
|
||||
scope.setEval(this.exp, value);
|
||||
}
|
||||
if (value !== this.lastValue) {
|
||||
input.value = value ? value : "";
|
||||
this.lastValue = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
// MultiSelectController
|
||||
///////////////////////
|
||||
function MultiSelectController(view, exp) {
|
||||
this.view = view;
|
||||
this.exp = exp;
|
||||
this.lastValue = undefined;
|
||||
this.initialValue = this.selected();
|
||||
};
|
||||
|
||||
MultiSelectController.prototype = {
|
||||
selected: function () {
|
||||
var value = [];
|
||||
var options = this.view.options;
|
||||
for ( var i = 0; i < options.length; i++) {
|
||||
var option = options[i];
|
||||
if (option.selected) {
|
||||
value.push(option.value);
|
||||
}
|
||||
}
|
||||
return value;
|
||||
},
|
||||
|
||||
updateModel: function(scope) {
|
||||
var value = this.selected();
|
||||
// TODO: This is wrong! no caching going on here as we are always comparing arrays
|
||||
if (this.lastValue === value) {
|
||||
return false;
|
||||
} else {
|
||||
scope.setEval(this.exp, value);
|
||||
this.lastValue = value;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var input = this.view;
|
||||
var selected = scope.get(this.exp);
|
||||
if (typeof selected === "undefined") {
|
||||
selected = this.initialValue;
|
||||
scope.setEval(this.exp, selected);
|
||||
}
|
||||
if (selected !== this.lastValue) {
|
||||
var options = input.options;
|
||||
for ( var i = 0; i < options.length; i++) {
|
||||
var option = options[i];
|
||||
option.selected = _.include(selected, option.value);
|
||||
}
|
||||
this.lastValue = selected;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
// RadioController
|
||||
///////////////////////
|
||||
function RadioController(view, exp) {
|
||||
this.view = view;
|
||||
this.exp = exp;
|
||||
this.lastChecked = undefined;
|
||||
this.lastValue = undefined;
|
||||
this.inputValue = view.value;
|
||||
this.initialValue = view.checked ? view.value : null;
|
||||
};
|
||||
|
||||
RadioController.prototype = {
|
||||
updateModel: function(scope) {
|
||||
var input = this.view;
|
||||
if (this.lastChecked) {
|
||||
return false;
|
||||
} else {
|
||||
input.checked = true;
|
||||
this.lastValue = scope.setEval(this.exp, this.inputValue);
|
||||
this.lastChecked = true;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
updateView: function(scope) {
|
||||
var input = this.view;
|
||||
var value = scope.get(this.exp);
|
||||
if (this.initialValue && typeof value === "undefined") {
|
||||
value = this.initialValue;
|
||||
scope.setEval(this.exp, value);
|
||||
}
|
||||
if (this.lastValue != value) {
|
||||
this.lastChecked = input.checked = this.inputValue == (''+value);
|
||||
this.lastValue = value;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
//ElementController
|
||||
///////////////////////
|
||||
function BindUpdater(view, exp) {
|
||||
this.view = view;
|
||||
this.exp = Binder.parseBindings(exp);
|
||||
this.hasError = false;
|
||||
};
|
||||
|
||||
BindUpdater.toText = function(obj) {
|
||||
var e = escapeHtml;
|
||||
switch(typeof obj) {
|
||||
case "string":
|
||||
case "boolean":
|
||||
case "number":
|
||||
return e(obj);
|
||||
case "function":
|
||||
return BindUpdater.toText(obj());
|
||||
case "object":
|
||||
if (isNode(obj)) {
|
||||
return outerHTML(obj);
|
||||
} else if (obj instanceof angular.filter.Meta) {
|
||||
switch(typeof obj.html) {
|
||||
case "string":
|
||||
case "number":
|
||||
return obj.html;
|
||||
case "function":
|
||||
return obj.html();
|
||||
case "object":
|
||||
if (isNode(obj.html))
|
||||
return outerHTML(obj.html);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch(typeof obj.text) {
|
||||
case "string":
|
||||
case "number":
|
||||
return e(obj.text);
|
||||
case "function":
|
||||
return e(obj.text());
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (obj === null)
|
||||
return "";
|
||||
return e(toJson(obj, true));
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
BindUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
var html = [];
|
||||
var parts = this.exp;
|
||||
var length = parts.length;
|
||||
for(var i=0; i<length; i++) {
|
||||
var part = parts[i];
|
||||
var binding = Binder.binding(part);
|
||||
if (binding) {
|
||||
scope.evalWidget(this, binding, {$element:this.view}, function(value){
|
||||
html.push(BindUpdater.toText(value));
|
||||
}, function(e, text){
|
||||
setHtml(this.view, text);
|
||||
});
|
||||
if (this.hasError) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
html.push(escapeHtml(part));
|
||||
}
|
||||
}
|
||||
setHtml(this.view, html.join(''));
|
||||
}
|
||||
};
|
||||
|
||||
function BindAttrUpdater(view, attrs) {
|
||||
this.view = view;
|
||||
this.attrs = attrs;
|
||||
};
|
||||
|
||||
BindAttrUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
var jNode = jQuery(this.view);
|
||||
var attributeTemplates = this.attrs;
|
||||
if (this.hasError) {
|
||||
this.hasError = false;
|
||||
jNode.
|
||||
removeClass('ng-exception').
|
||||
removeAttr('ng-error');
|
||||
}
|
||||
var isImage = jNode.is('img');
|
||||
for (var attrName in attributeTemplates) {
|
||||
var attributeTemplate = Binder.parseBindings(attributeTemplates[attrName]);
|
||||
var attrValues = [];
|
||||
for ( var i = 0; i < attributeTemplate.length; i++) {
|
||||
var binding = Binder.binding(attributeTemplate[i]);
|
||||
if (binding) {
|
||||
try {
|
||||
var value = scope.eval(binding, {$element:jNode[0], attrName:attrName});
|
||||
if (value && (value.constructor !== array || value.length !== 0))
|
||||
attrValues.push(value);
|
||||
} catch (e) {
|
||||
this.hasError = true;
|
||||
error('BindAttrUpdater', e);
|
||||
var jsonError = toJson(e, true);
|
||||
attrValues.push('[' + jsonError + ']');
|
||||
jNode.
|
||||
addClass('ng-exception').
|
||||
attr('ng-error', jsonError);
|
||||
}
|
||||
} else {
|
||||
attrValues.push(attributeTemplate[i]);
|
||||
}
|
||||
}
|
||||
var attrValue = attrValues.length ? attrValues.join('') : null;
|
||||
if(isImage && attrName == 'src' && !attrValue)
|
||||
attrValue = scope.get('$config.blankImage');
|
||||
jNode.attr(attrName, attrValue);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function EvalUpdater(view, exp) {
|
||||
this.view = view;
|
||||
this.exp = exp;
|
||||
this.hasError = false;
|
||||
};
|
||||
EvalUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp);
|
||||
}
|
||||
};
|
||||
|
||||
function HideUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
HideUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(hideValue){
|
||||
var view = jQuery(this.view);
|
||||
if (toBoolean(hideValue)) {
|
||||
view.hide();
|
||||
} else {
|
||||
view.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function ShowUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
ShowUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(hideValue){
|
||||
var view = jQuery(this.view);
|
||||
if (toBoolean(hideValue)) {
|
||||
view.show();
|
||||
} else {
|
||||
view.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function ClassUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
ClassUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(classValue){
|
||||
if (classValue !== null && classValue !== undefined) {
|
||||
this.view.className = classValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function ClassEvenUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
ClassEvenUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(classValue){
|
||||
var index = scope.get('$index');
|
||||
jQuery(this.view).toggleClass(classValue, index % 2 === 1);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function ClassOddUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
ClassOddUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(classValue){
|
||||
var index = scope.get('$index');
|
||||
jQuery(this.view).toggleClass(classValue, index % 2 === 0);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
function StyleUpdater(view, exp) { this.view = view; this.exp = exp; };
|
||||
StyleUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.exp, {}, function(styleValue){
|
||||
jQuery(this.view).attr('style', "").css(styleValue);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////
|
||||
// RepeaterUpdater
|
||||
///////////////////////
|
||||
function RepeaterUpdater(view, repeaterExpression, template, prefix) {
|
||||
this.view = view;
|
||||
this.template = template;
|
||||
this.prefix = prefix;
|
||||
this.children = [];
|
||||
var match = repeaterExpression.match(/^\s*(.+)\s+in\s+(.*)\s*$/);
|
||||
if (! match) {
|
||||
throw "Expected ng-repeat in form of 'item in collection' but got '" +
|
||||
repeaterExpression + "'.";
|
||||
}
|
||||
var keyValue = match[1];
|
||||
this.iteratorExp = match[2];
|
||||
match = keyValue.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/);
|
||||
if (!match) {
|
||||
throw "'item' in 'item in collection' should be identifier or (key, value) but get '" +
|
||||
keyValue + "'.";
|
||||
}
|
||||
this.valueExp = match[3] || match[1];
|
||||
this.keyExp = match[2];
|
||||
};
|
||||
|
||||
RepeaterUpdater.prototype = {
|
||||
updateModel: noop,
|
||||
updateView: function(scope) {
|
||||
scope.evalWidget(this, this.iteratorExp, {}, function(iterator){
|
||||
var self = this;
|
||||
if (!iterator) {
|
||||
iterator = [];
|
||||
if (scope.isProperty(this.iteratorExp)) {
|
||||
scope.set(this.iteratorExp, iterator);
|
||||
}
|
||||
}
|
||||
var childrenLength = this.children.length;
|
||||
var cursor = this.view;
|
||||
var time = 0;
|
||||
var child = null;
|
||||
var keyExp = this.keyExp;
|
||||
var valueExp = this.valueExp;
|
||||
var iteratorCounter = 0;
|
||||
foreach(iterator, function(value, key){
|
||||
if (iteratorCounter < childrenLength) {
|
||||
// reuse children
|
||||
child = self.children[iteratorCounter];
|
||||
child.scope.set(valueExp, value);
|
||||
} else {
|
||||
// grow children
|
||||
var name = self.prefix +
|
||||
valueExp + " in " + self.iteratorExp + "[" + iteratorCounter + "]";
|
||||
var childScope = new Scope(scope.state, name);
|
||||
childScope.set('$index', iteratorCounter);
|
||||
if (keyExp)
|
||||
childScope.set(keyExp, key);
|
||||
childScope.set(valueExp, value);
|
||||
child = { scope:childScope, element:self.template(childScope, self.prefix, iteratorCounter) };
|
||||
cursor.after(child.element);
|
||||
self.children.push(child);
|
||||
}
|
||||
cursor = child.element;
|
||||
var s = new Date().getTime();
|
||||
child.scope.updateView();
|
||||
time += new Date().getTime() - s;
|
||||
iteratorCounter++;
|
||||
});
|
||||
// shrink children
|
||||
for ( var r = childrenLength; r > iteratorCounter; --r) {
|
||||
this.children.pop().element.remove();
|
||||
}
|
||||
// Special case for option in select
|
||||
if (child && child.element[0].nodeName === "OPTION") {
|
||||
var select = jQuery(child.element[0].parentNode);
|
||||
var cntl = select.data('controller');
|
||||
if (cntl) {
|
||||
cntl.lastValue = undefined;
|
||||
cntl.updateView(scope);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// PopUp
|
||||
//////////////////////////////////
|
||||
|
||||
function PopUp(doc) {
|
||||
this.doc = doc;
|
||||
};
|
||||
|
||||
PopUp.OUT_EVENT = "mouseleave mouseout click dblclick keypress keyup";
|
||||
|
||||
PopUp.onOver = function(e) {
|
||||
PopUp.onOut();
|
||||
var jNode = jQuery(this);
|
||||
jNode.bind(PopUp.OUT_EVENT, PopUp.onOut);
|
||||
var position = jNode.position();
|
||||
var de = document.documentElement;
|
||||
var w = self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
|
||||
var hasArea = w - position.left;
|
||||
var width = 300;
|
||||
var title = jNode.hasClass("ng-exception") ? "EXCEPTION:" : "Validation error...";
|
||||
var msg = jNode.attr("ng-error");
|
||||
|
||||
var x;
|
||||
var arrowPos = hasArea>(width+75) ? "left" : "right";
|
||||
var tip = jQuery(
|
||||
"<div id='ng-callout' style='width:"+width+"px'>" +
|
||||
"<div class='ng-arrow-"+arrowPos+"'/>" +
|
||||
"<div class='ng-title'>"+title+"</div>" +
|
||||
"<div class='ng-content'>"+msg+"</div>" +
|
||||
"</div>");
|
||||
jQuery("body").append(tip);
|
||||
if(arrowPos === 'left'){
|
||||
x = position.left + this.offsetWidth + 11;
|
||||
}else{
|
||||
x = position.left - (width + 15);
|
||||
tip.find('.ng-arrow-right').css({left:width+1});
|
||||
}
|
||||
|
||||
tip.css({left: x+"px", top: (position.top - 3)+"px"});
|
||||
return true;
|
||||
};
|
||||
|
||||
PopUp.onOut = function() {
|
||||
jQuery('#ng-callout').
|
||||
unbind(PopUp.OUT_EVENT, PopUp.onOut).
|
||||
remove();
|
||||
return true;
|
||||
};
|
||||
|
||||
PopUp.prototype = {
|
||||
bind: function () {
|
||||
var self = this;
|
||||
this.doc.find('.ng-validation-error,.ng-exception').
|
||||
live("mouseover", PopUp.onOver);
|
||||
}
|
||||
};
|
||||
|
||||
//////////////////////////////////
|
||||
// Status
|
||||
//////////////////////////////////
|
||||
|
||||
function NullStatus(body) {
|
||||
};
|
||||
|
||||
NullStatus.prototype = {
|
||||
beginRequest:function(){},
|
||||
endRequest:function(){}
|
||||
};
|
||||
|
||||
function Status(body) {
|
||||
this.requestCount = 0;
|
||||
this.body = body;
|
||||
};
|
||||
|
||||
Status.DOM ='<div id="ng-spacer"></div><div id="ng-loading">loading....</div>';
|
||||
|
||||
Status.prototype = {
|
||||
beginRequest: function () {
|
||||
if (this.requestCount === 0) {
|
||||
(this.loader = this.loader || this.body.append(Status.DOM).find("#ng-loading")).show();
|
||||
}
|
||||
this.requestCount++;
|
||||
},
|
||||
|
||||
endRequest: function () {
|
||||
this.requestCount--;
|
||||
if (this.requestCount === 0) {
|
||||
this.loader.hide("fold");
|
||||
}
|
||||
}
|
||||
};
|
||||
261
src/directives.js
Normal file
261
src/directives.js
Normal file
|
|
@ -0,0 +1,261 @@
|
|||
angularDirective("ng-init", function(expression){
|
||||
return function(element){
|
||||
this.$tryEval(expression, element);
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-controller", function(expression){
|
||||
return function(element){
|
||||
var controller = getter(window, expression, true) || getter(this, expression, true);
|
||||
if (!controller)
|
||||
throw "Can not find '"+expression+"' controller.";
|
||||
if (!isFunction(controller))
|
||||
throw "Reference '"+expression+"' is not a class.";
|
||||
this.$become(controller);
|
||||
(this.init || noop)();
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-eval", function(expression){
|
||||
return function(element){
|
||||
this.$onEval(expression, element);
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-bind", function(expression){
|
||||
return function(element) {
|
||||
var lastValue = noop, lastError = noop;
|
||||
this.$onEval(function() {
|
||||
var error,
|
||||
value = this.$tryEval(expression, function(e){
|
||||
error = toJson(e);
|
||||
}),
|
||||
isHtml,
|
||||
isDomElement;
|
||||
if (lastValue === value && lastError == error) return;
|
||||
isHtml = value instanceof HTML,
|
||||
isDomElement = isElement(value);
|
||||
if (!isHtml && !isDomElement && isObject(value)) {
|
||||
value = toJson(value);
|
||||
}
|
||||
if (value != lastValue || error != lastError) {
|
||||
lastValue = value;
|
||||
lastError = error;
|
||||
elementError(element, NG_EXCEPTION, error);
|
||||
if (error) value = error;
|
||||
if (isHtml) {
|
||||
element.html(value.html);
|
||||
} else if (isDomElement) {
|
||||
element.html('');
|
||||
element.append(value);
|
||||
} else {
|
||||
element.text(value);
|
||||
}
|
||||
}
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
var bindTemplateCache = {};
|
||||
function compileBindTemplate(template){
|
||||
var fn = bindTemplateCache[template];
|
||||
if (!fn) {
|
||||
var bindings = [];
|
||||
foreach(parseBindings(template), function(text){
|
||||
var exp = binding(text);
|
||||
bindings.push(exp ? function(element){
|
||||
var error, value = this.$tryEval(exp, function(e){
|
||||
error = toJson(e);
|
||||
});
|
||||
elementError(element, NG_EXCEPTION, error);
|
||||
return error ? error : value;
|
||||
} : function() {
|
||||
return text;
|
||||
});
|
||||
});
|
||||
bindTemplateCache[template] = fn = function(element){
|
||||
var parts = [], self = this;
|
||||
for ( var i = 0; i < bindings.length; i++) {
|
||||
var value = bindings[i].call(self, element);
|
||||
if (isElement(value))
|
||||
value = '';
|
||||
else if (isObject(value))
|
||||
value = toJson(value, true);
|
||||
parts.push(value);
|
||||
};
|
||||
return parts.join('');
|
||||
};
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
|
||||
angularDirective("ng-bind-template", function(expression){
|
||||
var templateFn = compileBindTemplate(expression);
|
||||
return function(element) {
|
||||
var lastValue;
|
||||
this.$onEval(function() {
|
||||
var value = templateFn.call(this, element);
|
||||
if (value != lastValue) {
|
||||
element.text(value);
|
||||
lastValue = value;
|
||||
}
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
var REMOVE_ATTRIBUTES = {
|
||||
'disabled':'disabled',
|
||||
'readonly':'readOnly',
|
||||
'checked':'checked'
|
||||
};
|
||||
angularDirective("ng-bind-attr", function(expression){
|
||||
return function(element){
|
||||
var lastValue = {};
|
||||
this.$onEval(function(){
|
||||
var values = this.$eval(expression);
|
||||
for(var key in values) {
|
||||
var value = compileBindTemplate(values[key]).call(this, element),
|
||||
specialName = REMOVE_ATTRIBUTES[lowercase(key)];
|
||||
if (lastValue[key] !== value) {
|
||||
lastValue[key] = value;
|
||||
if (specialName) {
|
||||
if (element[specialName] = toBoolean(value)) {
|
||||
element.attr(specialName, value);
|
||||
} else {
|
||||
element.removeAttr(key);
|
||||
}
|
||||
(element.data('$validate')||noop)();
|
||||
} else {
|
||||
element.attr(key, value);
|
||||
}
|
||||
}
|
||||
};
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
angularWidget("@ng-non-bindable", noop);
|
||||
|
||||
angularWidget("@ng-repeat", function(expression, element){
|
||||
element.removeAttr('ng-repeat');
|
||||
element.replaceWith(this.comment("ng-repeat: " + expression));
|
||||
var template = this.compile(element);
|
||||
return function(reference){
|
||||
var match = expression.match(/^\s*(.+)\s+in\s+(.*)\s*$/),
|
||||
lhs, rhs, valueIdent, keyIdent;
|
||||
if (! match) {
|
||||
throw "Expected ng-repeat in form of 'item in collection' but got '" +
|
||||
expression + "'.";
|
||||
}
|
||||
lhs = match[1];
|
||||
rhs = match[2];
|
||||
match = lhs.match(/^([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\)$/);
|
||||
if (!match) {
|
||||
throw "'item' in 'item in collection' should be identifier or (key, value) but got '" +
|
||||
keyValue + "'.";
|
||||
}
|
||||
valueIdent = match[3] || match[1];
|
||||
keyIdent = match[2];
|
||||
|
||||
if (isUndefined(this.$eval(rhs))) this.$set(rhs, []);
|
||||
|
||||
var children = [], currentScope = this;
|
||||
this.$onEval(function(){
|
||||
var index = 0, childCount = children.length, childScope, lastElement = reference,
|
||||
collection = this.$tryEval(rhs, reference);
|
||||
for ( var key in collection) {
|
||||
if (index < childCount) {
|
||||
// reuse existing child
|
||||
childScope = children[index];
|
||||
childScope[valueIdent] = collection[key];
|
||||
if (keyIdent) childScope[keyIdent] = key;
|
||||
} else {
|
||||
// grow children
|
||||
childScope = template(element.clone(), createScope(currentScope));
|
||||
childScope[valueIdent] = collection[key];
|
||||
if (keyIdent) childScope[keyIdent] = key;
|
||||
lastElement.after(childScope.$element);
|
||||
childScope.$index = index;
|
||||
childScope.$element.attr('ng-repeat-index', index);
|
||||
childScope.$init();
|
||||
children.push(childScope);
|
||||
}
|
||||
childScope.$eval();
|
||||
lastElement = childScope.$element;
|
||||
index ++;
|
||||
};
|
||||
// shrink children
|
||||
while(children.length > index) {
|
||||
children.pop().$element.remove();
|
||||
}
|
||||
}, reference);
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-click", function(expression, element){
|
||||
return function(element){
|
||||
var self = this;
|
||||
element.bind('click', function(){
|
||||
self.$tryEval(expression, element);
|
||||
self.$root.$eval();
|
||||
return false;
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-watch", function(expression, element){
|
||||
return function(element){
|
||||
var self = this;
|
||||
new Parser(expression).watch()({
|
||||
addListener:function(watch, exp){
|
||||
self.$watch(watch, function(){
|
||||
return exp(self);
|
||||
}, element);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
function ngClass(selector) {
|
||||
return function(expression, element){
|
||||
var existing = element[0].className + ' ';
|
||||
return function(element){
|
||||
this.$onEval(function(){
|
||||
var value = this.$eval(expression);
|
||||
if (selector(this.$index)) {
|
||||
if (isArray(value)) value = value.join(' ');
|
||||
element[0].className = trim(existing + value);
|
||||
}
|
||||
}, element);
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
angularDirective("ng-class", ngClass(function(){return true;}));
|
||||
angularDirective("ng-class-odd", ngClass(function(i){return i % 2 === 0;}));
|
||||
angularDirective("ng-class-even", ngClass(function(i){return i % 2 === 1;}));
|
||||
|
||||
angularDirective("ng-show", function(expression, element){
|
||||
return function(element){
|
||||
this.$onEval(function(){
|
||||
element.css('display', toBoolean(this.$eval(expression)) ? '' : 'none');
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-hide", function(expression, element){
|
||||
return function(element){
|
||||
this.$onEval(function(){
|
||||
element.css('display', toBoolean(this.$eval(expression)) ? 'none' : '');
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
angularDirective("ng-style", function(expression, element){
|
||||
return function(element){
|
||||
this.$onEval(function(){
|
||||
element.css(this.$eval(expression));
|
||||
}, element);
|
||||
};
|
||||
});
|
||||
|
||||
298
src/filters.js
Normal file
298
src/filters.js
Normal file
|
|
@ -0,0 +1,298 @@
|
|||
var angularFilterGoogleChartApi;
|
||||
|
||||
foreach({
|
||||
'currency': function(amount){
|
||||
this.$element.toggleClass('ng-format-negative', amount < 0);
|
||||
return '$' + angularFilter['number'].apply(this, [amount, 2]);
|
||||
},
|
||||
|
||||
'number': function(amount, fractionSize){
|
||||
if (isNaN(amount) || !isFinite(amount)) {
|
||||
return '';
|
||||
}
|
||||
fractionSize = typeof fractionSize == 'undefined' ? 2 : fractionSize;
|
||||
var isNegative = amount < 0;
|
||||
amount = Math.abs(amount);
|
||||
var pow = Math.pow(10, fractionSize);
|
||||
var text = "" + Math.round(amount * pow);
|
||||
var whole = text.substring(0, text.length - fractionSize);
|
||||
whole = whole || '0';
|
||||
var frc = text.substring(text.length - fractionSize);
|
||||
text = isNegative ? '-' : '';
|
||||
for (var i = 0; i < whole.length; i++) {
|
||||
if ((whole.length - i)%3 === 0 && i !== 0) {
|
||||
text += ',';
|
||||
}
|
||||
text += whole.charAt(i);
|
||||
}
|
||||
if (fractionSize > 0) {
|
||||
for (var j = frc.length; j < fractionSize; j++) {
|
||||
frc += '0';
|
||||
}
|
||||
text += '.' + frc.substring(0, fractionSize);
|
||||
}
|
||||
return text;
|
||||
},
|
||||
|
||||
'date': function(amount) {
|
||||
},
|
||||
|
||||
'json': function(object) {
|
||||
this.$element.addClass("ng-monospace");
|
||||
return toJson(object, true);
|
||||
},
|
||||
|
||||
'trackPackage': (function(){
|
||||
var MATCHERS = [
|
||||
{ name: "UPS",
|
||||
url: "http://wwwapps.ups.com/WebTracking/processInputRequest?sort_by=status&tracknums_displayed=1&TypeOfInquiryNumber=T&loc=en_US&track.x=0&track.y=0&InquiryNumber1=",
|
||||
regexp: [
|
||||
/^1Z[0-9A-Z]{16}$/i]},
|
||||
{ name: "FedEx",
|
||||
url: "http://www.fedex.com/Tracking?tracknumbers=",
|
||||
regexp: [
|
||||
/^96\d{10}?$/i,
|
||||
/^96\d{17}?$/i,
|
||||
/^96\d{20}?$/i,
|
||||
/^\d{15}$/i,
|
||||
/^\d{12}$/i]},
|
||||
{ name: "USPS",
|
||||
url: "http://trkcnfrm1.smi.usps.com/PTSInternetWeb/InterLabelInquiry.do?origTrackNum=",
|
||||
regexp: [
|
||||
/^(91\d{20})$/i,
|
||||
/^(91\d{18})$/i]}];
|
||||
return function(trackingNo, noMatch) {
|
||||
trackingNo = trim(trackingNo);
|
||||
var tNo = trackingNo.replace(/ /g, '');
|
||||
var returnValue;
|
||||
foreach(MATCHERS, function(carrier){
|
||||
foreach(carrier.regexp, function(regexp){
|
||||
if (!returnValue && regexp.test(tNo)) {
|
||||
var text = carrier.name + ": " + trackingNo;
|
||||
var url = carrier.url + trackingNo;
|
||||
returnValue = jqLite('<a></a>');
|
||||
returnValue.text(text);
|
||||
returnValue.attr('href', url);
|
||||
}
|
||||
});
|
||||
});
|
||||
if (returnValue)
|
||||
return returnValue;
|
||||
else if (trackingNo)
|
||||
return noMatch || trackingNo + " is not recognized";
|
||||
else
|
||||
return null;
|
||||
};})(),
|
||||
|
||||
'link': function(obj, title) {
|
||||
if (obj) {
|
||||
var text = title || obj.text || obj;
|
||||
var url = obj.url || obj;
|
||||
if (url) {
|
||||
if (angular.validator.email(url) === null) {
|
||||
url = "mailto:" + url;
|
||||
}
|
||||
var a = jqLite('<a></a>');
|
||||
a.attr('href', url);
|
||||
a.text(text);
|
||||
return a;
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
|
||||
'bytes': (function(){
|
||||
var SUFFIX = ['bytes', 'KB', 'MB', 'GB', 'TB', 'PB'];
|
||||
return function(size) {
|
||||
if(size === null) return "";
|
||||
|
||||
var suffix = 0;
|
||||
while (size > 1000) {
|
||||
size = size / 1024;
|
||||
suffix++;
|
||||
}
|
||||
var txt = "" + size;
|
||||
var dot = txt.indexOf('.');
|
||||
if (dot > -1 && dot + 2 < txt.length) {
|
||||
txt = txt.substring(0, dot + 2);
|
||||
}
|
||||
return txt + " " + SUFFIX[suffix];
|
||||
};
|
||||
})(),
|
||||
|
||||
'image': function(obj, width, height) {
|
||||
if (obj && obj.url) {
|
||||
var style = "", img = jqLite('<img>');
|
||||
if (width) {
|
||||
img.css('max-width', width + 'px');
|
||||
img.css('max-height', (height || width) + 'px');
|
||||
}
|
||||
img.attr('src', obj.url);
|
||||
return img;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
'lowercase': lowercase,
|
||||
|
||||
'uppercase': uppercase,
|
||||
|
||||
'linecount': function (obj) {
|
||||
if (isString(obj)) {
|
||||
if (obj==='') return 1;
|
||||
return obj.split(/\n|\f/).length;
|
||||
}
|
||||
return 1;
|
||||
},
|
||||
|
||||
'if': function (result, expression) {
|
||||
return expression ? result : undefined;
|
||||
},
|
||||
|
||||
'unless': function (result, expression) {
|
||||
return expression ? undefined : result;
|
||||
},
|
||||
|
||||
'googleChartApi': extend(
|
||||
function(type, data, width, height) {
|
||||
data = data || {};
|
||||
var chart = {
|
||||
'cht':type,
|
||||
'chco':angularFilterGoogleChartApi['collect'](data, 'color'),
|
||||
'chtt':angularFilterGoogleChartApi['title'](data),
|
||||
'chdl':angularFilterGoogleChartApi['collect'](data, 'label'),
|
||||
'chd':angularFilterGoogleChartApi['values'](data),
|
||||
'chf':'bg,s,FFFFFF00'
|
||||
};
|
||||
if (_.isArray(data['xLabels'])) {
|
||||
chart['chxt']='x';
|
||||
chart['chxl']='0:|' + data.xLabels.join('|');
|
||||
}
|
||||
return angularFilterGoogleChartApi['encode'](chart, width, height);
|
||||
},
|
||||
{
|
||||
'values': function(data){
|
||||
var seriesValues = [];
|
||||
foreach(data['series']||[], function(serie){
|
||||
var values = [];
|
||||
foreach(serie['values']||[], function(value){
|
||||
values.push(value);
|
||||
});
|
||||
seriesValues.push(values.join(','));
|
||||
});
|
||||
var values = seriesValues.join('|');
|
||||
return values === "" ? null : "t:" + values;
|
||||
},
|
||||
|
||||
'title': function(data){
|
||||
var titles = [];
|
||||
var title = data['title'] || [];
|
||||
foreach(_.isArray(title)?title:[title], function(text){
|
||||
titles.push(encodeURIComponent(text));
|
||||
});
|
||||
return titles.join('|');
|
||||
},
|
||||
|
||||
'collect': function(data, key){
|
||||
var outterValues = [];
|
||||
var count = 0;
|
||||
foreach(data['series']||[], function(serie){
|
||||
var innerValues = [];
|
||||
var value = serie[key] || [];
|
||||
foreach(_.isArray(value)?value:[value], function(color){
|
||||
innerValues.push(encodeURIComponent(color));
|
||||
count++;
|
||||
});
|
||||
outterValues.push(innerValues.join('|'));
|
||||
});
|
||||
return count?outterValues.join(','):null;
|
||||
},
|
||||
|
||||
'encode': function(params, width, height) {
|
||||
width = width || 200;
|
||||
height = height || width;
|
||||
var url = "http://chart.apis.google.com/chart?",
|
||||
urlParam = [],
|
||||
img = jqLite('<img>');
|
||||
params['chs'] = width + "x" + height;
|
||||
foreach(params, function(value, key){
|
||||
if (value) {
|
||||
urlParam.push(key + "=" + value);
|
||||
}
|
||||
});
|
||||
urlParam.sort();
|
||||
url += urlParam.join("&");
|
||||
img.attr('src', url);
|
||||
img.css({width: width + 'px', height: height + 'px'});
|
||||
return img;
|
||||
}
|
||||
}
|
||||
),
|
||||
|
||||
|
||||
'qrcode': function(value, width, height) {
|
||||
return angularFilterGoogleChartApi['encode']({
|
||||
'cht':'qr', 'chl':encodeURIComponent(value)}, width, height);
|
||||
},
|
||||
'chart': {
|
||||
'pie':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('p', data, width, height);
|
||||
},
|
||||
'pie3d':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('p3', data, width, height);
|
||||
},
|
||||
'pieConcentric':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('pc', data, width, height);
|
||||
},
|
||||
'barHorizontalStacked':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('bhs', data, width, height);
|
||||
},
|
||||
'barHorizontalGrouped':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('bhg', data, width, height);
|
||||
},
|
||||
'barVerticalStacked':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('bvs', data, width, height);
|
||||
},
|
||||
'barVerticalGrouped':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('bvg', data, width, height);
|
||||
},
|
||||
'line':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('lc', data, width, height);
|
||||
},
|
||||
'sparkline':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('ls', data, width, height);
|
||||
},
|
||||
'scatter':function(data, width, height) {
|
||||
return angularFilterGoogleChartApi('s', data, width, height);
|
||||
}
|
||||
},
|
||||
|
||||
'html': function(html){
|
||||
return new HTML(html);
|
||||
},
|
||||
|
||||
'linky': function(text){
|
||||
if (!text) return text;
|
||||
function regExpEscape(text) {
|
||||
return text.replace(/([\/\.\*\+\?\|\(\)\[\]\{\}\\])/g, '\\$1');
|
||||
}
|
||||
var URL = /(ftp|http|https|mailto):\/\/([^\(\)|\s]+)/;
|
||||
var match;
|
||||
var raw = text;
|
||||
var html = [];
|
||||
while (match=raw.match(URL)) {
|
||||
var url = match[0].replace(/[\.\;\,\(\)\{\}\<\>]$/,'');
|
||||
var i = raw.indexOf(url);
|
||||
html.push(escapeHtml(raw.substr(0, i)));
|
||||
html.push('<a href="' + url + '">');
|
||||
html.push(url);
|
||||
html.push('</a>');
|
||||
raw = raw.substring(i + url.length);
|
||||
}
|
||||
html.push(escapeHtml(raw));
|
||||
return new HTML(html.join(''));
|
||||
}
|
||||
}, function(v,k){angularFilter[k] = v;});
|
||||
|
||||
angularFilterGoogleChartApi = angularFilter['googleChartApi'];
|
||||
32
src/formatters.js
Normal file
32
src/formatters.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
function formatter(format, parse) {return {'format':format, 'parse':parse || format};}
|
||||
function toString(obj) {return (isDefined(obj) && obj !== null) ? "" + obj : obj;}
|
||||
|
||||
var NUMBER = /^\s*[-+]?\d*(\.\d*)?\s*$/;
|
||||
|
||||
extend(angularFormatter, {
|
||||
'noop':formatter(identity, identity),
|
||||
'boolean':formatter(toString, toBoolean),
|
||||
'number':formatter(toString,
|
||||
function(obj){
|
||||
if (isString(obj) && NUMBER.exec(obj)) {
|
||||
return obj ? 1*obj : null;
|
||||
}
|
||||
throw "Not a number";
|
||||
}),
|
||||
|
||||
'list':formatter(
|
||||
function(obj) { return obj ? obj.join(", ") : obj; },
|
||||
function(value) {
|
||||
var list = [];
|
||||
foreach((value || '').split(','), function(item){
|
||||
item = trim(item);
|
||||
if (item) list.push(item);
|
||||
});
|
||||
return list;
|
||||
}
|
||||
),
|
||||
|
||||
'trim':formatter(
|
||||
function(obj) { return obj ? trim("" + obj) : ""; }
|
||||
)
|
||||
});
|
||||
248
src/jqLite.js
Normal file
248
src/jqLite.js
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
//////////////////////////////////
|
||||
//JQLite
|
||||
//////////////////////////////////
|
||||
|
||||
var jqCache = {};
|
||||
var jqName = 'ng-' + new Date().getTime();
|
||||
var jqId = 1;
|
||||
function jqNextId() { return (jqId++); }
|
||||
|
||||
var addEventListener = window.document.attachEvent ?
|
||||
function(element, type, fn) {
|
||||
element.attachEvent('on' + type, fn);
|
||||
} : function(element, type, fn) {
|
||||
element.addEventListener(type, fn, false);
|
||||
};
|
||||
|
||||
var removeEventListener = window.document.detachEvent ?
|
||||
function(element, type, fn) {
|
||||
element.detachEvent('on' + type, fn);
|
||||
} : function(element, type, fn) {
|
||||
element.removeEventListener(type, fn, false);
|
||||
};
|
||||
|
||||
function jqClearData(element) {
|
||||
var cacheId = element[jqName],
|
||||
cache = jqCache[cacheId];
|
||||
if (cache) {
|
||||
foreach(cache.bind || {}, function(fn, type){
|
||||
removeEventListener(element, type, fn);
|
||||
});
|
||||
delete jqCache[cacheId];
|
||||
if (msie)
|
||||
element[jqName] = ''; // ie does not allow deletion of attributes on elements.
|
||||
else
|
||||
delete element[jqName];
|
||||
}
|
||||
}
|
||||
|
||||
function JQLite(element) {
|
||||
if (isElement(element)) {
|
||||
this[0] = element;
|
||||
this.length = 1;
|
||||
} else if (isDefined(element.length) && element.item) {
|
||||
for(var i=0; i < element.length; i++) {
|
||||
this[i] = element[i];
|
||||
}
|
||||
this.length = element.length;
|
||||
}
|
||||
}
|
||||
|
||||
JQLite.prototype = {
|
||||
data: function(key, value) {
|
||||
var element = this[0],
|
||||
cacheId = element[jqName],
|
||||
cache = jqCache[cacheId || -1];
|
||||
if (isDefined(value)) {
|
||||
if (!cache) {
|
||||
element[jqName] = cacheId = jqNextId();
|
||||
cache = jqCache[cacheId] = {};
|
||||
}
|
||||
cache[key] = value;
|
||||
} else {
|
||||
return cache ? cache[key] : null;
|
||||
}
|
||||
},
|
||||
|
||||
removeData: function(){
|
||||
jqClearData(this[0]);
|
||||
},
|
||||
|
||||
dealoc: function(){
|
||||
(function dealoc(element){
|
||||
jqClearData(element);
|
||||
for ( var i = 0, children = element.childNodes; i < children.length; i++) {
|
||||
dealoc(children[i]);
|
||||
}
|
||||
})(this[0]);
|
||||
},
|
||||
|
||||
bind: function(type, fn){
|
||||
var self = this,
|
||||
element = self[0],
|
||||
bind = self.data('bind'),
|
||||
eventHandler;
|
||||
if (!bind) this.data('bind', bind = {});
|
||||
foreach(type.split(' '), function(type){
|
||||
eventHandler = bind[type];
|
||||
if (!eventHandler) {
|
||||
bind[type] = eventHandler = function(event) {
|
||||
var bubbleEvent = false;
|
||||
foreach(eventHandler.fns, function(fn){
|
||||
bubbleEvent = bubbleEvent || fn.call(self, event);
|
||||
});
|
||||
if (!bubbleEvent) {
|
||||
if (msie) {
|
||||
event.returnValue = false;
|
||||
event.cancelBubble = true;
|
||||
} else {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
};
|
||||
eventHandler.fns = [];
|
||||
addEventListener(element, type, eventHandler);
|
||||
}
|
||||
eventHandler.fns.push(fn);
|
||||
});
|
||||
},
|
||||
|
||||
trigger: function(type) {
|
||||
var evnt = document.createEvent('MouseEvent');
|
||||
evnt.initMouseEvent(type, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
|
||||
this[0].dispatchEvent(evnt);
|
||||
},
|
||||
|
||||
replaceWith: function(replaceNode) {
|
||||
this[0].parentNode.replaceChild(jqLite(replaceNode)[0], this[0]);
|
||||
},
|
||||
|
||||
children: function() {
|
||||
return new JQLite(this[0].childNodes);
|
||||
},
|
||||
|
||||
append: function(node) {
|
||||
var self = this[0];
|
||||
node = jqLite(node);
|
||||
foreach(node, function(child){
|
||||
self.appendChild(child);
|
||||
});
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.dealoc();
|
||||
var parentNode = this[0].parentNode;
|
||||
if (parentNode) parentNode.removeChild(this[0]);
|
||||
},
|
||||
|
||||
removeAttr: function(name) {
|
||||
this[0].removeAttribute(name);
|
||||
},
|
||||
|
||||
after: function(element) {
|
||||
this[0].parentNode.insertBefore(jqLite(element)[0], this[0].nextSibling);
|
||||
},
|
||||
|
||||
hasClass: function(selector) {
|
||||
var className = " " + selector + " ";
|
||||
if ( (" " + this[0].className + " ").replace(/[\n\t]/g, " ").indexOf( className ) > -1 ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
removeClass: function(selector) {
|
||||
this[0].className = trim((" " + this[0].className + " ").replace(/[\n\t]/g, " ").replace(" " + selector + " ", ""));
|
||||
},
|
||||
|
||||
toggleClass: function(selector, condition) {
|
||||
var self = this;
|
||||
(condition ? self.addClass : self.removeClass).call(self, selector);
|
||||
},
|
||||
|
||||
addClass: function( selector ) {
|
||||
if (!this.hasClass(selector)) {
|
||||
this[0].className = trim(this[0].className + ' ' + selector);
|
||||
}
|
||||
},
|
||||
|
||||
css: function(name, value) {
|
||||
var style = this[0].style;
|
||||
if (isString(name)) {
|
||||
if (isDefined(value)) {
|
||||
style[name] = value;
|
||||
} else {
|
||||
return style[name];
|
||||
}
|
||||
} else {
|
||||
extend(style, name);
|
||||
}
|
||||
},
|
||||
|
||||
attr: function(name, value){
|
||||
var e = this[0];
|
||||
if (isObject(name)) {
|
||||
foreach(name, function(value, name){
|
||||
e.setAttribute(name, value);
|
||||
});
|
||||
} else if (isDefined(value)) {
|
||||
e.setAttribute(name, value);
|
||||
} else {
|
||||
var attributes = e.attributes,
|
||||
item = attributes ? attributes.getNamedItem(name) : undefined;
|
||||
return item && item.specified ? item.value : undefined;
|
||||
}
|
||||
},
|
||||
|
||||
text: function(value) {
|
||||
if (isDefined(value)) {
|
||||
this[0].textContent = value;
|
||||
}
|
||||
return this[0].textContent;
|
||||
},
|
||||
|
||||
val: function(value) {
|
||||
if (isDefined(value)) {
|
||||
this[0].value = value;
|
||||
}
|
||||
return this[0].value;
|
||||
},
|
||||
|
||||
html: function(value) {
|
||||
if (isDefined(value)) {
|
||||
var i = 0, childNodes = this[0].childNodes;
|
||||
for ( ; i < childNodes.length; i++) {
|
||||
jqLite(childNodes[i]).dealoc();
|
||||
}
|
||||
this[0].innerHTML = value;
|
||||
}
|
||||
return this[0].innerHTML;
|
||||
},
|
||||
|
||||
parent: function() {
|
||||
return jqLite(this[0].parentNode);
|
||||
},
|
||||
|
||||
clone: function() { return jqLite(this[0].cloneNode(true)); }
|
||||
};
|
||||
|
||||
if (msie) {
|
||||
extend(JQLite.prototype, {
|
||||
text: function(value) {
|
||||
var e = this[0];
|
||||
// NodeType == 3 is text node
|
||||
if (e.nodeType == 3) {
|
||||
if (isDefined(value)) e.nodeValue = value;
|
||||
return e.nodeValue;
|
||||
} else {
|
||||
if (isDefined(value)) e.innerText = value;
|
||||
return e.innerText;
|
||||
}
|
||||
},
|
||||
|
||||
trigger: function(type) {
|
||||
this[0].fireEvent('on' + type);
|
||||
}
|
||||
});
|
||||
}
|
||||
85
src/markups.js
Normal file
85
src/markups.js
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
function parseBindings(string) {
|
||||
var results = [];
|
||||
var lastIndex = 0;
|
||||
var index;
|
||||
while((index = string.indexOf('{{', lastIndex)) > -1) {
|
||||
if (lastIndex < index)
|
||||
results.push(string.substr(lastIndex, index - lastIndex));
|
||||
lastIndex = index;
|
||||
|
||||
index = string.indexOf('}}', index);
|
||||
index = index < 0 ? string.length : index + 2;
|
||||
|
||||
results.push(string.substr(lastIndex, index - lastIndex));
|
||||
lastIndex = index;
|
||||
}
|
||||
if (lastIndex != string.length)
|
||||
results.push(string.substr(lastIndex, string.length - lastIndex));
|
||||
return results.length === 0 ? [ string ] : results;
|
||||
}
|
||||
|
||||
function binding(string) {
|
||||
var binding = string.replace(/\n/gm, ' ').match(/^\{\{(.*)\}\}$/);
|
||||
return binding ? binding[1] : null;
|
||||
}
|
||||
|
||||
function hasBindings(bindings) {
|
||||
return bindings.length > 1 || binding(bindings[0]) !== null;
|
||||
}
|
||||
|
||||
angularTextMarkup('{{}}', function(text, textNode, parentElement) {
|
||||
var bindings = parseBindings(text),
|
||||
self = this;
|
||||
if (hasBindings(bindings)) {
|
||||
if (isLeafNode(parentElement[0])) {
|
||||
parentElement.attr('ng-bind-template', text);
|
||||
} else {
|
||||
var cursor = textNode, newElement;
|
||||
foreach(parseBindings(text), function(text){
|
||||
var exp = binding(text);
|
||||
if (exp) {
|
||||
newElement = self.element('span');
|
||||
newElement.attr('ng-bind', exp);
|
||||
} else {
|
||||
newElement = self.text(text);
|
||||
}
|
||||
if (msie && text.charAt(0) == ' ') {
|
||||
newElement = jqLite('<span> </span>');
|
||||
var nbsp = newElement.html();
|
||||
newElement.text(text.substr(1));
|
||||
newElement.html(nbsp + newElement.html());
|
||||
}
|
||||
cursor.after(newElement);
|
||||
cursor = newElement;
|
||||
});
|
||||
}
|
||||
textNode.remove();
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: this should be widget not a markup
|
||||
angularTextMarkup('OPTION', function(text, textNode, parentElement){
|
||||
if (nodeName(parentElement) == "OPTION") {
|
||||
var select = document.createElement('select');
|
||||
select.insertBefore(parentElement[0].cloneNode(true), null);
|
||||
if (!select.innerHTML.match(/<option(\s.*\s|\s)value\s*=\s*.*>.*<\/\s*option\s*>/gi)) {
|
||||
parentElement.attr('value', text);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var NG_BIND_ATTR = 'ng-bind-attr';
|
||||
angularAttrMarkup('{{}}', function(value, name, element){
|
||||
if (name.substr(0, 3) != 'ng-') {
|
||||
if (msie && name == 'src')
|
||||
value = decodeURI(value);
|
||||
var bindings = parseBindings(value),
|
||||
bindAttr;
|
||||
if (hasBindings(bindings)) {
|
||||
element.removeAttr(name);
|
||||
bindAttr = fromJson(element.attr(NG_BIND_ATTR) || "{}");
|
||||
bindAttr[name] = value;
|
||||
element.attr(NG_BIND_ATTR, toJson(bindAttr));
|
||||
}
|
||||
}
|
||||
});
|
||||
72
src/moveToAngularCom/ControlBar.js
Normal file
72
src/moveToAngularCom/ControlBar.js
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
function ControlBar(document, serverUrl, database) {
|
||||
this._document = document;
|
||||
this.serverUrl = serverUrl;
|
||||
this.database = database;
|
||||
this._window = window;
|
||||
this.callbacks = [];
|
||||
};
|
||||
|
||||
ControlBar.HTML =
|
||||
'<div>' +
|
||||
'<div class="ui-widget-overlay"></div>' +
|
||||
'<div id="ng-login" ng-non-bindable="true">' +
|
||||
'<div class="ng-login-container"></div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
|
||||
ControlBar.FORBIDEN =
|
||||
'<div ng-non-bindable="true" title="Permission Error:">' +
|
||||
'Sorry, you do not have permission for this!'+
|
||||
'</div>';
|
||||
|
||||
ControlBar.prototype = {
|
||||
bind: function () {
|
||||
},
|
||||
|
||||
login: function (loginSubmitFn) {
|
||||
this.callbacks.push(loginSubmitFn);
|
||||
if (this.callbacks.length == 1) {
|
||||
this.doTemplate("/user_session/new.mini?database="+encodeURIComponent(this.database)+"&return_url=" + encodeURIComponent(this.urlWithoutAnchor()));
|
||||
}
|
||||
},
|
||||
|
||||
logout: function (loginSubmitFn) {
|
||||
this.callbacks.push(loginSubmitFn);
|
||||
if (this.callbacks.length == 1) {
|
||||
this.doTemplate("/user_session/do_destroy.mini");
|
||||
}
|
||||
},
|
||||
|
||||
urlWithoutAnchor: function (path) {
|
||||
return this._window['location']['href'].split("#")[0];
|
||||
},
|
||||
|
||||
doTemplate: function (path) {
|
||||
var self = this;
|
||||
var id = new Date().getTime();
|
||||
var url = this.urlWithoutAnchor() + "#$iframe_notify=" + id;
|
||||
var iframeHeight = 330;
|
||||
var loginView = jQuery('<div style="overflow:hidden; padding:2px 0 0 0;"><iframe name="'+ url +'" src="'+this.serverUrl + path + '" width="500" height="'+ iframeHeight +'"/></div>');
|
||||
this._document.append(loginView);
|
||||
loginView['dialog']({
|
||||
'height':iframeHeight + 33, 'width':500,
|
||||
'resizable': false, 'modal':true,
|
||||
'title': 'Authentication: <a href="http://www.getangular.com"><tt><angular/></tt></a>'
|
||||
});
|
||||
angularCallbacks["_iframe_notify_" + id] = function() {
|
||||
loginView['dialog']("destroy");
|
||||
loginView['remove']();
|
||||
foreach(self.callbacks, function(callback){
|
||||
callback();
|
||||
});
|
||||
self.callbacks = [];
|
||||
};
|
||||
},
|
||||
|
||||
notAuthorized: function () {
|
||||
if (this.forbidenView) return;
|
||||
this.forbidenView = jQuery(ControlBar.FORBIDEN);
|
||||
this.forbidenView.dialog({bgiframe:true, height:70, modal:true});
|
||||
}
|
||||
};
|
||||
330
src/moveToAngularCom/DataStore.js
Normal file
330
src/moveToAngularCom/DataStore.js
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
function DataStore(post, users, anchor) {
|
||||
this.post = post;
|
||||
this.users = users;
|
||||
this._cache_collections = [];
|
||||
this._cache = {'$collections':this._cache_collections};
|
||||
this.anchor = anchor;
|
||||
this.bulkRequest = [];
|
||||
};
|
||||
|
||||
DataStore.NullEntity = extend(function(){}, {
|
||||
'all': function(){return [];},
|
||||
'query': function(){return [];},
|
||||
'load': function(){return {};},
|
||||
'title': undefined
|
||||
});
|
||||
|
||||
DataStore.prototype = {
|
||||
cache: function(document) {
|
||||
if (! document.datastore === this) {
|
||||
throw "Parameter must be an instance of Entity! " + toJson(document);
|
||||
}
|
||||
var key = document['$entity'] + '/' + document['$id'];
|
||||
var cachedDocument = this._cache[key];
|
||||
if (cachedDocument) {
|
||||
Model.copyDirectFields(document, cachedDocument);
|
||||
} else {
|
||||
this._cache[key] = document;
|
||||
cachedDocument = document;
|
||||
}
|
||||
return cachedDocument;
|
||||
},
|
||||
|
||||
load: function(instance, id, callback, failure) {
|
||||
if (id && id !== '*') {
|
||||
var self = this;
|
||||
this._jsonRequest(["GET", instance['$entity'] + "/" + id], function(response) {
|
||||
instance['$loadFrom'](response);
|
||||
instance['$migrate']();
|
||||
var clone = instance['$$entity'](instance);
|
||||
self.cache(clone);
|
||||
(callback||noop)(instance);
|
||||
}, failure);
|
||||
}
|
||||
return instance;
|
||||
},
|
||||
|
||||
loadMany: function(entity, ids, callback) {
|
||||
var self=this;
|
||||
var list = [];
|
||||
var callbackCount = 0;
|
||||
foreach(ids, function(id){
|
||||
list.push(self.load(entity(), id, function(){
|
||||
callbackCount++;
|
||||
if (callbackCount == ids.length) {
|
||||
(callback||noop)(list);
|
||||
}
|
||||
}));
|
||||
});
|
||||
return list;
|
||||
},
|
||||
|
||||
loadOrCreate: function(instance, id, callback) {
|
||||
var self=this;
|
||||
return this.load(instance, id, callback, function(response){
|
||||
if (response['$status_code'] == 404) {
|
||||
instance['$id'] = id;
|
||||
(callback||noop)(instance);
|
||||
} else {
|
||||
throw response;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
loadAll: function(entity, callback) {
|
||||
var self = this;
|
||||
var list = [];
|
||||
list['$$accept'] = function(doc){
|
||||
return doc['$entity'] == entity['title'];
|
||||
};
|
||||
this._cache_collections.push(list);
|
||||
this._jsonRequest(["GET", entity['title']], function(response) {
|
||||
var rows = response;
|
||||
for ( var i = 0; i < rows.length; i++) {
|
||||
var document = entity();
|
||||
document['$loadFrom'](rows[i]);
|
||||
list.push(self.cache(document));
|
||||
}
|
||||
(callback||noop)(list);
|
||||
});
|
||||
return list;
|
||||
},
|
||||
|
||||
save: function(document, callback) {
|
||||
var self = this;
|
||||
var data = {};
|
||||
document['$saveTo'](data);
|
||||
this._jsonRequest(["POST", "", data], function(response) {
|
||||
document['$loadFrom'](response);
|
||||
var cachedDoc = self.cache(document);
|
||||
_.each(self._cache_collections, function(collection){
|
||||
if (collection['$$accept'](document)) {
|
||||
angularArray['includeIf'](collection, cachedDoc, true);
|
||||
}
|
||||
});
|
||||
if (document['$$anchor']) {
|
||||
self.anchor[document['$$anchor']] = document['$id'];
|
||||
}
|
||||
if (callback)
|
||||
callback(document);
|
||||
});
|
||||
},
|
||||
|
||||
remove: function(document, callback) {
|
||||
var self = this;
|
||||
var data = {};
|
||||
document['$saveTo'](data);
|
||||
this._jsonRequest(["DELETE", "", data], function(response) {
|
||||
delete self._cache[document['$entity'] + '/' + document['$id']];
|
||||
_.each(self._cache_collections, function(collection){
|
||||
for ( var i = 0; i < collection.length; i++) {
|
||||
var item = collection[i];
|
||||
if (item['$id'] == document['$id']) {
|
||||
collection.splice(i, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
(callback||noop)(response);
|
||||
});
|
||||
},
|
||||
|
||||
_jsonRequest: function(request, callback, failure) {
|
||||
request['$$callback'] = callback;
|
||||
request['$$failure'] = failure||function(response){
|
||||
throw response;
|
||||
};
|
||||
this.bulkRequest.push(request);
|
||||
},
|
||||
|
||||
flush: function() {
|
||||
if (this.bulkRequest.length === 0) return;
|
||||
var self = this;
|
||||
var bulkRequest = this.bulkRequest;
|
||||
this.bulkRequest = [];
|
||||
log('REQUEST:', bulkRequest);
|
||||
function callback(code, bulkResponse){
|
||||
log('RESPONSE[' + code + ']: ', bulkResponse);
|
||||
if(bulkResponse['$status_code'] == 401) {
|
||||
self.users['login'](function(){
|
||||
self.post(bulkRequest, callback);
|
||||
});
|
||||
} else if(bulkResponse['$status_code']) {
|
||||
alert(toJson(bulkResponse));
|
||||
} else {
|
||||
for ( var i = 0; i < bulkResponse.length; i++) {
|
||||
var response = bulkResponse[i];
|
||||
var request = bulkRequest[i];
|
||||
var responseCode = response['$status_code'];
|
||||
if(responseCode) {
|
||||
if(responseCode == 403) {
|
||||
self.users['notAuthorized']();
|
||||
} else {
|
||||
request['$$failure'](response);
|
||||
}
|
||||
} else {
|
||||
request['$$callback'](response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.post(bulkRequest, callback);
|
||||
},
|
||||
|
||||
saveScope: function(scope, callback) {
|
||||
var saveCounter = 1;
|
||||
function onSaveDone() {
|
||||
saveCounter--;
|
||||
if (saveCounter === 0 && callback)
|
||||
callback();
|
||||
}
|
||||
for(var key in scope) {
|
||||
var item = scope[key];
|
||||
if (item && item['$save'] == Model.prototype['$save']) {
|
||||
saveCounter++;
|
||||
item['$save'](onSaveDone);
|
||||
}
|
||||
}
|
||||
onSaveDone();
|
||||
},
|
||||
|
||||
query: function(type, query, arg, callback){
|
||||
var self = this;
|
||||
var queryList = [];
|
||||
queryList['$$accept'] = function(doc){
|
||||
return false;
|
||||
};
|
||||
this._cache_collections.push(queryList);
|
||||
var request = type['title'] + '/' + query + '=' + arg;
|
||||
this._jsonRequest(["GET", request], function(response){
|
||||
var list = response;
|
||||
foreach(list, function(item){
|
||||
var document = type()['$loadFrom'](item);
|
||||
queryList.push(self.cache(document));
|
||||
});
|
||||
(callback||noop)(queryList);
|
||||
});
|
||||
return queryList;
|
||||
},
|
||||
|
||||
entities: function(callback) {
|
||||
var entities = [];
|
||||
var self = this;
|
||||
this._jsonRequest(["GET", "$entities"], function(response) {
|
||||
foreach(response, function(value, entityName){
|
||||
entities.push(self.entity(entityName));
|
||||
});
|
||||
entities.sort(function(a,b){return a.title > b.title ? 1 : -1;});
|
||||
(callback||noop)(entities);
|
||||
});
|
||||
return entities;
|
||||
},
|
||||
|
||||
documentCountsByUser: function(){
|
||||
var counts = {};
|
||||
var self = this;
|
||||
self.post([["GET", "$users"]], function(code, response){
|
||||
extend(counts, response[0]);
|
||||
});
|
||||
return counts;
|
||||
},
|
||||
|
||||
userDocumentIdsByEntity: function(user){
|
||||
var ids = {};
|
||||
var self = this;
|
||||
self.post([["GET", "$users/" + user]], function(code, response){
|
||||
extend(ids, response[0]);
|
||||
});
|
||||
return ids;
|
||||
},
|
||||
|
||||
entity: function(name, defaults){
|
||||
if (!name) {
|
||||
return DataStore.NullEntity;
|
||||
}
|
||||
var self = this;
|
||||
var entity = extend(function(initialState){
|
||||
return new Model(entity, initialState);
|
||||
}, {
|
||||
// entity.name does not work as name seems to be reserved for functions
|
||||
'title': name,
|
||||
'$$factory': true,
|
||||
datastore: this, //private, obfuscate
|
||||
'defaults': defaults || {},
|
||||
'load': function(id, callback){
|
||||
return self.load(entity(), id, callback);
|
||||
},
|
||||
'loadMany': function(ids, callback){
|
||||
return self.loadMany(entity, ids, callback);
|
||||
},
|
||||
'loadOrCreate': function(id, callback){
|
||||
return self.loadOrCreate(entity(), id, callback);
|
||||
},
|
||||
'all': function(callback){
|
||||
return self.loadAll(entity, callback);
|
||||
},
|
||||
'query': function(query, queryArgs, callback){
|
||||
return self.query(entity, query, queryArgs, callback);
|
||||
},
|
||||
'properties': function(callback) {
|
||||
self._jsonRequest(["GET", name + "/$properties"], callback);
|
||||
}
|
||||
});
|
||||
return entity;
|
||||
},
|
||||
|
||||
join: function(join){
|
||||
function fn(){
|
||||
throw "Joined entities can not be instantiated into a document.";
|
||||
};
|
||||
function base(name){return name ? name.substring(0, name.indexOf('.')) : undefined;}
|
||||
function next(name){return name.substring(name.indexOf('.') + 1);}
|
||||
var joinOrder = _(join).chain().
|
||||
map(function($, name){
|
||||
return name;}).
|
||||
sortBy(function(name){
|
||||
var path = [];
|
||||
do {
|
||||
if (_(path).include(name)) throw "Infinite loop in join: " + path.join(" -> ");
|
||||
path.push(name);
|
||||
if (!join[name]) throw _("Named entity '<%=name%>' is undefined.").template({name:name});
|
||||
name = base(join[name].on);
|
||||
} while(name);
|
||||
return path.length;
|
||||
}).
|
||||
value();
|
||||
if (_(joinOrder).select(function($){return join[$].on;}).length != joinOrder.length - 1)
|
||||
throw "Exactly one entity needs to be primary.";
|
||||
fn['query'] = function(exp, value) {
|
||||
var joinedResult = [];
|
||||
var baseName = base(exp);
|
||||
if (baseName != joinOrder[0]) throw _("Named entity '<%=name%>' is not a primary entity.").template({name:baseName});
|
||||
var Entity = join[baseName].join;
|
||||
var joinIndex = 1;
|
||||
Entity['query'](next(exp), value, function(result){
|
||||
var nextJoinName = joinOrder[joinIndex++];
|
||||
var nextJoin = join[nextJoinName];
|
||||
var nextJoinOn = nextJoin.on;
|
||||
var joinIds = {};
|
||||
_(result).each(function(doc){
|
||||
var row = {};
|
||||
joinedResult.push(row);
|
||||
row[baseName] = doc;
|
||||
var id = Scope.getter(row, nextJoinOn);
|
||||
joinIds[id] = id;
|
||||
});
|
||||
nextJoin.join.loadMany(_.toArray(joinIds), function(result){
|
||||
var byId = {};
|
||||
_(result).each(function(doc){
|
||||
byId[doc.$id] = doc;
|
||||
});
|
||||
_(joinedResult).each(function(row){
|
||||
var id = Scope.getter(row, nextJoinOn);
|
||||
row[nextJoinName] = byId[id];
|
||||
});
|
||||
});
|
||||
});
|
||||
return joinedResult;
|
||||
};
|
||||
return fn;
|
||||
}
|
||||
};
|
||||
68
src/moveToAngularCom/Server.js
Normal file
68
src/moveToAngularCom/Server.js
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
function Server(url, getScript) {
|
||||
this.url = url;
|
||||
this.nextId = 0;
|
||||
this.getScript = getScript;
|
||||
this.uuid = "_" + ("" + Math.random()).substr(2) + "_";
|
||||
this.maxSize = 1800;
|
||||
};
|
||||
|
||||
Server.prototype = {
|
||||
base64url: function(txt) {
|
||||
return Base64.encode(txt);
|
||||
},
|
||||
|
||||
request: function(method, url, request, callback) {
|
||||
var requestId = this.uuid + (this.nextId++);
|
||||
var payload = this.base64url(toJson({'u':url, 'm':method, 'p':request}));
|
||||
var totalPockets = Math.ceil(payload.length / this.maxSize);
|
||||
var baseUrl = this.url + "/$/" + requestId + "/" + totalPockets + "/";
|
||||
angularCallbacks[requestId] = function(response) {
|
||||
delete angularCallbacks[requestId];
|
||||
callback(200, response);
|
||||
};
|
||||
for ( var pocketNo = 0; pocketNo < totalPockets; pocketNo++) {
|
||||
var pocket = payload.substr(pocketNo * this.maxSize, this.maxSize);
|
||||
this.getScript(baseUrl + (pocketNo+1) + "?h=" + pocket, noop);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function FrameServer(frame) {
|
||||
this.frame = frame;
|
||||
};
|
||||
FrameServer.PREFIX = "$DATASET:";
|
||||
|
||||
FrameServer.prototype = {
|
||||
read:function(){
|
||||
this.data = fromJson(this.frame.name.substr(FrameServer.PREFIX.length));
|
||||
},
|
||||
write:function(){
|
||||
this.frame.name = FrameServer.PREFIX + toJson(this.data);
|
||||
},
|
||||
request: function(method, url, request, callback) {
|
||||
//alert(method + " " + url + " " + toJson(request) + " " + toJson(callback));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function VisualServer(delegate, status, update) {
|
||||
this.delegate = delegate;
|
||||
this.update = update;
|
||||
this.status = status;
|
||||
};
|
||||
|
||||
VisualServer.prototype = {
|
||||
request:function(method, url, request, callback) {
|
||||
var self = this;
|
||||
this.status.beginRequest(request);
|
||||
this.delegate.request(method, url, request, function() {
|
||||
self.status.endRequest();
|
||||
try {
|
||||
callback.apply(this, arguments);
|
||||
} catch (e) {
|
||||
alert(toJson(e));
|
||||
}
|
||||
self.update();
|
||||
});
|
||||
}
|
||||
};
|
||||
35
src/moveToAngularCom/Users.js
Normal file
35
src/moveToAngularCom/Users.js
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
function Users(server, controlBar) {
|
||||
this.server = server;
|
||||
this.controlBar = controlBar;
|
||||
};
|
||||
|
||||
extend(Users.prototype, {
|
||||
'fetchCurrentUser':function(callback) {
|
||||
var self = this;
|
||||
this.server.request("GET", "/account.json", {}, function(code, response){
|
||||
self['current'] = response['user'];
|
||||
callback(response['user']);
|
||||
});
|
||||
},
|
||||
|
||||
'logout': function(callback) {
|
||||
var self = this;
|
||||
this.controlBar.logout(function(){
|
||||
delete self['current'];
|
||||
(callback||noop)();
|
||||
});
|
||||
},
|
||||
|
||||
'login': function(callback) {
|
||||
var self = this;
|
||||
this.controlBar.login(function(){
|
||||
self['fetchCurrentUser'](function(){
|
||||
(callback||noop)();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
'notAuthorized': function(){
|
||||
this.controlBar.notAuthorized();
|
||||
}
|
||||
});
|
||||
29
src/moveToAngularCom/directivesAngularCom.js
Normal file
29
src/moveToAngularCom/directivesAngularCom.js
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
angular.directive("auth", function(expression, element){
|
||||
return function(){
|
||||
if(expression == "eager") {
|
||||
this.$users.fetchCurrent();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
//expression = "book=Book:{year=2000}"
|
||||
angular.directive("entity", function(expression, element){
|
||||
//parse expression, ignore element
|
||||
var entityName; // "Book";
|
||||
var instanceName; // "book";
|
||||
var defaults; // {year: 2000};
|
||||
|
||||
parse(expression);
|
||||
|
||||
return function(){
|
||||
this[entityName] = this.$datastore.entity(entityName, defaults);
|
||||
this[instanceName] = this[entityName]();
|
||||
this.$watch("$anchor."+instanceName, function(newAnchor){
|
||||
this[instanceName] = this[entityName].get(this.$anchor[instanceName]);
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
63
src/scenario/DSL.js
Normal file
63
src/scenario/DSL.js
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
angular.scenario.dsl.browser = {
|
||||
navigateTo: function(url){
|
||||
$scenario.addStep('Navigate to: ' + url, function(done){
|
||||
var self = this;
|
||||
this.testFrame.load(function(){
|
||||
self.testFrame.unbind();
|
||||
self.testWindow = self.testFrame[0].contentWindow;
|
||||
self.testDocument = jQuery(self.testWindow.document);
|
||||
self.$browser = self.testWindow.angular.service.$browser();
|
||||
self.notifyWhenNoOutstandingRequests = bind(self.$browser, self.$browser.notifyWhenNoOutstandingRequests);
|
||||
self.notifyWhenNoOutstandingRequests(done);
|
||||
});
|
||||
if (this.testFrame.attr('src') == url) {
|
||||
this.testFrame[0].contentWindow.location.reload();
|
||||
} else {
|
||||
this.testFrame.attr('src', url);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
angular.scenario.dsl.input = function(selector) {
|
||||
return {
|
||||
enter: function(value){
|
||||
$scenario.addStep("Set input text of '" + selector + "' to '" +
|
||||
value + "'", function(done){
|
||||
var input = this.testDocument.find('input[name=' + selector + ']');
|
||||
input.val(value);
|
||||
this.testWindow.angular.element(input[0]).trigger('change');
|
||||
done();
|
||||
});
|
||||
},
|
||||
select: function(value){
|
||||
$scenario.addStep("Select radio '" + selector + "' to '" +
|
||||
value + "'", function(done){
|
||||
var input = this.testDocument.
|
||||
find(':radio[name$=@' + selector + '][value=' + value + ']');
|
||||
var event = this.testWindow.document.createEvent('MouseEvent');
|
||||
event.initMouseEvent('click', true, true, this.testWindow, 0,0,0,0,0, false, false, false, false, 0, null);
|
||||
input[0].dispatchEvent(event);
|
||||
done();
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
angular.scenario.dsl.expect = {
|
||||
repeater: function(selector) {
|
||||
return {
|
||||
count: {
|
||||
toEqual: function(number) {
|
||||
$scenario.addStep("Expect that there are " + number + " items in Repeater with selector '" + selector + "'", function(done) {
|
||||
var items = this.testDocument.find(selector);
|
||||
if (items.length != number) {
|
||||
this.result.fail("Expected " + number + " but was " + items.length);
|
||||
}
|
||||
done();
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
161
src/scenario/Runner.js
Normal file
161
src/scenario/Runner.js
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
angular['scenario'] = angular['scenario'] || (angular['scenario'] = {});
|
||||
angular.scenario['dsl'] = angular.scenario['dsl'] || (angular.scenario['dsl'] = {});
|
||||
|
||||
angular.scenario.Runner = function(scope, jQuery){
|
||||
var self = scope.$scenario = this;
|
||||
this.scope = scope;
|
||||
this.jQuery = jQuery;
|
||||
|
||||
var specs = this.specs = {};
|
||||
var path = [];
|
||||
this.scope.describe = function(name, body){
|
||||
path.push(name);
|
||||
body();
|
||||
path.pop();
|
||||
};
|
||||
var beforeEach = noop;
|
||||
var afterEach = noop;
|
||||
this.scope.beforeEach = function(body) {
|
||||
beforeEach = body;
|
||||
};
|
||||
this.scope.afterEach = function(body) {
|
||||
afterEach = body;
|
||||
};
|
||||
this.scope.it = function(name, body) {
|
||||
var specName = path.join(' ') + ': it ' + name;
|
||||
self.currentSpec = specs[specName] = {
|
||||
name: specName,
|
||||
steps:[]
|
||||
};
|
||||
try {
|
||||
beforeEach();
|
||||
body();
|
||||
} catch(err) {
|
||||
self.addStep(err.message || 'ERROR', function(){
|
||||
throw err;
|
||||
});
|
||||
} finally {
|
||||
afterEach();
|
||||
}
|
||||
self.currentSpec = null;
|
||||
};
|
||||
this.logger = function returnNoop(){
|
||||
return extend(returnNoop, {close:noop, fail:noop});;
|
||||
};
|
||||
};
|
||||
|
||||
angular.scenario.Runner.prototype = {
|
||||
run: function(body){
|
||||
var jQuery = this.jQuery;
|
||||
body.append(
|
||||
'<div id="runner">' +
|
||||
'<div class="console"></div>' +
|
||||
'</div>' +
|
||||
'<div id="testView">' +
|
||||
'<iframe></iframe>' +
|
||||
'</div>');
|
||||
var console = body.find('#runner .console');
|
||||
console.find('li').live('click', function(){
|
||||
jQuery(this).toggleClass('collapsed');
|
||||
});
|
||||
this.testFrame = body.find('#testView iframe');
|
||||
function logger(parent) {
|
||||
var container;
|
||||
return function(type, text) {
|
||||
if (!container) {
|
||||
container = jQuery('<ul></ul>');
|
||||
parent.append(container);
|
||||
}
|
||||
var element = jQuery('<li class="running '+type+'"><span></span></li>');
|
||||
element.find('span').text(text);
|
||||
container.append(element);
|
||||
return extend(logger(element), {
|
||||
close: function(){
|
||||
element.removeClass('running');
|
||||
if(!element.hasClass('fail'))
|
||||
element.addClass('collapsed');
|
||||
console.scrollTop(console[0].scrollHeight);
|
||||
},
|
||||
fail: function(){
|
||||
element.removeClass('running');
|
||||
var current = element;
|
||||
while (current[0] != console[0]) {
|
||||
if (current.is('li'))
|
||||
current.addClass('fail');
|
||||
current = current.parent();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
this.logger = logger(console);
|
||||
var specNames = [];
|
||||
foreach(this.specs, function(spec, name){
|
||||
specNames.push(name);
|
||||
}, this);
|
||||
specNames.sort();
|
||||
var self = this;
|
||||
function callback(){
|
||||
var next = specNames.shift();
|
||||
if(next) {
|
||||
self.execute(next, callback);
|
||||
}
|
||||
};
|
||||
callback();
|
||||
},
|
||||
|
||||
addStep: function(name, step) {
|
||||
this.currentSpec.steps.push({name:name, fn:step});
|
||||
},
|
||||
|
||||
execute: function(name, callback) {
|
||||
var spec = this.specs[name],
|
||||
self = this,
|
||||
result = {
|
||||
passed: false,
|
||||
failed: false,
|
||||
finished: false,
|
||||
fail: function(error) {
|
||||
result.passed = false;
|
||||
result.failed = true;
|
||||
result.error = error;
|
||||
result.log('fail', isString(error) ? error : toJson(error)).fail();
|
||||
}
|
||||
},
|
||||
specThis = createScope({
|
||||
result: result,
|
||||
testFrame: this.testFrame,
|
||||
testWindow: this.testWindow
|
||||
}, angularService, {});
|
||||
this.self = specThis;
|
||||
var stepLogger = this.logger('spec', name);
|
||||
spec.nextStepIndex = 0;
|
||||
function done() {
|
||||
result.finished = true;
|
||||
stepLogger.close();
|
||||
self.self = null;
|
||||
(callback||noop).call(specThis);
|
||||
}
|
||||
function next(){
|
||||
var step = spec.steps[spec.nextStepIndex];
|
||||
(result.log || {close:noop}).close();
|
||||
result.log = null;
|
||||
if (step) {
|
||||
spec.nextStepIndex ++;
|
||||
result.log = stepLogger('step', step.name);
|
||||
try {
|
||||
step.fn.call(specThis, next);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
result.fail(e);
|
||||
done();
|
||||
}
|
||||
} else {
|
||||
result.passed = !result.failed;
|
||||
done();
|
||||
}
|
||||
};
|
||||
next();
|
||||
return specThis;
|
||||
}
|
||||
};
|
||||
30
src/scenario/angular.prefix
Normal file
30
src/scenario/angular.prefix
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* The MIT License
|
||||
*
|
||||
* Copyright (c) 2010 Adam Abrons and Misko Hevery http://getangular.com
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
(function(window, document, previousOnLoad){
|
||||
window.angular = {
|
||||
scenario: {
|
||||
dsl: window
|
||||
}
|
||||
};
|
||||
|
||||
11
src/scenario/angular.suffix
Normal file
11
src/scenario/angular.suffix
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
var $scenarioRunner = new angular.scenario.Runner(window, jQuery);
|
||||
|
||||
window.onload = function(){
|
||||
try {
|
||||
if (previousOnLoad) previousOnLoad();
|
||||
} catch(e) {}
|
||||
$scenarioRunner.run(jQuery(window.document.body));
|
||||
};
|
||||
|
||||
})(window, document, window.onload);
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue