├── tools ├── yuidoc │ ├── dana-theme │ │ ├── VERSION │ │ ├── classmap.tmpl │ │ ├── index.tmpl │ │ ├── CHANGELOG.markdown │ │ ├── css │ │ │ ├── main.css │ │ │ ├── navigation.css │ │ │ ├── content.css │ │ │ └── 960fluid.min.css │ │ ├── js │ │ │ ├── jquery.cookie.min.js │ │ │ └── main.js │ │ ├── LICENSE_MIT.txt │ │ └── README.markdown │ ├── ext │ │ ├── _namemapper.pyd │ │ └── setuptools-0.6c9.tar.gz │ ├── template │ │ ├── assets │ │ │ ├── yui.png │ │ │ ├── bg_hd.gif │ │ │ └── reset-fonts-grids-min.css │ │ ├── index.tmpl │ │ └── classmap.tmpl │ ├── CHANGES │ ├── test │ │ ├── lang │ │ │ ├── python │ │ │ │ └── test.py │ │ │ ├── cs │ │ │ │ └── test.cs │ │ │ ├── perl │ │ │ │ └── test.pl │ │ │ ├── java │ │ │ │ └── test.java │ │ │ ├── php │ │ │ │ └── test.php │ │ │ └── ruby │ │ │ │ └── test.rb │ │ ├── intl.sh │ │ ├── dd.sh │ │ ├── yui.sh │ │ ├── base.sh │ │ ├── node.sh │ │ ├── json.sh │ │ ├── queue.sh │ │ ├── event.sh │ │ ├── lang.sh │ │ ├── intl │ │ │ └── intl.js │ │ └── apidocs.sh │ ├── bin │ │ ├── yuidoclog.conf │ │ ├── example.bat │ │ ├── example.sh │ │ ├── const.py │ │ ├── yuidoc.py │ │ └── yuidoc_highlight.py │ ├── license.txt │ ├── README │ ├── INSTALL │ └── TAGS ├── jsl ├── jsl.exe └── yuicompressor-2.4.2.jar ├── tests ├── test_harness_start.js ├── ext │ ├── droid_sans_mono.css │ └── qunit.css ├── test_fieldValidityState.js ├── test_plugin.js ├── test_observable.js ├── test_harness_end.js ├── test_enumerableMixin.js ├── test_fieldPlaceholderDecorator.js ├── test_event.js ├── test_listPluginFormRow.js ├── test_listPluginBindToCollection.js ├── test_collectionArray.js ├── test_dataForm.js ├── test_dataContainer.js ├── test_form.js ├── test_aobject.js ├── test_fieldPluginValidation.js └── test_collectionPluginModel.js ├── adapters.list ├── LICENSE ├── .gitignore ├── per_user.properties.sample ├── site ├── stylesheets │ ├── main.scss │ ├── mobile.css │ ├── navigation.scss │ ├── cssreset.scss │ ├── content.scss │ ├── aframejs.scss │ └── shThemeDefault.scss ├── scripts │ ├── shBrushJScript.js │ └── apidocs.js └── demos │ └── index.html ├── includes.node.list ├── includes.list ├── yuidoc.properties ├── demos └── add_friend │ ├── index.html │ └── scripts │ └── demoapp.js └── src ├── plugin.js ├── arrayCommonFunctionsMixin.js ├── collectionPluginREST.js ├── enumerableMixin.js ├── observable.js ├── collectionPluginModel.js ├── fieldValidityState.js ├── core.js ├── listPluginBindToCollection.js ├── event.js ├── fieldPlaceholderDecorator.js ├── class.js └── field.js /tools/yuidoc/dana-theme/VERSION: -------------------------------------------------------------------------------- 1 | 1.1 -------------------------------------------------------------------------------- /tests/test_harness_start.js: -------------------------------------------------------------------------------- 1 | var testsToRun = []; 2 | -------------------------------------------------------------------------------- /adapters.list: -------------------------------------------------------------------------------- 1 | adapters.list=jquery,\ 2 | mootools,\ 3 | prototype 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/LICENSE -------------------------------------------------------------------------------- /tools/jsl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/jsl -------------------------------------------------------------------------------- /tools/jsl.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/jsl.exe -------------------------------------------------------------------------------- /tools/yuicompressor-2.4.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/yuicompressor-2.4.2.jar -------------------------------------------------------------------------------- /tools/yuidoc/ext/_namemapper.pyd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/yuidoc/ext/_namemapper.pyd -------------------------------------------------------------------------------- /tools/yuidoc/template/assets/yui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/yuidoc/template/assets/yui.png -------------------------------------------------------------------------------- /tools/yuidoc/ext/setuptools-0.6c9.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/yuidoc/ext/setuptools-0.6c9.tar.gz -------------------------------------------------------------------------------- /tools/yuidoc/template/assets/bg_hd.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shane-tomlinson/AFrame-JS/master/tools/yuidoc/template/assets/bg_hd.gif -------------------------------------------------------------------------------- /tools/yuidoc/template/index.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /tools/yuidoc/CHANGES: -------------------------------------------------------------------------------- 1 | ChangeLog 2 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3 | 4 | Next 5 | * added multi-language support 6 | * improved international character support 7 | * added known issues and workarounds 8 | 9 | 1.0.0b1 10 | * Initial release 11 | -------------------------------------------------------------------------------- /tests/ext/droid_sans_mono.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | @font-face { 3 | font-family: 'Droid Sans Mono'; 4 | font-style: normal; 5 | font-weight: normal; 6 | src: local('Droid Sans Mono'), local('DroidSansMono'), url('http://themes.googleusercontent.com/font?kit=ns-m2xQYezAtqh7ai59hJYW_AySPyikQrZReizgrnuw') format('truetype'); 7 | } 8 | } -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/classmap.tmpl: -------------------------------------------------------------------------------- 1 | YAHOO.env.classMap = ${pkgmap}; 2 | 3 | YAHOO.env.resolveClass = function(className) { 4 | var a=className.split('.'), ns=YAHOO.env.classMap; 5 | 6 | for (var i=0; i 3 | 4 | 5 | 6 | 7 | Redirecting to ${cleansedmodulename} documentation 8 | 9 | 10 | 11 | ${cleansedmodulename} documentation 12 | 13 | 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # the distribution directory 2 | dist/ 3 | 4 | # parts of the site directory that are built 5 | site/docs/ 6 | site/src/ 7 | site/tests/ 8 | 9 | # pyc files built by python for document generation 10 | *.pyc 11 | 12 | # temp directories for document generation 13 | docparse/ 14 | 15 | # generated documents 16 | docs 17 | 18 | # per_user.properties copied from sample 19 | per_user.properties 20 | 21 | 22 | -------------------------------------------------------------------------------- /per_user.properties.sample: -------------------------------------------------------------------------------- 1 | 2 | #User specific properties 3 | 4 | #The root directory of the installation 5 | peruser.root=/home/set117/development/aframe 6 | 7 | #The location of the ant-contrib jar 8 | peruser.antcontrib.location=/usr/share/java/ant-contrib.jar 9 | 10 | #the location of the sass command, only needed if doing a build site 11 | peruser.sass.location=/var/lib/gems/1.8/gems/haml-3.0.25/bin/sass 12 | -------------------------------------------------------------------------------- /site/stylesheets/main.scss: -------------------------------------------------------------------------------- 1 | 2 | #container { 3 | background-color: #fff; 4 | } 5 | 6 | 7 | #hd h1 { 8 | font-size: 2.3em; 9 | line-height: 100%; 10 | margin: 0.5em 0 0.5em 0; 11 | font-weight: normal; 12 | color: #888; 13 | 14 | a { 15 | color: #ff8200; 16 | font-weight: bold; 17 | } 18 | } 19 | 20 | #sub-hd > div { 21 | background-color: #eee; 22 | margin: 0 0 1.5em 0; 23 | padding: 0.5em; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /includes.node.list: -------------------------------------------------------------------------------- 1 | includes.node.list=core.js,\ 2 | aframe.js,\ 3 | class.js,\ 4 | observable.js,\ 5 | observablesMixin.js,\ 6 | enumerableMixin.js,\ 7 | aobject.js,\ 8 | dataContainer.js,\ 9 | plugin.js,\ 10 | arrayCommonFunctionsMixin.js,\ 11 | collectionHash.js,\ 12 | collectionArray.js,\ 13 | collectionPluginPersistence.js,\ 14 | collectionPluginModel.js,\ 15 | schema.js,\ 16 | dataValidation.js,\ 17 | model.js,\ 18 | event.js,\ 19 | fieldValidityState.js 20 | -------------------------------------------------------------------------------- /site/stylesheets/mobile.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-size: 1em; 3 | } 4 | 5 | .container { 6 | margin-top: 10px; 7 | padding: 5px; 8 | } 9 | 10 | .container_12 { 11 | width: auto; 12 | } 13 | 14 | .container_12 .grid_12, .container_12 .grid_3, .container_12 .grid_9 { 15 | width: 100%; 16 | margin: 10px 0; 17 | } 18 | 19 | section { 20 | margin: 0; 21 | font-size: 1em; 22 | } 23 | 24 | .syntaxhighlighter code { 25 | font-size: .8em !important; 26 | } 27 | 28 | -------------------------------------------------------------------------------- /tests/test_fieldValidityState.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.FieldValidityState", 4 | 5 | testDefaultValidity: function() { 6 | var validity = AFrame.FieldValidityState.create(); 7 | Assert.isTrue( validity.valid, 'default validity is true' ); 8 | }, 9 | 10 | testOverriddenValidity: function() { 11 | var validity = AFrame.FieldValidityState.create( { valid: false } ); 12 | Assert.isFalse( validity.valid, 'validity set to false' ); 13 | } 14 | } ); 15 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/python/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | ''' 3 | /** 4 | * Test Python File 5 | * @module testpy 6 | */ 7 | ''' 8 | import os, sys, string, shutil, urllib2, urllib, pprint, simplejson, datetime 9 | from cStringIO import StringIO 10 | from subprocess import call, PIPE, Popen 11 | 12 | ''' 13 | /** 14 | * This is a test class 15 | * @class TestPy 16 | * @namespace Python 17 | */ 18 | ''' 19 | 20 | ''' 21 | /** 22 | * Test Method 23 | * @method test 24 | */ 25 | ''' 26 | def test(): 27 | pass 28 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/cs/test.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | /** 3 | * C# Module Description 4 | * @module lang.csharp 5 | */ 6 | 7 | /** 8 | * C# Class Description 9 | * @class ReadAll 10 | * @namespace PlayingAround 11 | */ 12 | namespace PlayingAround { 13 | class ReadAll { 14 | /** 15 | * Main Method 16 | * @method Main 17 | * @static 18 | */ 19 | public static void Main(string[] args) { 20 | string contents = System.IO.File.ReadAllText(@"C:\t1"); 21 | Console.Out.WriteLine("contents = " + contents); 22 | } 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/CHANGELOG.markdown: -------------------------------------------------------------------------------- 1 | ### 1.1 (01-09-2010) 2 | 3 | * Methods, constructors, events: if there are several parameters in the style 4 | `obj.property`, only a sole `obj` will be displayed as parameter in the 5 | tables' first columns. 6 | Before: `method( obj.param1, obj.param2, obj.param3 )`. 7 | Now: `method( obj )`. 8 | 9 | * Fixed freestanding comma issues in methods, constructors and events tables. 10 | Before: `method( param1 , param2 , param3 )`. 11 | Now: `method( param1, param2, param3 )`. 12 | 13 | 14 | ### 1.0.1 (31-08-2010) 15 | 16 | * FIX: Fixed link in footer. 17 | * ADD: Added note re IE8 to `README.markdown`. 18 | -------------------------------------------------------------------------------- /includes.list: -------------------------------------------------------------------------------- 1 | includes.list=core.js,\ 2 | aframe.js,\ 3 | class.js,\ 4 | observable.js,\ 5 | observablesMixin.js,\ 6 | enumerableMixin.js,\ 7 | aobject.js,\ 8 | dataContainer.js,\ 9 | plugin.js,\ 10 | arrayCommonFunctionsMixin.js,\ 11 | collectionHash.js,\ 12 | collectionArray.js,\ 13 | display.js,\ 14 | list.js,\ 15 | listPluginBindToCollection.js,\ 16 | collectionPluginPersistence.js,\ 17 | collectionPluginREST.js,\ 18 | collectionPluginModel.js,\ 19 | form.js,\ 20 | field.js,\ 21 | fieldPluginValidation.js,\ 22 | fieldValidityState.js,\ 23 | fieldPlaceholderDecorator.js,\ 24 | schema.js,\ 25 | listPluginFormRow.js,\ 26 | dataForm.js,\ 27 | dataValidation.js,\ 28 | model.js,\ 29 | event.js 30 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/perl/test.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env perl 2 | =begin 3 | /** 4 | * Test Perl File 5 | * @module lang.perltest 6 | */ 7 | =cut 8 | use strict; 9 | =begin 10 | /** 11 | * Test Perl Class 12 | * @class PerlTest 13 | * @namespace Perl 14 | */ 15 | =cut 16 | 17 | =begin 18 | /** 19 | * Arith Method 20 | * @method arith 21 | */ 22 | =cut 23 | sub arith($); 24 | 25 | my %h = ( 26 | 'add' => '+', 27 | 'sub' => '-', 28 | 'mul' => '*', 29 | 'div' => '/', 30 | ); 31 | 32 | print arith(eval $ARGV[0]), "\n"; 33 | 34 | sub arith($) { 35 | my $a = shift; 36 | ref $a ? eval join $h{$a->[0]}, map arith($_), @{$a}[1..$#$a] : $a; 37 | } 38 | 39 | 40 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/java/test.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Test Java Module Description 3 | * @module lang.javatest 4 | */ 5 | import java.util.*; 6 | 7 | /** 8 | * This is the class description for this Java Class 9 | * @class Test 10 | * @namespace Java 11 | * @constructor 12 | */ 13 | public class Test { 14 | /** 15 | * x property 16 | * @property x 17 | * @type {Double} 18 | */ 19 | private double x; 20 | /** 21 | * y property 22 | * @property y 23 | * @type {Double} 24 | */ 25 | private double y; 26 | 27 | /** 28 | * Main Method 29 | * @method main 30 | */ 31 | public static void main (String[] args) { 32 | System.out.println("Hello, World!!"); 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/css/main.css: -------------------------------------------------------------------------------- 1 | * { 2 | line-height: 130%; 3 | } 4 | 5 | body { 6 | background-color: #eee; 7 | } 8 | 9 | p, dl, hr, h1, h2, h3, h4, h5, h6, ol, ul, pre, table, address, fieldset { 10 | margin-bottom: 0.8em; 11 | } 12 | 13 | 14 | a { 15 | text-decoration: none; 16 | color: #55d; 17 | } 18 | 19 | code, code a[name] { 20 | color: #007000; 21 | font-family: "Droid Sans Mono"; 22 | } 23 | 24 | 25 | #container { 26 | background-color: #fff; 27 | } 28 | 29 | 30 | #hd h1 { 31 | font-size: 2.3em; 32 | line-height: 100%; 33 | margin: 0.5em 0 0.5em 0; 34 | font-weight: normal; 35 | color: #888; 36 | } 37 | 38 | #hd h1 a { 39 | color: #ff8200; 40 | font-weight: bold; 41 | } 42 | 43 | 44 | #sub-hd > div { 45 | background-color: #eee; 46 | margin: 0 0 1.5em 0; 47 | padding: 0.5em; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/js/jquery.cookie.min.js: -------------------------------------------------------------------------------- 1 | /*jslint browser: true */ /*global jQuery: true */ 2 | 3 | /** 4 | * jQuery Cookie plugin 5 | * 6 | * Copyright (c) 2010 Klaus Hartl (stilbuero.de) 7 | * Dual licensed under the MIT and GPL licenses: 8 | * http://www.opensource.org/licenses/mit-license.php 9 | * http://www.gnu.org/licenses/gpl.html 10 | * 11 | */ 12 | jQuery.cookie=function(d,e,b){if(arguments.length>1&&(e===null||typeof e!=="object")){b=jQuery.extend({},b);if(e===null){b.expires=-1}if(typeof b.expires==="number"){var g=b.expires,c=b.expires=new Date();c.setDate(c.getDate()+g)}return(document.cookie=[encodeURIComponent(d),"=",b.raw?String(e):encodeURIComponent(String(e)),b.expires?"; expires="+b.expires.toUTCString():"",b.path?"; path="+b.path:"",b.domain?"; domain="+b.domain:"",b.secure?"; secure":""].join(""))}b=e||{};var a,f=b.raw?function(h){return h}:decodeURIComponent;return(a=new RegExp("(?:^|; )"+encodeURIComponent(d)+"=([^;]*)").exec(document.cookie))?f(a[1]):null}; -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/php/test.php: -------------------------------------------------------------------------------- 1 | 54 | -------------------------------------------------------------------------------- /tools/yuidoc/test/intl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=. 11 | 12 | parser_in="$src/intl" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version="localtest" 26 | 27 | ############################################################################## 28 | 29 | python $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/yuidoclog.conf: -------------------------------------------------------------------------------- 1 | [formatters] 2 | keys: detailed,simple 3 | 4 | [handlers] 5 | keys: console,syslog 6 | 7 | [loggers] 8 | keys: root,parse,highlight,generate 9 | 10 | [formatter_simple] 11 | #format: %(name)s:%(levelname)s: %(message)s 12 | format: %(levelname)s: %(message)s 13 | 14 | [formatter_detailed] 15 | format: %(name)s:%(levelname)s %(module)s:%(lineno)d: %(message)s 16 | 17 | [handler_console] 18 | class: StreamHandler 19 | args: [] 20 | formatter: simple 21 | 22 | [handler_syslog] 23 | class: handlers.SysLogHandler 24 | args: [('127.0.0.1', handlers.SYSLOG_UDP_PORT), handlers.SysLogHandler.LOG_USER] 25 | formatter: detailed 26 | 27 | [logger_root] 28 | level: INFO 29 | handlers: syslog 30 | 31 | [logger_parse] 32 | level: INFO 33 | qualname: yuidoc.parse 34 | handlers: console 35 | 36 | [logger_highlight] 37 | level: INFO 38 | qualname: yuidoc.highlight 39 | handlers: console 40 | 41 | [logger_generate] 42 | level: INFO 43 | qualname: yuidoc.generate 44 | handlers: console 45 | -------------------------------------------------------------------------------- /tools/yuidoc/test/dd.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/dd/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version="localtest" 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/yui.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/yui/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version="localtest" 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/base.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/base/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version="localtest" 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/node/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version="localtest" 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/json.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/io/js $src/json/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version=test 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/queue.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/queue/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version=`cat version.txt` 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/event.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | parser_in="$src/yui/js $src/event-custom/js $src/event/js $src/dump/js $src/substitute/js $src/anim/js $src/collection/js $src/base/js $src/attribute/js" 13 | 14 | # The location to output the parser data. This output is a file containing a 15 | # json string, and copies of the parsed files. 16 | parser_out=build_tmp/yuidoc_tmp 17 | 18 | # The directory to put the html file outputted by the generator 19 | generator_out=build_tmp/api 20 | 21 | # The location of the template files. Any subdirectories here will be copied 22 | # verbatim to the destination directory. 23 | template=$yuidoc_home/template 24 | 25 | version=test 26 | 27 | ############################################################################## 28 | 29 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 30 | 31 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang/ruby/test.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby -w 2 | 3 | =begin 4 | /** 5 | * Module Info for test Ruby File 6 | * @module lang.rubytest 7 | */ 8 | =end 9 | 10 | require 'rubygems' 11 | require 'grit' 12 | require 'optparse' 13 | require 'logger' 14 | require 'fileutils' 15 | 16 | 17 | module RubyTest 18 | =begin 19 | /** 20 | * Class Information 21 | * @class test 22 | * @namespace Ruby 23 | */ 24 | =end 25 | class Test 26 | =begin 27 | /** 28 | * Execute desc 29 | * @method execute 30 | */ 31 | =end 32 | 33 | def self.execute 34 | #foo 35 | end 36 | =begin 37 | /** 38 | * Parse desc 39 | * @method parse 40 | */ 41 | =end 42 | 43 | def self.parse(args) 44 | #foo 45 | end 46 | =begin 47 | /** 48 | * Initialize Method 49 | * @method initialize 50 | */ 51 | =end 52 | 53 | def initialize(args) 54 | =begin 55 | /** 56 | * Args Property 57 | * @property args 58 | */ 59 | =end 60 | @args = args.foo 61 | =begin 62 | /** 63 | * Bar Property 64 | * @property bar 65 | */ 66 | =end 67 | @bar = 'Bar' 68 | end 69 | 70 | end 71 | end 72 | 73 | 74 | -------------------------------------------------------------------------------- /yuidoc.properties: -------------------------------------------------------------------------------- 1 | yuidoc.home=${peruser.root}/tools/yuidoc 2 | 3 | # The location of the files to parse. Parses subdirectories, but will fail if 4 | # there are duplicate file names in these directories. You can specify multiple 5 | # source trees: 6 | # parser_in="%HOME/www/yui/src %HOME/www/event/src" 7 | yuidoc.parser_in=${peruser.root}/src 8 | 9 | # The location to output the parser data. This output is a file containing a 10 | # json string, and copies of the parsed files. 11 | yuidoc.parser_out=${peruser.root}/docparse 12 | 13 | # The directory to put the html file outputted by the generator 14 | yuidoc.generator_out=${peruser.root}/docs 15 | 16 | # The location of the template files. Any subdirectories here will be copied 17 | # verbatim to the destination directory. 18 | yuidoc.template=${yuidoc.home}/dana-theme 19 | 20 | # The version of YUI the project is using. This effects the output for 21 | # YUI configuration attributes. This should start with '2' or '3'. 22 | yuidoc.yuiversion=3 23 | 24 | yuidoc.projecturl="http://www.aframejs.com/" 25 | yuidoc.projectname="AFrameJS" 26 | yuidoc.copyrighttag="Shane Tomlinson" -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/LICENSE_MIT.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Carlo Zottmann, http://municode.de/ 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /demos/add_friend/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AFrame Introduction 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 16 | 17 | 18 | 19 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/example.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM ########################################################################## 4 | 5 | REM The location of your yuidoc install 6 | SET yuidoc_home=c:\home\www\yuidoc\yuidoc 7 | 8 | REM The location of the files to parse. Parses subdirectories, but will fail if 9 | REM there are duplicate file names in these directories. You can specify multiple 10 | REM source trees: 11 | REM SET parser_in="c:\home\www\yahoo.dev\src\js c:\home\www\Event.dev\src" 12 | SET parser_in=c:\home\www\yahoo.dev\src\js 13 | 14 | REM The location to output the parser data. This output is a file containing a 15 | REM json string, and copies of the parsed files. 16 | SET parser_out=c:\home\www\docs\parser 17 | 18 | REM The directory to put the html file outputted by the generator 19 | SET generator_out=c:\home\www\docs\generator 20 | 21 | REM The location of the template files. Any subdirectories here will be copied 22 | REM verbatim to the destination directory. 23 | SET template=%yuidoc_home%\template 24 | 25 | REM The project version that will be displayed in the documentation. 26 | SET version="1.0.0" 27 | 28 | REM The version of YUI the project uses. 29 | SET yuiversion="2" 30 | 31 | "%yuidoc_home%\bin\yuidoc.py" "%parser_in%" -p "%parser_out%" -o "%generator_out%" -t "%template%" -v %version% -Y %yuiversion% 32 | 33 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/example.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # The location of your yuidoc install 3 | yuidoc_home=~/www/yuidoc/yuidoc 4 | 5 | # The location of the files to parse. Parses subdirectories, but will fail if 6 | # there are duplicate file names in these directories. You can specify multiple 7 | # source trees: 8 | # parser_in="%HOME/www/yui/src %HOME/www/event/src" 9 | parser_in="$HOME/src" 10 | 11 | # The location to output the parser data. This output is a file containing a 12 | # json string, and copies of the parsed files. 13 | parser_out=~/www/docs/parser 14 | 15 | # The directory to put the html file outputted by the generator 16 | generator_out=~/www/docs/generator 17 | 18 | # The location of the template files. Any subdirectories here will be copied 19 | # verbatim to the destination directory. 20 | template=$yuidoc_home/template 21 | 22 | # The version of your project to display within the documentation. 23 | version=1.0.0 24 | 25 | # The version of YUI the project is using. This effects the output for 26 | # YUI configuration attributes. This should start with '2' or '3'. 27 | yuiversion=2 28 | 29 | ############################################################################## 30 | # add -s to the end of the line to show items marked private 31 | 32 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -Y $yuiversion 33 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/css/navigation.css: -------------------------------------------------------------------------------- 1 | #navigation > div { 2 | border: 1px solid #eee; 3 | overflow: hidden; 4 | } 5 | 6 | #navigation h4 { 7 | background-color: #888; 8 | color: #fff; 9 | font-size: 1.0em; 10 | text-shadow: rgba(0, 0, 0, 0.5) 0 -1pt 0; 11 | margin-bottom: 0.5em; 12 | padding: 0.3em 0.3em 0.3em 1em; 13 | } 14 | 15 | #navigation ul { 16 | list-style: none; 17 | } 18 | 19 | #navigation li { 20 | margin-left: 1em; 21 | } 22 | 23 | #navigation li.selected { 24 | background-color: #eef; 25 | margin-left: 0; 26 | padding-left: 1em 27 | } 28 | 29 | #navigation li span.access-private { 30 | color: #a22; 31 | } 32 | 33 | #navigation li span.access-protected { 34 | color: #d88; 35 | } 36 | 37 | #navigation li span.deprecated { 38 | background-color: #d53; 39 | color: #fff; 40 | padding: 0 0.4em; 41 | } 42 | 43 | #navigation li span.access-private, 44 | #navigation li span.access-protected, 45 | #navigation li span.deprecated { 46 | font-size: 0.85em; 47 | } 48 | 49 | 50 | #show-toggles { 51 | float: right; 52 | font-size: 0.85em; 53 | background-color: #f8f8f8; 54 | color: #888; 55 | padding: 0.5em; 56 | } 57 | 58 | #show-toggles fieldset { 59 | margin: 0; 60 | } 61 | 62 | 63 | #search-form { 64 | float: right; 65 | margin-top: -0.25em; 66 | } 67 | 68 | #search-form label { 69 | color: #666; 70 | } 71 | 72 | #search-form #search { 73 | border: 1pt solid #ddd; 74 | width: 20em; 75 | } 76 | 77 | -------------------------------------------------------------------------------- /site/stylesheets/navigation.scss: -------------------------------------------------------------------------------- 1 | #navigation > div { 2 | border: 1px solid #eee; 3 | overflow: hidden; 4 | margin-bottom: 4em; 5 | } 6 | 7 | #navigation h4 { 8 | background-color: #888; 9 | color: #fff; 10 | font-size: 1.0em; 11 | text-shadow: rgba(0, 0, 0, 0.5) 0 -1pt 0; 12 | margin-bottom: 0.5em; 13 | padding: 0.3em 0.3em 0.3em 1em; 14 | } 15 | 16 | #navigation ul { 17 | list-style: none; 18 | } 19 | 20 | #navigation li { 21 | margin-left: 1em; 22 | } 23 | 24 | #navigation li.selected { 25 | background-color: #eef; 26 | margin-left: 0; 27 | padding-left: 1em 28 | } 29 | 30 | #navigation li span.access-private { 31 | color: #a22; 32 | } 33 | 34 | #navigation li span.access-protected { 35 | color: #d88; 36 | } 37 | 38 | #navigation li span.deprecated { 39 | background-color: #d53; 40 | color: #fff; 41 | padding: 0 0.4em; 42 | } 43 | 44 | #navigation li span.access-private, 45 | #navigation li span.access-protected, 46 | #navigation li span.deprecated { 47 | font-size: 0.85em; 48 | } 49 | 50 | 51 | #show-toggles { 52 | float: right; 53 | font-size: 0.85em; 54 | background-color: #f8f8f8; 55 | color: #888; 56 | padding: 0.5em; 57 | } 58 | 59 | #show-toggles fieldset { 60 | margin: 0; 61 | } 62 | 63 | 64 | #search-form { 65 | float: right; 66 | margin-top: -0.25em; 67 | } 68 | 69 | #search-form label { 70 | color: #666; 71 | } 72 | 73 | #search-form #search { 74 | border: 1pt solid #ddd; 75 | width: 20em; 76 | } 77 | 78 | -------------------------------------------------------------------------------- /tools/yuidoc/test/lang.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | # The location of the files to parse. Parses subdirectories, but will fail if 11 | # there are duplicate file names in these directories. 12 | # parser_in="$src/animation \ 13 | # $src/attribute \ 14 | # $src/base \ 15 | # $src/dd \ 16 | # $src/dom \ 17 | # $src/json \ 18 | # $src/json-parse \ 19 | # $src/json-stringify \ 20 | # $src/node \ 21 | # $src/queue \ 22 | # $src/yui" 23 | 24 | # parser_in="lang" 25 | parser_in="lang/java lang/python lang/perl lang/ruby" 26 | 27 | # The location to output the parser data. This output is a file containing a 28 | # json string, and copies of the parsed files. 29 | parser_out=build_tmp/yuidoc_tmp 30 | 31 | # The directory to put the html file outputted by the generator 32 | generator_out=build_tmp/api 33 | 34 | # The location of the template files. Any subdirectories here will be copied 35 | # verbatim to the destination directory. 36 | template=$yuidoc_home/template 37 | 38 | version=`test` 39 | 40 | ############################################################################## 41 | 42 | $yuidoc_home/bin/yuidoc.py $parser_in -e .py,.java,.rb,.pl -p $parser_out -o $generator_out -t $template -v $version -s $* 43 | 44 | -------------------------------------------------------------------------------- /src/plugin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A basic plugin, used to extend functionality of an object without either subclassing or directly 3 | * extending that object. Plugins make it easy to create configurable objects by adding 4 | * small units of coherent functionality and plugging a base object. When creating an object, 5 | * if the functionality is needed, add the plugin, if not, leave it out. When the plugged 6 | * object is torn down, the plugin will automatically be torn down as well. 7 | * @class AFrame.Plugin 8 | * @extends AFrame.AObject 9 | * @constructor 10 | */ 11 | AFrame.Plugin = ( function() { 12 | "use strict"; 13 | 14 | var Plugin = AFrame.AObject.extend( { 15 | importconfig: [ 'plugged' ], 16 | events: { 17 | 'onTeardown plugged': 'teardown', 18 | 'onInit plugged': 'onPluggedInit' 19 | }, 20 | 21 | /** 22 | * Get a reference to the plugged object. 23 | * @method getPlugged 24 | * @return {AFrame.AObject} the plugged object 25 | */ 26 | getPlugged: function() { 27 | return this.plugged; 28 | }, 29 | 30 | teardown: function() { 31 | AFrame.remove( this, 'plugged' ); 32 | Plugin.sc.teardown.call( this ); 33 | }, 34 | 35 | /** 36 | * Override to do some specialized handling when a plugged object is initialized. 37 | * @method onPluggedInit 38 | */ 39 | onPluggedInit: function() { 40 | // do nothing 41 | } 42 | } ); 43 | 44 | return Plugin; 45 | }() ); 46 | -------------------------------------------------------------------------------- /tests/test_plugin.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.Plugin", 4 | 5 | setUp: function() { 6 | 7 | this.pluggedObject = AFrame.AObject.create(); 8 | this.plugin = AFrame.Plugin.create( { 9 | plugged: this.pluggedObject 10 | } ); 11 | }, 12 | 13 | tearDown : function () { 14 | this.pluggedObject.teardown(); 15 | this.pluggedObject = null; 16 | delete this.pluggedObject; 17 | 18 | this.plugin.teardown(); 19 | this.plugin = null; 20 | delete this.plugin; 21 | 22 | }, 23 | 24 | testPlugged: function() { 25 | var plugged = this.plugin.getPlugged(); 26 | 27 | Assert.isObject( plugged, 'plugged is an object' ); 28 | Assert.areSame( plugged, this.pluggedObject, 'plugged object correctly set' ); 29 | }, 30 | 31 | testTeardownOnPluggedTeardown: function() { 32 | var pluginTeardown = false; 33 | this.plugin.bindEvent( 'onTeardown', function() { 34 | pluginTeardown = true; 35 | } ); 36 | 37 | this.pluggedObject.teardown(); 38 | 39 | Assert.isTrue( pluginTeardown, 'plugin was torn down' ); 40 | }, 41 | 42 | testOnPluggedInit: function() { 43 | var onPluggedInitCalled = false; 44 | var Plugin = AFrame.Plugin.extend( { 45 | onPluggedInit: function() { 46 | onPluggedInitCalled = true; 47 | } 48 | } ); 49 | 50 | var item = AFrame.AObject.create( { 51 | plugins: [ Plugin ] 52 | } ); 53 | 54 | Assert.isTrue( onPluggedInitCalled, 'onPluggedInit automatically called' ); 55 | } 56 | } ); 57 | -------------------------------------------------------------------------------- /tools/yuidoc/test/intl/intl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The text module lets you format and parse text in many languages from around the world. 3 | *

This module uses the following identifiers: 4 | *

13 | *

14 | * @module text 15 | */ 16 | 17 | /** 18 | * Provides functionality for formatting date and time information. 19 | * @class DateFormat 20 | * @constructor 21 | * @param {Style | Style[] | String} style Style constant or pattern string for the desired date format. 22 | * @param {String} language The RFC 4646 language tag for the language of the date format. 23 | * @param {String} timeZone future The tz database identifier for the time zone of the date format. 24 | * Optional - the browser time zone is used by default. 25 | */ 26 | 27 | /** 28 | * future Calendar month format. Examples: 29 | * 33 | * @property CALENDAR_MONTH 34 | */ 35 | 36 | /** 37 | * subclass method 38 | * @method subclassmethod 39 | */ 40 | 41 | /** 42 | * DateFormat subclass 43 | * @class DateFormatSubclass 44 | * @extends DateFormat 45 | */ 46 | 47 | /** 48 | * subclass method 49 | * @method subclassmethod 50 | */ 51 | -------------------------------------------------------------------------------- /tools/yuidoc/license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010, Yahoo! Inc. All rights reserved. 2 | Code licensed under the BSD License: 3 | 4 | Redistribution and use of this software in source and binary forms, with or 5 | without modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright notice, this 9 | list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above copyright notice, 12 | this list of conditions and the following disclaimer in the documentation 13 | and/or other materials provided with the distribution. 14 | 15 | * Neither the name of Yahoo! Inc. nor the names of its contributors may be used 16 | to endorse or promote products derived from this software without specific 17 | prior written permission of Yahoo! Inc. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 20 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 23 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 26 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | 30 | 31 | http://developer.yahoo.net/yui/license.html 32 | -------------------------------------------------------------------------------- /src/arrayCommonFunctionsMixin.js: -------------------------------------------------------------------------------- 1 | AFrame.ArrayCommonFuncsMixin = (function() { 2 | "use strict"; 3 | 4 | /** 5 | * Common functions to all arrays 6 | * @class AFrame.ArrayCommonFuncsMixin 7 | * @static 8 | */ 9 | var Mixin = { 10 | /** 11 | * Get the current count of items. Should be overridden. 12 | * 13 | * // list is an AFrame.List 14 | * var count = list.getCount(); 15 | * 16 | * @method getCount 17 | * @return {number} current count 18 | * @throw 'operation not supported' if not overridden properly. 19 | */ 20 | getCount: function() { /* Should be overridden */ 21 | throw 'operation not supported'; 22 | }, 23 | 24 | /** 25 | * @private 26 | * Given an tentative index, get the index the item would be inserted at 27 | * @method getActualInsertIndex 28 | * @param {number} index - index to check for 29 | */ 30 | getActualInsertIndex: function( index ) { 31 | var len = this.getCount(); 32 | 33 | if( 'undefined' == typeof( index ) ) { 34 | index = len; 35 | } 36 | else if( index < 0 ) { 37 | index = len + ( index + 1 ); 38 | } 39 | 40 | index = Math.max( 0, index ); 41 | index = Math.min( len, index ); 42 | 43 | return index; 44 | }, 45 | 46 | /** 47 | * @private 48 | * Given an tentative index, get the item's real index. 49 | * @method getActualIndex 50 | * @param {number} index - index to check for 51 | */ 52 | getActualIndex: function( index ) { 53 | var len = this.getCount(); 54 | 55 | // check from end 56 | if( index < 0 ) { 57 | index = len + index; 58 | } 59 | 60 | // invalid indexes; 61 | if( index < 0 || len <= index ) { 62 | index = undefined; 63 | } 64 | 65 | return index; 66 | } 67 | }; 68 | 69 | return Mixin; 70 | }()); 71 | -------------------------------------------------------------------------------- /demos/add_friend/scripts/demoapp.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | // Instead of creating a model, create a SchemaConfig. 3 | // A Model in AFrame is an instance of data combined 4 | // with a Schema. The schema config will be used when 5 | // creating the model. 6 | var friendSchemaConfig = { 7 | name: { type: 'text' } 8 | }; 9 | 10 | // Our friends collection is an array. Instead of binding 11 | // directly to an event on the collection, when creating 12 | // the list, we bind the list to the collection. 13 | // The ListPluginBindToCollection will take care of 14 | // updating of the list. 15 | var friendsCollection = AFrame.CollectionArray.create( { 16 | plugins: [ [ AFrame.CollectionPluginModel, { 17 | schema: friendSchemaConfig 18 | } ] ] 19 | } ); 20 | 21 | // This is the friends list. It is bound to the 22 | // friendsCollection, so any time a model is added or 23 | // removed from the friends collection, the list will update. 24 | var friendsList = AFrame.List.create( { 25 | target: '#friendList', 26 | listElementFactory: function( model, index ) { 27 | return AFrame.DOM.createElement( 'li', 28 | model.get( 'name' ) ); 29 | }, 30 | plugins: [ [ AFrame.ListPluginBindToCollection, { 31 | collection: friendsCollection 32 | } ] ] 33 | } ); 34 | 35 | // we insert into the friendsCollection once we 36 | // have a name. The list will be updated automatically. 37 | $( '#add-friend' ).click( function( event ) { 38 | var friend_name = prompt("Who is your friend?"); 39 | // A new model will be created when adding 40 | // to the friend collection. 41 | friendsCollection.insert( { name: friend_name } ); 42 | } ); 43 | }); 44 | -------------------------------------------------------------------------------- /site/scripts/shBrushJScript.js: -------------------------------------------------------------------------------- 1 | /** 2 | * SyntaxHighlighter 3 | * http://alexgorbatchev.com/SyntaxHighlighter 4 | * 5 | * SyntaxHighlighter is donationware. If you are using it, please donate. 6 | * http://alexgorbatchev.com/SyntaxHighlighter/donate.html 7 | * 8 | * @version 9 | * 3.0.83 (July 02 2010) 10 | * 11 | * @copyright 12 | * Copyright (C) 2004-2010 Alex Gorbatchev. 13 | * 14 | * @license 15 | * Dual licensed under the MIT and GPL licenses. 16 | */ 17 | ;(function() 18 | { 19 | // CommonJS 20 | typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null; 21 | 22 | function Brush() 23 | { 24 | var keywords = 'break case catch continue ' + 25 | 'default delete do else false ' + 26 | 'for function if in instanceof ' + 27 | 'new null return super switch ' + 28 | 'this throw true try typeof var while with' 29 | ; 30 | 31 | var r = SyntaxHighlighter.regexLib; 32 | 33 | this.regexList = [ 34 | { regex: r.multiLineDoubleQuotedString, css: 'string' }, // double quoted strings 35 | { regex: r.multiLineSingleQuotedString, css: 'string' }, // single quoted strings 36 | { regex: r.singleLineCComments, css: 'comments' }, // one line comments 37 | { regex: r.multiLineCComments, css: 'comments' }, // multiline comments 38 | { regex: /\s*#.*/gm, css: 'preprocessor' }, // preprocessor tags like #region and #endregion 39 | { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keywords 40 | ]; 41 | 42 | this.forHtmlScript(r.scriptScriptTags); 43 | }; 44 | 45 | Brush.prototype = new SyntaxHighlighter.Highlighter(); 46 | Brush.aliases = ['js', 'jscript', 'javascript']; 47 | 48 | SyntaxHighlighter.brushes.JScript = Brush; 49 | 50 | // CommonJS 51 | typeof(exports) != 'undefined' ? exports.Brush = Brush : null; 52 | })(); 53 | -------------------------------------------------------------------------------- /tools/yuidoc/README: -------------------------------------------------------------------------------- 1 | yuidoc README 2 | 3 | yuidoc is a set of tools to generate the API documentation for the JavaScript 4 | in the YUI library. The docs are derived completely from JavaDoc style 5 | comment blocks; no attempt is made to understand the javascript itself. 6 | 7 | yuidoc requires Python 2.3+ with the following extensions: 8 | simplejson - for reading and writing json (required for Python versions below 2.6.0) 9 | cheetah - for generating the html docs 10 | pygments - for colorizing the source 11 | 12 | The code for yuidoc is provided under a BSD license: 13 | http://developer.yahoo.net/yui/license.html 14 | 15 | Project home page: 16 | http://developer.yahoo.com/yui/yuidoc/ 17 | 18 | Source code: 19 | http://github.com/yui/yuidoc 20 | 21 | Issue tracker: 22 | http://yuilibrary.com/projects/yuidoc 23 | 24 | 25 | Files: 26 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 27 | 28 | README 29 | This file 30 | 31 | CHANGES 32 | The change log 33 | 34 | INSTALL 35 | Installation instructions 36 | 37 | KNOWN_ISSUES 38 | Known issues and workarounds. 39 | 40 | TAGS 41 | Supported tags 42 | 43 | license.txt 44 | Open source license details. 45 | 46 | bin/yuidoc_parse.py 47 | The comment block parser. Parses all javascript files in the the specified 48 | directories and outputs a single file containing a json structure of the 49 | parsed documentation. 50 | 51 | bin/yuidoc_highlight.py 52 | Colorizes the script source 53 | 54 | bin/yuidoc_generate.py 55 | Reads the json output from parser.py and generates HTML docs. 56 | 57 | bin/yuidoc.py 58 | Wrapper for yuidoc_parse, yuidoc_highlight, and yuidoc_generate 59 | 60 | bin/example.sh 61 | An example shell script to run both the parser and generator on a src tree 62 | 63 | bin/example.bat 64 | An example batch for for DOS/Windows 65 | 66 | ext 67 | External required packages, provided for convenience 68 | 69 | 70 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/const.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copyright (c) 2010, Yahoo! Inc. All rights reserved. 3 | Code licensed under the BSD License: 4 | http://developer.yahoo.net/yui/license.html 5 | version: 1.0.0b1 6 | ''' 7 | 8 | ACCESS='access' 9 | ATTRIBUTE='attribute' 10 | BEFORE='before' 11 | BETA='beta' 12 | BUBBLES='bubbles' 13 | CANCELABLE='cancelable' 14 | CHAINABLE='chainable' 15 | CHANGEEVENT='Change' 16 | CLASS='class' 17 | CLASS_MAP='classmap' 18 | CLASS_LIST='classlist' 19 | CLASS_MODS='classmods' 20 | CONFIG='config' 21 | CONFIGS='configs' 22 | CONSTRUCTOR='constructor' 23 | CONSTRUCTORS='constructors' 24 | DEFAULT='default' 25 | DEPRECATED='deprecated' 26 | DESCRIPTION='description' 27 | EXPERIMENTAL='experimental' 28 | EVENT='event' 29 | EVENTS='events' 30 | EXTENDS='extends' 31 | FILE='file' 32 | FILE_LIST='filelist' 33 | FILE_MAP='filemap' 34 | FILE_MARKER='filemarker' 35 | FINAL='final' 36 | FOR='for' 37 | FUNCTION='function' 38 | GLOBAL='global' 39 | GUESSEDNAME='guessedname' 40 | GUESSEDTYPE='guessedtype' 41 | HASEVENTS='hasevents' 42 | HOST='host' 43 | IGNORE_PATTERNS = ('*.pyc','CVS','^.git','.svn') 44 | LONGNAME='longname' 45 | LOGCONFIG='yuidoclog.conf' 46 | METHOD='method' 47 | METHODS='methods' 48 | MAJOR_VERSION='majorversion' 49 | MODULE='module' 50 | MODULE_PREFIX='module_' 51 | MODULES='modules' 52 | NAME='name' 53 | NAMESPACE='namespace' 54 | NAMESPACES='namespaces' 55 | NBWS=' ' 56 | OBJECT='object' 57 | OPTIONAL='optional' 58 | PARAM='param' 59 | PARAMS='params' 60 | PRIVATE='private' 61 | PREVENTABLE='preventable' 62 | PROPERTY='property' 63 | PROPERTIES='properties' 64 | PROTECTED='protected' 65 | READONLY='readonly' # readonly is static for config properties 66 | REQUIRES='requires' 67 | RETURN='return' 68 | SHORTNAME='shortname' 69 | SUBMODULE='submodule' 70 | SUBMODULES='submodules' 71 | SUBDATA='subdata' 72 | SUPERCLASS='superclass' 73 | SEE='see' 74 | STATIC='static' 75 | TITLE='title' 76 | TYPE='type' 77 | UNKNOWN='unknown' 78 | URL='url' 79 | USES='uses' 80 | VERSION='version' 81 | VOID='void' 82 | WRITEONCE='writeonce' 83 | -------------------------------------------------------------------------------- /src/collectionPluginREST.js: -------------------------------------------------------------------------------- 1 | AFrame.CollectionPluginREST = (function() { 2 | var Plugin = AFrame.CollectionPluginPersistence.extend( { 3 | importconfig: [ 'url', 'net' ], 4 | loadCallback: function( options ) { 5 | var me=this; 6 | me.net.ajax( { 7 | url: me.url, 8 | success: options.onComplete 9 | } ); 10 | }, 11 | 12 | addCallback: function( item, options ) { 13 | var me=this; 14 | me.net.ajax( { 15 | url: me.url, 16 | data: getItemData( item ), 17 | type: 'POST', 18 | success: function( body, textStatus, xhr ) { 19 | var loc = xhr.getResponseHeader( 'Location' ); 20 | loc = loc.replace( me.url + '/', '' ); 21 | setItemData( item, 'id', loc ); 22 | options.onComplete && options.onComplete(); 23 | } 24 | } ); 25 | }, 26 | 27 | deleteCallback: function( item, options ) { 28 | var me=this; 29 | me.net.ajax( { 30 | url: me.url + '/' + getItemID( item ), 31 | type: 'DELETE', 32 | success: options.onComplete 33 | } ); 34 | }, 35 | 36 | saveCallback: function( item, options ) { 37 | var me=this; 38 | me.net.ajax( { 39 | url: me.url + '/' + getItemID( item ), 40 | data: getItemData( item ), 41 | type: 'PUT', 42 | success: options.onComplete 43 | } ); 44 | } 45 | } ); 46 | 47 | function getItemID( item ) { 48 | return item.get ? item.get( 'id' ) : item.id; 49 | } 50 | 51 | function getItemData( item ) { 52 | return item.toJSON ? item.toJSON() : item; 53 | } 54 | 55 | function setItemData( item, key, data ) { 56 | if( item.set ) { 57 | item.set( key, data ); 58 | } 59 | else { 60 | item[ key ] = data; 61 | } 62 | } 63 | 64 | return Plugin; 65 | }()); 66 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/css/content.css: -------------------------------------------------------------------------------- 1 | #content h2 { 2 | font-weight: normal; 3 | } 4 | 5 | #content h2 span.extends { 6 | display: block; 7 | } 8 | 9 | #content h2 span.extends span.class { 10 | color: #fff; 11 | } 12 | 13 | #content pre, section pre, section .syntaxhighlighter { 14 | border: 1px solid #eee; 15 | padding: 0.5em; 16 | background-color: #f8f8f8; 17 | overflow: auto; 18 | } 19 | 20 | #content div.deprecated { 21 | background-color: #d53; 22 | color: #fff; 23 | padding: 0 1em; 24 | margin-bottom: 0.4em; 25 | display: inline-block; 26 | } 27 | 28 | #content div.section { 29 | margin-top: 3em; 30 | padding-top: 2em; 31 | border-top: 8pt solid #fcfcfc; 32 | } 33 | 34 | #content div.section h3 { 35 | background-color: #555; 36 | color: #fff; 37 | padding: 0.1em 0.5em; 38 | text-shadow: rgba(0, 0, 0, 0.5) 0 -1pt 0; 39 | } 40 | 41 | #content div.section h4 { 42 | color: #444; 43 | margin-top: 1.25em; 44 | } 45 | 46 | #content div.section table th, 47 | #content div.section table td { 48 | padding: 0.5em; 49 | vertical-align: top; 50 | text-align: left; 51 | } 52 | 53 | #content div.section table th { 54 | background-color: #eeeeff; 55 | border: 1px solid #ddd; 56 | } 57 | 58 | #content div.section table td { 59 | border: 1px solid #eee; 60 | } 61 | 62 | #content div.section table td.description { 63 | vertical-align: top; 64 | padding-right: 2em; 65 | } 66 | 67 | #content div.section table td.description a.top { 68 | margin-right: -1.5em; 69 | float: right; 70 | color: #ddd; 71 | } 72 | 73 | #content div.section table td.type code, 74 | #content div.section table td.returns code { 75 | display: block; 76 | } 77 | 78 | #content div.section table td.type span, 79 | #content div.section table td.returns span { 80 | font-size: 90%; 81 | color: #777; 82 | padding: 0 0.5em 0 0; 83 | } 84 | 85 | #content div.section table td.type span.access-private, 86 | #content div.section table td.returns span.access-private { 87 | color: #a22; 88 | } 89 | 90 | #content div.section table td.type span.access-protected, 91 | #content div.section table td.returns span.access-protected { 92 | color: #d88; 93 | } 94 | 95 | -------------------------------------------------------------------------------- /site/scripts/apidocs.js: -------------------------------------------------------------------------------- 1 | $( function() { 2 | var openExample; 3 | 4 | var showExample = function( event ) { 5 | event.preventDefault(); 6 | event.stopPropagation(); 7 | 8 | openExample && openExample.fadeOut(); 9 | 10 | openExample = $( event.currentTarget ).next( '.example' ); 11 | openExample.fadeIn(); 12 | }; 13 | 14 | var hideOpenExample = function() { 15 | openExample && openExample.fadeOut(); 16 | openExample = null; 17 | }; 18 | 19 | var hideExample = function( event ) { 20 | event.preventDefault(); 21 | hideOpenExample(); 22 | }; 23 | 24 | var stopEvent = function( event ) { 25 | event.preventDefault(); 26 | event.stopPropagation(); 27 | }; 28 | 29 | $( 'body' ).bind( 'click', hideOpenExample ).bind( 'keyup', function( event ) { 30 | if( event.which == 27 && openExample ) { 31 | hideOpenExample(); 32 | } 33 | } ); 34 | 35 | var examples = $( 'td.description > pre' ); 36 | examples.each( function( index, item ) { 37 | var example = $( item ); 38 | var anchor = $( 'See Example' ); 39 | anchor.insertBefore( example ); 40 | 41 | var container = $( '

Example Usage

Close
' ); 42 | container.append( example ); 43 | container.insertAfter( anchor ); 44 | 45 | $( container ).bind( 'click', stopEvent ); 46 | 47 | $( '.btnClose', container ).bind( 'click', hideExample ); 48 | 49 | anchor.bind( 'click', showExample ); 50 | } ); 51 | 52 | /** 53 | * Remove the code parent and put it directly into the pre so that we can 54 | * do code highlighting 55 | */ 56 | $( 'pre > code' ).each( function( index, element ) { 57 | element = $( element ); 58 | var parent = element.parent(); 59 | parent.html( element.html() ); 60 | } ); 61 | 62 | SyntaxHighlighter.defaults['toolbar'] = false; 63 | SyntaxHighlighter.defaults['gutter'] = false; 64 | SyntaxHighlighter.all( { brush: 'js' } ); 65 | } ); -------------------------------------------------------------------------------- /site/stylesheets/cssreset.scss: -------------------------------------------------------------------------------- 1 | /* 2 | html5doctor.com Reset Stylesheet 3 | v1.6.1 4 | Last Updated: 2010-09-17 5 | Author: Richard Clark - http://richclarkdesign.com 6 | Twitter: @rich_clark 7 | */ 8 | 9 | html, body, div, span, object, iframe, 10 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 11 | abbr, address, cite, code, 12 | del, dfn, em, img, ins, kbd, q, samp, 13 | small, strong, sub, sup, var, 14 | b, i, 15 | dl, dt, dd, ol, ul, li, 16 | fieldset, form, label, legend, 17 | table, caption, tbody, tfoot, thead, tr, th, td, 18 | article, aside, canvas, details, figcaption, figure, 19 | footer, header, hgroup, menu, nav, section, summary, 20 | time, mark, audio, video { 21 | margin:0; 22 | padding:0; 23 | border:0; 24 | outline:0; 25 | font-size:100%; 26 | vertical-align:baseline; 27 | background:transparent; 28 | } 29 | 30 | body { 31 | line-height:1; 32 | } 33 | 34 | article,aside,details,figcaption,figure, 35 | footer,header,hgroup,menu,nav,section { 36 | display:block; 37 | } 38 | 39 | nav ul { 40 | list-style:none; 41 | margin: 0; 42 | padding: 0; 43 | } 44 | 45 | blockquote, q { 46 | quotes:none; 47 | } 48 | 49 | blockquote:before, blockquote:after, 50 | q:before, q:after { 51 | content:''; 52 | content:none; 53 | } 54 | 55 | a { 56 | margin:0; 57 | padding:0; 58 | font-size:100%; 59 | vertical-align:baseline; 60 | background:transparent; 61 | } 62 | 63 | /* change colours to suit your needs */ 64 | ins { 65 | background-color:#ff9; 66 | color:#000; 67 | text-decoration:none; 68 | } 69 | 70 | /* change colours to suit your needs */ 71 | mark { 72 | background-color:#ff9; 73 | color:#000; 74 | font-style:italic; 75 | font-weight:bold; 76 | } 77 | 78 | del { 79 | text-decoration: line-through; 80 | } 81 | 82 | abbr[title], dfn[title] { 83 | border-bottom:1px dotted; 84 | cursor:help; 85 | } 86 | 87 | table { 88 | border-collapse:collapse; 89 | border-spacing:0; 90 | } 91 | 92 | /* change border colour to suit your needs */ 93 | hr { 94 | display:block; 95 | height:1px; 96 | border:0; 97 | border-top:1px solid #cccccc; 98 | margin:1em 0; 99 | padding:0; 100 | } 101 | 102 | input, select { 103 | vertical-align:middle; 104 | } -------------------------------------------------------------------------------- /site/stylesheets/content.scss: -------------------------------------------------------------------------------- 1 | #content h2 { 2 | font-weight: normal; 3 | 4 | span.extends { 5 | display: block; 6 | 7 | span.class { 8 | color: #fff; 9 | } 10 | } 11 | 12 | } 13 | 14 | #content pre, section pre, .syntaxhighlighter { 15 | border: 1px solid #eee; 16 | padding: 0.5em; 17 | background-color: #f8f8f8; 18 | overflow: auto; 19 | } 20 | 21 | .example .syntaxhighlighter { 22 | margin: 10px !important; 23 | width: auto !important; 24 | } 25 | 26 | #content div.deprecated { 27 | background-color: #d53; 28 | color: #fff; 29 | padding: 0 1em; 30 | margin-bottom: 0.4em; 31 | display: inline-block; 32 | } 33 | 34 | #content div.section { 35 | margin-top: 3em; 36 | padding-top: 2em; 37 | border-top: 8pt solid #fcfcfc; 38 | } 39 | 40 | #content div.section h3 { 41 | background-color: #555; 42 | color: #fff; 43 | padding: 0.1em 0.5em; 44 | text-shadow: rgba(0, 0, 0, 0.5) 0 -1pt 0; 45 | } 46 | 47 | #content div.section h4 { 48 | color: #444; 49 | margin-top: 1.25em; 50 | } 51 | 52 | #content div.section table th, 53 | #content div.section table td { 54 | padding: 0.5em; 55 | vertical-align: top; 56 | text-align: left; 57 | } 58 | 59 | #content div.section table th { 60 | background-color: #eeeeff; 61 | border: 1px solid #ddd; 62 | } 63 | 64 | #content div.section table td { 65 | border: 1px solid #eee; 66 | } 67 | 68 | #content div.section table td.description { 69 | vertical-align: top; 70 | padding-right: 2em; 71 | } 72 | 73 | #content div.section table td.description a.top, h3 a.top, h4 a.top { 74 | margin-right: -1.5em; 75 | float: right; 76 | color: #ddd; 77 | } 78 | 79 | #content div.section table td.type code, 80 | #content div.section table td.returns code { 81 | display: block; 82 | } 83 | 84 | #content div.section table td.type span, 85 | #content div.section table td.returns span { 86 | font-size: 90%; 87 | color: #777; 88 | padding: 0 0.5em 0 0; 89 | } 90 | 91 | #content div.section table td.type span.access-private, 92 | #content div.section table td.returns span.access-private { 93 | color: #a22; 94 | } 95 | 96 | #content div.section table td.type span.access-protected, 97 | #content div.section table td.returns span.access-protected { 98 | color: #d88; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /tests/test_observable.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.Observable", 4 | 5 | setUp : function () { 6 | this.observable = AFrame.Observable.create(); 7 | this.boundCalled = false; 8 | this.args; 9 | var me=this; 10 | this.bindFunc = function() { 11 | me.boundCalled = true; 12 | me.args = Array.prototype.slice.call( arguments, 0 ); 13 | this.thisBound = true; 14 | }; 15 | }, 16 | 17 | tearDown : function () { 18 | this.observable.unbindAll(); 19 | this.observable = null; 20 | delete this.observable; 21 | }, 22 | 23 | testBindTrigger: function() { 24 | this.observable.bind( this.bindFunc ); 25 | this.observable.trigger(); 26 | 27 | Assert.isTrue( this.boundCalled, 'bindFunc function called' ); 28 | Assert.areEqual( 0, this.args.length, 'arguments length is 0' ); 29 | 30 | this.observable.trigger( 1, 2 ); 31 | Assert.areEqual( 2, this.args.length, 'arguments length correctly passed' ); 32 | }, 33 | 34 | testUnbind: function() { 35 | var bindID = this.observable.bind( this.bindFunc ); 36 | this.observable.unbind( bindID ); 37 | this.observable.trigger(); 38 | Assert.isFalse( this.boundCalled, 'bound function unbound' ); 39 | }, 40 | 41 | testUnbindAll: function() { 42 | var secondBound = false; 43 | var secondBindFunc = function() { 44 | secondBound = true; 45 | }; 46 | 47 | this.observable.bind( this.bindFunc ); 48 | this.observable.bind( secondBound ); 49 | 50 | this.observable.unbindAll(); 51 | 52 | this.observable.trigger(); 53 | Assert.isFalse( this.boundCalled, 'bound function unbound' ); 54 | Assert.isFalse( secondBound, 'secondBound function unbound' ); 55 | }, 56 | 57 | testIsTriggered: function() { 58 | Assert.isFalse( this.observable.isTriggered(), 'observable has not been triggered' ); 59 | 60 | this.observable.trigger(); 61 | 62 | Assert.isTrue( this.observable.isTriggered(), 'observable has been triggered' ); 63 | }, 64 | 65 | testTeardown: function() { 66 | this.observable.teardown(); 67 | }, 68 | 69 | testUniqueIDsAcrossObservables: function() { 70 | var observable1 = AFrame.Observable.create(); 71 | var observable2 = AFrame.Observable.create(); 72 | 73 | var id1 = observable1.bind( function() {} ); 74 | var id2 = observable2.bind( function() {} ); 75 | 76 | Assert.areNotEqual( id1, id2, 'ids are unique' ); 77 | } 78 | } ); 79 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/js/main.js: -------------------------------------------------------------------------------- 1 | /*jslint adsafe: false, bitwise: true, browser: true, cap: false, css: false, 2 | debug: false, devel: true, eqeqeq: true, es5: false, evil: false, 3 | forin: false, fragment: false, immed: true, laxbreak: false, newcap: true, 4 | nomen: false, on: false, onevar: true, passfail: false, plusplus: true, 5 | regexp: false, rhino: true, safe: false, strict: false, sub: false, 6 | undef: true, white: false, widget: false, windows: false */ 7 | /*global jQuery: false, $: false, window: false */ 8 | "use strict"; 9 | 10 | 11 | $( document ).ready( function() { 12 | 13 | function initAC() { 14 | $( "#search" ).autocomplete( "destroy" ); 15 | 16 | $.ajax({ 17 | url: "./index.json", 18 | dataType: "json", 19 | success: function( acdata ) { 20 | var supply = []; 21 | 22 | $.each( acdata, function( i, dataset ) { 23 | var key = "show_" + dataset.access, 24 | label = [ dataset.host, " → ", 25 | dataset.name, 26 | " (", dataset.type, ")" 27 | ].join( "" ); 28 | 29 | if ( !!$.cookie( key ) || dataset.access === "" ) { 30 | supply.push({ 31 | label: label, 32 | url: dataset.url 33 | }); 34 | } 35 | }); 36 | 37 | $( "#search" ).autocomplete({ 38 | source: supply, 39 | focus: function( event, ui ) { 40 | $('#search').val( ui.item.label ); 41 | return false; 42 | }, 43 | select: function( event, ui ) { 44 | document.location.href = ui.item.url; 45 | return false; 46 | } 47 | }); 48 | } 49 | }); 50 | } 51 | 52 | 53 | $.each( [ "private", "protected", "deprecated" ], function( i, kind ) { 54 | var key = "show_" + kind; 55 | 56 | if ( !!$.cookie( key ) ) { 57 | $( "#show-toggles :checkbox#" + key ).attr( "checked", true ); 58 | $( "." + kind ).show(); 59 | } 60 | else { 61 | $( "." + kind ).hide(); 62 | } 63 | }); 64 | 65 | $( "#show-toggles :checkbox" ).click( function( evt ) { 66 | var elem = $( this ), 67 | name = elem.attr( "name" ), 68 | what = name.replace( /^show_/, "" ), 69 | checked = ( elem.filter( ":checked" ).length !== 0 ); 70 | 71 | $.cookie( name, checked ? true : null ); 72 | 73 | if ( !!checked ) { 74 | $( "." + what ).show(); 75 | } 76 | else { 77 | $( "." + what ).hide(); 78 | } 79 | 80 | initAC(); 81 | }); 82 | 83 | 84 | initAC(); 85 | 86 | }); 87 | -------------------------------------------------------------------------------- /tests/test_harness_end.js: -------------------------------------------------------------------------------- 1 | jQuery(function() { 2 | window.Assert = { 3 | deepEqual: function( expected, check, message ) { 4 | deepEqual( expected, check, message ); 5 | }, 6 | 7 | areEqual: function( expected, check, message ) { 8 | equal( check, expected, message ); 9 | }, 10 | 11 | areNotEqual: function( expected, check, message ) { 12 | notEqual( check, expected, message ); 13 | }, 14 | 15 | areSame: function( expected, check, message ) { 16 | strictEqual( true, check === expected, message ); 17 | }, 18 | 19 | isUndefined: function( check, message ) { 20 | strictEqual( typeof check, 'undefined', message ); 21 | }, 22 | 23 | isNotUndefined: function( check, message ) { 24 | notStrictEqual( typeof check, 'undefined', message ); 25 | }, 26 | 27 | isTrue: function( check, message ) { 28 | strictEqual( true, check, message ); 29 | }, 30 | 31 | isFalse: function( check, message ) { 32 | strictEqual( false, check, message ); 33 | }, 34 | 35 | isString: function( check, message ) { 36 | strictEqual( {}.toString.apply( check ), '[object String]', message ); 37 | }, 38 | 39 | isFunction: function( check, message ) { 40 | strictEqual( {}.toString.apply( check ), '[object Function]', message ); 41 | }, 42 | 43 | isObject: function( check, message ) { 44 | strictEqual( typeof check, 'object', message ); 45 | }, 46 | 47 | isArray: function( check, message ) { 48 | strictEqual( {}.toString.apply( check ), '[object Array]', message ); 49 | }, 50 | 51 | isNumber: function( check, message ) { 52 | strictEqual( {}.toString.apply( check ), '[object Number]', message ); 53 | } 54 | }; 55 | 56 | var reserved = [ 'name', 'setUp', 'tearDown' ]; 57 | 58 | function createTest( testConfig ) { 59 | var config = {}; 60 | if( testConfig.setUp ) { 61 | config.setup = testConfig.setUp; 62 | } 63 | 64 | if( testConfig.tearDown ) { 65 | config.teardown = testConfig.tearDown; 66 | } 67 | 68 | module( testConfig.name, config ); 69 | 70 | for( var key in testConfig ) { 71 | if( testConfig.hasOwnProperty( key ) && reserved.indexOf( key ) === -1 ) { 72 | test( key, testConfig[ key ] ); 73 | } 74 | } 75 | } 76 | 77 | testsToRun.forEach( createTest ); 78 | 79 | }); 80 | 81 | -------------------------------------------------------------------------------- /tools/yuidoc/test/apidocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ############################################################################## 4 | 5 | # The location of your yuidoc install 6 | # yuidoc_home=yahoo/presentation/tools/yuidoc 7 | # yuidoc_home=~/www/yuidoc/yuidoc 8 | yuidoc_home=.. 9 | 10 | src=~/src/yui3/src 11 | 12 | # The location of the files to parse. Parses subdirectories, but will fail if 13 | # there are duplicate file names in these directories. 14 | # parser_in="$src/animation \ 15 | # $src/attribute \ 16 | # $src/base \ 17 | # $src/dd \ 18 | # $src/dom \ 19 | # $src/json \ 20 | # $src/json-parse \ 21 | # $src/json-stringify \ 22 | # $src/node \ 23 | # $src/queue \ 24 | # $src/yui" 25 | #parser_in="$src" 26 | 27 | parser_in="$src/yui \ 28 | $src/anim \ 29 | $src/attribute \ 30 | $src/base \ 31 | $src/cache \ 32 | $src/classnamemanager \ 33 | $src/collection \ 34 | $src/console \ 35 | $src/console-filters \ 36 | $src/cookie \ 37 | $src/dataschema \ 38 | $src/datasource \ 39 | $src/datatype \ 40 | $src/dd \ 41 | $src/dom \ 42 | $src/dump \ 43 | $src/event \ 44 | $src/event-custom \ 45 | $src/event-simulate \ 46 | $src/history \ 47 | $src/imageloader \ 48 | $src/io \ 49 | $src/json \ 50 | $src/node \ 51 | $src/node-focusmanager \ 52 | $src/node-menunav \ 53 | $src/oop \ 54 | $src/overlay \ 55 | $src/plugin \ 56 | $src/profiler \ 57 | $src/slider \ 58 | $src/stylesheet \ 59 | $src/substitute \ 60 | $src/test \ 61 | $src/widget \ 62 | $src/widget-position \ 63 | $src/widget-position-ext \ 64 | $src/widget-stdmod \ 65 | $src/widget-stack" 66 | 67 | # The location to output the parser data. This output is a file containing a 68 | # json string, and copies of the parsed files. 69 | parser_out=build_tmp/yuidoc_tmp 70 | 71 | # The directory to put the html file outputted by the generator 72 | generator_out=build_tmp/api 73 | 74 | # The location of the template files. Any subdirectories here will be copied 75 | # verbatim to the destination directory. 76 | template=$yuidoc_home/template 77 | 78 | version=`cat version.txt` 79 | 80 | ############################################################################## 81 | 82 | $yuidoc_home/bin/yuidoc.py $parser_in -p $parser_out -o $generator_out -t $template -v $version -s $* 83 | 84 | -------------------------------------------------------------------------------- /src/enumerableMixin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A collection of functions common to enumerable objects. When mixing in 3 | * this class, the class being mixed into must define a forEach function. 4 | * 5 | * @class AFrame.EnumerableMixin 6 | * @static 7 | */ 8 | AFrame.EnumerableMixin = ( function() { 9 | "use strict"; 10 | 11 | var Mixin = { 12 | /** 13 | * Get a set of items in the collection using the search function. The search function will 14 | * be called once for each item in the collection. Any time the search function returns true, 15 | * the item will be added to the results list. 16 | * 17 | * // Filter the collection to find a set of items that have company == 'AFrame Foundary' 18 | * var matches = collection.filter( function( item, id, collection ) { 19 | * // do search here, returning true if item matches. 20 | * return item.company == 'AFrame Foundary'; 21 | * } ); 22 | * 23 | * @method filter 24 | * @param {function} search - the search function 25 | * @return {array} array of results. If no results are found, returns an empty array. 26 | */ 27 | filter: function( search ) { 28 | var items = []; 29 | 30 | this.forEach( function( item, id ) { 31 | if( true === search( item, id, this ) ) { 32 | items.push( item ); 33 | } 34 | }, this ); 35 | 36 | return items; 37 | }, 38 | 39 | /** 40 | * Search for the first item in the collection that matches the search function. 41 | * 42 | * // search for the first item with company == 'AFrame Foundary' 43 | * var item = collection.search( function( item, id, collection ) { 44 | * return item.company == 'AFrame Foundary'; 45 | * } ); 46 | * 47 | * @method search 48 | * @param {function} search - the search function. 49 | * @return {item} item if an item matches, undefined otw. 50 | */ 51 | search: function( search ) { 52 | return this.filter( search )[ 0 ]; 53 | }, 54 | 55 | /** 56 | * Get the current count of items 57 | * 58 | * // using hash from top of the page 59 | * var count = hash.getCount(); 60 | * 61 | * @method getCount 62 | * @return {number} current count 63 | */ 64 | getCount: function() { 65 | var count = 0; 66 | 67 | this.forEach( function( item ) { 68 | count++; 69 | } ); 70 | 71 | return count; 72 | } 73 | }; 74 | 75 | return Mixin; 76 | 77 | }() ); -------------------------------------------------------------------------------- /tools/yuidoc/INSTALL: -------------------------------------------------------------------------------- 1 | ********************************************************************** 2 | NOTE: 2009-10-27 -- there have been reports of easy_install trying 3 | to pull Cheetah 2.4.0 and failing. If this occurs, download and 4 | install version 2.2.2 (which is the current stable version): 5 | 6 | http://pypi.python.org/packages/source/C/Cheetah/Cheetah-2.2.2.tar.gz#md5=e0d89113ab6bb0935d2b67395960264c 7 | ********************************************************************** 8 | 9 | One-time setup for python: 10 | 11 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 | Unix (including cygwin): 13 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 14 | 15 | 1. Check to see if setuptools is installed. 16 | Execute this command: 17 | which easy_install 18 | 19 | If it returns something, it's installed skip to step #3. 20 | 21 | 22 | 2. Install Setup Tools: 23 | Extract the archive in ext and install the package 24 | sudo python setup.py install (no sudo needed for cygwin or windows) 25 | 26 | setuptools 27 | cd ext 28 | tar xfvz setuptools-0.6c9.tar.gz 29 | cd setuptools-0.6c9 30 | sudo python setup.py install 31 | 32 | 3. Install the dependencies 33 | 34 | easy_install pygments 35 | easy_install Cheetah 36 | 37 | * For Python version below 2.6.0, also install simplejson * 38 | easy_install simplejson 39 | 40 | 41 | 4. Make a copy of yuidoc/bin/example.sh and modify the paths to suit your needs. 42 | 43 | 44 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 45 | DOS/Windows: 46 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 47 | 48 | 1. Install Python 49 | 50 | * Use Python 2.4.3 as 2.5 generates warnings because the json parser has 51 | not been updated yet: 52 | 53 | http://www.python.org/ftp/python/2.4.3/python-2.4.3.msi 54 | 55 | * Extract each of the archives with WinZIP and install as described in 56 | the unix section. 57 | 58 | * Copy _namemapper.pyd to C:\Python24\Lib\site-packages\Cheetah 59 | 60 | 61 | 2,3. Same as above 62 | 63 | 4. Add C:\python24 to your PATH 64 | 65 | 5. Copy yuidoc\bin\example.bat and modify the paths to suit your needs 66 | 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | See TAGS for a brief description of the supported tags. Checking out the 70 | source for the YUI library is a good way to get to know how it works. Ex: 71 | http://developer.yahoo.com/yui/docs/Event.js.html 72 | 73 | NOTE: This tool will generally work with code that has been commented for 74 | jsdoc, with one exception: you must have at least one @module block defined 75 | somewhere in your source. If you don't, the program will run but won't 76 | generate anything. 77 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/README.markdown: -------------------------------------------------------------------------------- 1 | # YUIDoc Theme "Dana" 2 | 3 | I like [YUIDoc](http://developer.yahoo.com/yui/yuidoc/). I don't like its 4 | default theme. Since I couldn't find any other themes on them internets, I 5 | wrote my own, named "Dana". 6 | 7 | Since I normally use YUIDoc to document either pure Javascript or jQuery code, 8 | I didn't keep any of the old YUI code; I've ditched pretty much everything and 9 | started from scratch. 10 | 11 | Why "Dana"? Just following the lead of Evan Weaver ([RDoc theme 12 | "Allison"](http://github.com/fauna/allison)) and Mislav ([RDoc theme 13 | "Hanna"](http://github.com/mislav/hanna)), is all. Also it's the name of my 14 | wife. Ah, romance. :) 15 | 16 | This is a work in progress. It's reasonably stable and working for me so far. 17 | YMMV. If you encounter errors, please [create a 18 | ticket](http://github.com/carlo/yuidoc-theme-dana/issues). 19 | 20 | 21 | ## Example 22 | 23 | Here's the original YUI documentation in its [original 24 | look](http://developer.yahoo.com/yui/docs/index.html). 25 | 26 | And here is the very same documentation sporting the new [Dana 27 | theme](http://zottmann.org/yuidoc-theme-dana-example/index.html). 28 | 29 | I hope you find the latter more pleasing. :) Click around a bit; check some of 30 | the class documentations for a more in-depth comparison; play with the 31 | filters; feel the luxurious yet cheap plastic underneath. 32 | 33 | 34 | ## Installation / Usage 35 | 36 | I assume you've got YUIDoc up and running at this point. Just 37 | [download](http://github.com/carlo/yuidoc-theme-dana/downloads) this here 38 | theme, unpack it, and point `yuidoc.py` to it using the script's 39 | `-t/--template` option. 40 | 41 | Tested in Safari 5 (OSX), FF3.6 (OSX), IE8 (WinXP). 42 | 43 | 44 | ## Acknowledgements 45 | 46 | My thanks go to the [YUIDoc](http://developer.yahoo.com/yui/yuidoc/) guys, 47 | obviously. The original templates might be a bit shitty unorthodox 48 | in their free-spirited way of indention and cleanliness, but the overall 49 | system is sound. ;) 50 | 51 | Also, thanks to my good friend [Mike West](http://mikewest.org/), web dev 52 | extraordinaire, who [forked the original 53 | YUIDoc](http://github.com/mikewest/yuidoc) and added Markdown support so I 54 | didn't have to. Big ups, playa! 55 | 56 | This software uses... 57 | 58 | * the [Fluid 960 Grid System](http://960.gs/) by Nathan Smith, 59 | [960.gs](http://960.gs/), dual-licensed under MIT & GNU GPL. 60 | * [jQuery](http://jquery.com/), dual-licensed under MIT & GNU GPL. 61 | * [jQuery-cookie](http://stilbuero.de/jquery/cookie/), by Klaus Hartl, 62 | dual-licensed under MIT & GNU GPL. 63 | 64 | 65 | ## Known issues 66 | 67 | Code blocks (i.e. `
` tags) sometimes cause some minor layout upfuckery
68 | in the tables.
69 | 
70 | 
71 | ## Author
72 | 
73 | Carlo Zottmann, [municode.de](http://municode.de/), carlo@municode.de.  Nice
74 | to meet you.
75 | 
76 | 
77 | ## License
78 | 
79 | Dual-license, MIT & GNU GPL v2.
80 | 
81 | 


--------------------------------------------------------------------------------
/tests/test_enumerableMixin.js:
--------------------------------------------------------------------------------
 1 | testsToRun.push( {
 2 | 	 
 3 | 		name: "TestCase AFrame.EnumerableMixin",
 4 |         
 5 |         setUp: function() {
 6 |             this.enumerable = {
 7 |                 data: [],
 8 |                 forEach: function( callback ) {
 9 |                     this.data.forEach( callback );
10 |                 }
11 |             };
12 |             
13 |             AFrame.mixin( this.enumerable, AFrame.EnumerableMixin );
14 |         },
15 | 
16 |         testFilter: function() {
17 |             var items = [ {
18 | 				cid: 1,
19 | 				field: 'field1'
20 | 			}, {
21 | 				cid: 2,
22 | 				field: 'field2',
23 |                 duplicate: 'duplicate'
24 | 			}, {
25 | 				cid: 3,
26 | 				field: 'field3',
27 |                 duplicate: 'duplicate'
28 | 			} ];
29 |             
30 |             this.enumerable.data = items;
31 |             
32 |             var filteredSet = this.enumerable.filter( function( item, cid ) {
33 |                 return item.field == 'field3';
34 |             } );
35 |             
36 |             Assert.isArray( filteredSet, 'filtered set is an array' );
37 |             Assert.areEqual( 1, filteredSet.length, 'filtered set has one found item' );
38 |             Assert.areEqual( items[ 2 ], filteredSet[ 0 ], 'item is the correct item found' );
39 | 
40 |             filteredSet = this.enumerable.filter( function( item, cid ) {
41 |                 return item.field == 'field4';
42 |             } );
43 |             
44 |             Assert.isArray( filteredSet, 'filtered set is an array' );
45 |             Assert.areEqual( 0, filteredSet.length, 'filtered set has no found items' );
46 | 
47 |             filteredSet = this.enumerable.filter( function( item, cid ) {
48 |                 return item.duplicate == 'duplicate';
49 |             } );
50 |             
51 |             Assert.areEqual( 2, filteredSet.length, 'filtered set has two found items' );
52 |         },
53 |         
54 |         testSearch: function() {
55 |             var items = [ {
56 | 				cid: 1,
57 | 				field: 'field1'
58 | 			}, {
59 | 				cid: 2,
60 | 				field: 'field2',
61 |                 duplicate: 'duplicate'
62 | 			}, {
63 | 				cid: 3,
64 | 				field: 'field3',
65 |                 duplicate: 'duplicate'
66 | 			} ];
67 |             
68 |             this.enumerable.data = items;
69 |             
70 |             var item = this.enumerable.search( function( item, cid ) {
71 |                 return item.field == 'field3';
72 |             } );
73 |             
74 |             Assert.areEqual( items[ 2 ], item, 'item is the correct item found' );
75 | 
76 |             item = this.enumerable.search( function( item, cid ) {
77 |                 return item.field == 'field4';
78 |             } );
79 |             
80 |             Assert.isUndefined( item, 'item was not found, return undefined' );
81 | 
82 |             item = this.enumerable.search( function( item, cid ) {
83 |                 return item.duplicate == 'duplicate';
84 |             } );
85 |             
86 |             Assert.areEqual( item, items[ 1 ], 'with duplicate items, first item is returned' );
87 |         }
88 |         
89 | 		
90 | 
91 | } );
92 | 


--------------------------------------------------------------------------------
/src/observable.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * An Observable is the way events are done.  Observables are very similar to DOM Events in that
 3 |  * each object has a set of events that it can trigger.  Objects that are concerned with a particular event register a callback to be
 4 |  * called whenever the event is triggered.  Observables allow for each event to have zero or many listeners, meaning the developer does not have
 5 |  * to manually keep track of who to notify when a particular event happens.  This completely decouples the triggering object from any
 6 |  * objects that care about it.
 7 |  *
 8 |  * @class AFrame.Observable
 9 |  */
10 | AFrame.Observable = ( function() {
11 |     "use strict";
12 | 
13 |     var Observable = AFrame.Class( {
14 |         /**
15 |          * Initialize the observable
16 |          * @method init
17 |          */
18 |         init: function() {
19 |             this.callbacks = {};
20 |         },
21 | 
22 |         /**
23 |          * Tear the observable down, free references
24 |          * @method teardown
25 |          */
26 |         teardown: function() {
27 |             this.unbindAll();
28 |         },
29 | 
30 |         /**
31 |          * Trigger the observable, calls any callbacks bound to the observable.
32 |          * @method trigger
33 |          * @param {variant} optional - any arguments will be passed to the callbacks
34 |          */
35 |         trigger: function() {
36 |             var me=this,
37 |                 key;
38 | 
39 |             me.triggered = true;
40 |             for( key in me.callbacks ) {
41 |                 me.callbacks[ key ].apply( me, arguments );
42 |             }
43 |         },
44 | 
45 |         /**
46 |          * Bind a callback to the observable
47 |          * @method bind
48 |          * @param {function} callback - callback to register
49 |          * @return {id} id that can be used to unbind the callback.  Note, all ids for all bindings are unique.
50 |          */
51 |         bind: function( callback ) {
52 |             var id = AFrame.getUniqueID();
53 | 
54 |             this.callbacks[ id ] = callback;
55 | 
56 |             return id;
57 |         },
58 | 
59 |         /**
60 |          * Unbind an observable
61 |          * @method unbind
62 |          * @param {id} id - id of observable to unbind
63 |          */
64 |         unbind: function( id ) {
65 |             AFrame.remove( this.callbacks, id );
66 |         },
67 | 
68 |         /**
69 |          * Unbind all observables
70 |          * @method unbindAll
71 |          */
72 |         unbindAll: function() {
73 |             var me=this,
74 |                 key;
75 |             for( key in me.callbacks ) {
76 |               AFrame.remove( me.callbacks, key );
77 |             }
78 |         },
79 | 
80 |         /**
81 |          * Check whether the observable has been triggered
82 |          * @method isTriggered
83 |          * @return {boolean} true if observable has been triggered, false otw.
84 |          */
85 |         isTriggered: function() {
86 |             return !!this.triggered;
87 |         }
88 |     } );
89 | 
90 |     return Observable;
91 | }() );
92 | 


--------------------------------------------------------------------------------
/src/collectionPluginModel.js:
--------------------------------------------------------------------------------
 1 | /**
 2 | * A plugin to a Collection that automates the creation of models.  If all items
 3 | *   in a collection share a [Schema](AFrame.Schema.html), instead of creating
 4 | *   a model for each insert, the data can be inserted directly and a model will
 5 | *   automatically be created.  When doing a "get" on the collection, the models
 6 | *   will be returned.  Model creation will occur as soon as data enters the collection,
 7 | *   so it happens on insert always before the onBeforeInsert event is triggered.
 8 | *   If the collection has CollectionPluginPersistence, the model will be created
 9 | *   before the onBeforeAdd event is triggered.
10 | *
11 | *    // Define the schema
12 | *    var schemaConfig = {
13 | *        name: { type: 'text' },
14 | *        employer: { type: 'text', 'def': 'AFrame Foundary' }
15 | *    };
16 | *
17 | *    // create the collection.
18 | *    this.collection = AFrame.CollectionArray.create( {
19 | *        plugins: [ [ AFrame.CollectionPluginModel, {
20 | *            schema: schemaConfig
21 | *        } ] ]
22 | *    } );
23 | *
24 | * @class AFrame.CollectionPluginModel
25 | * @extends AFrame.Plugin
26 | * @constructor
27 | */
28 | /**
29 | * The schema or schemaConfig to use.
30 | * @config schema
31 | * @type {SchemaConfig || Schema || Model}
32 | */
33 | /**
34 | * The model factory to use.  If not given, a default model factory is used
35 | *   which creates an AFrame.Model with the data inserted and the schema
36 | *   given.  The factory will be called with two parameters, the data
37 | *   and the schema.
38 | *
39 | *    // example of an overridden model factory function.
40 | *    var modelFactory = function( data, schema ) {
41 | *       return SpecializedMode.create( {
42 | *           data: data,
43 | *           schema: schema
44 | *       } );
45 | *    };
46 | *
47 | * @config modelFactory
48 | * @type {function}
49 | * @default modelFactory
50 | */
51 | AFrame.CollectionPluginModel = ( function() {
52 |     "use strict";
53 | 
54 |     var Plugin = AFrame.Plugin.extend( {
55 |         importconfig: [ 'schema' ],
56 | 
57 |         init: function( config ) {
58 |         	var me=this;
59 |             me.modelFactory = config.modelFactory || createModel;
60 | 
61 |             Plugin.sc.init.call( me, config );
62 | 
63 | 			me.defaultModelConstructor = AFrame.extendsFrom( me.schema, AFrame.Model ) ? me.schema : AFrame.Model;
64 | 
65 |             var plugged = me.getPlugged();
66 |             plugged.insert = augmentInsert.bind( me, plugged.insert );
67 | 
68 |             if( plugged.add ) {
69 |                 plugged.add = augmentInsert.bind( me, plugged.add );
70 |             }
71 |         }
72 | 
73 |     } );
74 | 
75 |     function augmentInsert( decorated, item, insertAt ) {
76 |         if( !( item instanceof AFrame.Model ) ) {
77 |             item = this.modelFactory( item );
78 |         }
79 | 
80 |         return decorated.call( this.getPlugged(), item, insertAt );
81 |     }
82 | 
83 |     function createModel( data ) {
84 | 		var model = this.defaultModelConstructor.create( {
85 | 			schema: this.schema,
86 | 			data: data
87 | 		} );
88 |         return model;
89 |     }
90 | 
91 |     return Plugin;
92 | }() );
93 | 


--------------------------------------------------------------------------------
/site/stylesheets/aframejs.scss:
--------------------------------------------------------------------------------
  1 | @import "cssreset";
  2 | @import "grid";
  3 | @import "jquery-ui-1.8.4.custom";
  4 | @import "main";
  5 | @import "navigation";
  6 | @import "content";
  7 | 
  8 | $header-color: #ff8200;
  9 | $border-color: #eee;
 10 | $content-shadow: 0 0 15px 5px rgba(0,0,0,.3);
 11 | 
 12 | html {
 13 | 	font-family: arial;
 14 | }
 15 | 
 16 | body {
 17 | 	color: #333;
 18 | 	background-color: #C6B9AC;
 19 | 	font: 13px/1.5 Helvetica,Arial,'Liberation Sans',FreeSans,sans-serif;
 20 | }
 21 | 
 22 | .container {
 23 | 	background: #fff;
 24 | 	margin-top: 50px;
 25 | }
 26 | 
 27 | .container.container_12 {
 28 | 	-moz-box-shadow: $content-shadow;
 29 | 	-webkit-box-shadow: $content-shadow;
 30 | 	box-shadow: $content-shadow;
 31 | }
 32 | 
 33 | .container_12 {
 34 | 	padding: 50px;
 35 | }
 36 | 
 37 | 
 38 | header {
 39 | 	padding-bottom: 10px;
 40 | 	text-align: center;
 41 |     
 42 |     h1 {
 43 |         color: $header-color;
 44 |         font-size: 2.2em;
 45 |     }
 46 |     
 47 |     h2 {
 48 |         color: $header-color;
 49 |         margin-bottom: 1.1em;
 50 |         font-size: 1.1em;
 51 |         
 52 |         strong {
 53 |             font-style: italic;
 54 |         }
 55 |     }
 56 |     
 57 |     nav {
 58 |         background: $border-color;
 59 |         
 60 | 
 61 |         ul {
 62 |             li {
 63 |                 font-size: 0.8em;
 64 |                 line-height: 1.6em;
 65 |                 display: inline;
 66 |                 margin: 0 4px;
 67 |             }
 68 |         }
 69 |     }
 70 | }
 71 | 
 72 | #content h3, h4, h5 {
 73 |     margin-top: .5em;
 74 |     font-weight: bold;
 75 | }
 76 | 
 77 | ul {
 78 | 	padding-left: 20px;
 79 |     
 80 |     li {
 81 |         list-style: none;
 82 |     }
 83 | }
 84 | 
 85 | 
 86 | code, code a[name] {
 87 |   color: #007000;
 88 |   font-family: "Droid Sans Mono";
 89 | }
 90 | 
 91 | 
 92 | 
 93 | 
 94 | footer {
 95 | 	clear: both;
 96 | 	padding-top: 1em;
 97 | 	border-top: 5pt solid $border-color;
 98 | 	font-size: 0.7em;
 99 |     margin: 1em 0 0;
100 | }
101 | 
102 | a {
103 | 	color: #777;
104 | 	text-decoration: none;
105 |     &:hover {
106 |         color: #444;
107 |         text-decoration: underline;
108 |     }
109 | }
110 | 
111 | 
112 | section {
113 | 	clear: both;
114 | 	margin: 10px;
115 | 	padding: 0 10px;
116 | 	font-size: .9em;
117 |     
118 |     h2 {
119 |         margin-bottom: 10px;
120 |         margin-left: -10px;
121 |         font-size: 1.2em;
122 |     }
123 |     
124 |     p {
125 |         margin: 10px 0;
126 |         line-height: 1.6em;
127 |     }
128 | }
129 | 
130 | 
131 | 
132 | .summary.description > ul,
133 | .summary.description > ul > li {
134 |     list-style-type: disc;
135 |     margin-left: 20px;
136 | }
137 | 
138 | 
139 | td.description {
140 |     position: relative;
141 |     
142 |     .btnSeeExample {
143 |         margin-bottom: 1em;
144 |         display: block;
145 |     }
146 |     
147 |     .example {
148 |         display: none;
149 |         position: absolute;
150 |         background: #fff;
151 |         border: 1px solid $border-color;
152 |         min-width: 500px;
153 |         z-index: 1;
154 |         
155 |         .btnClose {
156 |             margin-left: .5em;
157 |         }
158 |         
159 |         pre {
160 |             margin: 0 .5em .5em;
161 |         }
162 |     }
163 | }
164 | 
165 | @import "shCore";
166 | @import "shThemeDefault";
167 | 


--------------------------------------------------------------------------------
/src/fieldValidityState.js:
--------------------------------------------------------------------------------
  1 | /**
  2 | * An object that keeps track of a field's validity, mirrors the
  3 | * [HTML5](http://www.whatwg.org/specs/web-apps/current-work/multipage/association-of-controls-and-forms.html#the-constraint-validation-api) spec.
  4 | *
  5 | * @class AFrame.FieldValidityState
  6 | * @constructor
  7 | */
  8 | AFrame.FieldValidityState = function( config ) {
  9 | 	if( config ) {
 10 | 		AFrame.mixin( this, config );
 11 | 	}
 12 | };
 13 | /**
 14 | * Get an instance of the FieldValidityState object
 15 | * @method AFrame.FieldValidityState.create
 16 | * @param {object} config - object with a list of fields to set on the validity object
 17 | * @returns {AFrame.FieldValidityState}
 18 | */
 19 | AFrame.FieldValidityState.create = function( config ) {
 20 | 	return new AFrame.FieldValidityState( config || {} );
 21 | };
 22 | AFrame.FieldValidityState.prototype = {
 23 | 	/**
 24 | 	* True if the element has no value but is a required field; false otherwise.
 25 | 	* @property valueMissing
 26 | 	* @type {boolean}
 27 | 	*/
 28 | 	valueMissing: false,
 29 | 	/**
 30 | 	* True if the element's value is not in the correct syntax; false otherwise.
 31 | 	* @property typeMismatch
 32 | 	* @type {boolean}
 33 | 	*/
 34 | 	typeMismatch: false,
 35 | 	/**
 36 | 	* True if the element's value doesn't match the provided pattern; false otherwise.
 37 | 	* @property patternMismatch
 38 | 	* @type {boolean}
 39 | 	*/
 40 | 	patternMismatch: false,
 41 | 	/**
 42 | 	* True if the element's value is longer than the provided maximum length; false otherwise.
 43 | 	* @property tooLong
 44 | 	* @type {boolean}
 45 | 	*/
 46 | 	tooLong: false,
 47 | 	/**
 48 | 	* True if the element's value is lower than the provided minimum; false otherwise.
 49 | 	* @property rangeUnderflow
 50 | 	* @type {boolean}
 51 | 	*/
 52 | 	rangeUnderflow: false,
 53 | 	/**
 54 | 	* True if the element's value is higher than the provided maximum; false otherwise.
 55 | 	* @property rangeOverflow
 56 | 	* @type {boolean}
 57 | 	*/
 58 | 	rangeOverflow: false,
 59 | 	/**
 60 | 	* True if the element's value doesn't fit the rules given by the step attribute; false otherwise.
 61 | 	* @property stepMismatch
 62 | 	* @type {boolean}
 63 | 	*/
 64 | 	stepMismatch: false,
 65 | 	/**
 66 | 	* True if the element has a custom error; false otherwise.
 67 | 	* @property customError
 68 | 	* @type {boolean}
 69 | 	*/
 70 | 	customError: false,
 71 | 	/**
 72 | 	* True if the element's value has no validity problems; false otherwise.
 73 | 	* @property valid
 74 | 	* @type {boolean}
 75 | 	*/
 76 | 	valid: true,
 77 | 	/**
 78 | 	* The error message that would be shown to the user if the element was to be checked for validity.
 79 | 	* @property validationMessage
 80 | 	* @type {string}
 81 | 	*/
 82 | 	validationMessage: '',
 83 | 
 84 | 	/**
 85 | 	* Set an error on the state
 86 | 	* @method setError
 87 | 	* @param {string} errorType - type of error
 88 | 	*/
 89 | 	setError: function( errorType ) {
 90 | 		this[ errorType ] = true;
 91 | 		this.valid = false;
 92 | 	},
 93 | 
 94 | 	/**
 95 | 	* Set the custom error message
 96 | 	* @method setCustomValidity
 97 | 	* @param {string} customError - the error message
 98 | 	*/
 99 | 	setCustomValidity: function( customError ) {
100 | 		if( customError ) {
101 | 			this.valid = false;
102 | 			this.customError = true;
103 | 			this.validationMessage = customError;
104 | 		}
105 | 	}
106 | };
107 | 


--------------------------------------------------------------------------------
/site/stylesheets/shThemeDefault.scss:
--------------------------------------------------------------------------------
  1 | /**
  2 |  * SyntaxHighlighter
  3 |  * http://alexgorbatchev.com/SyntaxHighlighter
  4 |  *
  5 |  * SyntaxHighlighter is donationware. If you are using it, please donate.
  6 |  * http://alexgorbatchev.com/SyntaxHighlighter/donate.html
  7 |  *
  8 |  * @version
  9 |  * 3.0.83 (July 02 2010)
 10 |  * 
 11 |  * @copyright
 12 |  * Copyright (C) 2004-2010 Alex Gorbatchev.
 13 |  *
 14 |  * @license
 15 |  * Dual licensed under the MIT and GPL licenses.
 16 |  */
 17 | .syntaxhighlighter {
 18 |  /* background-color: white !important;*/
 19 | }
 20 | .syntaxhighlighter .line.alt1 {
 21 |   /*background-color: white !important;*/
 22 | }
 23 | .syntaxhighlighter .line.alt2 {
 24 |   /*background-color: white !important;*/
 25 | }
 26 | .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
 27 |   background-color: #e0e0e0 !important;
 28 | }
 29 | .syntaxhighlighter .line.highlighted.number {
 30 |   color: black !important;
 31 | }
 32 | .syntaxhighlighter table caption {
 33 |   color: black !important;
 34 | }
 35 | .syntaxhighlighter .gutter {
 36 |   color: #afafaf !important;
 37 | }
 38 | .syntaxhighlighter .gutter .line {
 39 |   border-right: 3px solid #6ce26c !important;
 40 | }
 41 | .syntaxhighlighter .gutter .line.highlighted {
 42 |   background-color: #6ce26c !important;
 43 |   color: white !important;
 44 | }
 45 | .syntaxhighlighter.printing .line .content {
 46 |   border: none !important;
 47 | }
 48 | .syntaxhighlighter.collapsed {
 49 |   overflow: visible !important;
 50 | }
 51 | .syntaxhighlighter.collapsed .toolbar {
 52 |   color: blue !important;
 53 |   background: white !important;
 54 |   border: 1px solid #6ce26c !important;
 55 | }
 56 | .syntaxhighlighter.collapsed .toolbar a {
 57 |   color: blue !important;
 58 | }
 59 | .syntaxhighlighter.collapsed .toolbar a:hover {
 60 |   color: red !important;
 61 | }
 62 | .syntaxhighlighter .toolbar {
 63 |   color: white !important;
 64 |   background: #6ce26c !important;
 65 |   border: none !important;
 66 | }
 67 | .syntaxhighlighter .toolbar a {
 68 |   color: white !important;
 69 | }
 70 | .syntaxhighlighter .toolbar a:hover {
 71 |   color: black !important;
 72 | }
 73 | .syntaxhighlighter .plain, .syntaxhighlighter .plain a {
 74 |   color: black !important;
 75 | }
 76 | .syntaxhighlighter .comments, .syntaxhighlighter .comments a {
 77 |   color: #008200 !important;
 78 | }
 79 | .syntaxhighlighter .string, .syntaxhighlighter .string a {
 80 |   color: blue !important;
 81 | }
 82 | .syntaxhighlighter .keyword {
 83 |   color: #006699 !important;
 84 | }
 85 | .syntaxhighlighter .preprocessor {
 86 |   color: gray !important;
 87 | }
 88 | .syntaxhighlighter .variable {
 89 |   color: #aa7700 !important;
 90 | }
 91 | .syntaxhighlighter .value {
 92 |   color: #009900 !important;
 93 | }
 94 | .syntaxhighlighter .functions {
 95 |   color: #ff1493 !important;
 96 | }
 97 | .syntaxhighlighter .constants {
 98 |   color: #0066cc !important;
 99 | }
100 | .syntaxhighlighter .script {
101 |   font-weight: bold !important;
102 |   color: #006699 !important;
103 |   background-color: none !important;
104 | }
105 | .syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
106 |   color: gray !important;
107 | }
108 | .syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
109 |   color: #ff1493 !important;
110 | }
111 | .syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
112 |   color: red !important;
113 | }
114 | 
115 | .syntaxhighlighter .keyword {
116 |   font-weight: bold !important;
117 | }
118 | 


--------------------------------------------------------------------------------
/src/core.js:
--------------------------------------------------------------------------------
  1 | /**
  2 | * Note, this class does not really exist!  It is a placeholder for extensions to system prototypes like Function, Array, Date.  
  3 | * @class SystemExtensions
  4 | */
  5 | 
  6 | /**
  7 |  * The main AFrame module.  All AFrame related items are under this.
  8 |  * @module AFrame
  9 | */
 10 | 
 11 | /**
 12 | * bind a function to a context - taken from https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind
 13 | * @methopd Function.prototype.bind
 14 | */
 15 | if ( !Function.prototype.bind ) {
 16 | 
 17 |   Function.prototype.bind = function( obj ) {
 18 |     var slice = [].slice,
 19 |         args = slice.call(arguments, 1), 
 20 |         self = this, 
 21 |         nop = function () {}, 
 22 |         bound = function () {
 23 |           return self.apply( this instanceof nop ? this : ( obj || {} ), 
 24 |                               args.concat( slice.call(arguments) ) );    
 25 |         };
 26 | 
 27 |     nop.prototype = self.prototype;
 28 | 
 29 |     bound.prototype = new nop();
 30 | 
 31 |     return bound;
 32 |   };
 33 | }
 34 |   
 35 | /**
 36 | * Run a function over each element in the array.  Comes from http://userscripts.org/topics/2304?page=1#posts-9660
 37 | * @method Array.prototype.forEach
 38 | * @param {function} callback - callback to call on each member of the array.  Function will be called with three parameters, item, index, and "this"
 39 | * @param {object} context (optional) - optional context to call function in
 40 | */
 41 | if (!Array.prototype.forEach)
 42 | {
 43 |   Array.prototype.forEach = function( callback, context )
 44 |   {
 45 |     var len = this.length;
 46 | 	if( typeof callback != "function" ) {
 47 |       throw new TypeError();
 48 | 	}
 49 | 
 50 | 	for (var i = 0, item; item = this[ i ]; ++i) {
 51 |       if ( i in this ) {
 52 | 		callback.call( context, item, i, this );
 53 |       }
 54 |     }
 55 |   };
 56 | }
 57 | 
 58 | /**
 59 | * if not included in the browsers implementation, add it - finds the index of an element in the array
 60 | * @method Array.prototype.indexOf
 61 | * @param {variant} element to search for
 62 | * @return {number} index if found, -1 otw.
 63 | */
 64 | if (!Array.prototype.indexOf) {
 65 |   Array.prototype.indexOf = function(elt /*, from*/)
 66 |   {
 67 |     var len = this.length >>> 0;
 68 | 
 69 |     var from = Number(arguments[1]) || 0;
 70 | 	from = from < 0 ? Math.ceil(from) : Math.floor(from);
 71 |     if (from < 0) {
 72 |       from += len;
 73 | 	}
 74 | 
 75 |     for (; from < len; from++) {
 76 | 		if (from in this && this[from] === elt) {
 77 | 			return from;
 78 | 		}
 79 |     }
 80 |     return -1;
 81 |   };
 82 | }
 83 | 
 84 | /**
 85 | * Convert a Date object to an ISO8601 formatted string
 86 | * @method Date.prototype.toISOString
 87 | * @return {string} ISO8601 formatted date
 88 | */
 89 | if(!Date.prototype.toISOString) {
 90 | 	Date.prototype.toISOString = function() {
 91 | 		var pad_two = function(n) {
 92 | 			return (n < 10 ? '0' : '') + n;
 93 | 		};
 94 | 		var pad_three = function(n) {
 95 | 			return (n < 100 ? '0' : '') + (n < 10 ? '0' : '') + n;
 96 | 		};
 97 | 		return [
 98 | 			this.getUTCFullYear(),
 99 | 			'-',
100 | 			pad_two(this.getUTCMonth() + 1),
101 | 			'-',
102 | 			pad_two(this.getUTCDate()),
103 | 			'T',
104 | 			pad_two(this.getUTCHours()),
105 | 			':',
106 | 			pad_two(this.getUTCMinutes()),
107 | 			':',
108 | 			pad_two(this.getUTCSeconds()),
109 | 			'.',
110 | 			pad_three(this.getUTCMilliseconds()),
111 | 			'Z'
112 | 		].join('');
113 | 	};
114 | }
115 | 


--------------------------------------------------------------------------------
/site/demos/index.html:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     
 5 |     AFrameJS - Javascript MVC Library - Demos Page
 6 | 
 7 |     
10 | 
11 | 
12 |     
13 |     
14 |     
15 |     
16 | 
17 |     
18 | 
19 | 
20 | 
21 |     
22 |         Fork me on GitHub
23 |     
24 | 
25 | 	
26 |
27 |

AFrameJS

- Javascript MVC Library

28 | 29 | 40 | 41 |
42 | 43 | 44 |
45 |
    46 |
  • Simple "Add Friend" Demo - A super simple case of using Collections, Models, and Views
  • 47 |
  • MobileNotes Demo - A more full featured app demonstrating Collections, Models, Views, Forms, DB Adapters and more.
  • 48 |
49 |
50 | 51 |
52 | 53 |

54 | Copyright © 2011 Shane Tomlinson (set117 at yahoo period com). All rights reserved. 55 |

56 | 57 |

58 | http://www.shanetomlinson.com 59 |

60 | 61 |
62 |
63 | 64 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /tests/test_fieldPlaceholderDecorator.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | var input = document.createElement( 'input' ); 3 | var html5Support = ( 'placeholder' in input ); 4 | 5 | testsToRun.push( { 6 | 7 | 8 | name: "TestCase AFrame.FieldPlaceholderDecorator", 9 | 10 | testPlaceholderTextHTML5Support: function() { 11 | if( html5Support ) { 12 | var target = jQuery( '#noValueFormElement' ); 13 | target.val( '' ); 14 | 15 | var textField = AFrame.Field.create( { 16 | target: target 17 | } ); 18 | 19 | Assert.areSame( '', textField.get(), 'correct get' ); 20 | Assert.areSame( '', textField.getDisplayed(), 'help text not displayed for browsers supporting HTML5 spec' ); 21 | } 22 | }, 23 | 24 | testPlaceholderTextNoHTML5Support: function() { 25 | if( !html5Support ) { 26 | var target = jQuery( '#noValueFormElement' ); 27 | target.val( '' ); 28 | 29 | var textField = AFrame.Field.create( { 30 | target: '#noValueFormElement' 31 | } ); 32 | 33 | //Assert.isUndefined( textField.get(), 'correct get' ); 34 | Assert.areSame( 'No Value Text', target.val(), 'help text displayed' ); 35 | Assert.areSame( '', textField.getDisplayed(), 'getDisplayed returns empty string when help text displayed' ); 36 | Assert.isTrue( target.hasClass( 'empty' ), 'empty class name added to help text' ); 37 | 38 | AFrame.DOM.fireEvent( '#noValueFormElement', 'focus' ); 39 | Assert.areSame( '', target.val(), 'when a focus happens, help text is cleared' ); 40 | 41 | AFrame.DOM.fireEvent( '#noValueFormElement', 'blur' ); 42 | Assert.areSame( 'No Value Text', target.val(), 'help text displayed when setting display to empty' ); 43 | Assert.areSame( '', textField.getDisplayed(), 'getDisplayed returns empty when help text displayed' ); 44 | Assert.isTrue( target.hasClass( 'empty' ), 'empty class name added to help text' ); 45 | textField.save(); 46 | //Assert.isUndefined( textField.get(), 'help text is not saved for get' ); 47 | 48 | textField.display( 'New Value' ); 49 | Assert.isFalse( target.hasClass( 'empty' ), 'empty class name removed with normal text' ); 50 | 51 | AFrame.DOM.fireEvent( '#noValueFormElement', 'focus' ); 52 | Assert.areSame( 'New Value', textField.getDisplayed(), 'when a focus happens, updated value is not cleared' ); 53 | 54 | AFrame.DOM.fireEvent( '#noValueFormElement', 'blur' ); 55 | Assert.areSame( 'New Value', textField.getDisplayed(), 'when blur happens, updated text is not reverted to help text' ); 56 | 57 | textField.set( '' ); 58 | Assert.areSame( 'No Value Text', target.val(), 'help text displayed when setting display to empty' ); 59 | Assert.areSame( '', textField.get(), 'setting help text to empty does now allow get to be help text' ); 60 | Assert.areSame( '', textField.getDisplayed(), 'getDisplayed returns empty string with placeholder' ); 61 | Assert.isTrue( target.hasClass( 'empty' ), 'empty class name added to help text' ); 62 | Assert.areSame( '', textField.get(), 'help text is not used for "get" after a "set(\'\')"' ); 63 | 64 | 65 | } 66 | } 67 | 68 | } ); 69 | })(); 70 | -------------------------------------------------------------------------------- /src/listPluginBindToCollection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A plugin that binds a list to a collection. When the collection is updated, the list 3 | * is automatically updated to reflect the change. List updates occure when 4 | * the collection trigger the onInsert or onRemove events. 5 | * This plugin adds getIndex to the plugged list. 6 | * 7 | * 8 | * 10 | * 11 | * --------- 12 | * // A List with the same results as the previous example is 13 | * // the expected result 14 | * 15 | * // First we need to set up the collection 16 | * var collection = AFrame.CollectionArray.create(); 17 | * 18 | * 19 | * var renderItem = function( index, data ) { 20 | * var listItem = AFrame.DOM.createElement( 'li', data.name + ', ' + data.employer ); 21 | * return listItem; 22 | * }; 23 | * 24 | * // Sets up our list with the ListPluginBindToCollection. Notice the 25 | * // ListPluginBindToCollection has a collection config parameter. 26 | * var list = AFrame.List.create( { 27 | * target: '#clientList', 28 | * renderItem: renderItem, 29 | * plugins: [ 30 | * [ AFrame.ListPluginBindToCollection, { 31 | * collection: collection 32 | * } ] 33 | * ] 34 | * } ); 35 | * 36 | * collection.insert( { 37 | * name: 'Shane Tomlinson', 38 | * employer: 'AFrame Foundary' 39 | * } ); 40 | * 41 | * collection.insert( { 42 | * name: 'Joe Smith', 43 | * employer: 'The Coffee Shop' 44 | * }, 0 ); 45 | * 46 | * // The same list as in the example above is shown 47 | * --------- 48 | * 49 | * 53 | * 54 | * ---------- 55 | * 56 | * collection.remove( 0 ); 57 | * 58 | * // Joe Smith has been removed 59 | * 60 | * --------- 61 | * 62 | * 65 | * 66 | * 67 | * @class AFrame.ListPluginBindToCollection 68 | * @extends AFrame.Plugin 69 | * @constructor 70 | */ 71 | /** 72 | * The collection to bind to 73 | * @config collection 74 | * @type {Collection} 75 | */ 76 | AFrame.ListPluginBindToCollection = ( function() { 77 | "use strict"; 78 | 79 | var Plugin = AFrame.Plugin.extend( { 80 | importconfig: [ 'collection' ], 81 | events: { 82 | 'onInsert collection': 'onInsert', 83 | 'onRemove collection': 'onRemove' 84 | }, 85 | 86 | init: function( config ) { 87 | this.cids = []; 88 | 89 | Plugin.sc.init.call( this, config ); 90 | 91 | this.getPlugged().getIndex = this.getIndex.bind( this ); 92 | }, 93 | 94 | onInsert: function( event ) { 95 | var index = this.getPlugged().insert( event.item, event.index || -1 ); 96 | 97 | this.cids.splice( index, 0, event.cid ); 98 | }, 99 | 100 | onRemove: function( event ) { 101 | var index = this.cids.indexOf( event.cid ); 102 | 103 | this.getPlugged().remove( index ); 104 | 105 | this.cids.splice( index, 1 ); 106 | }, 107 | 108 | /** 109 | * Given an index or cid, get the index. 110 | * @param {number || id} indexCID - either the index or the cid of an item 111 | * @return {number} index of item 112 | */ 113 | getIndex: function( indexCID ) { 114 | var index = indexCID; 115 | 116 | if( 'string' == typeof( indexCID ) ) { 117 | index = this.cids.indexOf( indexCID ); 118 | } 119 | 120 | return index; 121 | } 122 | } ); 123 | 124 | return Plugin; 125 | }() ); 126 | -------------------------------------------------------------------------------- /tests/test_event.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.Event", 4 | 5 | setUp: function() { 6 | this.event = AFrame.Event.create( 'event' ); 7 | }, 8 | 9 | tearDown: function () { 10 | this.event = null; 11 | }, 12 | 13 | testEvent: function() { 14 | var event = this.event; 15 | 16 | Assert.areEqual( 'event', event.type, 'event.type set correctly to event' ); 17 | Assert.isTrue( event.timestamp instanceof Date, 'event.timestamp is a date' ); 18 | }, 19 | 20 | testPreventDefault: function() { 21 | var event = this.event; 22 | 23 | Assert.isFalse( event.isDefaultPrevented(), 'default has not yet been prevented' ); 24 | 25 | event.preventDefault(); 26 | Assert.isTrue( event.isDefaultPrevented(), 'default has been prevented' ); 27 | }, 28 | 29 | testCreateEventWithObject: function() { 30 | var event = AFrame.Event.create( { 31 | type: 'event', 32 | target: this, 33 | extraField: 'extraValue' 34 | } ); 35 | 36 | Assert.areEqual( 'event', event.type, 'type correctly set' ); 37 | Assert.areEqual( this, event.target, 'target correctly set' ); 38 | Assert.areEqual( 'extraValue', event.extraField, 'extraField correctly set' ); 39 | Assert.isTrue( event.timestamp instanceof Date, 'timestamp set' ); 40 | }, 41 | 42 | testEventNoType: function() { 43 | var error; 44 | 45 | try { 46 | var event = AFrame.Event.create( { 47 | target: this, 48 | extraField: 'extraValue' 49 | } ); 50 | } catch ( e ) { 51 | error = e; 52 | } 53 | 54 | Assert.areEqual( 'Event type undefined', error, 'no type error was thrown for createEvent with object' ); 55 | 56 | error = undefined; 57 | 58 | try { 59 | var event = AFrame.Event.create(); 60 | } catch ( e ) { 61 | error = e; 62 | } 63 | 64 | Assert.areEqual( 'Event type undefined', error, 'no type error was thrown for createEvent with no arguments' ); 65 | 66 | error = undefined; 67 | 68 | try { 69 | var event = AFrame.Event.create( '' ); 70 | } catch ( e ) { 71 | error = e; 72 | } 73 | 74 | Assert.areEqual( 'Event type undefined', error, 'no type error was thrown for createEvent with empty string' ); 75 | }, 76 | 77 | testProxyEventNoTarget: function() { 78 | var proxy = {}; 79 | this.event.proxyEvent( proxy ); 80 | 81 | Assert.areEqual( proxy, this.event.target, 'event successfully proxied' ); 82 | Assert.isUndefined( this.event.originalTarget, 'originalTarget undefined' ); 83 | 84 | var secondProxy = {}; 85 | this.event.proxyEvent( secondProxy ); 86 | Assert.areEqual( secondProxy, this.event.target, 'event successfully proxied to second proxy' ); 87 | Assert.isUndefined( this.event.originalTarget, 'originalTarget undefined' ); 88 | }, 89 | 90 | testProxyEventTarget: function() { 91 | var event = AFrame.Event.create( { 92 | target: this, 93 | type: 'event' 94 | } ); 95 | 96 | var proxy = {}; 97 | event.proxyEvent( proxy ); 98 | Assert.areEqual( proxy, event.target, 'event successfully proxied' ); 99 | Assert.areEqual( this, event.originalTarget, 'originalTarget set to this' ); 100 | 101 | var secondProxy = {}; 102 | event.proxyEvent( secondProxy ); 103 | Assert.areEqual( secondProxy, event.target, 'event successfully proxied to second proxy' ); 104 | Assert.areEqual( this, event.originalTarget, 'originalTarget still set to this' ); 105 | } 106 | 107 | 108 | } ); 109 | -------------------------------------------------------------------------------- /src/event.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A basic event, very loosly modeled after [W3C DOM Level 2 Events](http://www.w3.org/TR/DOM-Level-2-Events/events.html) 3 | * @class AFrame.Event 4 | * @constructor 5 | */ 6 | /** 7 | * The event type 8 | * @config type 9 | * @type {string} 10 | */ 11 | /** 12 | * When the event was created. 13 | * @property timestamp 14 | * @type {Date} 15 | */ 16 | /** 17 | * Type of event. 18 | * @property type 19 | * @type {string} 20 | */ 21 | /** 22 | * event target, not always set 23 | * @property target 24 | * @type {object} 25 | */ 26 | /** 27 | * original event target, before any proxying, not always set 28 | * @property originalTarget 29 | * @type {object} 30 | */ 31 | AFrame.Event = (function() { 32 | "use strict"; 33 | 34 | var Event = AFrame.Class( { 35 | /** 36 | * initialize the event. All items in configuration will be added to event. If timestamp 37 | * is specified, it will be ignored. type must be specified. 38 | * @param {object} config 39 | * @param {string} config.type - type of event 40 | */ 41 | init: function( config ) { 42 | for( var key in config ) { 43 | this[ key ] = config[ key ]; 44 | } 45 | 46 | if( !this.type ) { 47 | throw 'Event type undefined'; 48 | } 49 | 50 | if( this.target ) { 51 | this.setOriginalTarget = true; 52 | } 53 | 54 | this.timestamp = new Date(); 55 | }, 56 | 57 | /** 58 | * Check if preventDefault has been called. 59 | * 60 | * // Check if preventDefault has been called 61 | * var isPrevented = event.isDefaultPrevented(); 62 | * 63 | * @method isDefaultPrevented 64 | * @return {booelan} true if preventDefault has been called, false otw. 65 | */ 66 | isDefaultPrevented: function() { 67 | return !!this.defaultPrevented; 68 | }, 69 | 70 | /** 71 | * Cancel the default action of the event. Note, this does nothing on its own, 72 | * any object that passes an Event object must check isDefaultPrevented to see 73 | * whether an action should be cancelled. 74 | * 75 | * // Prevent the default action 76 | * event.preventDefault(); 77 | * 78 | * @method preventDefault 79 | */ 80 | preventDefault: function() { 81 | this.defaultPrevented = true; 82 | }, 83 | 84 | /** 85 | * Proxy an event. If this is the first time the event is proxied, causes 86 | * originalTarget to be set to the original target, and updates target to 87 | * point to the proxy. 88 | * 89 | * event.proxyEvent( proxy ); 90 | * 91 | * @method proxyEvent 92 | * @param {object} proxy - object proxying event 93 | */ 94 | proxyEvent: function( proxy ) { 95 | if( this.setOriginalTarget ) { 96 | this.originalTarget = this.target; 97 | this.setOriginalTarget = false; 98 | } 99 | 100 | this.target = proxy; 101 | } 102 | } ); 103 | 104 | /** 105 | * A factory method to create an event. 106 | * 107 | * // returns an event with event.type == 'eventType' 108 | * var event = AFrame.Event.create( 'eventType' ); 109 | * 110 | * // returns an event with event.type == 'eventType', extraField == 'extraValue' 111 | * var event = AFrame.Event.create( { 112 | * type: 'eventType', 113 | * extraField: 'extraValue' 114 | * } ); 115 | * 116 | * @method AFrame.Event.create 117 | * @param {object||string} config - if an object, object is used as Event config, 118 | * if a string, the string signifies the type of event 119 | * @return {AFrame.Event} event with type 120 | */ 121 | var origCreate = Event.create; 122 | 123 | Event.create = function( config ) { 124 | if( AFrame.string( config ) ) { 125 | config = { type: config }; 126 | } 127 | return origCreate( config ); 128 | }; 129 | 130 | return Event; 131 | })(); 132 | -------------------------------------------------------------------------------- /tests/test_listPluginFormRow.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.ListPluginFormRow", 4 | 5 | setUp: function() { 6 | this.list = AFrame.List.create( { 7 | target: '.list', 8 | renderItem: function( data, index ) { 9 | this.insertedIndex = index; 10 | this.insertedData = data; 11 | var rowElement = AFrame.DOM.createElement( 'li', '' ); 12 | AFrame.DOM.setAttr( rowElement, 'id', ( data.cid ? data.cid : 'inserted' + index ) ); 13 | return rowElement; 14 | }.bind( this ), 15 | 16 | plugins: [ [ AFrame.ListPluginFormRow, { 17 | formFactory: function( rowElement, data ) { 18 | this.form = { 19 | reset: function() { 20 | this.resetCalled = true; 21 | }.bind( this ), 22 | 23 | validate: function() { 24 | this.validateCalled = true; 25 | return true; 26 | }.bind( this ), 27 | 28 | clear: function() { 29 | this.clearCalled = true; 30 | }.bind( this ), 31 | 32 | save: function() { 33 | this.saveCalled = true; 34 | }.bind( this ), 35 | 36 | resetTest: function() { 37 | this.resetCalled = false; 38 | this.validateCalled = false; 39 | this.clearCalled = false; 40 | this.saveCalled = false; 41 | }.bind( this ), 42 | 43 | teardown: function() {} 44 | }; 45 | 46 | this.form.data = data; 47 | 48 | return this.form; 49 | }.bind( this ) 50 | } 51 | ] ] 52 | } ); 53 | }, 54 | 55 | tearDown: function() { 56 | this.list.clear(); 57 | this.list.teardown(); 58 | 59 | AFrame.remove( this, 'collection' ); 60 | AFrame.remove( this, 'list' ); 61 | }, 62 | 63 | testFunctionsAdded: function() { 64 | Assert.isFunction( this.list.reset, 'Reset added' ); 65 | Assert.isFunction( this.list.save, 'Save added' ); 66 | Assert.isFunction( this.list.validate, 'Validate added' ); 67 | Assert.isFunction( this.list.clear, 'Clear added' ); 68 | }, 69 | 70 | testFormFormFactoryDataCorrect: function() { 71 | var data = { 72 | cid: 'cid0' 73 | }; 74 | this.list.insert( data ); 75 | Assert.areSame( data, this.form.data, 'data is good' ); 76 | }, 77 | 78 | testReset: function() { 79 | this.list.insert( { 80 | cid: 'cid0' 81 | }, 0 ); 82 | 83 | this.form.resetTest(); 84 | this.list.reset(); 85 | 86 | Assert.isTrue( this.resetCalled, 'Field\'s reset has been called' ); 87 | }, 88 | 89 | testSave: function() { 90 | this.list.insert( { 91 | cid: 'cid0' 92 | }, 0 ); 93 | 94 | this.form.resetTest(); 95 | this.list.save(); 96 | 97 | Assert.isTrue( this.saveCalled, 'Field\'s save has been called' ); 98 | }, 99 | 100 | testValidate: function() { 101 | this.list.insert( { 102 | cid: 'cid0' 103 | }, 0); 104 | 105 | this.form.resetTest(); 106 | this.list.validate(); 107 | 108 | Assert.isTrue( this.validateCalled, 'Field\'s validate has been called' ); 109 | 110 | this.form.resetTest(); 111 | 112 | this.list.validate( 0 ); 113 | Assert.isTrue( this.validateCalled, 'Field\'s validate has been called' ); 114 | 115 | this.form.resetTest(); 116 | 117 | this.list.validate( 1 ); 118 | Assert.isFalse( this.validateCalled, 'Field\'s validate was not called' ); 119 | 120 | this.form.resetTest(); 121 | }, 122 | 123 | testClear: function() { 124 | this.list.insert( { 125 | cid: 'cid0' 126 | }, 0 ); 127 | 128 | this.form.resetTest(); 129 | this.list.clear(); 130 | 131 | Assert.isTrue( this.clearCalled, 'Field\'s clear has been called' ); 132 | }, 133 | 134 | testDefaultFormFactory: function() { 135 | var list = AFrame.List.create( { 136 | target: '.list', 137 | plugins: [ AFrame.ListPluginFormRow ] 138 | } ); 139 | 140 | // Just make sure we don't blow our tops. 141 | list.insert( { 142 | name: 'AFrame' 143 | } ); 144 | 145 | var form = list.getForm( 0 ); 146 | Assert.isTrue( form instanceof AFrame.Form, 'default form returned, is of type form' ); 147 | } 148 | 149 | } ); 150 | -------------------------------------------------------------------------------- /tools/yuidoc/TAGS: -------------------------------------------------------------------------------- 1 | 2 | General Notes: 3 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 4 | 5 | --General Notes: 6 | 7 | * All comment blocks should have one, and only one, of the following tags: 8 | module, class, property, method. If one is not supplied, the parser will 9 | complain and the block will likely be skipped. 10 | 11 | * The four block types require a description. This description should appear 12 | as the first thing in your comment block. 13 | 14 | /** 15 | * My method description. Like other pieces of your comment blocks, 16 | * this can span multiple lines. 17 | * @method methodName 18 | */ 19 | 20 | This might work too, but I have not tried it.. I like the other convention: 21 | 22 | /** 23 | * @method methodName 24 | * @description My method description. Like other pieces of your 25 | * comment blocks, this can span multiple lines. 26 | */ 27 | 28 | * It will warn about any tag that does not contain a description, with the 29 | exception of the following: constructor, public, private, static 30 | 31 | 32 | Supported Tags: 33 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 34 | 35 | @module modulename 36 | Include one these blocks in one of your files for your util/widget. The 37 | description will appear on the splash page. 38 | 39 | NOTE: At least one @module is required. Put one of these near the top 40 | of your source and use it to describe your component. Do not combine 41 | @module with @class. 42 | 43 | @namespace YAHOO.namespace 44 | While it is optional to provide a namespace, it is recommended. This lets you 45 | describe your class just with the name: YAHOO.util.Event -> Event. It only 46 | needs to be included one time as long as this is the first file that is parsed. 47 | Probably safer to put it in each file. 48 | 49 | @class ClassName 50 | 51 | @extends YAHOO.namespace.ClassName 52 | 53 | @property propertyName 54 | 55 | @config configName 56 | similar to @property, but separates config items from normal properties 57 | 58 | @attribute configName 59 | similar to @config, but also auto-generates the [event]Change and 60 | the before[Event]Change events 61 | 62 | @method methodName 63 | 64 | @event 65 | similar to @method, but no @return, and the @params define the signature 66 | the listeners are executed with. 67 | 68 | @constructor 69 | Only put this if the class can be instantiated 70 | 71 | @static 72 | For classes, methods, properties, etc ... 73 | Probably should have either @constructor or @static in the @class block 74 | 75 | @final 76 | for constants (properties and read-only configs) 77 | 78 | @param {type} name description -or- 79 | @param name {type} description 80 | Supported in method blocks or class/constructor blocks. 81 | 82 | @for ClassName 83 | Used to define an inner class: 84 | /** 85 | * An inner class 86 | * @class foo 87 | * @for OuterClass 88 | */ 89 | After the class is done, you need to inform the parser to start working on 90 | the outer class again: 91 | /** 92 | * Another method for the outer class 93 | * @method bar 94 | * @for OuterClass 95 | */ 96 | 97 | @return {type} description 98 | for methods 99 | 100 | @type type 101 | for properties and configs 102 | 103 | @see 104 | This is barely supported at this point 105 | 106 | @deprecated explaination 107 | The explaination does not need to be provided, but the parser will warn if 108 | you don't. Usually you'll want to say what to use instead 109 | 110 | @public 111 | Allowed to exist as a singular tag, but does nothing. Everthing is assumed 112 | public unless marked private 113 | 114 | @private 115 | Use to mark that the method/property should not be accessed by implementers 116 | (even if it is accessible to them). By default, privates are not present 117 | in the api docs. 118 | 119 | @protected 120 | Use to indicate the method/property should not be accessed by implementers 121 | unless they are subclassing. 122 | 123 | @requires module1, module2 124 | Supported in the @module declaration. The comma separated list of module 125 | short names will eventually be matched against a lookup table when 126 | cross-linking is supported 127 | 128 | @default 129 | The default value of a property or config 130 | 131 | @uses YAHOO.namespace.ClassName [method1, method2] 132 | For classes that use YAHOO.augment 133 | The optional method/properties are not supported yet 134 | 135 | 136 | -------------------------------------------------------------------------------- /tools/yuidoc/dana-theme/css/960fluid.min.css: -------------------------------------------------------------------------------- 1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;vertical-align:baseline;background:transparent;}body{line-height:1;}ol,ul{list-style:none;}blockquote,q{quotes:none;}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}:focus{outline:0;}ins{text-decoration:none;}del{text-decoration:line-through;}table{border-collapse:collapse;border-spacing:0;}body{font:13px/1.5 Helvetica,Arial,'Liberation Sans',FreeSans,sans-serif;}a:focus{outline:1px dotted invert;}hr{border-color:#ccc;border-style:solid;border-width:1px 0 0;clear:both;height:0;}h1{font-size:25px;}h2{font-size:23px;}h3{font-size:21px;}h4{font-size:19px;}h5{font-size:17px;}h6{font-size:15px;}ol{list-style:decimal;}ul{list-style:square;}li{margin-left:30px;}p,dl,hr,h1,h2,h3,h4,h5,h6,ol,ul,pre,table,address,fieldset{margin-bottom:20px;}.container_12,.container_16{width:92%;margin-left:4%;margin-right:4%;}.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12,.grid_13,.grid_14,.grid_15,.grid_16{display:inline;float:left;margin-left:1%;margin-right:1%;}.container_12 .grid_3,.container_16 .grid_4{width:23%;}.container_12 .grid_6,.container_16 .grid_8{width:48%;}.container_12 .grid_9,.container_16 .grid_12{width:73%;}.container_12 .grid_12,.container_16 .grid_16{width:98%;}.alpha{margin-left:0;}.omega{margin-right:0;}.container_12 .grid_1{width:6.333%;}.container_12 .grid_2{width:14.666%;}.container_12 .grid_4{width:31.333%;}.container_12 .grid_5{width:39.666%;}.container_12 .grid_7{width:56.333%;}.container_12 .grid_8{width:64.666%;}.container_12 .grid_10{width:81.333%;}.container_12 .grid_11{width:89.666%;}.container_16 .grid_1{width:4.25%;}.container_16 .grid_2{width:10.5%;}.container_16 .grid_3{width:16.75%;}.container_16 .grid_5{width:29.25%;}.container_16 .grid_6{width:35.5%;}.container_16 .grid_7{width:41.75%;}.container_16 .grid_9{width:54.25%;}.container_16 .grid_10{width:60.5%;}.container_16 .grid_11{width:66.75%;}.container_16 .grid_13{width:79.25%;}.container_16 .grid_14{width:85.5%;}.container_16 .grid_15{width:91.75%;}.container_12 .prefix_3,.container_16 .prefix_4{padding-left:25%;}.container_12 .prefix_6,.container_16 .prefix_8{padding-left:50%;}.container_12 .prefix_9,.container_16 .prefix_12{padding-left:75%;}.container_12 .prefix_1{padding-left:8.333%;}.container_12 .prefix_2{padding-left:16.666%;}.container_12 .prefix_4{padding-left:33.333%;}.container_12 .prefix_5{padding-left:41.666%;}.container_12 .prefix_7{padding-left:58.333%;}.container_12 .prefix_8{padding-left:66.666%;}.container_12 .prefix_10{padding-left:83.333%;}.container_12 .prefix_11{padding-left:91.666%;}.container_16 .prefix_1{padding-left:6.25%;}.container_16 .prefix_2{padding-left:12.5%;}.container_16 .prefix_3{padding-left:18.75%;}.container_16 .prefix_5{padding-left:31.25%;}.container_16 .prefix_6{padding-left:37.5%;}.container_16 .prefix_7{padding-left:43.75%;}.container_16 .prefix_9{padding-left:56.25%;}.container_16 .prefix_10{padding-left:62.5%;}.container_16 .prefix_11{padding-left:68.75%;}.container_16 .prefix_13{padding-left:81.25%;}.container_16 .prefix_14{padding-left:87.5%;}.container_16 .prefix_15{padding-left:93.75%;}.container_12 .suffix_3,.container_16 .suffix_4{padding-right:25%;}.container_12 .suffix_6,.container_16 .suffix_8{padding-right:50%;}.container_12 .suffix_9,.container_16 .suffix_12{padding-right:75%;}.container_12 .suffix_1{padding-right:8.333%;}.container_12 .suffix_2{padding-right:16.666%;}.container_12 .suffix_4{padding-right:33.333%;}.container_12 .suffix_5{padding-right:41.666%;}.container_12 .suffix_7{padding-right:58.333%;}.container_12 .suffix_8{padding-right:66.666%;}.container_12 .suffix_10{padding-right:83.333%;}.container_12 .suffix_11{padding-right:91.666%;}.container_16 .suffix_1{padding-right:6.25%;}.container_16 .suffix_2{padding-right:16.5%;}.container_16 .suffix_3{padding-right:18.75%;}.container_16 .suffix_5{padding-right:31.25%;}.container_16 .suffix_6{padding-right:37.5%;}.container_16 .suffix_7{padding-right:43.75%;}.container_16 .suffix_9{padding-right:56.25%;}.container_16 .suffix_10{padding-right:62.5%;}.container_16 .suffix_11{padding-right:68.75%;}.container_16 .suffix_13{padding-right:81.25%;}.container_16 .suffix_14{padding-right:87.5%;}.container_16 .suffix_15{padding-right:93.75%;}html body * span.clear,html body * div.clear,html body * li.clear,html body * dd.clear{background:none;border:0;clear:both;display:block;float:none;font-size:0;list-style:none;margin:0;padding:0;overflow:hidden;visibility:hidden;width:0;height:0;}.clearfix:after{clear:both;content:'.';display:block;visibility:hidden;height:0;}.clearfix{display:inline-block;}* html .clearfix{height:1%;}.clearfix{display:block;} -------------------------------------------------------------------------------- /tests/test_listPluginBindToCollection.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.ListPluginBindToCollection with CollectionArray", 4 | 5 | setUp: function() { 6 | this.store = AFrame.CollectionArray.create(); 7 | 8 | this.list = AFrame.List.create( { 9 | target: '.list', 10 | renderItem: function( data, index ) { 11 | this.insertedIndex = index; 12 | this.insertedData = data; 13 | 14 | var rowElement = AFrame.DOM.createElement( 'li', 'Inserted Element' ); 15 | AFrame.DOM.setAttr( rowElement, 'id', ( data.cid ? data.cid : 'inserted' + index ) ); 16 | return rowElement; 17 | }.bind( this ), 18 | plugins: [ 19 | [ AFrame.ListPluginBindToCollection, { 20 | collection: this.store 21 | } 22 | ] 23 | ] 24 | } ); 25 | }, 26 | 27 | tearDown: function() { 28 | this.store.teardown(); 29 | this.list.clear(); 30 | this.list.teardown(); 31 | 32 | AFrame.remove( this, 'store' ); 33 | AFrame.remove( this, 'list' ); 34 | }, 35 | 36 | testInsert: function() { 37 | this.store.insert( { cid: 'inserted0' } ); 38 | this.store.insert( { cid: 'inserted1' } ); 39 | 40 | Assert.areEqual( 1, jQuery( 'ul > li#inserted0' ).length, 'list element0 inserted' ); 41 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 inserted' ); 42 | }, 43 | 44 | testRemove: function() { 45 | this.store.insert( { cid: 'inserted0' } ); 46 | this.store.insert( { cid: 'inserted1' } ); 47 | 48 | Assert.areEqual( 1, jQuery( 'ul > li#inserted0' ).length, 'list element0 inserted' ); 49 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 inserted' ); 50 | 51 | this.store.remove( 0 ); 52 | Assert.areEqual( 0, jQuery( 'ul > li#inserted0' ).length, 'list element0 removed' ); 53 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 not removed' ); 54 | 55 | this.store.remove( 'inserted1' ); 56 | Assert.areEqual( 0, jQuery( 'ul > li#inserted1' ).length, 'list element1 removed' ); 57 | }, 58 | 59 | testGetIndex: function() { 60 | this.store.insert( { cid: 'inserted0' } ); 61 | this.store.insert( { cid: 'inserted1' } ); 62 | 63 | var index = this.list.getIndex( 'inserted1' ); 64 | Assert.areEqual( 1, index, 'correct index' ); 65 | 66 | var index = this.list.getIndex( 0 ); 67 | Assert.areEqual( 0, index, 'correct index' ); 68 | } 69 | } ); 70 | 71 | testsToRun.push( { 72 | 73 | name: "TestCase AFrame.ListPluginBindToCollection with CollectionHash", 74 | 75 | setUp: function() { 76 | this.store = AFrame.CollectionHash.create(); 77 | 78 | this.list = AFrame.List.create( { 79 | target: '.list', 80 | renderItem: function( data, index ) { 81 | this.insertedIndex = index; 82 | this.insertedData = data; 83 | var rowElement = AFrame.DOM.createElement( 'li', 'Inserted Element' ); 84 | AFrame.DOM.setAttr( rowElement, 'id', ( data.cid ? data.cid : 'inserted' + index ) ); 85 | return rowElement; 86 | }.bind( this ), 87 | plugins: [ [ AFrame.ListPluginBindToCollection, { 88 | collection: this.store 89 | } 90 | ] ] 91 | } ); 92 | }, 93 | 94 | tearDown: function() { 95 | this.store.teardown(); 96 | this.list.clear(); 97 | this.list.teardown(); 98 | 99 | AFrame.remove( this, 'store' ); 100 | AFrame.remove( this, 'list' ); 101 | }, 102 | 103 | testInsert: function() { 104 | this.store.insert( { cid: 'inserted0' } ); 105 | this.store.insert( { cid: 'inserted1' } ); 106 | 107 | Assert.areEqual( 1, jQuery( 'ul > li#inserted0' ).length, 'list element0 inserted' ); 108 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 inserted' ); 109 | }, 110 | 111 | testRemove: function() { 112 | this.store.insert( { cid: 'inserted0' } ); 113 | this.store.insert( { cid: 'inserted1' } ); 114 | 115 | Assert.areEqual( 1, jQuery( 'ul > li#inserted0' ).length, 'list element0 inserted' ); 116 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 inserted' ); 117 | 118 | this.store.remove( 'inserted0' ); 119 | Assert.areEqual( 0, jQuery( 'ul > li#inserted0' ).length, 'list element0 removed' ); 120 | Assert.areEqual( 1, jQuery( 'ul > li#inserted1' ).length, 'list element1 not removed' ); 121 | 122 | this.store.remove( 'inserted1' ); 123 | Assert.areEqual( 0, jQuery( 'ul > li#inserted1' ).length, 'list element1 removed' ); 124 | }, 125 | 126 | testGetIndex: function() { 127 | this.store.insert( { cid: 'inserted0' } ); 128 | this.store.insert( { cid: 'inserted1' } ); 129 | 130 | var index = this.list.getIndex( 'inserted1' ); 131 | Assert.areEqual( 1, index, 'correct index' ); 132 | 133 | var index = this.list.getIndex( 0 ); 134 | Assert.areEqual( 0, index, 'correct index' ); 135 | } 136 | } ); 137 | -------------------------------------------------------------------------------- /tests/test_collectionArray.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.CollectionArray", 4 | 5 | setUp: function() { 6 | this.array = AFrame.CollectionArray.create(); 7 | 8 | this.item = { 9 | fieldName: 'fieldValue' 10 | }; 11 | 12 | }, 13 | 14 | tearDown : function () { 15 | this.array.teardown(); 16 | this.array = null; 17 | delete this.array; 18 | 19 | this.item = null; 20 | delete this.item; 21 | }, 22 | 23 | testInsertGet: function() { 24 | 25 | var index = 0; 26 | var id = this.array.insert( this.item, index ); 27 | 28 | var retrievedByIndexItem = this.array.get( index ); 29 | Assert.areSame( this.item, retrievedByIndexItem, 'insert then retrieval by index works' ); 30 | 31 | var retrievedByIdItem = this.array.get( id ); 32 | Assert.areSame( this.item, retrievedByIdItem, 'insert then retrieval by id works' ); 33 | }, 34 | 35 | testInsertMetaSetCorrectly: function() { 36 | var insertData; 37 | this.array.bindEvent( 'onInsert', function( data ) { 38 | insertData = data; 39 | } ); 40 | 41 | var index = 0; 42 | this.array.insert( this.item, index ); 43 | 44 | Assert.areEqual( index, insertData.index, 'index set in the meta data' ); 45 | }, 46 | 47 | testOnInsertCanCallForEach: function() { 48 | var maxIndex = -1, array = this.array; 49 | array.bindEvent( 'onInsert', function( data ) { 50 | array.forEach( function( item, index ) { 51 | maxIndex = index; 52 | } ); 53 | } ); 54 | 55 | array.insert( this.item ); 56 | 57 | Assert.areEqual( 0, maxIndex, 'forEach can be called on onInsert' ); 58 | }, 59 | 60 | testRemove: function() { 61 | var index = 0; 62 | var id = this.array.insert( this.item, index ); 63 | 64 | var removedItem = this.array.remove( index ); 65 | Assert.areSame( this.item, removedItem, 'removedItem and original item are the same'); 66 | 67 | var removedItemByID = this.array.get( id ); 68 | Assert.isUndefined( removedItemByID, 'item really is removed' ); 69 | }, 70 | 71 | testRemoveByID: function() { 72 | var index = 0; 73 | var id = this.array.insert( this.item, index ); 74 | 75 | var removedItem = this.array.remove( id ); 76 | 77 | var removedItemByID = this.array.get( id ); 78 | Assert.isUndefined( removedItemByID, 'item really is removed' ); 79 | }, 80 | 81 | testGetCount: function() { 82 | var count = this.array.getCount(); 83 | Assert.areSame( 0, count, 'emtpy gives correct count' ); 84 | 85 | var index = 0; 86 | this.array.insert( this.item, index ); 87 | count = this.array.getCount(); 88 | Assert.areEqual( 1, count, 'one added gives correct count' ); 89 | 90 | this.array.remove( 0 ); 91 | count = this.array.getCount(); 92 | Assert.areEqual( 0, count, 'one removed gives correct count' ); 93 | }, 94 | 95 | testInsertGetWithCID: function() { 96 | var dataWithCID = { 97 | cid: 'datacid' 98 | }; 99 | var cid = this.array.insert( dataWithCID ); 100 | 101 | Assert.areEqual( 'datacid', cid, 'cid is correctly set using data' ); 102 | 103 | var getData = this.array.get( 'datacid' ); 104 | Assert.areEqual( dataWithCID, getData, 'correct data gotten' ); 105 | 106 | var getByIndexData = this.array.get( 0 ); 107 | Assert.areEqual( dataWithCID, getByIndexData, 'correct data gotten by index' ); 108 | }, 109 | 110 | testInsertWithNegativeIndex: function() { 111 | var cid = this.array.insert( this.item, -1 ); 112 | var item = this.array.get( -1 ); 113 | 114 | Assert.areEqual( this.item, item, 'can insert and retreive using -1' ); 115 | }, 116 | 117 | testGetInvalidIndex: function() { 118 | var cid = this.array.insert( this.item ); 119 | 120 | // there is only one item in the array 121 | var item = this.array.get( 2 ); 122 | Assert.isUndefined( item ); 123 | 124 | var item = this.array.get( -5 ); 125 | Assert.isUndefined( item ); 126 | }, 127 | 128 | testClear: function() { 129 | var cid = this.array.insert( this.item ); 130 | Assert.areEqual( 1, this.array.getCount(), 'item inserted' ); 131 | 132 | this.array.clear(); 133 | Assert.areEqual( 0, this.array.getCount(), 'array cleared' ); 134 | 135 | var item = this.array.get( cid ); 136 | Assert.isUndefined( item, 'could not get item' ); 137 | }, 138 | 139 | testForEach: function() { 140 | var items = [ { 141 | cid: '1', 142 | field: 'field1' 143 | }, { 144 | cid: '2', 145 | field: 'field2', 146 | duplicate: 'duplicate' 147 | }, { 148 | cid: '3', 149 | field: 'field3', 150 | duplicate: 'duplicate' 151 | } ]; 152 | 153 | items.forEach( function( item, index ) { 154 | this.array.insert( item ); 155 | }, this ); 156 | 157 | var callbackCount = 0; 158 | this.array.forEach( function( item, index ) { 159 | Assert.isObject( item, 'item is an object' ); 160 | //Assert.isNumber( index, 'index is a number' ); 161 | callbackCount++; 162 | } ); 163 | 164 | Assert.areEqual( 3, callbackCount, 'callback called once for each item' ); 165 | } 166 | 167 | } ); 168 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/yuidoc.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim: et sw=4 ts=4 4 | 5 | ''' 6 | Copyright (c) 2010, Yahoo! Inc. All rights reserved. 7 | Code licensed under the BSD License: 8 | http://developer.yahoo.net/yui/license.html 9 | version: 1.0.0b1 10 | ''' 11 | 12 | import yuidoc_parse, yuidoc_highlight, yuidoc_generate 13 | 14 | def main(): 15 | from optparse import OptionParser 16 | optparser = OptionParser("usage: %prog inputdir [options] inputdir") 17 | optparser.set_defaults(extension=".js", 18 | newext=".highlighted", 19 | parseroutdir="/tmp", 20 | outputdir="docs", 21 | parserfile="parsed.json", 22 | showprivate=False, 23 | project="Yahoo! UI Library", 24 | version="", 25 | copyrighttag="Yahoo! Inc.", 26 | projecturl="http://developer.yahoo.com/yui/", 27 | yuiversion=False, 28 | ydn=False 29 | ) 30 | optparser.add_option( "-p", "--parseroutdir", 31 | action="store", dest="parseroutdir", type="string", 32 | help="Directory to write the parser temp data" ) 33 | optparser.add_option( "-o", "--outputdir", 34 | action="store", dest="outputdir", type="string", 35 | help="Directory to write the html documentation" ) 36 | optparser.add_option( "-f", "--file", 37 | action="store", dest="parserfile", type="string", 38 | help="The name of the file that contains the JSON doc info" ) 39 | optparser.add_option( "-t", "--template", 40 | action="store", dest="templatedir", type="string", 41 | help="The directory containing the html tmplate" ) 42 | optparser.add_option( "-c", "--crosslink", 43 | action="store", dest="crosslinkdir", type="string", 44 | help="The directory containing json data for other modules to crosslink" ) 45 | optparser.add_option( "-C", "--copyright", 46 | action="store", dest="copyrighttag", type="string", 47 | help="The name to use in the copyright line at the bottom of the pages." ) 48 | optparser.add_option( "-s", "--showprivate", 49 | action="store_true", dest="showprivate", 50 | help="Should private properties/methods be in the docs?" ) 51 | optparser.add_option( "-e", "--extension", 52 | action="store", dest="extension", type="string", 53 | help="The extension to parse" ) 54 | optparser.add_option( "-n", "--newextension", 55 | action="store", dest="newext", type="string", 56 | help="The extension to append to the yuisyntax highlighted output file" ) 57 | optparser.add_option( "-m", "--project", 58 | action="store", dest="project", type="string", 59 | help="The name of the project" ) 60 | optparser.add_option( "-v", "--version", 61 | action="store", dest="version", type="string", 62 | help="The version of the project" ) 63 | 64 | optparser.add_option( "-u", "--projecturl", 65 | action="store", dest="projecturl", type="string", 66 | help="The project url" ) 67 | 68 | optparser.add_option( "-Y", "--yuiversion", 69 | action="store", dest="yuiversion", type="string", 70 | help="The version of YUI library used in the project. This parameter applies to the output for attributes, which differs between YUI2 and YUI3." ) 71 | 72 | optparser.add_option( "-y", "--ydn", 73 | action="store_true", dest="ydn", 74 | help="Add YDN MyBlogLog intrumentation?" ) 75 | 76 | (opts, inputdirs) = optparser.parse_args() 77 | 78 | if len(inputdirs) > 0: 79 | docparser = yuidoc_parse.DocParser( inputdirs, 80 | opts.parseroutdir, 81 | opts.parserfile, 82 | opts.extension, 83 | opts.version, 84 | opts.yuiversion 85 | ) 86 | 87 | highlighter = yuidoc_highlight.DocHighlighter( [opts.parseroutdir], 88 | opts.parseroutdir, 89 | opts.extension, 90 | opts.newext ) 91 | 92 | gen = yuidoc_generate.DocGenerator( opts.parseroutdir, 93 | opts.parserfile, 94 | opts.outputdir, 95 | opts.templatedir, 96 | opts.newext, 97 | opts.showprivate, 98 | opts.project, 99 | opts.version, 100 | opts.projecturl, 101 | opts.ydn, 102 | opts.copyrighttag 103 | ) 104 | gen.process() 105 | else: 106 | optparser.error("Incorrect number of arguments") 107 | 108 | if __name__ == '__main__': 109 | main() 110 | 111 | -------------------------------------------------------------------------------- /tests/test_dataForm.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.DataForm with DataContainer", 4 | 5 | setUp: function() { 6 | this.dataSource = AFrame.DataContainer.create( { 7 | data: { 8 | name: 'AFrame', 9 | field2: 'Field2' 10 | } } ); 11 | 12 | this.form = AFrame.DataForm.create( { 13 | target: '#AFrame_Form', 14 | fieldFactory: function( formElement ) { 15 | this.factoryFormElement = formElement; 16 | this.field = AFrame.Field.create( { 17 | target: formElement 18 | } ); 19 | 20 | return this.field; 21 | }.bind( this ), 22 | data: this.dataSource 23 | } ); 24 | }, 25 | 26 | tearDown: function() { 27 | this.form.teardown(); 28 | this.form = null; 29 | }, 30 | 31 | testBindToDataSource: function() { 32 | Assert.areEqual( 'AFrame', jQuery( '#textFormElement' ).html(), 'field bound to data source' ); 33 | }, 34 | 35 | testUpdateDataSource: function() { 36 | this.dataSource.set( 'name', 'Shane' ); 37 | Assert.areEqual( 'Shane', jQuery( '#textFormElement' ).html(), 'field updated when store updated' ); 38 | }, 39 | 40 | testSave: function() { 41 | this.field.set( 'Charlotte' ); 42 | 43 | Assert.areEqual( 'Field2', this.dataSource.get( 'field2' ), 'dataSource has not been updated before save' ); 44 | 45 | this.form.save(); 46 | 47 | Assert.areEqual( 'Charlotte', this.dataSource.get( 'field2' ), 'dataSource updated after save' ); 48 | } 49 | 50 | 51 | } ); 52 | 53 | testsToRun.push( { 54 | 55 | name: "TestCase AFrame.DataForm with Model", 56 | 57 | setUp: function() { 58 | this.dataSource = AFrame.Model.create( { 59 | schema: { 60 | name: { type: 'text' }, 61 | field2: { type: 'text' } 62 | }, 63 | data: { 64 | name: 'AFrame', 65 | field2: 'Field2' 66 | } 67 | } ); 68 | 69 | this.form = AFrame.DataForm.create( { 70 | target: '#AFrame_Form', 71 | fieldFactory: function( formElement ) { 72 | this.factoryFormElement = formElement; 73 | this.field = AFrame.Field.create( { 74 | target: formElement 75 | } ); 76 | 77 | return this.field; 78 | }.bind( this ), 79 | data: this.dataSource 80 | } ); 81 | }, 82 | 83 | tearDown: function() { 84 | this.form.teardown(); 85 | this.form = null; 86 | }, 87 | 88 | testCheckValidity: function() { 89 | this.field.set( 'asdf' ); 90 | 91 | Assert.areSame( 'Field2', this.dataSource.get( 'field2' ), 'dataSource has not been updated before save' ); 92 | 93 | var valid = this.form.checkValidity(); 94 | Assert.isTrue( valid, 'trying to set text field to an integer, dies.' ); 95 | 96 | var validityState = this.field.getValidityState(); 97 | Assert.isTrue( validityState.valid, 'setting text field to integer is invalid' ); 98 | }, 99 | 100 | testValidateFormWithModel: function() { 101 | var mockValidityCalled = false; 102 | var modelMock = { 103 | checkValidity: function() { 104 | mockValidityCalled = true; 105 | return false; 106 | } 107 | }; 108 | 109 | this.form.validateFormFieldsWithModel( modelMock ); 110 | 111 | Assert.isTrue( mockValidityCalled, 'the mock model\'s checkValidity was called' ); 112 | }, 113 | 114 | testSave: function() { 115 | this.field.set( 'test value' ); 116 | 117 | Assert.areSame( 'Field2', this.dataSource.get( 'field2' ), 'dataSource has not been updated before save' ); 118 | 119 | this.form.save(); 120 | Assert.areSame( 'test value', this.dataSource.get( 'field2' ), 'dataSource updated after save' ); 121 | } 122 | 123 | } ); 124 | 125 | testsToRun.push( { 126 | 127 | name: "TestCase AFrame.DataForm with autosave", 128 | 129 | setUp: function() { 130 | this.dataSource = AFrame.DataContainer.create( { 131 | data: { 132 | name: 'AFrame', 133 | field2: 'Field2' 134 | } 135 | } ); 136 | 137 | this.form = AFrame.DataForm.create( { 138 | autosave: true, 139 | target: '#AFrame_Form', 140 | fieldFactory: function( formElement ) { 141 | this.factoryFormElement = formElement; 142 | this.field = AFrame.Field.create( { 143 | target: formElement 144 | } ); 145 | 146 | return this.field; 147 | }.bind( this ), 148 | data: this.dataSource 149 | } ); 150 | }, 151 | 152 | tearDown: function() { 153 | this.form.teardown(); 154 | this.form = null; 155 | }, 156 | 157 | 158 | testAutoSaveOnChange: function() { 159 | this.field.set( 'Charlotte' ); 160 | 161 | Assert.areSame( 'Charlotte', this.dataSource.get( 'field2' ), 162 | 'field2 is updated' ); 163 | } 164 | } ); 165 | -------------------------------------------------------------------------------- /tests/test_dataContainer.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.DataContainer", 4 | 5 | setUp: function() { 6 | this.dataContainer = AFrame.DataContainer.create(); 7 | }, 8 | 9 | tearDown : function () { 10 | this.dataContainer.teardown(); 11 | this.dataContainer = null; 12 | delete this.dataContainer; 13 | }, 14 | 15 | testSet: function() { 16 | /* When we set an item, it should trigger a message that the field was set */ 17 | var eventData; 18 | this.dataContainer.bindEvent( 'onSet', function( event ) { 19 | eventData = event; 20 | } ); 21 | 22 | var oldValue = this.dataContainer.set( 'fieldName', 'fieldValue' ); 23 | 24 | Assert.isUndefined( oldValue, 'initial set with no initial data should return oldValue of undefined' ); 25 | 26 | Assert.isObject( eventData, 'onSet correctly triggered with data' ); 27 | Assert.isTrue( eventData.hasOwnProperty( 'oldValue' ), 'oldValue is in data set' ); 28 | Assert.isString( eventData.value, 'value is in data set' ); 29 | Assert.isString( eventData.fieldName, 'fieldName is in data set' ); 30 | 31 | 32 | /* second set should give oldValue of fieldValue */ 33 | 34 | oldValue = this.dataContainer.set( 'fieldName', 'value2' ); 35 | 36 | Assert.areEqual( 'fieldValue', oldValue, 'second set gives return of correct oldValue' ); 37 | Assert.areEqual( 'fieldValue', eventData.oldValue, 'eventData of second set gives correct oldValue' ); 38 | }, 39 | 40 | testGet: function() { 41 | this.dataContainer.set( 'fieldName', 'fieldValue' ); 42 | 43 | var fieldValue = this.dataContainer.get( 'fieldName' ); 44 | Assert.areEqual( 'fieldValue', fieldValue, 'get correctly gets the data' ); 45 | }, 46 | 47 | testBindFieldUnbindField: function() { 48 | var bindFieldData; 49 | 50 | var id = this.dataContainer.bindField( 'fieldName', function( data ) { 51 | bindFieldData = data; 52 | }, this ); 53 | 54 | Assert.isObject( bindFieldData, 'callback correctly called with data' ); 55 | Assert.isTrue( bindFieldData.hasOwnProperty( 'oldValue' ), 'oldValue is in data set' ); 56 | Assert.isTrue( bindFieldData.hasOwnProperty( 'value' ), 'value is in data set' ); 57 | Assert.isObject( bindFieldData.container, 'container is in data set' ); 58 | Assert.isString( bindFieldData.fieldName, 'fieldName is in data set' ); 59 | 60 | this.dataContainer.set( 'fieldName', 'value2' ); 61 | Assert.areEqual( 'value2', bindFieldData.value, 'bound callback called with data after set' ); 62 | 63 | this.dataContainer.unbindField( id ); 64 | 65 | this.dataContainer.set( 'fieldName', 'value3' ); 66 | Assert.areEqual( 'value2', bindFieldData.value, 'bound callback not called after field is unbound' ); 67 | }, 68 | 69 | testForEach: function() { 70 | var forEachCount = 0; 71 | 72 | this.dataContainer.set( 'field1', 1 ); 73 | this.dataContainer.set( 'field2', 1 ); 74 | this.dataContainer.set( 'field3', 1 ); 75 | 76 | this.dataContainer.forEach( function( data, fieldName ) { 77 | forEachCount++; 78 | } ); 79 | 80 | Assert.areEqual( 3, forEachCount, 'forEach called once for each field' ); 81 | }, 82 | 83 | testConstructor: function() { 84 | var data = { 85 | field1: 'value1', 86 | field2: 'value2' 87 | }; 88 | 89 | var dataContainer = AFrame.DataContainer.create( { data: data } ); 90 | Assert.isTrue( ( dataContainer instanceof AFrame.DataContainer ), 'successful creation of DataContainer from data' ); 91 | 92 | var secondDataContainer = AFrame.DataContainer.create( { data: dataContainer } ); 93 | 94 | Assert.isTrue( ( secondDataContainer instanceof AFrame.DataContainer ), 'successful creation of DataContainer from another DataContainer' ); 95 | 96 | var thirdDataContainer = AFrame.DataContainer.create( { data: data } ); 97 | Assert.isTrue( ( thirdDataContainer === dataContainer ), 'making a second DataContainer from data gives back the same DataContainer' ); 98 | }, 99 | 100 | testGetDataObject: function() { 101 | var data = { 102 | field1: 'value1', 103 | field2: 'value2' 104 | }; 105 | 106 | var dataCopy = AFrame.mixin( {}, data ); 107 | var dataContainer = AFrame.DataContainer.create( { data: data } ); 108 | 109 | var dataObject = dataContainer.toJSON(); 110 | Assert.isUndefined( dataObject.__dataContainer, '__dataContainer not returned' ); 111 | Assert.deepEqual( dataObject, dataCopy, 'toJSON returns same data as original object' ); 112 | }, 113 | 114 | testBulkSet: function() { 115 | var data = { 116 | field1: 'value1', 117 | field2: 'value2' 118 | }; 119 | 120 | var dataContainer = AFrame.DataContainer.create( { data: { 121 | field0: 'value0' 122 | } } ); 123 | 124 | var prevVals = dataContainer.set( data ); 125 | 126 | Assert.areEqual( 'value0', dataContainer.get( 'field0' ), 'field0 remains the same' ); 127 | Assert.areEqual( 'value1', dataContainer.get( 'field1' ), 'field1 set' ); 128 | Assert.areEqual( 'value2', dataContainer.get( 'field2' ), 'field2 set' ); 129 | 130 | Assert.isTrue( prevVals.hasOwnProperty( 'field1' ) && 131 | 'undefined' == typeof( prevVals.field1 ), 'field1 previously undefined' ); 132 | } 133 | 134 | } ); 135 | -------------------------------------------------------------------------------- /tools/yuidoc/template/assets/reset-fonts-grids-min.css: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2008, Yahoo! Inc. All rights reserved. 3 | Code licensed under the BSD License: 4 | http://developer.yahoo.net/yui/license.txt 5 | version: 2.6.0 6 | */ 7 | html{color:#000;background:#FFF;}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}table{border-collapse:collapse;border-spacing:0;}fieldset,img{border:0;}address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}li{list-style:none;}caption,th{text-align:left;}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}q:before,q:after{content:'';}abbr,acronym{border:0;font-variant:normal;}sup{vertical-align:text-top;}sub{vertical-align:text-bottom;}input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}input,textarea,select{*font-size:100%;}legend{color:#000;}del,ins{text-decoration:none;}body{font:13px/1.231 arial,helvetica,clean,sans-serif;*font-size:small;*font:x-small;}select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;}table{font-size:inherit;font:100%;}pre,code,kbd,samp,tt{font-family:monospace;*font-size:108%;line-height:100%;}body{text-align:center;}#ft{clear:both;}#doc,#doc2,#doc3,#doc4,.yui-t1,.yui-t2,.yui-t3,.yui-t4,.yui-t5,.yui-t6,.yui-t7{margin:auto;text-align:left;width:57.69em;*width:56.25em;min-width:750px;}#doc2{width:73.076em;*width:71.25em;}#doc3{margin:auto 10px;width:auto;}#doc4{width:74.923em;*width:73.05em;}.yui-b{position:relative;}.yui-b{_position:static;}#yui-main .yui-b{position:static;}#yui-main,.yui-g .yui-u .yui-g{width:100%;}{width:100%;}.yui-t1 #yui-main,.yui-t2 #yui-main,.yui-t3 #yui-main{float:right;margin-left:-25em;}.yui-t4 #yui-main,.yui-t5 #yui-main,.yui-t6 #yui-main{float:left;margin-right:-25em;}.yui-t1 .yui-b{float:left;width:12.30769em;*width:12.00em;}.yui-t1 #yui-main .yui-b{margin-left:13.30769em;*margin-left:13.05em;}.yui-t2 .yui-b{float:left;width:13.8461em;*width:13.50em;}.yui-t2 #yui-main .yui-b{margin-left:14.8461em;*margin-left:14.55em;}.yui-t3 .yui-b{float:left;width:23.0769em;*width:22.50em;}.yui-t3 #yui-main .yui-b{margin-left:24.0769em;*margin-left:23.62em;}.yui-t4 .yui-b{float:right;width:13.8456em;*width:13.50em;}.yui-t4 #yui-main .yui-b{margin-right:14.8456em;*margin-right:14.55em;}.yui-t5 .yui-b{float:right;width:18.4615em;*width:18.00em;}.yui-t5 #yui-main .yui-b{margin-right:19.4615em;*margin-right:19.125em;}.yui-t6 .yui-b{float:right;width:23.0769em;*width:22.50em;}.yui-t6 #yui-main .yui-b{margin-right:24.0769em;*margin-right:23.62em;}.yui-t7 #yui-main .yui-b{display:block;margin:0 0 1em 0;}#yui-main .yui-b{float:none;width:auto;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf,.yui-gc .yui-u,.yui-gd .yui-g,.yui-g .yui-gc .yui-u,.yui-ge .yui-u,.yui-ge .yui-g,.yui-gf .yui-g,.yui-gf .yui-u{float:right;}.yui-g div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first,.yui-ge div.first,.yui-gf div.first,.yui-g .yui-gc div.first,.yui-g .yui-ge div.first,.yui-gc div.first div.first{float:left;}.yui-g .yui-u,.yui-g .yui-g,.yui-g .yui-gb,.yui-g .yui-gc,.yui-g .yui-gd,.yui-g .yui-ge,.yui-g .yui-gf{width:49.1%;}.yui-gb .yui-u,.yui-g .yui-gb .yui-u,.yui-gb .yui-g,.yui-gb .yui-gb,.yui-gb .yui-gc,.yui-gb .yui-gd,.yui-gb .yui-ge,.yui-gb .yui-gf,.yui-gc .yui-u,.yui-gc .yui-g,.yui-gd .yui-u{width:32%;margin-left:1.99%;}.yui-gb .yui-u{*margin-left:1.9%;*width:31.9%;}.yui-gc div.first,.yui-gd .yui-u{width:66%;}.yui-gd div.first{width:32%;}.yui-ge div.first,.yui-gf .yui-u{width:74.2%;}.yui-ge .yui-u,.yui-gf div.first{width:24%;}.yui-g .yui-gb div.first,.yui-gb div.first,.yui-gc div.first,.yui-gd div.first{margin-left:0;}.yui-g .yui-g .yui-u,.yui-gb .yui-g .yui-u,.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u,.yui-ge .yui-g .yui-u,.yui-gf .yui-g .yui-u{width:49%;*width:48.1%;*margin-left:0;}.yui-g .yui-g .yui-u{width:48.1%;}.yui-g .yui-gb div.first,.yui-gb .yui-gb div.first{*margin-right:0;*width:32%;_width:31.7%;}.yui-g .yui-gc div.first,.yui-gd .yui-g{width:66%;}.yui-gb .yui-g div.first{*margin-right:4%;_margin-right:1.3%;}.yui-gb .yui-gc div.first,.yui-gb .yui-gd div.first{*margin-right:0;}.yui-gb .yui-gb .yui-u,.yui-gb .yui-gc .yui-u{*margin-left:1.8%;_margin-left:4%;}.yui-g .yui-gb .yui-u{_margin-left:1.0%;}.yui-gb .yui-gd .yui-u{*width:66%;_width:61.2%;}.yui-gb .yui-gd div.first{*width:31%;_width:29.5%;}.yui-g .yui-gc .yui-u,.yui-gb .yui-gc .yui-u{width:32%;_float:right;margin-right:0;_margin-left:0;}.yui-gb .yui-gc div.first{width:66%;*float:left;*margin-left:0;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf .yui-u{margin:0;}.yui-gb .yui-gb .yui-u{_margin-left:.7%;}.yui-gb .yui-g div.first,.yui-gb .yui-gb div.first{*margin-left:0;}.yui-gc .yui-g .yui-u,.yui-gd .yui-g .yui-u{*width:48.1%;*margin-left:0;} .yui-gb .yui-gd div.first{width:32%;}.yui-g .yui-gd div.first{_width:29.9%;}.yui-ge .yui-g{width:24%;}.yui-gf .yui-g{width:74.2%;}.yui-gb .yui-ge div.yui-u,.yui-gb .yui-gf div.yui-u{float:right;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf div.first{float:left;}.yui-gb .yui-ge .yui-u,.yui-gb .yui-gf div.first{*width:24%;_width:20%;}.yui-gb .yui-ge div.first,.yui-gb .yui-gf .yui-u{*width:73.5%;_width:65.5%;}.yui-ge div.first .yui-gd .yui-u{width:65%;}.yui-ge div.first .yui-gd div.first{width:32%;}#bd:after,.yui-g:after,.yui-gb:after,.yui-gc:after,.yui-gd:after,.yui-ge:after,.yui-gf:after{content:".";display:block;height:0;clear:both;visibility:hidden;}#bd,.yui-g,.yui-gb,.yui-gc,.yui-gd,.yui-ge,.yui-gf{zoom:1;} 8 | -------------------------------------------------------------------------------- /tools/yuidoc/bin/yuidoc_highlight.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # vim: et sw=4 ts=4 4 | 5 | ''' 6 | Copyright (c) 2010, Yahoo! Inc. All rights reserved. 7 | Code licensed under the BSD License: 8 | http://developer.yahoo.net/yui/license.html 9 | version: 1.0.0b1 10 | ''' 11 | 12 | import os, re, string, logging, logging.config 13 | from const import * 14 | from optparse import OptionParser 15 | from pygments import highlight 16 | from pygments.formatters import HtmlFormatter 17 | import codecs 18 | 19 | try: 20 | logging.config.fileConfig(os.path.join(sys.path[0], LOGCONFIG)) 21 | except: 22 | pass 23 | 24 | log = logging.getLogger('yuidoc.highlight') 25 | 26 | 27 | class DocHighlighter(object): 28 | 29 | def __init__(self, inputdirs, outputdir, ext, newext): 30 | 31 | def _mkdir(newdir): 32 | if os.path.isdir(newdir): pass 33 | elif os.path.isfile(newdir): 34 | raise OSError("a file with the same name as the desired " \ 35 | "dir, '%s', already exists." % newdir) 36 | else: 37 | head, tail = os.path.split(newdir) 38 | if head and not os.path.isdir(head): _mkdir(head) 39 | if tail: os.mkdir(newdir) 40 | 41 | def highlightString(src): 42 | try: 43 | if self.currentExt == 'php': 44 | from pygments.lexers import PhpLexer 45 | return highlight(src, PhpLexer(), HtmlFormatter()) 46 | elif self.currentExt == 'py': 47 | from pygments.lexers import PythonLexer 48 | return highlight(src, PythonLexer(), HtmlFormatter()) 49 | elif self.currentExt == 'rb': 50 | from pygments.lexers import RubyLexer 51 | return highlight(src, RubyLexer(), HtmlFormatter()) 52 | elif self.currentExt == 'pl': 53 | from pygments.lexers import PerlLexer 54 | return highlight(src, PerlLexer(), HtmlFormatter()) 55 | elif self.currentExt == 'java': 56 | from pygments.lexers import JavaLexer 57 | return highlight(src, JavaLexer(), HtmlFormatter()) 58 | elif self.currentExt == 'cs': 59 | from pygments.lexers import CSharpLexer 60 | return highlight(src, CSharpLexer(), HtmlFormatter()) 61 | else: 62 | from pygments.lexers import JavascriptLexer 63 | return highlight(src, JavascriptLexer(), HtmlFormatter()) 64 | except: 65 | return "File could not be highlighted" 66 | 67 | def highlightFile(path, file): 68 | f=open(os.path.join(path, file)) 69 | fileStr = codecs.open( os.path.join(path, file), "r", "utf-8" ).read() 70 | 71 | f.close() 72 | log.info("highlighting " + os.path.join(path, file)) 73 | 74 | self.currentExt = os.path.splitext(file)[1].replace('.', '') 75 | 76 | highlighted = highlightString(fileStr) 77 | 78 | out = codecs.open( os.path.join(self.outputdir, file + self.newext), "w", "utf-8" ) 79 | out.write(highlighted) 80 | out.close() 81 | 82 | def highlightDir(path): 83 | subdirs = [] 84 | dircontent = "" 85 | for i in os.listdir(path): 86 | fullname = os.path.join(path, i) 87 | if os.path.isdir(fullname): 88 | subdirs.append(fullname) 89 | else: 90 | for ext in self.ext_check: 91 | if i.lower().endswith(ext): 92 | highlightFile(path, i) 93 | 94 | for i in subdirs: 95 | highlightDir(i) 96 | 97 | self.inputdirs = inputdirs 98 | self.outputdir = os.path.abspath(outputdir) 99 | _mkdir(self.outputdir) 100 | self.ext = ext 101 | self.currentExt = '' 102 | self.ext_check = ext.split(',') 103 | self.newext = newext 104 | 105 | log.info("-------------------------------------------------------") 106 | 107 | for i in inputdirs: 108 | highlightDir(os.path.abspath(i)) 109 | 110 | 111 | def main(): 112 | optparser = OptionParser("usage: %prog [options] inputdir1 inputdir2 etc") 113 | optparser.set_defaults(outputdir="out", ext=".js", newext=".highlighted") 114 | optparser.add_option( "-o", "--outputdir", 115 | action="store", dest="outputdir", type="string", 116 | help="Directory to write the parser results" ) 117 | optparser.add_option( "-e", "--extension", 118 | action="store", dest="ext", type="string", 119 | help="The extension for the files that should be parsed" ) 120 | optparser.add_option( "-n", "--newextension", 121 | action="store", dest="newext", type="string", 122 | help="The extension to append to the output file" ) 123 | (opts, inputdirs) = optparser.parse_args() 124 | if len(inputdirs) > 0: 125 | docparser = DocHighlighter( inputdirs, 126 | opts.outputdir, 127 | opts.ext, 128 | opts.newext ) 129 | else: 130 | optparser.error("Incorrect number of arguments") 131 | 132 | if __name__ == '__main__': 133 | main() 134 | -------------------------------------------------------------------------------- /src/fieldPlaceholderDecorator.js: -------------------------------------------------------------------------------- 1 | /** 2 | * A decorator on a [Field](AFrame.Field.html) that takes care of displaying placeholder text if the browser does not 3 | * natively support this feature. This class never needs called directly and will be automatically 4 | * attached to the [Field](AFrame.Field.html) if the behavior is needed. For browsers that do 5 | * not support placeholder text natively, the decorator will come into play to add it. The idea 6 | * of placeholder text is if the field has no value displayed, but the element has text in its 7 | * placeholder attribute, the text will be displayed until either a value is entered or the user 8 | * places the mouse into the input. If the user still has not entered text whenever the element 9 | * loses focus, the placeholder text is again displayed. Any element that has its placeholder text 10 | * shown will have the "empty" class attached. Note, in CSS, this is different to the :empty class 11 | * which the browser can natively add. 12 | * 13 | *#Example of Using Placeholder Text# 14 | * 15 | * 16 | * 17 | * @class AFrame.FieldPluginPlaceholder 18 | * @static 19 | */ 20 | AFrame.FieldPluginPlaceholder = ( function() { 21 | var Placeholder = { 22 | init: function() { 23 | this.decorators = {}; 24 | 25 | // All functions are called as if they were on the Field. We are overriding init, bindEvents, 26 | // set, display, and save. These functions pertain to our handling of the placeholder text. 27 | decorate( 'init', decoratorInit ); 28 | decorate( 'bindEvents', decoratorBindEvents ); 29 | decorate( 'get', decoratorGet ); 30 | decorate( 'getDisplayed', decoratorGetDisplayed ); 31 | decorate( 'save', decoratorSave ); 32 | decorate( 'display', decoratorDisplay ); 33 | } 34 | }; 35 | 36 | function decorate( name, decorator ) { 37 | var decorated = AFrame.Field.prototype; 38 | 39 | Placeholder[ '_' + name ] = decorated[ name ]; 40 | decorated[ name ] = decorator; 41 | } 42 | 43 | function decoratorInit( config ) { 44 | Placeholder._init.call( this, config ); 45 | 46 | // display the placeholder text until the value is set. 47 | this.display( this.getDisplayed() ); 48 | } 49 | 50 | function decoratorBindEvents() { 51 | var target = this.getTarget(); 52 | 53 | // we care about the focus and blur evnts. 54 | this.bindDOMEvent( target, 'focus', onFieldFocus ); 55 | this.bindDOMEvent( target, 'blur', onFieldBlur ); 56 | 57 | Placeholder._bindEvents.call( this ); 58 | } 59 | 60 | function decoratorGet() { 61 | var placeholder = getPlaceholder.call( this ); 62 | var val = Placeholder._get.call( this ); 63 | 64 | if( val === placeholder ) { 65 | var undefined; 66 | val = undefined; 67 | } 68 | 69 | return val; 70 | } 71 | 72 | function decoratorGetDisplayed() { 73 | var placeholder = getPlaceholder.call( this ); 74 | var val = Placeholder._getDisplayed.call( this ); 75 | 76 | if( val === placeholder ) { 77 | val = ''; 78 | } 79 | 80 | return val; 81 | } 82 | 83 | function decoratorDisplay( val ) { 84 | Placeholder._display.call( this, val ); 85 | updatePlaceholder.call( this ); 86 | } 87 | 88 | function decoratorSave() { 89 | var placeholder = getPlaceholder.call( this ); 90 | 91 | var placeHolderDisplayed = this.getDisplayed() == placeholder; 92 | 93 | if( placeHolderDisplayed ) { 94 | this.display( '' ); 95 | } 96 | 97 | Placeholder._save.call( this ); 98 | 99 | if( placeHolderDisplayed ) { 100 | this.display( placeholder ); 101 | } 102 | } 103 | 104 | function onFieldFocus() { 105 | this.focused = true; 106 | updatePlaceholder.call( this ); 107 | } 108 | 109 | function onFieldBlur() { 110 | this.focused = false; 111 | updatePlaceholder.call( this ); 112 | } 113 | 114 | function updatePlaceholder() { 115 | var placeholder = getPlaceholder.call( this ); 116 | var displayed = Placeholder._getDisplayed.call( this ); 117 | 118 | var target = this.getTarget(); 119 | AFrame.DOM.removeClass( target, 'empty' ); 120 | 121 | if( this.focused ) { 122 | if( placeholder == displayed ) { 123 | Placeholder._display.call( this, '' ); 124 | } 125 | } 126 | else if( '' === Placeholder._getDisplayed.call( this ) ) { 127 | AFrame.DOM.addClass( target, 'empty' ); 128 | 129 | Placeholder._display.call( this, getPlaceholder.call( this ) ); 130 | } 131 | } 132 | 133 | function getPlaceholder() { 134 | var target = this.getTarget(); 135 | return AFrame.DOM.getAttr( target, 'placeholder' ) || ''; 136 | } 137 | 138 | if( typeof( document ) !== 'undefined' ) { 139 | // we only want to initialize the Placeholder if the browser does not support HTML5 140 | var inp = document.createElement( 'input' ); 141 | if( !( 'placeholder' in inp ) ) { 142 | Placeholder.init(); 143 | } 144 | } 145 | 146 | return Placeholder; 147 | }() ); 148 | 149 | -------------------------------------------------------------------------------- /tests/ext/qunit.css: -------------------------------------------------------------------------------- 1 | /** 2 | * QUnit - A JavaScript Unit Testing Framework 3 | * 4 | * http://docs.jquery.com/QUnit 5 | * 6 | * Copyright (c) 2011 John Resig, Jörn Zaefferer 7 | * Dual licensed under the MIT (MIT-LICENSE.txt) 8 | * or GPL (GPL-LICENSE.txt) licenses. 9 | */ 10 | 11 | /** Font Family and Sizes */ 12 | 13 | #qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { 14 | font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; 15 | } 16 | 17 | #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } 18 | #qunit-tests { font-size: smaller; } 19 | 20 | 21 | /** Resets */ 22 | 23 | #qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { 24 | margin: 0; 25 | padding: 0; 26 | } 27 | 28 | 29 | /** Header */ 30 | 31 | #qunit-header { 32 | padding: 0.5em 0 0.5em 1em; 33 | 34 | color: #8699a4; 35 | background-color: #0d3349; 36 | 37 | font-size: 1.5em; 38 | line-height: 1em; 39 | font-weight: normal; 40 | 41 | border-radius: 15px 15px 0 0; 42 | -moz-border-radius: 15px 15px 0 0; 43 | -webkit-border-top-right-radius: 15px; 44 | -webkit-border-top-left-radius: 15px; 45 | } 46 | 47 | #qunit-header a { 48 | text-decoration: none; 49 | color: #c2ccd1; 50 | } 51 | 52 | #qunit-header a:hover, 53 | #qunit-header a:focus { 54 | color: #fff; 55 | } 56 | 57 | #qunit-banner { 58 | height: 5px; 59 | } 60 | 61 | #qunit-testrunner-toolbar { 62 | padding: 0.5em 0 0.5em 2em; 63 | color: #5E740B; 64 | background-color: #eee; 65 | } 66 | 67 | #qunit-userAgent { 68 | padding: 0.5em 0 0.5em 2.5em; 69 | background-color: #2b81af; 70 | color: #fff; 71 | text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; 72 | } 73 | 74 | 75 | /** Tests: Pass/Fail */ 76 | 77 | #qunit-tests { 78 | list-style-position: inside; 79 | } 80 | 81 | #qunit-tests li { 82 | padding: 0.4em 0.5em 0.4em 2.5em; 83 | border-bottom: 1px solid #fff; 84 | list-style-position: inside; 85 | } 86 | 87 | #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { 88 | display: none; 89 | } 90 | 91 | #qunit-tests li strong { 92 | cursor: pointer; 93 | } 94 | 95 | #qunit-tests li a { 96 | padding: 0.5em; 97 | color: #c2ccd1; 98 | text-decoration: none; 99 | } 100 | #qunit-tests li a:hover, 101 | #qunit-tests li a:focus { 102 | color: #000; 103 | } 104 | 105 | #qunit-tests ol { 106 | margin-top: 0.5em; 107 | padding: 0.5em; 108 | 109 | background-color: #fff; 110 | 111 | border-radius: 15px; 112 | -moz-border-radius: 15px; 113 | -webkit-border-radius: 15px; 114 | 115 | box-shadow: inset 0px 2px 13px #999; 116 | -moz-box-shadow: inset 0px 2px 13px #999; 117 | -webkit-box-shadow: inset 0px 2px 13px #999; 118 | } 119 | 120 | #qunit-tests table { 121 | border-collapse: collapse; 122 | margin-top: .2em; 123 | } 124 | 125 | #qunit-tests th { 126 | text-align: right; 127 | vertical-align: top; 128 | padding: 0 .5em 0 0; 129 | } 130 | 131 | #qunit-tests td { 132 | vertical-align: top; 133 | } 134 | 135 | #qunit-tests pre { 136 | margin: 0; 137 | white-space: pre-wrap; 138 | word-wrap: break-word; 139 | } 140 | 141 | #qunit-tests del { 142 | background-color: #e0f2be; 143 | color: #374e0c; 144 | text-decoration: none; 145 | } 146 | 147 | #qunit-tests ins { 148 | background-color: #ffcaca; 149 | color: #500; 150 | text-decoration: none; 151 | } 152 | 153 | /*** Test Counts */ 154 | 155 | #qunit-tests b.counts { color: black; } 156 | #qunit-tests b.passed { color: #5E740B; } 157 | #qunit-tests b.failed { color: #710909; } 158 | 159 | #qunit-tests li li { 160 | margin: 0.5em; 161 | padding: 0.4em 0.5em 0.4em 0.5em; 162 | background-color: #fff; 163 | border-bottom: none; 164 | list-style-position: inside; 165 | } 166 | 167 | /*** Passing Styles */ 168 | 169 | #qunit-tests li li.pass { 170 | color: #5E740B; 171 | background-color: #fff; 172 | border-left: 26px solid #C6E746; 173 | } 174 | 175 | #qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } 176 | #qunit-tests .pass .test-name { color: #366097; } 177 | 178 | #qunit-tests .pass .test-actual, 179 | #qunit-tests .pass .test-expected { color: #999999; } 180 | 181 | #qunit-banner.qunit-pass { background-color: #C6E746; } 182 | 183 | /*** Failing Styles */ 184 | 185 | #qunit-tests li li.fail { 186 | color: #710909; 187 | background-color: #fff; 188 | border-left: 26px solid #EE5757; 189 | } 190 | 191 | #qunit-tests > li:last-child { 192 | border-radius: 0 0 15px 15px; 193 | -moz-border-radius: 0 0 15px 15px; 194 | -webkit-border-bottom-right-radius: 15px; 195 | -webkit-border-bottom-left-radius: 15px; 196 | } 197 | 198 | #qunit-tests .fail { color: #000000; background-color: #EE5757; } 199 | #qunit-tests .fail .test-name, 200 | #qunit-tests .fail .module-name { color: #000000; } 201 | 202 | #qunit-tests .fail .test-actual { color: #EE5757; } 203 | #qunit-tests .fail .test-expected { color: green; } 204 | 205 | #qunit-banner.qunit-fail { background-color: #EE5757; } 206 | 207 | 208 | /** Result */ 209 | 210 | #qunit-testresult { 211 | padding: 0.5em 0.5em 0.5em 2.5em; 212 | 213 | color: #2b81af; 214 | background-color: #D2E0E6; 215 | 216 | border-bottom: 1px solid white; 217 | } 218 | 219 | /** Fixture */ 220 | 221 | #qunit-fixture { 222 | position: absolute; 223 | top: -10000px; 224 | left: -10000px; 225 | } 226 | -------------------------------------------------------------------------------- /tests/test_form.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.Form", 4 | 5 | setUp: function() { 6 | this.validateCount = 0; 7 | this.validateReturn = true; 8 | 9 | var validate = function() { 10 | this.validateCount++; 11 | return this.validateReturn; 12 | }.bind( this ); 13 | 14 | this.saveCount = 0; 15 | var save = function() { 16 | this.saveCount++; 17 | }.bind( this ); 18 | 19 | this.resetCount = 0; 20 | var reset = function() { 21 | this.resetCount++; 22 | }.bind( this ); 23 | 24 | this.clearCount = 0; 25 | var clear = function() { 26 | this.clearCount++; 27 | }.bind( this ); 28 | 29 | this.teardownCount = 0; 30 | var teardown = function() { 31 | this.teardownCount++; 32 | }.bind( this ); 33 | 34 | this.form = AFrame.Form.create( { 35 | target: '#AFrame_Form', 36 | fieldFactory: function( formElement ) { 37 | this.factoryFormElement = formElement; 38 | 39 | return { 40 | checkValidity: validate, 41 | save: save, 42 | reset: reset, 43 | clear: clear, 44 | teardown: teardown 45 | }; 46 | }.bind( this ) 47 | } ); 48 | }, 49 | 50 | tearDown: function () { 51 | this.form.teardown(); 52 | this.form = null; 53 | delete this.form; 54 | }, 55 | 56 | testGetFormElements: function() { 57 | var formElements = this.form.getFormElements(); 58 | Assert.areEqual( 2, formElements.length, 'formElement was found' ); 59 | }, 60 | 61 | testGetFormFields: function() { 62 | var formFields = this.form.getFormFields(); 63 | Assert.areEqual( 2, formFields.length, 'formField was created' ); 64 | }, 65 | 66 | testFactoryPassedWithCorrectData: function() { 67 | var expectedFormElement = jQuery( '#textFormElement2' )[ 0 ]; 68 | Assert.areEqual( expectedFormElement, this.factoryFormElement[ 0 ], 'formElement passed correctly' ); 69 | }, 70 | 71 | testValidate: function() { 72 | Assert.areEqual( 0, this.validateCount, 'field\'s checkValidity has not been called' ); 73 | 74 | this.validateReturn = true; 75 | var valid = this.form.checkValidity(); 76 | 77 | Assert.areEqual( true, valid, 'valid correctly returns form is valid' ); 78 | Assert.areEqual( 2, this.validateCount, 'field\'s checkValidity has been called' ); 79 | 80 | this.validateReturn = false;/*{ 81 | field: this, 82 | error: 'some error' 83 | };*/ 84 | this.validateCount = 0; 85 | valid = this.form.checkValidity(); 86 | Assert.isFalse( valid, 'valid correctly returns form is invalid as object return value' ); 87 | /*Assert.areEqual( this.validateReturn, valid, 'valid correctly returns checkValidityReturn' ); 88 | Assert.areEqual( 1, this.validateCount, 'validate has been called once' ); 89 | */ 90 | }, 91 | 92 | testClear: function() { 93 | Assert.areEqual( 0, this.clearCount, 'clear has not been called yet' ); 94 | this.form.bindEvent("clear", function() { 95 | Assert.isTrue(true, "clear event triggered"); 96 | start(); 97 | }); 98 | 99 | this.form.clear(); 100 | Assert.areEqual( 2, this.clearCount, 'clear has been called' ); 101 | stop(); 102 | }, 103 | 104 | testReset: function() { 105 | Assert.areEqual( 0, this.resetCount, 'reset has not been called yet' ); 106 | this.form.bindEvent("reset", function() { 107 | Assert.isTrue(true, "reset event triggered"); 108 | start(); 109 | }); 110 | this.form.reset(); 111 | Assert.areEqual( 2, this.resetCount, 'reset has been called' ); 112 | stop(); 113 | }, 114 | 115 | testSave: function() { 116 | Assert.areEqual( 0, this.saveCount, 'save has not been called yet' ); 117 | 118 | this.validateReturn = true; 119 | this.form.bindEvent("save", function() { 120 | Assert.isTrue(true, "save event triggered"); 121 | start(); 122 | }); 123 | var valid = this.form.save(); 124 | 125 | Assert.areEqual( 2, this.saveCount, 'save has been called' ); 126 | Assert.isTrue( valid, 'form was valid' ); 127 | 128 | this.validateReturn = false; 129 | valid = this.form.save(); 130 | 131 | Assert.areEqual( 2, this.saveCount, 'form was not valid, save was not called' ); 132 | Assert.isFalse( valid, 'form was not valid' ); 133 | stop(); 134 | }, 135 | 136 | testTeardown: function() { 137 | this.form.teardown(); 138 | Assert.areEqual( 2, this.teardownCount, 'field teardown was called ' ); 139 | }, 140 | 141 | testBindFormElement: function() { 142 | var field = this.form.bindFormElement( '#formElement' ); 143 | Assert.isNotUndefined( field, 'field was created' ); 144 | }, 145 | 146 | testDefaultFieldFactory: function() { 147 | var form = AFrame.Form.create( { 148 | target: '#AFrame_Form' 149 | } ); 150 | var field = form.bindFormElement( '#formElement' ); 151 | 152 | Assert.isTrue( field instanceof AFrame.Field, 'default field factory creates a field' ); 153 | }, 154 | 155 | testOverrideFormFactory: function() { 156 | var overriddenFactoryCalled = false; 157 | AFrame.Form.setDefaultFieldFactory( function( element ) { 158 | overriddenFactoryCalled = true; 159 | } ); 160 | 161 | var form = AFrame.Form.create( { 162 | target: '#AFrame_Form' 163 | } ); 164 | form.bindFormElement( '#formElement' ); 165 | 166 | Assert.isTrue( overriddenFactoryCalled, 'overridden factory called' ); 167 | } 168 | } ); 169 | -------------------------------------------------------------------------------- /tests/test_aobject.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var aobject; 3 | 4 | testsToRun.push( { 5 | 6 | name: "TestCase AFrame.AObject", 7 | 8 | setUp: function() { 9 | aobject = new AFrame.AObject(); 10 | }, 11 | 12 | tearDown : function () { 13 | aobject.teardown(); 14 | aobject = null; 15 | }, 16 | 17 | testInit: function() { 18 | aobject.init( { 19 | configVal: true 20 | } ); 21 | 22 | var objectConfig = aobject.getConfig(); 23 | Assert.isTrue( objectConfig.configVal, 'configuration correctly set' ); 24 | }, 25 | 26 | testCIDSetInConfig: function() { 27 | aobject.init( { 28 | cid: 'testcid' 29 | } ); 30 | 31 | Assert.areEqual( 'testcid', aobject.getCID(), 'CID assigned correctly' ); 32 | }, 33 | 34 | testCIDAssigned: function() { 35 | aobject.init( {} ); 36 | 37 | Assert.isNotUndefined( aobject.getCID(), 'CID assigned automatically' ); 38 | }, 39 | 40 | testIsTriggeredNoListener: function() { 41 | Assert.isFalse( aobject.isEventTriggered( 'onInit' ), 'onInit event not triggered' ); 42 | var callback = function() {}; 43 | 44 | aobject.init( { 45 | configVal: true 46 | } ); 47 | 48 | Assert.isFalse( aobject.isEventTriggered( 'onInit' ), 'onInit event not triggered, no listener' ); 49 | 50 | }, 51 | 52 | testIsTriggeredListener: function() { 53 | Assert.isFalse( aobject.isEventTriggered( 'onInit' ), 'onInit event not triggered' ); 54 | var callback = function() {}; 55 | 56 | aobject.bindEvent( 'onInit', callback ); 57 | aobject.init( { 58 | configVal: true 59 | } ); 60 | 61 | Assert.isTrue( aobject.isEventTriggered( 'onInit' ), 'onInit event triggered' ); 62 | }, 63 | 64 | testTriggerEvent: function() { 65 | var triggeredEvent, extraParam = true; 66 | var callback = function( event, extra ) { 67 | triggeredEvent = event; 68 | extraParam = extra; 69 | }; 70 | 71 | aobject.bindEvent( 'onInit', callback ); 72 | aobject.triggerEvent( 'onInit' ); 73 | 74 | Assert.areEqual( 'onInit', triggeredEvent.type, 'triggeredEvent type is set' ); 75 | Assert.areEqual( aobject, triggeredEvent.target, 'triggeredEvent target is set' ); 76 | Assert.isUndefined( extraParam, 'extraParam is undefined' ); 77 | 78 | aobject.triggerEvent( 'onInit', 'blue' ); 79 | Assert.areEqual( 'blue', extraParam, 'extraParam is set to blue' ); 80 | }, 81 | 82 | testTriggerProxy: function() { 83 | var proxy = aobject.triggerProxy( 'proxiedEvent' ); 84 | 85 | var eventTriggered = false; 86 | aobject.bindEvent( 'proxiedEvent', function() { 87 | eventTriggered = true; 88 | } ); 89 | 90 | // call the proxied function 91 | proxy(); 92 | 93 | Assert.isTrue( eventTriggered, 'triggerProxy works' ); 94 | }, 95 | 96 | testAddChild: function() { 97 | var tornDown = false; 98 | var objectToTeardown = { 99 | teardown: function() { 100 | tornDown = true; 101 | }, 102 | getCID: function() { 103 | return 1; 104 | } 105 | }; 106 | 107 | aobject.init( {} ); 108 | aobject.addChild( objectToTeardown ); 109 | aobject.teardown(); 110 | Assert.isTrue( tornDown, 'child\'s teardown called' ); 111 | }, 112 | 113 | testRemoveChild: function() { 114 | var tornDown = false; 115 | var objectToRemove = { 116 | teardown: function() { 117 | tornDown = true; 118 | }, 119 | getCID: function() { 120 | return 1; 121 | } 122 | }; 123 | 124 | aobject.init( {} ); 125 | aobject.addChild( objectToRemove ); 126 | aobject.removeChild( 1 ); 127 | aobject.teardown(); 128 | Assert.isFalse( tornDown, 'child\'s teardown not called since it was already removed' ); 129 | }, 130 | 131 | testDeclareImportConfig: function() { 132 | var Class = AFrame.AObject.extend( { 133 | importconfig: [ 'blue' ] 134 | } ); 135 | 136 | var SubClass = Class.extend( { 137 | importconfig: [ 'green', 'indigo' ] 138 | } ); 139 | 140 | var instance = SubClass.create( { 141 | blue: 'blueish', 142 | green: 'greenish', 143 | indigo: 'indigoish', 144 | yellow: 'yellowish' 145 | } ); 146 | 147 | Assert.areEqual( 'blueish', instance.blue, 'blue imported correctly' ); 148 | Assert.areEqual( 'greenish', instance.green, 'green imported correctly' ); 149 | Assert.areEqual( 'indigoish', instance.indigo, 'indigo imported correctly' ); 150 | Assert.isUndefined( instance.yellow, 'yellow not imported' ); 151 | }, 152 | 153 | testDeclareBindings: function() { 154 | var event1HandlerCalled = false; 155 | var Class = AFrame.AObject.extend( { 156 | importconfig: [ 'insertedObj' ], 157 | events: { 158 | 'event1 insertedObj': function() { 159 | event1HandlerCalled = true; 160 | } 161 | } 162 | } ); 163 | 164 | 165 | var inserted = AFrame.AObject.create(); 166 | var instance = Class.create( { 167 | insertedObj: inserted 168 | } ); 169 | 170 | inserted.triggerEvent( 'event1' ); 171 | Assert.isTrue( event1HandlerCalled, 'the handler on inserted\'s event is called' ) 172 | }, 173 | 174 | testDeclarBindingsWithInheritance: function() { 175 | var eventCallCount = 0; 176 | var Super = AFrame.AObject.extend( { 177 | importconfig: [ 'insertedObj' ], 178 | events: { 179 | 'event1 insertedObj': function() { 180 | eventCallCount++; 181 | } 182 | } 183 | } ); 184 | 185 | var Sub = Super.extend(); 186 | 187 | var inserted = AFrame.AObject.create(); 188 | var instance = Sub.create( { 189 | insertedObj: inserted 190 | } ); 191 | 192 | inserted.triggerEvent( 'event1' ); 193 | Assert.areEqual( 1, eventCallCount, 'the handler was called once.' ) 194 | 195 | } 196 | } ); 197 | 198 | 199 | }()); 200 | -------------------------------------------------------------------------------- /tests/test_fieldPluginValidation.js: -------------------------------------------------------------------------------- 1 | testsToRun.push( { 2 | 3 | name: "TestCase AFrame.FieldPluginValidation", 4 | 5 | setUp: function() { 6 | this.field = AFrame.Field.create( { 7 | target: 'textarea[data-field][name=name]', 8 | } ); 9 | 10 | 11 | }, 12 | tearDown: function() { 13 | this.field.teardown(); 14 | this.field = null; 15 | }, 16 | 17 | testGetValidityState: function() { 18 | var validityState = this.field.getValidityState(); 19 | Assert.isTrue( validityState instanceof AFrame.FieldValidityState, 'getValidityState returns a FieldValidityState' ); 20 | }, 21 | 22 | testValidateValueMissing: function() { 23 | this.field.set( 'value' ); 24 | var isValid = this.field.validate(); 25 | 26 | Assert.isTrue( isValid, 'field is currently valid' ); 27 | 28 | this.field.set( '' ); 29 | isValid = this.field.validate( this.field ); 30 | 31 | Assert.isFalse( isValid, 'field is invalid, missing value' ); 32 | 33 | var validityState = this.field.getValidityState( this.field ); 34 | Assert.isTrue( validityState.valueMissing, 'valueMissing set to true' ); 35 | }, 36 | 37 | testValidatorAddedAsPlugin: function() { 38 | var ourValidatorCalled = false; 39 | 40 | var ValidatorPlugin = AFrame.FieldPluginValidation.extend( { 41 | validate: function() { 42 | ourValidatorCalled = true; 43 | } 44 | } ); 45 | 46 | var field = AFrame.Field.create( { 47 | target: 'textarea[data-field][name=name]', 48 | plugins: [ ValidatorPlugin ] 49 | } ); 50 | 51 | field.validate(); 52 | 53 | Assert.isTrue( ourValidatorCalled, 'plugin validator correctly overrides inline validator' ); 54 | }, 55 | 56 | testInvalidEvent: function() { 57 | var target = jQuery( 'textarea[data-field][name=name]' ); 58 | target.val( '' ); 59 | 60 | var field = AFrame.Field.create( { 61 | target: 'textarea[data-field][name=name]' 62 | } ); 63 | 64 | var invalidTriggered = false; 65 | AFrame.DOM.bindEvent( 'textarea[data-field][name=name]', 'invalid', function( event ) { 66 | invalidTriggered = true; 67 | } ); 68 | 69 | field.setError( 'fakeError' ); 70 | Assert.isTrue( invalidTriggered, 'setError causes invalid event' ); 71 | 72 | invalidTriggered = false; 73 | field.setCustomValidity( 'custom validity' ); 74 | Assert.isTrue( invalidTriggered, 'setCustomValidity causes invalid event' ); 75 | }, 76 | 77 | testManualErrorShowsStandardErrors: function() { 78 | var target = jQuery( 'textarea[data-field][name=name]' ); 79 | target.val( '' ); 80 | 81 | var field = AFrame.Field.create( { 82 | target: 'textarea[data-field][name=name]' 83 | } ); 84 | 85 | field.setError( 'fakeError' ); 86 | 87 | var validityState = field.getValidityState(); 88 | Assert.isTrue( validityState.valueMissing, 'setError sets the valueMissing field as well.' ); 89 | 90 | // this resets the errors. 91 | field.set( '' ); 92 | 93 | field.setCustomValidity( 'custom validity' ); 94 | 95 | var validityState = field.getValidityState(); 96 | Assert.isTrue( validityState.valueMissing, 'setCustomValidity sets the valueMissing field as well.' ); 97 | }, 98 | 99 | testGetCriteria: function() { 100 | var target = jQuery( 'input#validationField' ); 101 | var field = { 102 | getTarget: function() { 103 | return AFrame.DOM.getElements( 'input#validationField' ); 104 | }, 105 | bindEvent: function() {} 106 | }; 107 | 108 | var validation = AFrame.FieldPluginValidation.create( { 109 | plugged: field 110 | } ); 111 | 112 | var criteria = validation.getCriteria(); 113 | Assert.areSame( 'text', criteria.type, 'input with no type sets type to text' ); 114 | 115 | Assert.isUndefined( criteria.min, 'min not set' ); 116 | target.attr( 'min', 10 ); 117 | criteria = validation.getCriteria(); 118 | Assert.areSame( 10, criteria.min, 'min set on criteria' ); 119 | 120 | 121 | Assert.isUndefined( criteria.max, 'max not set' ); 122 | target.attr( 'max', 100 ); 123 | criteria = validation.getCriteria(); 124 | Assert.areSame( 100, criteria.max, 'max set on criteria' ); 125 | 126 | 127 | Assert.isUndefined( criteria.required, 'required not set' ); 128 | target.attr( 'required', 'required' ); 129 | criteria = validation.getCriteria(); 130 | Assert.isTrue( criteria.required, 'required set on criteria' ); 131 | 132 | 133 | Assert.isUndefined( criteria.step, 'step not set' ); 134 | target.attr( 'step', .25 ); 135 | criteria = validation.getCriteria(); 136 | Assert.areSame( .25, criteria.step, 'step set on criteria' ); 137 | 138 | 139 | Assert.isUndefined( criteria.maxlength, 'maxlength not set' ); 140 | target.attr( 'maxlength', '15' ); 141 | criteria = validation.getCriteria(); 142 | Assert.areSame( 15, criteria.maxlength, 'maxlength set on criteria' ); 143 | 144 | Assert.isUndefined( criteria.pattern, 'pattern not set' ); 145 | target.attr( 'pattern', 'abc' ); 146 | criteria = validation.getCriteria(); 147 | Assert.areSame( 'abc', criteria.pattern, 'pattern set on criteria' ); 148 | 149 | } 150 | } ); 151 | -------------------------------------------------------------------------------- /tests/test_collectionPluginModel.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var schemaConfig = { 3 | name: { type: 'text' }, 4 | employer: { type: 'text', 'def': 'AFrame Foundary' } 5 | }; 6 | 7 | var testModel = AFrame.Model.extend( { 8 | schema: schemaConfig 9 | } ); 10 | 11 | testsToRun.push( { 12 | 13 | name: "TestCase AFrame.CollectionPluginModel", 14 | 15 | setUp: function() { 16 | this.collection = AFrame.CollectionArray.create( { 17 | plugins: [ AFrame.CollectionPluginPersistence, 18 | [ AFrame.CollectionPluginModel, { 19 | schema: schemaConfig 20 | } ] 21 | ] 22 | } ); 23 | }, 24 | 25 | teardDown: function() { 26 | this.collection.teardown(); 27 | }, 28 | 29 | testInsertData: function() { 30 | this.collection.insert( { 31 | name: 'Shane Tomlinson', 32 | } ); 33 | 34 | var model = this.collection.get( 0 ); 35 | 36 | Assert.areSame( true, model instanceof AFrame.Model, 'Inserted data creates a model' ); 37 | 38 | Assert.areSame( 'Shane Tomlinson', model.get( 'name' ) ); 39 | 40 | // use default value 41 | Assert.areSame( 'AFrame Foundary', model.get( 'employer' ) ); 42 | }, 43 | 44 | testInsertModel: function() { 45 | var model = AFrame.Model.create( { 46 | schema: schemaConfig, 47 | data: { 48 | name: 'Shane Tomlinson' 49 | } 50 | } ); 51 | 52 | var cid = this.collection.insert( model ); 53 | 54 | var model = this.collection.get( 0 ); 55 | 56 | Assert.areSame( 'Shane Tomlinson', model.get( 'name' ) ); 57 | Assert.isNotUndefined( cid, 'cid is still defined' ); 58 | }, 59 | 60 | testAddData: function() { 61 | var beforeAddItem; 62 | this.collection.bindEvent( 'onBeforeAdd', function( event ) { 63 | beforeAddItem = event.item; 64 | } ); 65 | 66 | this.collection.add( { 67 | name: 'Shane Tomlinson', 68 | } ); 69 | 70 | var model = this.collection.get( 0 ); 71 | Assert.areSame( true, beforeAddItem instanceof AFrame.Model, 'Inserted data creates a model' ); 72 | }, 73 | 74 | testAddModel: function() { 75 | var beforeAddItem; 76 | this.collection.bindEvent( 'onBeforeAdd', function( event ) { 77 | beforeAddItem = event.item; 78 | } ); 79 | 80 | var model = AFrame.Model.create( { 81 | schema: schemaConfig, 82 | data: { 83 | name: 'Shane Tomlinson' 84 | } 85 | } ); 86 | 87 | this.collection.add( model ); 88 | 89 | var model = this.collection.get( 0 ); 90 | Assert.areSame( model, beforeAddItem, 'Inserted uses given model' ); 91 | }, 92 | 93 | testAddNotAddedIfNoPersistencePlugin: function() { 94 | var collection = AFrame.CollectionArray.create( { 95 | plugins: [ 96 | [ AFrame.CollectionPluginModel, { 97 | schema: schemaConfig 98 | } ] 99 | ] 100 | } ); 101 | 102 | Assert.isUndefined( collection.add, 'add not added, no persistence plugin' ); 103 | }, 104 | 105 | testUseModelForSchema: function() { 106 | var TestModel = AFrame.Model.extend( { 107 | schema: schemaConfig 108 | } ); 109 | 110 | var collection = AFrame.CollectionArray.create( { 111 | plugins: [ AFrame.CollectionPluginPersistence, 112 | [ AFrame.CollectionPluginModel, { 113 | schema: TestModel 114 | } ] 115 | ] 116 | } ); 117 | 118 | collection.add( { 119 | name: 'Shane Tomlinson' 120 | } ); 121 | 122 | var model = collection.get( 0 ); 123 | Assert.isTrue( model instanceof TestModel, 'new model is an instace of TestModel' ); 124 | 125 | } 126 | 127 | 128 | } ); 129 | 130 | function OverrideModel( data ) { 131 | var data = data; 132 | this.get = function( name ) { 133 | return data[ name ]; 134 | }; 135 | }; 136 | 137 | var modelFactory = function( data ) { 138 | return new OverrideModel( data ); 139 | }; 140 | 141 | testsToRun.push( { 142 | 143 | name: "TestCase AFrame.CollectionPluginModel with overridden modelFactory", 144 | 145 | setUp: function() { 146 | this.collection = AFrame.CollectionArray.create( { 147 | plugins: [ [ AFrame.CollectionPluginModel, { 148 | schema: schemaConfig, 149 | modelFactory: modelFactory 150 | } ] ] 151 | } ); 152 | }, 153 | 154 | teardDown: function() { 155 | this.collection.teardown(); 156 | }, 157 | 158 | testInsertData: function() { 159 | this.collection.insert( { 160 | name: 'Shane Tomlinson', 161 | } ); 162 | 163 | var model = this.collection.get( 0 ); 164 | 165 | Assert.areSame( true, model instanceof OverrideModel, 'Inserted data creates an overridden model' ); 166 | 167 | Assert.areSame( 'Shane Tomlinson', model.get( 'name' ) ); 168 | } 169 | } ); 170 | }() ); 171 | -------------------------------------------------------------------------------- /src/class.js: -------------------------------------------------------------------------------- 1 | AFrame.Class = ( function() { 2 | "use strict"; 3 | 4 | /** 5 | * A shortcut to create a new class with a default constructor. A default 6 | * constructor does nothing unless it has a superclass, where it calls the 7 | * superclasses constructor. If the first parameter to Class is a function, 8 | * the parameter is assumed to be the superclass. All other parameters 9 | * should be objects which are mixed in to the new classes prototype. 10 | * 11 | * If a new class needs a non-standard constructor, the class constructor should 12 | * be created manually and then any mixins/superclasses set up using the 13 | * [AFrame.extend](#method_extend) function. 14 | * 15 | * // Create a class that is not subclassed off of anything 16 | * var Class = AFrame.Class( { 17 | * anOperation: function() { 18 | * // do an operation here 19 | * } 20 | * } ); 21 | * 22 | * // Create a Subclass of Class 23 | * var SubClass = Class.extend( { 24 | * anOperation: function() { 25 | * // do an operation here 26 | * } 27 | * } ); 28 | * 29 | * @method Class 30 | * @param {function} superclass (optional) - superclass to use. If not given, class has 31 | * no superclass. 32 | * @param {object} 33 | * @return {function} - the new class. 34 | */ 35 | var Class = function() { 36 | var args = [].slice.call( arguments, 0 ), 37 | F = createChain( args ); 38 | 39 | addMixins( F, args ); 40 | addCreate( F ); 41 | addExtend( F ); 42 | 43 | return F; 44 | }; 45 | 46 | /** 47 | * Walk the class chain of an object. The object must be an AFrame.Class/AFrame.extend based. 48 | * 49 | * // Walk the object's class chain 50 | * // SubClass is an AFrame.Class based class 51 | * var obj = SubClass.create(); 52 | * AFrame.Class.walkChain( function( currClass ) { 53 | * // do something. Context of function is the obj 54 | * }, obj ); 55 | * 56 | * @method AFrame.Class.walkChain 57 | * @param {function} callback - callback to call. Called with two parameters, currClass and 58 | * obj. 59 | * @param {AFrame.Class} obj - object to walk. 60 | */ 61 | Class.walkChain = function( callback, obj ) { 62 | var currClass = obj.constructor; 63 | do { 64 | callback.call( obj, currClass ); 65 | currClass = currClass.superclass; 66 | } while( currClass ); 67 | }; 68 | 69 | function createChain( args ) { 70 | var F; 71 | if( AFrame.func( args[ 0 ] ) ) { 72 | // we have a superclass, do everything related to a superclass 73 | F = chooseConstructor( args[ 1 ], function() { 74 | F.sc.constructor.call( this ); 75 | } ); 76 | extendWithSuper( F, args[ 0 ] ); 77 | args.splice( 0, 1 ); 78 | } 79 | else { 80 | F = chooseConstructor( args[ 0 ], function() {} ); 81 | } 82 | return F; 83 | } 84 | 85 | function chooseConstructor( checkForConst, alternate ) { 86 | var F; 87 | if( checkForConst && checkForConst.hasOwnProperty( 'constructor' ) ) { 88 | F = checkForConst.constructor; 89 | } 90 | else { 91 | F = alternate; 92 | } 93 | return F; 94 | } 95 | 96 | function extendWithSuper( subClass, superClass ) { 97 | var F = function() {}; 98 | F.prototype = superClass.prototype; 99 | subClass.prototype = new F; 100 | subClass.superclass = superClass; // superclass and sc are different. sc points to the superclasses prototype, superclass points to the superclass itself. 101 | subClass.sc = superClass.prototype; 102 | 103 | var mixins = [].slice.call( arguments, 2 ); 104 | for( var mixin, index = 0; mixin = mixins[ index ]; ++index ) { 105 | AFrame.mixin( subClass.prototype, mixin ); 106 | } 107 | subClass.prototype.constructor = subClass; 108 | 109 | addCreate( subClass ); 110 | } 111 | 112 | function addMixins( F, args ) { 113 | for( var mixin, index = 0; mixin = args[ index ]; ++index ) { 114 | AFrame.mixin( F.prototype, mixin ); 115 | } 116 | 117 | // Always set the constructor last in case any mixins overwrote it. 118 | F.prototype.constructor = F; 119 | } 120 | 121 | /** 122 | * @private 123 | * Add a create function to a Class if the Class has an init function. 124 | * The create function is an alias to call AFrame.create with this 125 | * class. 126 | * 127 | * @method addCreate 128 | * @param {function} Class 129 | */ 130 | function addCreate( _class ) { 131 | if( _class.prototype && AFrame.func( _class.prototype.init ) && !_class.create ) { 132 | // Add a create function so that every _class with init has one. 133 | _class.create = Class.create.bind( null, _class ); 134 | } 135 | } 136 | 137 | function addExtend( F ) { 138 | F.extend = Class.bind( null, F ); 139 | } 140 | 141 | Class.create = function( construct, config ) { 142 | var retval; 143 | if( construct ) { 144 | try { 145 | retval = new construct; 146 | } catch ( e ) { 147 | AFrame.log( e.toString() ); 148 | } 149 | 150 | AFrame.Class.walkChain( function( currClass ) { 151 | if( currClass.prototype && currClass.prototype.hasOwnProperty( 'plugins' ) ) { 152 | addPlugins( retval, currClass.prototype.plugins ); 153 | } 154 | }, retval ); 155 | 156 | config = config || {}; 157 | addPlugins( retval, config.plugins || [] ); 158 | 159 | retval.init( config ); 160 | } 161 | else { 162 | throw 'Class does not exist.'; 163 | } 164 | return retval; 165 | } 166 | 167 | function addPlugins( plugged, plugins ) { 168 | // recursively create and bind any plugins 169 | for( var index = 0, plugin; plugin = plugins[ index ]; ++index ) { 170 | plugin = AFrame.array( plugin ) ? plugin : [ plugin ]; 171 | var pluginConfig = AFrame.mixin( { plugged: plugged }, plugin[ 1 ] || {} ); 172 | plugin[ 0 ].create( pluginConfig ); 173 | } 174 | } 175 | 176 | return Class; 177 | }() ); 178 | -------------------------------------------------------------------------------- /src/field.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The base class for a field. A field is a basic unit for a form. With the new HTML5 spec, 3 | * each form field has an invalid event. Some browsers display an error message whenever the 4 | * invalid event is triggered. If default browser error message handling is desired, set 5 | * AFrame.Field.cancelInvalid = false. If cancelInvalid is set to true, the invalid event will 6 | * have its default action prevented. Field validation is taken care of through the [FieldPluginValidation](AFrame.FieldPluginValidation.html). 7 | * All Fields will have a FieldPluginValidation created for them unless one is already created 8 | * and attached as a plugin. To override the default validation for a field, subclass FieldPluginValidation 9 | * and attach the subclass as a plugin on field creation. 10 | * 11 | * A working example is found on [JSFiddle](http://jsfiddle.net/shane_tomlinson/s48Cn/) 12 | * 13 | * 14 | * 15 | * --------- 16 | * 17 | * var field = AFrame.Field.create( { 18 | * target: '#numberInput' 19 | * } ); 20 | * 21 | * // Set the value of the field, it is now displaying 3.1415 22 | * field.set(3.1415); 23 | * 24 | * // The field is cleared, displays nothing 25 | * field.clear(); 26 | * 27 | * var val = field.get(); 28 | * 29 | * 30 | * @class AFrame.Field 31 | * @extends AFrame.Display 32 | * @constructor 33 | */ 34 | AFrame.Field = ( function() { 35 | "use strict"; 36 | 37 | var Field = AFrame.Display.extend( { 38 | domevents: { 39 | keyup: 'onFieldChange', 40 | invalid: 'onFieldInvalid' 41 | }, 42 | 43 | init: function( config ) { 44 | createValidator.call( this ); 45 | 46 | Field.sc.init.call( this, config ); 47 | 48 | this.save(); 49 | }, 50 | 51 | /** 52 | * Set the value of the field and display the value. Sets the rest value to the value entered. 53 | * 54 | * nameField.set( 'AFrame' ); 55 | * 56 | * @method set 57 | * @param {variant} val value to display 58 | */ 59 | set: function( val ) { 60 | this.resetVal = val; 61 | this.display( val ); 62 | this.onFieldChange(); 63 | }, 64 | 65 | /** 66 | * Display a value, does not affect the reset value. Using this function can be useful to 67 | * change how a piece of data is visually represented on the screen. 68 | * 69 | * nameField.display( 'AFrame' ); 70 | * 71 | * @method display 72 | * @param {variant} val value to dipslay 73 | */ 74 | display: function( val ) { 75 | var target = this.getTarget(); 76 | AFrame.DOM.setInner( target, val || '' ); 77 | }, 78 | 79 | /** 80 | * Get the value that is displayed in the field. This can be different from what get returns 81 | * if the visual representation of the data is different from the data itself. 82 | * 83 | * var displayed = nameField.getDisplayed(); 84 | * console.log( 'displayedValue: ' + displayed ); 85 | * 86 | * @method getDisplayed 87 | * @returns {string} 88 | */ 89 | getDisplayed: function() { 90 | var target = this.getTarget(); 91 | return AFrame.DOM.getInner( target ); 92 | }, 93 | 94 | /** 95 | * Get the value of the field. This should be overridden by subclasses to convert field string 96 | * values to whatever native value that is expected. This means, the value returned by get 97 | * can be different if the visual representation is different from the underlying data. 98 | * Returns an empty string if no value entered. 99 | * 100 | * var val = nameField.get(); 101 | * 102 | * @method get 103 | * @return {variant} the value of the field 104 | */ 105 | get: function() { 106 | return this.getDisplayed(); 107 | }, 108 | 109 | /** 110 | * Reset the field to its last 'set' value. 111 | * 112 | * nameField.reset(); 113 | * 114 | * @method reset 115 | */ 116 | reset: function() { 117 | this.set( this.resetVal ); 118 | }, 119 | 120 | /** 121 | * Clear the field. A reset after this will cause the field to go back to the blank state. 122 | * 123 | * nameField.clear(); 124 | * 125 | * @method clear 126 | */ 127 | clear: function() { 128 | this.set( '' ); 129 | }, 130 | 131 | /** 132 | * Save the current value as a reset point 133 | * 134 | * nameField.save(); 135 | * 136 | * @method save 137 | */ 138 | save: function() { 139 | var displayed = this.getDisplayed(); 140 | 141 | if( !displayed.length ) { 142 | var undefined; 143 | displayed = undefined; 144 | } 145 | 146 | this.resetVal = displayed; 147 | }, 148 | 149 | onFieldChange: function() { 150 | /** 151 | * triggered whenever the field value changes 152 | * @event onChange 153 | * @param {string} fieldVal - the current field value. 154 | */ 155 | this.triggerEvent( 'onChange', this, this.get() ); 156 | }, 157 | 158 | onFieldInvalid: function( event ) { 159 | if( Field.cancelInvalid ) { 160 | event && event.preventDefault(); 161 | } 162 | } 163 | } ); 164 | Field.cancelInvalid = true; 165 | 166 | function createValidator() { 167 | if( !this.validate ) { 168 | var fieldValidator = AFrame.FieldPluginValidation.create( { 169 | plugged: this 170 | } ); 171 | } 172 | } 173 | 174 | 175 | 176 | return Field; 177 | }() ); 178 | --------------------------------------------------------------------------------