diff --git a/.gitignore b/.gitignore index a8507049..75eb2460 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,8 @@ dist build/github/jquerypp docs/* npm-debug.log +build/ci/can +build/ci/jquery +build/ci/funcunit +build/ci/steal +dist/ \ No newline at end of file diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..96725b65 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,54 @@ +{ + "globals": { + + "steal": true, + "can": true, + + + "Zepto": true, + + + "QUnit": true, + "test": true, + "asyncTest": true, + "expect": true, + "module": true, + "ok": true, + "equal": true, + "notEqual": true, + "deepEqual": true, + "notDeepEqual": true, + "strictEqual": true, + "notStrictEqual": true, + "raises": true, + "start": true, + "stop": true + }, + + + "curly": true, + "eqeqeq": true, + "freeze": true, + "indent": 2, + "latedef": true, + "noarg": true, + "undef": true, + "unused": "vars", + "trailing": true, + "maxdepth": 4, + "boss" : true, + + "eqnull": true, + "evil": true, + "loopfunc": true, + "smarttabs": true, + "maxerr" : 200, + + "jquery": true, + "dojo": true, + "mootools": true, + "yui": true, + "browser": true, + "phantom": true, + "rhino": true +} diff --git a/.npmignore b/.npmignore new file mode 100644 index 00000000..05a9d0cf --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +!dist/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 62037d2e..7fbd8557 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: node_js -node_js: 0.8 -before_script: build/ci/init.sh -script: phantomjs build/ci/phantom.js http://localhost:8000/jquery/qunit.html \ No newline at end of file +before_install: + - "export DISPLAY=:99.0" + - "sh -e /etc/init.d/xvfb start" +node_js: 0.10 diff --git a/1x1.jpg b/1x1.jpg new file mode 100644 index 00000000..b0d69110 Binary files /dev/null and b/1x1.jpg differ diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..394c62a9 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,104 @@ +var path = require('path'); +var normalize = function(depName, depLoad, curName, curLoad) { + depName = depName.substring(depName.indexOf('#') + 1, depName.length); + + if(depName === 'dist/jquery') { + return 'jquery'; + } + + if(curLoad) { + depName = path.relative(path.dirname(curLoad.address), depLoad.address); + if(depName[0] !== '.') { + depName = './' + depName; + } + } + + return depName; +}; + +module.exports = function (grunt) { + var _ = grunt.util._; + var builderJSON = grunt.file.readJSON('builder.json'); + var pkg = grunt.file.readJSON('package.json'); + + grunt.initConfig({ + jshint: { + options: { + jshintrc: true + }, + lib: [ + 'dom/**/*.js', 'event/**/*.js', 'lang/**/*.js', 'test/**/*.js' + ] + }, + + 'steal-export': { + dist: { + system: { + config: "package.json!npm", + main: "jquerypp" + }, + outputs: { + "cjs": { + graphs: ['jquerypp'], + format: 'cjs', + useNormalizedDependencies: true, + ignore: ['jquery'], + normalize: normalize, + dest: function(moduleName){ + return path.join(__dirname, 'dist/cjs/' + normalize(moduleName) + '.js'); + } + }, + "amd": { + graphs: ['jquerypp'], + format: 'amd', + useNormalizedDependencies: true, + ignore: ['jquery'], + normalize: normalize, + dest: function(moduleName){ + return path.join(__dirname, 'dist/amd/' + normalize(moduleName) + '.js'); + } + }, + "+global-js": { + ignore: ['jquery'], + exports: { 'jquery/jquery': 'jQuery' } + }, + 'min +global-js': { + minify: true, + dest: path.join(__dirname, 'dist/global/jquerypp.min.js') + } + } + } + }, + + usebanner: { + taskName: { + options: { + position: 'top', + banner: _.template(builderJSON.banner, { + pkg: pkg, + ids: [ 'jQuery++ dist build' ] + }), + linebreak: true + }, + files: { + src: [ 'dist/**/*.js' ] + } + } + }, + + testee: { + options: { + browsers: [ 'firefox' ] + }, + all: ['test.html'] + } + }); + + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('testee'); + grunt.loadNpmTasks('steal-tools'); + grunt.loadNpmTasks('grunt-banner'); + + grunt.registerTask('test', ['testee']); + grunt.registerTask('build', ['steal-export', 'usebanner']); +}; diff --git a/bower.json b/bower.json new file mode 100644 index 00000000..914e3ce5 --- /dev/null +++ b/bower.json @@ -0,0 +1,17 @@ +{ + "name": "jquerypp", + "title": "jQuery++", + "version": "2.0.0", + "repo": "bitovi/canjs", + "description": "jQuery's missing utils and special events", + "main": "can.jquery.js", + "keywords": [ + "mvc", + "canjs", + "can", + "requirejs", + "component", + "amd" + ], + "license": "MIT" +} \ No newline at end of file diff --git a/build/amdify.js b/build/amdify.js deleted file mode 100644 index 017d50cf..00000000 --- a/build/amdify.js +++ /dev/null @@ -1,140 +0,0 @@ -steal('steal/build', 'steal/build/pluginify', function(steal) { - var contents = {}, - modules = {}, - inexcludes = function(excludes, src) { - for(var i = 0; i < excludes.length; i++) { - if(src.indexOf(excludes[i]) !== -1) { - return true; - } - } - return false; - }, - /** - * Creates a variable name from a filename or AMD module name. - * - * @param {String} name The name of the AMD module or file - * @return {String} The variable name - */ - variableName = function(name) { - var start = name.lastIndexOf('/') + 1, - end = name.lastIndexOf('.') !== -1 ? name.lastIndexOf('.') : name.length; - return '__' + name.substring(start, end).replace(/\./g, '_'); - }, - /** - * Returns a steal.File instance from a filename or AMD module name. - * - * @param name - * @param suffix - * @return {*} - */ - getFile = function(name, suffix) { - var suffix = suffix || '.js', file = name; - if(name.indexOf(suffix, name.length - suffix.length) === -1) { - file = file + suffix; - } - return steal.File(file); - }, - /** - * Returns a list of steal dependencies for a given file and caches - * the plain content. - * - * @param {String} file The JavaScript file to load - * @param {Array} excludes A list of dependencies to exclude - * @param {Object} options Options - * @param {Function} callback A callback getting passed an array - * of steals - */ - getDependencies = function(file, excludes, options, callback) { - steal.build.open("steal/rhino/empty.html", { - startFile : file, - skipCallbacks: true - }, function(opener){ - var ret = []; - opener.each(function(stl, text){ - if(!inexcludes(excludes || [], stl.rootSrc.toString())) { - // Add the parsed content to cache - if(!contents[stl.rootSrc.toString().toString()]) { - contents[stl.rootSrc.toString()] = steal.build.pluginify.content(stl, options, text); - } - ret.push(stl); - } - }); - callback(ret); - }, null); - }, - /** - * Creates the actual module recursively - * - * @param {String} name The name of the main module file - * @param {Array} excludes A list of files to exclude - * @param {Object} options The options to use - */ - createModule = function(name, excludes, options) { - getDependencies(name, excludes, options, function(steals) { - var content, - dependencies = [], - names = [], - nameMap = options.names || {}, - map = options.map || {}, - where = getFile(options.out + (map[name] || name)); - - print(' > ' + name + ' -> ' + (map[name] || name)); - - steals.forEach(function(stl) { - var current = (map[stl.rootSrc.toString()] || stl.rootSrc.toString()); - if(stl.rootSrc.toString() !== name) { // Don't include the current file - if(!modules[stl.rootSrc.toString()]) { - createModule(stl.rootSrc.toString(), excludes, options); - } - dependencies.push("'" + current + "'"); - names.push(nameMap[current] || variableName(current)); - } - }); - - content = "define([" + - dependencies.join(',') + - '], function(' + - names.join(', ') + - ') { \n' + - (contents[name] || (' return ' + (options.global || '{}'))) + - ';\n})'; - - modules[name] = content; - - steal.File(where.dir()).mkdirs(); - where.save(content); - }); - }; - - /** - * Creates a set of AMD modules recursively. The `map` options contain a mapping from Steal - * rootSrc filenames to AMD module names. For examples: - * - * { "jquery/dom/compare/compare.js" : "jquerypp/compare" } - * - * Will map "jquery/dom/compare/compare.js" to "jquerypp/compare.js" in the output folder - * and all dependencies as well (e.g. dependent files would `define(['jquery/compare'], ...)`. - * By default it will use the Steal rootSrc name. - * The `names` mapping can be used to map AMD module names to variable names passed to the - * pluginified function. By default this will be the filename without extension, `__` prefixed and - * `.` converted to `_` (looking like `define(['jquery/compare`], function(__compare) { ... })`). - * - * @param {String} source The root JavaScript source file name to generate the modules from. - * @param {Object} options The options for generating AMD modules. - * The following options will be used: - * - * - `out` - The output folder - * - `excludes` - An array of files to exclude (must be the full Steal rootSrc) - * - `map` - A mapping from full Steal rootSrc filenames to the AMD module name. - * Any missing folders will be created automatically. - * - `names` - A mapping from AMD module names (as set in `map` or the default) - * to parameter variable names. - * - `global` - The global option passed to pluginify - */ - steal.build.amdify = function(source, options) { - var out = options.out; - print('Creating AMD modules for ' + source + " in " + options.out); - steal.File(out).mkdirs(); - createModule(source, options.exclude || {}, options); - } -}); diff --git a/build/ci/init.sh b/build/ci/init.sh deleted file mode 100755 index 76f97097..00000000 --- a/build/ci/init.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -BASEDIR=$(dirname $0) -cd $BASEDIR -../../node_modules/.bin/http-server -p 8000 & -git clone https://github.com/jupiterjs/canjs.git can -git clone https://github.com/jupiterjs/steal.git -git clone https://github.com/jupiterjs/jquerypp.git jquery -git clone https://github.com/jupiterjs/funcunit.git -cd funcunit -git submodule update --init --recursive \ No newline at end of file diff --git a/build/ci/phantom.js b/build/ci/phantom.js deleted file mode 100644 index 9200da17..00000000 --- a/build/ci/phantom.js +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Qt+WebKit powered headless test runner using Phantomjs - * - * Phantomjs installation: http://code.google.com/p/phantomjs/wiki/BuildInstructions - * - * Run with: - * phantomjs runner.js [url-of-your-qunit-testsuite] - * - * E.g. - * phantomjs runner.js http://localhost/qunit/test - */ - -var url = phantom.args[0]; - -var page = require('webpage').create(); - -// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this") -page.onConsoleMessage = function(msg) { - console.log(msg); -}; - -page.open(url, function(status){ - if (status !== "success") { - console.log("Unable to access network: " + status); - phantom.exit(1); - } else { - // page.evaluate(addLogging); - var interval = setInterval(function() { - if (finished()) { - clearInterval(interval); - onfinishedTests(); - } - }, 500); - } -}); - -page.onResourceReceived = function(data) { - page.evaluate(function(addLogging) { - // Only add setZeroTimeout to the window object, and hide everything - // else in a closure. - (function() { - var timeouts = []; - var messageName = "zero-timeout-message"; - - // Like setTimeout, but only takes a function argument. There's - // no time argument (always zero) and no arguments (you have to - // use a closure). - function setZeroTimeout(fn) { - timeouts.push(fn); - window.postMessage(messageName, "*"); - } - - function handleMessage(event) { - if (event.source == window && event.data == messageName) { - event.stopPropagation(); - if (timeouts.length > 0) { - var fn = timeouts.shift(); - fn(); - } - } - } - - window.addEventListener("message", handleMessage, true); - - // Add the one thing we want added to the window object. - window.setZeroTimeout = setZeroTimeout; - })(); - - setZeroTimeout(function() { - if(window.QUnit && !window.QUnit.__logging) { - console.log('Adding logging'); - addLogging(); - window.QUnit.__logging = true; - } - }); - }, addLogging); -} - -function finished() { - return page.evaluate(function(){ - return !!window.qunitDone; - }); -} - -function onfinishedTests() { - var output = page.evaluate(function() { - return JSON.stringify(window.qunitDone); - }); - phantom.exit(JSON.parse(output).failed > 0 ? 1 : 0); -} - -function addLogging() { - var print = function(msg) { - console.log(msg); - }; - - QUnit.begin(function() { - print("Starting ..."); - }); - - QUnit.log(function(o){ - var result = o.result, - message = o.message || 'okay'; - - // Testdox layout - if(result) { - print(' [x] ' + message); - } else { - print(' [ ] ' + message); - if(o.expected) { - print(' Actual: ' + o.actual); - print(' Expected: ' + o.expected); - } - } - }); - - QUnit.testStart(function(o){ - print(' ' + o.name); - }); - - QUnit.moduleStart(function(o){ - print("\n" + o.name); - }); - - QUnit.done(function(o) { - if(o.failed > 0) { - print("\n" + 'FAILURES!'); - print('Tests: ' + o.total - + ', Passed: ' + o.passed, - + ', Failures: ' + o.failed); - } else { - print("\n" + 'SUCESS!'); - print('Tests: ' + o.total); - } - print('Took: ' + o.runtime + 'ms'); - window.qunitDone = true; - }); -} diff --git a/build/ci/stealconfig.js b/build/ci/stealconfig.js deleted file mode 100644 index 08bbeefe..00000000 --- a/build/ci/stealconfig.js +++ /dev/null @@ -1,18 +0,0 @@ -steal.config({ - map: { - "*": { - 'jquery/jquery.js' : "jquery", - "can/util/util.js": "can/util/jquery/jquery.js" - } - }, - paths: { - "jquery": "can/util/jquery/jquery.1.8.1.js" - }, - ext: { - js: "js", - css: "css", - less: "steal/less/less.js", - coffee: "steal/coffee/coffee.js", - ejs: "can/view/ejs/ejs.js" - } -}) diff --git a/build/docco/.gitignore b/build/docco/.gitignore deleted file mode 100644 index 0820d537..00000000 --- a/build/docco/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -temp -docs diff --git a/build/docco/generate.js b/build/docco/generate.js deleted file mode 100644 index 8f14d00f..00000000 --- a/build/docco/generate.js +++ /dev/null @@ -1,146 +0,0 @@ -var path = require('path'), - fs = require('fs'), - child_process = require('child_process'), - os = require('os'), - - // Resolve directories - rhinoDir = path.join( path.dirname( fs.realpathSync( __filename )), '../../..' ), - jqueryDir = path.join( rhinoDir, 'jquery' ), - docsDir = path.join( jqueryDir, "docs" ), - doccoDir = path.join( jqueryDir, "build/docco" ), - doccoOutDir = path.join( doccoDir, "docs" ), - sourceDir = path.join( doccoDir, 'standalone' ), - makePath = path.join( doccoDir, "makestandalone.js" ), - genCommand; - -function execCommandWithOutput( command, cwd, callback ) { - - var spawn, parts; - - parts = command.split(" "); - spawn = child_process.spawn( parts.shift(), parts, { - cwd : cwd, - env : process.env - }); - - ["stdout", "stderr"].forEach( function( stream ) { - spawn[stream].setEncoding("utf-8"); - spawn[stream].pipe( process[stream] ); - }); - - spawn.on("exit", callback ); - -} - -function runDocco() { - - fs.mkdir(docsDir, function() { - - fs.readdir( path.join( doccoDir, "temp" ), function( err, files ) { - - files = files.map(function( file ) { - return path.join( "temp", file ); - }); - - var command = os.platform() != "win32" ? - "node_modules/docco/bin/docco " : - "sh node_modules/docco/bin/docco "; - - console.log( "Generating docco annotated source..." ); - - - execCommandWithOutput( command + files.join(" "), doccoDir, function( exitCode ) { - if ( exitCode == 0 ) { - fs.readdir( doccoOutDir, function( err, files ) { - console.log("Moving files into place..."); - files.forEach(function( file ) { - console.log( "\t" + file ); - fs.renameSync( path.join( doccoDir, "docs", file ), path.join( jqueryDir, "docs", file )); - }); - console.log("Cleaning up..."); - ["temp", "standalone", "docs"].forEach(function( dir ) { - fs.readdir( path.join( doccoDir, dir ), function( e, files ) { - files.forEach(function( file ) { - fs.unlinkSync( path.join( doccoDir, dir, file )); - }); - fs.rmdir( path.join( doccoDir, dir )); - }); - }); - console.log("Done!"); - }); - } else { - console.log("Error generating annotated source."); - } - }); - - }); - - - }); - -} - -function format( exitCode ) { - - if ( exitCode != 0 ) { - console.log("Error generating unminified sources."); - return - } - - fs.readdir( sourceDir, function( err, files ) { - - var count = 0; - - if ( ! files.length ) { - console.log("Error - Source directory is empty"); - } - - // Only annotate full srcs - files = files.filter(function( file ) { - return file.indexOf(".min.") < 0; - }); - - // Create the temp directory for stripped code - fs.mkdir( path.join( doccoDir, "temp"), function() { - - // Generate source for all standalones - console.log( "Stripping multiline comments and steal removes..." ); - console.log( "Converting tabs to 4 spaces." ); - - files.forEach(function( file ) { - fs.readFile( path.join( sourceDir, file ), "utf-8", function( err, code ) { - console.log( "\t" + file ); - - // Remove multiline comments - code = code.replace( /\/\*(?:.*)(?:\n\s+\*.*)*\n/gim, ""); - - // Remove double semicolons from steal pluginify - code = code.replace( /;[\s]*;/gim, ";"); - code = code.replace( /(\/\/.*)\n[\s]*;/gi, "$1"); - - // Tabs -> four spaces - code = code.replace( /\t/gim, " "); - - // Only single new lines - code = code.replace( /(\n){3,}/gim, "\n\n"); - - fs.writeFile( path.join( doccoDir, "temp", file ), code, "utf-8", function() { - if ( ++count == files.length ) { - runDocco(); - } - }); - }); - }); - }); - }); -} - -console.log("Generating unminified sources..."); - -if ( os.platform() != "win32" ) { - genCommand = "./js " + makePath; -} else { - genCommand = "js.bat " + makePath; -} - -execCommandWithOutput( genCommand, rhinoDir, format ); diff --git a/build/docco/makestandalone.js b/build/docco/makestandalone.js deleted file mode 100644 index cf70d2ca..00000000 --- a/build/docco/makestandalone.js +++ /dev/null @@ -1,47 +0,0 @@ -load("steal/rhino/rhino.js"); -steal('jquery/build/extract.js', 'steal/clean', function() { - - var out = "jquery/build/docco/standalone/", - excludes = [ 'steal/dev', - "can/util/jquery/jquery.1.7.1.js", - "jquery/build/lib.js" ], - plugins = { - "jquery/dom/animate/animate.js" : "jquery.animate.js", - "jquery/dom/compare/compare.js" : "jquery.compare.js", - "jquery/dom/cookie/cookie.js" : "jquery.cookie.js", - "jquery/dom/dimensions/dimensions.js" : "jquery.dimensions.js", - "jquery/dom/form_params/form_params.js" : "jquery.form_params.js", - "jquery/dom/range/range.js" : "jquery.range.js", - "jquery/dom/selection/selection.js" : "jquery.selection.js", - "jquery/dom/styles/styles.js" : "jquery.styles.js", - "jquery/dom/within/within.js" : "jquery.within.js", - "jquery/event/default/default.js" : "jquery.event.default.js", - "jquery/event/destroyed/destroyed.js" : "jquery.event.destroyed.js", - "jquery/event/drag/drag.js" : "jquery.event.drag.js", - "jquery/event/drop/drop.js" : "jquery.event.drop.js", - "jquery/event/fastfix/fastfix.js" : "jquery.event.fastfix.js", - "jquery/event/hover/hover.js" : "jquery.event.hover.js", - "jquery/event/key/key.js" : "jquery.event.key.js", - "jquery/event/pause/pause.js" : "jquery.event.pause.js", - "jquery/event/resize/resize.js" : "jquery.event.resize.js", - "jquery/event/swipe/swipe.js" : "jquery.event.swipe.js", - "jquery/event/livehack/livehack.js" : "jquery.event.livehack.js", - "jquery/lang/json/json.js" : "jquery.lang.json.js", - "jquery/lang/vector/vector.js" : "jquery.lang.vector.js" - }; - - steal.File(out).mkdirs(); - - steal.build.extract(plugins, { - skipCallbacks: true, - exclude : excludes.concat([ - 'jquery/dom/dom.js', 'jquery/event/event.js', 'jquery/jquery.js' - ]), - out : out - }); - - for(var name in plugins) { - console.log("Cleaning " + out + plugins[name]); - steal.clean(out + plugins[name]); - } -}); diff --git a/build/docco/package.json b/build/docco/package.json deleted file mode 100644 index 8811690c..00000000 --- a/build/docco/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "docco-generator", - "version" : "0.0.1", - "dependencies": { - "docco": ">= 0.1.x" - }, - "engine": "node >= 0.6.x" -} diff --git a/build/extract.js b/build/extract.js deleted file mode 100644 index 9dbfc86c..00000000 --- a/build/extract.js +++ /dev/null @@ -1,52 +0,0 @@ -steal('steal/build/pluginify', function() { - var inexcludes = function(excludes, src) { - for(var i = 0; i < excludes.length; i++) { - if(src.indexOf(excludes[i]) !== -1) { - return true; - } - } - return false; - }, - getDependencies = function(file, options, callback) { - steal.build.open("steal/rhino/empty.html", { - startFile : file, - skipCallbacks: true - }, function(opener){ - var ret = []; - opener.each(function(stl, text) { - var src = stl.src.toString(); - if(!inexcludes(options.exclude || [], src)) { - ret.push(src); - } - }); - callback(ret); - }, null); - }; - - steal.build.extract = function(plugins, options) { - var ops = steal.extend({ global : 'jQuery' }, options); - steal.File(ops.out).mkdirs(); - print('Extracting plugin files'); - for(var file in plugins) { - var content = ""; - - getDependencies(file, ops, function(steals) { - console.log(steals); -// if(steals.length > 1) { -// content += "// Dependencies:\n//\n"; -// } -// steals.forEach(function(stl) { -// if(stl.rootSrc !== file) { -// content += "// - " + (plugins[stl.rootSrc] || stl.rootSrc) + "\n"; -// } -// }); -// if(steals.length > 1) { -// content += "\n"; -// } -// content += steal.build.pluginify.content({ rootSrc : file }, ops); -// new steal.File(options.out + plugins[file]).save(content); -// print(' > ' + file + ' -> ' + plugins[file]); - }); - } - } -}); diff --git a/build/github/package.json b/build/github/package.json deleted file mode 100644 index 0312e102..00000000 --- a/build/github/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "github-download-updater", - "version" : "0.0.1", - "dependencies": { - "commander": ">= 0.1.x", - "github": ">= 0.1.x", - "underscore" : ">= 0.1.x", - "underscore.deferred" : ">= 0.1.x", - "tafa-misc-util" : ">= 0.1.x", - "mime" : ">= 1.2.5" - }, - "engine": "node >= 0.6.x" -} diff --git a/build/github/s3-post.js b/build/github/s3-post.js deleted file mode 100644 index 0f078d52..00000000 --- a/build/github/s3-post.js +++ /dev/null @@ -1,106 +0,0 @@ -// Generated by CoffeeScript 1.3.1 -(function() { - var crypto, https, joinBuffers, postToS3, readText, signPolicy, url, _ref; - - url = require('url'); - - https = require('https'); - - crypto = require('crypto'); - - _ref = require('tafa-misc-util'), joinBuffers = _ref.joinBuffers, readText = _ref.readText; - - signPolicy = function(secretKey, policy) { - var data, hmac, json, key, policy64, signature64; - json = JSON.stringify(policy); - policy64 = new Buffer(json).toString('base64'); - data = new Buffer(policy64, 'utf-8'); - key = new Buffer(secretKey, 'utf-8'); - hmac = crypto.createHmac('sha1', key); - hmac.update(data); - signature64 = hmac.digest('base64'); - return { - signature64: signature64, - policy64: policy64 - }; - }; - - postToS3 = function(_arg, callback) { - var AWSAccessKeyId, Filename, acl, addParam, arr, boundary, bucket, buf, ca, contentType, customUrl, data, host, hostname, key, options, policy64, port, protocol, req, req_body, signature64, success_action_status, _ref1; - AWSAccessKeyId = _arg.AWSAccessKeyId, policy64 = _arg.policy64, signature64 = _arg.signature64, bucket = _arg.bucket, key = _arg.key, data = _arg.data, boundary = _arg.boundary, customUrl = _arg.customUrl, ca = _arg.ca, acl = _arg.acl, success_action_status = _arg.success_action_status, Filename = _arg.Filename, contentType = _arg.contentType; - if (callback == null) { - callback = (function() {}); - } - if (customUrl) { - _ref1 = url.parse(customUrl), protocol = _ref1.protocol, hostname = _ref1.hostname, port = _ref1.port; - if (protocol !== "https:") { - return callback(new Error("customUrl must be https://")); - } - host = hostname; - port || (port = 443); - } else { - host = "" + bucket + ".s3.amazonaws.com"; - port = 443; - } - boundary || (boundary = '----------R46EARkAg4SAXSjufGsb6m'); - buf = function(x) { - return new Buffer(x); - }; - arr = []; - addParam = function(k, v) { - arr.push(buf('--' + boundary + '\r\n')); - arr.push(buf('Content-Disposition: form-data; name="' + k + '"\r\n\r\n')); - return arr.push(buf(v), buf('\r\n')); - }; - addParam('key', key); - addParam('acl', acl); - addParam('success_action_status', success_action_status); - addParam('Filename', Filename); - addParam('AWSAccessKeyId', AWSAccessKeyId); - addParam('Policy', policy64); - addParam('Signature', signature64); - addParam('Content-Type', contentType); - console.log(arr.join("")); - arr.push(buf('--' + boundary + '\r\n')); - arr.push(buf('Content-Disposition: form-data; name="file"; filename="data"\r\n')); - arr.push(buf("Content-Length: " + data.length + "\r\n")); - arr.push(buf('Content-Transfer-Encoding: binary\r\n\r\n')); - arr.push(data, buf('\r\n')); - arr.push(buf('--' + boundary + '--')); - req_body = joinBuffers(arr); - options = { - host: host, - port: port, - path: '/', - method: 'POST', - headers: { - 'Host': "" + bucket + ".s3.amazonaws.com", - 'Content-Type': 'multipart/form-data; boundary=' + boundary, - 'Content-Length': req_body.length - } - }; - if (ca) { - options.ca = ca; - } - req = https.request(options, function(res) { - var _ref2; - if ((200 <= (_ref2 = res.statusCode) && _ref2 < 300)) { - return callback(null); - } else { - return readText(res, function(text) { - return callback({ - responseCode: res.statusCode, - responseText: text - }); - }); - } - }); - return req.end(req_body); - }; - - module.exports = { - postToS3: postToS3, - signPolicy: signPolicy - }; - -}).call(this); \ No newline at end of file diff --git a/build/github/update-download.js b/build/github/update-download.js deleted file mode 100644 index 197c2b44..00000000 --- a/build/github/update-download.js +++ /dev/null @@ -1,273 +0,0 @@ -var path = require("path"), - fs = require("fs"), - spawn = require("child_process").spawn, - -// Third party modules - program = require("commander"), - GitHubApi = require("github"), - _ = require("underscore"), - s3p = require("./s3-post.js"), - mime = require('mime'), - -// Get the current version - version = fs.readFileSync(path.join(__dirname, "../version")).toString("utf8").trim(), - -// Describe all the files we'll be uploading to Github - descriptions = { - "jquerypp.js" : "jQuery++ #{VERSION} - All plugins", - }, - -// Figure out some paths - rhinoPath = path.join(__dirname, "../../.."), - distPathShort = "jquery/dist/", - distPath = path.join(__dirname, "../../dist"), - -// Github client - github = new GitHubApi({ - version : "3.0.0" - }), - remote = "git@github.com:jupiterjs/jquerypp.git", - -// Timeouts - stealTimeout, - -// For Github credentials - username, - password, - -// For steal build process - pluginify; - -// Get deferreds -_.mixin(require("underscore.deferred")); - -function updateDist() { - console.log("Copying built files to gh-pages."); - - var clone = spawn("git", [ "clone", remote ], { - cwd : __dirname - }), dfd = new _.Deferred(); - - clone.on("exit", function () { - - var clonePath = path.join(__dirname, "jquerypp"), - checkout = spawn("git", [ "checkout", "gh-pages"], { - cwd : clonePath - }); - - checkout.on("exit", function () { - var cloneReleasePath = path.join(clonePath, "release"), - latestPath = path.join(cloneReleasePath, "latest"), - versionPath = path.join(cloneReleasePath, version); - // Make sure directories exist - [ cloneReleasePath, versionPath, latestPath ].forEach(function (dir) { - if (!path.existsSync(dir)) { - fs.mkdirSync(dir); - } - }); - - fs.readdir(distPath, function (err, files) { - var dfds = files.map(function (file) { - var dfd = new _.Deferred(), - inPath, outPath, latestOutPath, - inStream; - - if(file.match(/.*\.js/)) { - inPath = path.join(distPath, file), - outPath = path.join(versionPath, file), - latestOutPath = path.join(latestPath, file), - inStream = fs.createReadStream(inPath); - inStream.pipe(fs.createWriteStream(outPath)); - inStream.pipe(fs.createWriteStream(latestOutPath)); - - inStream.on("end", function () { - dfd.resolve(); - }); - } else { - dfd.resolve(); - } - - return dfd.promise(); - - }); - - _.when.apply(_, dfds).done(function () { - console.log("Finished copying files. Cleaning up...") - var add = spawn("git", ["add", "release/*"], { - cwd : clonePath - }); - - add.on("exit", function () { - var commit = spawn("git", ["commit", "-m", "Generated release files for " + version ], { - cwd : clonePath - }); - - commit.on("exit", function () { - var push = spawn("git", ["push", "origin", "gh-pages"], { - cwd : clonePath - }); - - push.on("exit", function () { - - var remove = spawn("rm", ["-rf", "jquerypp"], { - cwd : __dirname - }); - console.log("Done!") - - }); - }); - }); - }); - }); - }); - - }); - - return dfd.promise(); -} - -// Upload files to the Github downloads page -function uploadFiles() { - console.log('Uploading files'); - - var dfd = new _.Deferred(), - dfds = _.map(descriptions, function (desc, filename) { - - var dfd = new _.Deferred(); - - desc = desc.replace("#{VERSION}", version); - - fs.readFile(path.join(distPath, filename), function (err, buf) { - console.log('Uploading ' + filename + ' MIME type ' + mime.lookup(filename)); - - github.httpSend({ - "user" : "jupiterjs", - "repo" : "jquerypp", - "name" : filename, - "size" : buf.length, - "description" : desc, - "content_type" : mime.lookup(filename) - }, { - "url" : "/repos/:user/:repo/downloads", - "method" : "POST", - "params" : { - "$user" : null, - "$repo" : null, - "$name" : null, - "$size" : null, - "description" : null, - "$content_type" : null - } - }, function (err, socket) { - console.log(err); - var data = JSON.parse(socket.data); - - - s3p.postToS3({ - key : data.path, - acl : data.acl, - success_action_status : "201", - Filename : data.name, - AWSAccessKeyId : data.accesskeyid, - policy64 : data.policy, - signature64 : data.signature, - contentType : data.mime_type, - data : buf, - bucket : "github" - }, function (e) { - if (e) { - console.log(e); - } - dfd.resolve(); - }) - - }); - - }); - - return dfd.promise(); - }); - - _.when.apply(_, dfds).done(dfd.resolve.bind(dfd)); - - return dfd.promise(); -} - -function stealBuild() { - - var dfd = new _.Deferred(), - zipFile; - - // Run Steal build script - pluginify = spawn(rhinoPath + "/js", ["jquery/build/make.js"], { - cwd : rhinoPath - }); - - pluginify.on("exit", function (code) { - // Create a zip file - // tar -cvzf jquery/dist/jquerypp.tar.gz jquery/dist - zipFile = 'jquerypp-' + version + '.zip'; - descriptions[zipFile] = "jQuery++ #{VERSION} - Full download"; - spawn("zip", ["-r", zipFile, '.'], { - cwd : distPath - }).on("exit", function () { - console.log("Done creating ZIP file " + zipFile); - dfd.resolve(code); - }); - }); - - return dfd.promise(); -} - -// Clean up on process exit -process.on("exit", function () { - process.stdout.write("\n") -}) - -// Get Github credentials -function getCredentials() { - - var dfd = new _.Deferred(); - - program.prompt("Github Username: ", function (name) { - username = name; - - program.password("Github Password: ", "*", function (pass) { - var timeout; - password = pass; - process.stdin.pause(); - - github.authenticate({ - type : "basic", - username : username, - password : password - }); - - process.stdout.write("Building jQuery++...") - stealTimeout = setInterval(function () { - process.stdout.write(".") - }, 1000) - dfd.resolve(); - }) - - }); - - return dfd.promise(); -} - -_.when(stealBuild(), getCredentials()).done(function (code) { - console.log('Built and got credentials'); - - if (stealTimeout) { - clearTimeout(stealTimeout); - process.stdout.write(" Done!\n") - } - - console.log(code); - if (code != 0) { - console.log("Steal build process failed.") - } else { - _.when(uploadFiles(), updateDist()).done(function () { - }); - } -}); diff --git a/build/lib.js b/build/lib.js deleted file mode 100644 index a9736545..00000000 --- a/build/lib.js +++ /dev/null @@ -1,24 +0,0 @@ -steal( - "jquery/dom/animate", - "jquery/dom/compare", - "jquery/dom/cookie", - "jquery/dom/dimensions", - "jquery/dom/form_params", - "jquery/dom/range", - "jquery/dom/selection", - "jquery/dom/styles", - "jquery/dom/within", - "jquery/event/default", - "jquery/event/destroyed", - "jquery/event/drag", - 'jquery/event/drag/limit', - 'jquery/event/drag/scroll', - 'jquery/event/drag/step', - "jquery/event/drop", - "jquery/event/fastfix", - "jquery/event/hover", - "jquery/event/key", - "jquery/event/pause", - "jquery/event/resize", - "jquery/event/swipe" -) \ No newline at end of file diff --git a/build/make.js b/build/make.js deleted file mode 100644 index 46b83617..00000000 --- a/build/make.js +++ /dev/null @@ -1,102 +0,0 @@ - -load("steal/rhino/rhino.js"); -steal('steal/build/pluginify', 'jquery/build/extract.js', // 'jquery/build/stealify.js', 'jquery/build/amdify.js', -function() { - - var out = "jquery/dist/", - excludes = [ 'steal/dev/', - 'jquery', - 'jquery/build/lib.js' ]; - - steal.File(out).mkdirs(); - - // Create full library -// steal.build.pluginify('jquery/build/lib.js', { -// out: out + "jquerypp.js", -// skipCallbacks: true, -// shim : { 'jquery' : 'jQuery' }, -// exclude : excludes.concat([ -// 'jquery/dom/dom.js', 'jquery/event/event.js', 'jquery/jquery.js' -// ]) -// }); - - // Create separate files - steal.build.extract({ - "jquery/dom/animate/animate.js" : "jquery.animate.js", - "jquery/dom/compare/compare.js" : "jquery.compare.js", - "jquery/dom/cookie/cookie.js" : "jquery.cookie.js", - "jquery/dom/dimensions/dimensions.js" : "jquery.dimensions.js", - "jquery/dom/form_params/form_params.js" : "jquery.form_params.js", - "jquery/dom/range/range.js" : "jquery.range.js", - "jquery/dom/selection/selection.js" : "jquery.selection.js", - "jquery/dom/styles/styles.js" : "jquery.styles.js", - "jquery/dom/within/within.js" : "jquery.within.js", - "jquery/event/default/default.js" : "jquery.event.default.js", - "jquery/event/destroyed/destroyed.js" : "jquery.event.destroyed.js", - "jquery/event/drag/drag.js" : "jquery.event.drag.js", - "jquery/event/drop/drop.js" : "jquery.event.drop.js", - "jquery/event/fastfix/fastfix.js" : "jquery.event.fastfix.js", - "jquery/event/hover/hover.js" : "jquery.event.hover.js", - "jquery/event/key/key.js" : "jquery.event.key.js", - "jquery/event/pause/pause.js" : "jquery.event.pause.js", - "jquery/event/resize/resize.js" : "jquery.event.resize.js", - "jquery/event/swipe/swipe.js" : "jquery.event.swipe.js", - "jquery/event/livehack/livehack.js" : "jquery.event.livehack.js", - "jquery/lang/json/json.js" : "jquery.lang.json.js", - "jquery/lang/vector/vector.js" : "jquery.lang.vector.js" - }, { - skipCallbacks: true, - exclude : excludes.concat([ - 'jquery/dom/dom.js', 'jquery/event/event.js', 'jquery/jquery.js' - ]), - out : out + 'lib/' - }); - - // Make Steal distributable -// steal.build.stealify('jquery/build/lib.js', { -// out : out + 'steal/', -// exclude : excludes -// }); - - // Make AMD modules -// steal.build.amdify('jquery/build/lib.js', { -// out : out + 'amd/', -// exclude : excludes.concat([ -// 'jquery/dom/dom.js', 'jquery/event/event.js' -// ]), -// map : { // steal file to CommonJS module name mappings -// "jquery/jquery.js" : "jquery", -// "jquery/build/lib.js" : "jquerypp/index", -// "jquery/lang/json/json.js" : "jquerypp/util/json", -// "jquery/lang/vector/vector.js" : "jquerypp/util/vector", -// "jquery/dom/animate/animate.js" : "jquerypp/animate", -// "jquery/dom/compare/compare.js" : "jquerypp/compare", -// "jquery/dom/cookie/cookie.js" : "jquerypp/cookie", -// "jquery/dom/dimensions/dimensions.js" : "jquerypp/dimensions", -// "jquery/dom/form_params/form_params.js" : "jquerypp/form_params", -// "jquery/dom/range/range.js" : "jquerypp/range", -// "jquery/dom/selection/selection.js" : "jquerypp/selection", -// "jquery/dom/styles/styles.js" : "jquerypp/styles", -// "jquery/dom/within/within.js" : "jquerypp/within", -// "jquery/event/default/default.js" : "jquerypp/event/default", -// "jquery/event/destroyed/destroyed.js" : "jquerypp/event/destroyed", -// "jquery/event/drag/drag.js" : "jquerypp/event/drag", -// "jquery/event/drag/limit/limit.js" : "jquerypp/event/drag.limit", -// "jquery/event/drag/scroll/scroll.js" : "jquerypp/event/drag.scroll", -// "jquery/event/drag/step/step.js" : "jquerypp/event/drag.step", -// "jquery/event/drop/drop.js" : "jquerypp/event/drop", -// "jquery/event/fastfix/fastfix.js" : "jquerypp/event/fastfix", -// "jquery/event/hover/hover.js" : "jquerypp/event/hover", -// "jquery/event/key/key.js" : "jquerypp/event/key", -// "jquery/event/reverse/reverse.js" : "jquerypp/event/reverse", -// "jquery/event/livehack/livehack.js" : "jquerypp/event/livehack", -// "jquery/event/pause/pause.js" : "jquerypp/event/pause", -// "jquery/event/resize/resize.js" : "jquerypp/event/resize", -// "jquery/event/swipe/swipe.js" : "jquerypp/event/swipe" -// }, -// names : { // Module name to variable name mappings -// 'jquery' : 'jQuery' -// }, -// global : 'jQuery' -// }); -}); diff --git a/build/stealify.js b/build/stealify.js deleted file mode 100644 index 1a936f21..00000000 --- a/build/stealify.js +++ /dev/null @@ -1,43 +0,0 @@ -steal('steal/build', function(steal) { - var inexcludes = function(excludes, src) { - for(var i = 0; i < excludes.length; i++) { - if(src.indexOf(excludes[i]) !== -1) { - return true; - } - } - return false; - }; - - /** - * A build plugin that copies only actual dependencies for a given file into - * a destination folder. The destination folder content is the minimal fileset - * you can deliver to be used with Steal. - * - * @param {String} source The source file to copy the dependencies for - * @param {Object} options The following options are available: - * - `out` - The output folder (will be created if it doesn't exist) - * - `excludes` - An array of files to exclude from copying - */ - steal.build.stealify = function(source, options) { - var out = options.out || steal.File(source).dir(); - print('Copying Steal dependencies for ' + source + ' to ' + out); - steal.File(out).mkdirs(); - steal.build.open("steal/rhino/empty.html", { - startFile : source, - skipCallbacks: true - }, function(opener){ - opener.each(function(stl){ - if(!inexcludes(options.exclude || [], stl.rootSrc.toString())) { - var file = steal.File(stl.rootSrc.toString()), - outPath = steal.File(out + file.dir()), - copyTo = outPath.path + '/' + file.filename(); - outPath.mkdirs(); - print(' > ' + copyTo); - file.copyTo(copyTo); - } else { - print(' Ignoring ' + stl.rootSrc.toString()); - } - }) - }); - } -}) \ No newline at end of file diff --git a/build/version b/build/version deleted file mode 100644 index afaf360d..00000000 --- a/build/version +++ /dev/null @@ -1 +0,0 @@ -1.0.0 \ No newline at end of file diff --git a/builder.json b/builder.json new file mode 100644 index 00000000..ca989169 --- /dev/null +++ b/builder.json @@ -0,0 +1,121 @@ +{ + "filename": "jquerypp.custom.js", + "banner": "/*!\n * <%= pkg.title || pkg.name %> - <%= pkg.version %>\n * <%= pkg.homepage %>\n * Copyright (c) <%= new Date().getFullYear() %> <%= pkg.author.name %>\n * <%= new Date().toUTCString() %>\n * Licensed <%= pkg.licenses[0].type %>\n<% if(typeof url !== \"undefined\") { %>\n * Includes: <%= ids %>\n * Download from: <%= url %>\n<% } %> */\n", + "modules": { + "jquerypp/dom/animate/animate": { + "name": "jQuery.animate", + "description": "Animate using CSS animations", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/compare/compare": { + "name": "jQuery.compare", + "description": "Compare element document position", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/cookie/cookie": { + "name": "jQuery.cookie", + "description": "Read and write cookies", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/form_params/form_params": { + "name": "jQuery.formParams", + "description": "Serializes a form into an object", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/range/range": { + "name": "jQuery.range", + "description": "Create and manipulate text ranges", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/selection/selection": { + "name": "jQuery.selection", + "description": "Get and set the current text selection", + "type": "dom", + "isDefault": true + }, + "jquerypp/dom/within/within": { + "name": "jQuery.within", + "description": "Get elements within an area or at a point", + "type": "dom", + "isDefault": true + }, + "jquerypp/event/removed/removed": { + "name": "jQuery.event.removed", + "description": "An element is removed from the DOM", + "type": "event", + "isDefault": true + }, + "jquerypp/event/drag/drag": { + "name": "jQuery.event.drag", + "description": "Delegatable drag events", + "type": "event", + "isDefault": true + }, + "jquerypp/event/drop/drop": { + "name": "jQuery.event.drop", + "description": "Delegatable drop events", + "type": "event", + "isDefault": true + }, + "jquerypp/event/hover/hover": { + "name": "jQuery.event.hover", + "description": "Delegatable hover events", + "type": "event", + "isDefault": true + }, + "jquerypp/event/key/key": { + "name": "jQuery.event.key", + "description": "Returns a string representation of the key pressed", + "type": "event", + "isDefault": true + }, + "jquerypp/event/pause/pause": { + "name": "jQuery.event.pause", + "description": "Pause and resume event propagation", + "type": "event", + "isDefault": true + }, + "jquerypp/event/resize/resize": { + "name": "jQuery.event.resize", + "description": "Listen to a resize event on every object", + "type": "event", + "isDefault": true + }, + "jquerypp/event/swipe/swipe": { + "name": "jQuery.event.swipe", + "description": "Delegatable swipe events", + "type": "event", + "isDefault": true + } + }, + "types": { + "dom": "DOM helpers", + "event": "Special events" + }, + "pluginify": { + "shim": { + "jquery/jquery.js": "$" + }, + "wrapper": "(function($) {\n<%= content %>\n})(jQuery);\n" + }, + "configurations": { + "default": { + "description": "jQuery", + "isDefault": true + } + }, + "ignore": ["dojo","dojo/dojo","dojo/main", + "jquery","jquery/jquery", + "mootools/mootools","mootools", + "zepto","zepto/zepto", + "yui","yui/yui"], + "exports": { + "jquery": "jQuery", + "zepto": "Zepto" + } +} \ No newline at end of file diff --git a/changelog.md b/changelog.md index 152c90a4..2dd60838 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,16 @@ ### Change Log +__1.0.1__ + +- fix: [Force hover leave on new mouseenter](https://github.com/bitovi/jquerypp/pull/65) +- fix: [Removing the element being hovered prevents all future hoverenter](https://github.com/bitovi/jquerypp/issues/64) +- fix: [hover.leave != 0 prevents hover of next element with same selecto](https://github.com/bitovi/jquerypp/issues/63) +- fix: [Changing jQuery references to local $](https://github.com/bitovi/jquerypp/pull/71) +- fix: [Breaks in jQuery.noConflict(true) Scenario](https://github.com/bitovi/jquerypp/issues/67) +- fix: [Can't download drag.limit, drag.step, and drag.scroll from downloader on website](https://github.com/bitovi/jquerypp/pull/66) +- feature: [jQuery 1.9.x support](https://github.com/bitovi/jquerypp/commit/692ed50a7b43fb2c6bfb9d89c5e0505ddcbd6595) +- feature: Added to the new [jQuery plugin repository](http://plugins.jquery.com/jquerypp) + __1.0.0__ - feature: jQuery 1.8.0+ compatibility @@ -11,6 +22,8 @@ __1.0.0__ - fix: [.stop() does not stop callbacks from being executed](https://github.com/jupiterjs/jquerypp/issues/28) - fix: [jQuery.event.swipe.max isn't actually being used](https://github.com/jupiterjs/jquerypp/issues/33) - fix: [Range triggers error on IE8](https://github.com/jupiterjs/jquerypp/issues/39) +- fix: [[FormParams] convertValue function: Null value to undefined (Internet Explorer Fix)](https://github.com/jupiterjs/jquerypp/pull/51) +- fix: [HoverInit delay 0 does not trigger hoverenter if immediately moused out](https://github.com/bitovi/jquerypp/issues/57) __1.0 Beta 2__ @@ -27,6 +40,6 @@ __1.0 Beta 2__ - Links to annotated sources ([e.g. jQuery.animate](http://donejs.com/jquery/docs/jquery.animate.html)) - Changelog and list of heroes section -__1.0 Beta__ (June 1st 2012) +__1.0 Beta__ - Released! \ No newline at end of file diff --git a/class/class.js b/class/class.js deleted file mode 100644 index c6e68fa3..00000000 --- a/class/class.js +++ /dev/null @@ -1,8 +0,0 @@ -//jQuery.Class -// This is a modified version of John Resig's class -// http://ejohn.org/blog/simple-javascript-inheritance/ -// It provides class level inheritance and callbacks. -//!steal-clean -steal("jquery", "can/construct", "can/construct/proxy","can/construct/super", function($, Construct) { - $.Class = Construct; -})(); diff --git a/class/class_test.js b/class/class_test.js deleted file mode 100644 index 61caa64d..00000000 --- a/class/class_test.js +++ /dev/null @@ -1,205 +0,0 @@ -steal("jquery/class") //load your app - .then('funcunit/qunit').then(function(){ - -module("jquery/class"); - -test("Creating", function(){ - - jQuery.Class.extend("Animal", - { - count: 0, - test: function() { - return this.match ? true : false - } - }, - { - init: function() { - this.constructor.count++; - this.eyes = false; - } - } - ); - Animal.extend("Dog", - { - match : /abc/ - }, - { - init: function() { - this._super(); - }, - talk: function() { - return "Woof"; - } - }); - Dog.extend("Ajax", - { - count : 0 - }, - { - init: function( hairs ) { - this._super(); - this.hairs = hairs; - this.setEyes(); - - }, - setEyes: function() { - this.eyes = true; - } - }); - new Dog(); - new Animal(); - new Animal(); - var ajax = new Ajax(1000); - - equals(2, Animal.count, "right number of animals"); - equals(1, Dog.count, "right number of animals") - ok(Dog.match, "right number of animals") - ok(!Animal.match, "right number of animals") - ok(Dog.test(), "right number of animals") - ok(!Animal.test(), "right number of animals") - equals(1, Ajax.count, "right number of animals") - equals(2, Animal.count, "right number of animals"); - equals(true, ajax.eyes, "right number of animals"); - equals(1000, ajax.hairs, "right number of animals"); -}) - - -test("new instance",function(){ - var d = Ajax.newInstance(6); - equals(6, d.hairs); -}) - - -test("namespaces",function(){ - var fb = $.Class.extend("Foo.Bar") - ok(Foo.Bar === fb, "returns class") - equals(fb.shortName, "Bar", "short name is right"); - equals(fb.fullName, "Foo.Bar","fullName is right") - -}) - -test("setups", function(){ - var order = 0, - staticSetup, - staticSetupArgs, - staticInit, - staticInitArgs, - protoSetup, - protoInitArgs, - protoInit, - staticProps = { - setup: function() { - staticSetup = ++order; - staticSetupArgs = arguments; - return ["something"] - }, - init: function() { - staticInit = ++order; - staticInitArgs = arguments; - } - }, - protoProps = { - setup: function( name ) { - protoSetup = ++order; - return ["Ford: "+name]; - }, - init: function() { - protoInit = ++order; - protoInitArgs = arguments; - } - } - $.Class.extend("Car",staticProps,protoProps); - - var geo = new Car("geo"); - equals(staticSetup, 1); - equals(staticInit, 2); - equals(protoSetup, 3); - equals(protoInit, 4); - - same($.makeArray(staticInitArgs), ["something"] ) - same($.makeArray(protoInitArgs),["Ford: geo"] ) - - same($.makeArray(staticSetupArgs),[$.Class, "Car",staticProps, protoProps] ,"static construct"); - - - //now see if staticSetup gets called again ... - Car.extend("Truck"); - equals(staticSetup, 5, "Static setup is called if overwriting"); - -}); - -test("callback", function(){ - var curVal = 0; - $.Class.extend("Car",{ - show: function( value ) { - equals(curVal, value) - } - },{ - show: function( value ) { - - } - }) - var cb = Car.proxy('show'); - curVal = 1; - cb(1) - - curVal = 2; - var cb2 = Car.proxy('show',2) - cb2(); -}); - -test("callback error", 1,function(){ - $.Class.extend("Car",{ - show: function( value ) { - equals(curVal, value) - } - },{ - show: function( value ) { - - } - }) - try{ - Car.proxy('huh'); - ok(false, "I should have errored") - }catch(e){ - ok(true, "Error was thrown") - } -}) - -test("Creating without extend", function(){ - $.Class("Bar",{ - ok : function(){ - ok(true, "ok called") - } - }); - new Bar().ok(); - - Bar("Foo",{ - dude : function(){ - ok(true, "dude called") - } - }); - new Foo().dude(true); -}) - - -/* Not sure I want to fix this yet. -test("Super in derived when parent doesn't have init", function(){ - $.Class("Parent",{ - }); - - Parent("Derived",{ - init : function(){ - this._super(); - } - }); - - try { - new Derived(); - ok(true, "Can call super in init safely") - } catch (e) { - ok(false, "Failed to call super in init with error: " + e) - } -})*/ - -}); \ No newline at end of file diff --git a/class/qunit.html b/class/qunit.html deleted file mode 100644 index 503f699f..00000000 --- a/class/qunit.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - -

Class Test Suite

-

-
-

-
    -
    - - - \ No newline at end of file diff --git a/controller/controller.html b/controller/controller.html deleted file mode 100644 index 56458d75..00000000 --- a/controller/controller.html +++ /dev/null @@ -1,88 +0,0 @@ - - - - Controller Example - - - -
    - -
    Tab 1 Content
    -
    Tab 2 Content
    -
    Tab 3 Content
    -
    - - - - \ No newline at end of file diff --git a/controller/controller.js b/controller/controller.js deleted file mode 100644 index cd0e96b7..00000000 --- a/controller/controller.js +++ /dev/null @@ -1,10 +0,0 @@ -steal('jquery', 'can/control', 'jquery/class','can/control/plugin',function($, Control) { - $.Controller = Control; - $.fn.controller = $.fn.control; - $.fn.controllers = $.fn.controls; - can.Control.prototype.find = can.Control.prototype.find || function(s) { - return this.element.find(s); - }; - $.Controller.prototype.bind = $.Controller.prototype.on; - $.Controller.prototype.delegate = $.Controller.prototype.on; -}); diff --git a/controller/controller_test.js b/controller/controller_test.js deleted file mode 100644 index d2322b85..00000000 --- a/controller/controller_test.js +++ /dev/null @@ -1,269 +0,0 @@ -steal("jquery/controller",'jquery/controller/subscribe') //load your app - .then('funcunit/qunit') //load qunit - .then(function(){ - -module("jquery/controller") -test("subscribe testing works", function(){ - - var ta = $("
    ").appendTo( $("#qunit-test-area") ) - - ta.html("click here") - - var clicks = 0, destroys = 0; - var subscribes = 0; - $.Controller.extend("MyTest",{ - click: function() { - clicks++ - }, - "a.b subscribe" : function() { - subscribes++ - }, - destroy: function() { - - this._super() - destroys++; - } - }) - ta.my_test(); - ta.trigger("click") - equals(clicks,1, "can listen to clicks") - - OpenAjax.hub.publish("a.b",{}) - equals(subscribes,1, "can subscribe") - var controllerInstance = ta.controller('my_test') - ok( controllerInstance.constructor == MyTest, "can get controller" ) - controllerInstance.destroy() - - equals(destroys,1, "destroy called once") - ok(!ta.controller(), "controller is removed") - - OpenAjax.hub.publish("a.b",{}) - equals(subscribes,1, "subscription is torn down") - ta.trigger("click") - equals(clicks,1, "No longer listening") - - - - ta.my_test(); - ta.trigger("click") - OpenAjax.hub.publish("a.b",{}) - equals(clicks,2, "can listen again to clicks") - equals(subscribes,2, "can listen again to subscription") - - ta.remove(); - - ta.trigger("click") - OpenAjax.hub.publish("a.b",{}) - equals(clicks,2, "Clicks stopped") - equals(subscribes,2, "Subscribes stopped") -}) - - - -test("bind to any special", function(){ - jQuery.event.special.crazyEvent = { - - } - var called = false; - jQuery.Controller.extend("WeirdBind",{ - crazyEvent: function() { - called = true; - } - }) - var a = $("
    ").appendTo($("#qunit-test-area")) - a.weird_bind(); - a.trigger("crazyEvent") - ok(called, "heard the trigger"); - - $("#qunit-test-area").html("") - -}) - -test("parameterized actions", function(){ - var called = false; - jQuery.Controller.extend("WeirderBind",{ - "{parameterized}" : function() { - called = true; - } - }) - var a = $("
    ").appendTo($("#qunit-test-area")) - a.weirder_bind({parameterized: "sillyEvent"}); - a.trigger("sillyEvent") - ok(called, "heard the trigger") - - $("#qunit-test-area").html("") -}) - -test("windowresize", function(){ - var called = false; - jQuery.Controller.extend("WindowBind",{ - "{window} resize" : function() { - called = true; - } - }) - $("#qunit-test-area").html("
    ") - $("#weird").window_bind(); - $(window).trigger('resize') - ok(called,"got window resize event"); - - $("#qunit-test-area").html("") -}) - -// this.delegate(this.cached.header.find('tr'), "th", "mousemove", "th_mousemove"); -test("delegate", function(){ - var called = false; - jQuery.Controller.extend("DelegateTest",{ - click: function() {} - }) - var els = $("
    click me
    ").appendTo($("#qunit-test-area")) - var c = els.delegate_test(); - c.controller().on(els.find("span"), "a", "click", function(){ - called = true; - }) - els.find("a").trigger('click') - ok(called, "delegate works") - $("#qunit-test-area").html("") -}) - -test("inherit", function(){ - var called = false; - $.Controller.extend( "Parent", { - click: function(){ - called = true; - } - }) - Parent.extend( "Child", { - - }) - var els = $("
    click me
    ").appendTo($("#qunit-test-area")) - els.child(); - els.find("a").trigger('click') - ok(called, "inherited the click method") - $("#qunit-test-area").html("") -}); - -test("objects in action", function(){ - $.Controller('Thing',{ - "{item} someEvent" : function(thing, ev){ - ok(true, "called"); - equals(ev.type, "someEvent","correct event") - equals(this.constructor.fullName, "Thing", "This is a controller isntance") - equals(thing.name,"Justin","Raw, not jQuery wrapped thing") - } - }); - - var thing1 = {name: "Justin"}; - - var ta = $("
    ").appendTo( $("#qunit-test-area") ) - ta.thing({item : thing1}); - - $(thing1).trigger("someEvent"); - - $("#qunit-test-area").html(""); - -}); - -test("dot",function(){ - $.Controller("Dot",{ - "foo.bar" : function(){ - ok(true,'called') - } - }); - - var ta = $("
    ").appendTo( $("#qunit-test-area") ); - ta.dot().trigger("foo.bar"); - $("#qunit-test-area").html(""); -}) - -// HTMLFormElement[0] breaks -test("the right element", 1, function(){ - $.Controller('FormTester',{ - init : function(){ - equals(this.element[0].nodeName.toLowerCase(), "form" ) - } - }) - $("
    ").appendTo( $("#qunit-test-area") ) - .form_tester(); - $("#qunit-test-area").html("") -}) - -test("pluginName", function() { - // Testing for controller pluginName fixes as reported in - // http://forum.javascriptmvc.com/#topic/32525000000253001 - // http://forum.javascriptmvc.com/#topic/32525000000488001 - expect(6); - - $.Controller("PluginName", { - pluginName : "my_plugin" - }, { - method : function(arg) { - ok(true, "Method called"); - }, - - update : function(options) { - this._super(options); - ok(true, "Update called"); - }, - - destroy : function() { - ok(true, "Destroyed"); - this._super(); - } - }); - - var ta = $("
    ").addClass('existing_class').appendTo( $("#qunit-test-area") ); - ta.my_plugin(); // Init - ok(ta.hasClass("my_plugin"), "Should have class my_plugin"); - ta.my_plugin(); // Update - ta.my_plugin("method"); // method() - ta.controller().destroy(); // destroy - ok(!ta.hasClass("my_plugin"), "Shouldn't have class my_plugin after being destroyed"); - ok(ta.hasClass("existing_class"), "Existing class should still be there"); -}) - -test("inherit defaults", function() { - $.Controller.extend("BaseController", { - defaults : { - foo: 'bar' - } - }, {}); - - BaseController.extend("InheritingController", { - defaults : { - newProp : 'newVal' - } - }, {}); - - ok(InheritingController.defaults.foo === 'bar', 'Class must inherit defaults from the parent class'); - ok(InheritingController.defaults.newProp == 'newVal', 'Class must have own defaults'); - var inst = new InheritingController($('
    '), {}); - ok(inst.options.foo === 'bar', 'Instance must inherit defaults from the parent class'); - ok(inst.options.newProp == 'newVal', 'Instance must have defaults of it`s class'); -}); - -test("update rebinding", 2, function(){ - var first = true; - $.Controller("Rebinder", { - "{item} foo" : function(item, ev){ - if(first){ - equals(item.id, 1, "first item"); - first = false; - } else { - equals(item.id, 2, "first item"); - } - } - }); - - var item1 = {id: 1}, - item2 = {id: 2}, - el = $('
    ').rebinder({item: item1}) - - $(item1).trigger("foo") - - el.rebinder({item: item2}); - - $(item2).trigger("foo") -}) - - -}); diff --git a/controller/demo-update.html b/controller/demo-update.html deleted file mode 100644 index cb5e936b..00000000 --- a/controller/demo-update.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - Controller Example - - - -
    -
    - - -
    -
    - - - - \ No newline at end of file diff --git a/controller/pages/listening.md b/controller/pages/listening.md deleted file mode 100644 index c27ab175..00000000 --- a/controller/pages/listening.md +++ /dev/null @@ -1,189 +0,0 @@ -@page jquery.controller.listening Listening To Events -@parent jQuery.Controller - -Controllers make creating and tearing down event handlers extremely -easy. The tearingdown of event handlers is especially important -in preventing memory leaks in long lived applications. - -## Automatic Binding - -When a [jQuery.Controller.prototype.setup new controller is created], -contoller checks its prototype methods for functions that are named like -event handlers. It binds these functions to the -controller's [jQuery.Controller.prototype.element element] with -event delegation. When -the controller is destroyed (or it's element is removed from the page), controller -will unbind its event handlers automatically. - -For example, each of the following controller's functions will automatically -bound: - - $.Controller("Crazy",{ - - // listens to all clicks on this element - "click" : function(el, ev){}, - - // listens to all mouseovers on - // li elements withing this controller - "li mouseover" : function(el, ev){} - - // listens to the window being resized - "{window} resize" : function(window, ev){} - }) - -Controller will bind function names with spaces, standard DOM events, and -event names in $.event.special. - -In general, Controller will know automatically when to bind event handler functions except for -one case - event names without selectors that are not in $.event.special. - -But to correct for this, you just need to add the -function to the [jQuery.Controller.static.listensTo listensTo] -property. Here's how: - - $.Controller("MyShow",{ - listensTo: ["show"] - },{ - show: function( el, ev ) { - el.show(); - } - }) - $('.show').my_show().trigger("show"); - -## Callback parameters - -Event handlers bound with controller are called back with the element and the event -as parameters. this refers to the controller instance. For example: - - $.Controller("Tabs",{ - - // li - the list element that was clicked - // ev - the click event - "li click" : function(li, ev){ - this.tab(li).hide() - }, - tab : function(li){ - return $(li.find("a").attr("href")) - } - }) - -## Templated Event Bindings - -One of Controller's most powerful features is templated event -handlers. You can parameterize the event name, -the selector, or event the root element. - -### Templating event names and selectors: - -Often, you want to make a widget's behavior -configurable. A common example is configuring which event -a menu should show a sub-menu (ex: on click or mouseenter). The -following controller lets you configure when a menu should show -sub-menus: - -The following makes two buttons. One says hello on click, -the other on a 'tap' event. - - $.Controller("Menu",{ - "li {showEvent}" : function(el){ - el.children('ul').show() - } - }) - - $("#clickMe").menu({showEvent : "click"}); - $("#touchMe").menu({showEvent : "mouseenter"}); - -$.Controller replaces value in {} with -values in a -controller's [jQuery.Controller.prototype.options options]. This means -we can easily provide a default showEvent value and create -a menu without providing a value like: - - $.Controller("Menu", - { - defaults : { - showEvent : "click" - } - }, - { - "li {showEvent}" : function(el){ - el.children('ul').show() - } - }); - - $("#clickMe").menu(); //defaults to using click - -Sometimes, we might might want to configure our widget to -use different elements. The following makes the menu widget's -button elements configurable: - - $.Controller("Menu",{ - "{button} {showEvent}" : function(el){ - el.children('ul').show() - } - }) - - $('#buttonMenu').menu({button: "button"}); - -### Templating the root element. - -Finally, controller lets you bind to objects outside -of the [jQuery.Controller.prototype.element controller's element]. - -The following listens to clicks on the window: - - $.Controller("HideOnClick",{ - "{window} click" : function(){ - this.element.hide() - } - }) - -The following listens to Todos being created: - - $.Controller("NewTodos",{ - "{App.Models.Todo} created" : function(Todo, ev, newTodo){ - this.element.append("newTodos.ejs", newTodo) - } - }); - -But instead of making NewTodos only work with the Todo model, -we can make it configurable: - - $.Controller("Newbie",{ - "{model} created" : function(Model, ev, newItem){ - this.element.append(this.options.view, newItem) - } - }); - - $('#newItems').newbie({ - model: App.Models.Todo, - view: "newTodos.ejs" - }) - -### How Templated events work - -When looking up a value to replace {}, -controller first looks up the item in the options, then it looks -up the value in the window object. It does not use eval to look up the -object. Instead it uses [jQuery.String.getObject]. - - -## Subscribing to OpenAjax messages and custom bindings - -The jquery/controller/subscribe plugin allows controllers to listen -to OpenAjax.hub messages like: - - $.Controller("Listener",{ - "something.updated subscribe" : function(called, data){ - - } - }) - -You can create your own binders by adding to [jQuery.Controller.static.processors]. - -## Manually binding to events. - -The [jQuery.Controller.prototype.bind] and [jQuery.Controller.prototype.delegate] -methods let you listen to events on other elements. These event handlers will -be unbound when the controller instance is destroyed. - diff --git a/controller/pages/plugin.md b/controller/pages/plugin.md deleted file mode 100644 index d3ee520f..00000000 --- a/controller/pages/plugin.md +++ /dev/null @@ -1,101 +0,0 @@ -@page jquery.controller.plugin The generated jQuery plugin -@parent jQuery.Controller - -When you create a controller, it creates a jQuery plugin that can be -used to: - - - Create controllers on an element or elements - - Call controller methods - - Update a controller - -For example, the following controller: - - $.Controller("My.Widget",{ - say : function(){ - alert(this.options.message); - } - }) - -creates a jQuery.fn.my_widget method that you can use like: - - // create my_widget on each .thing - $(".thing").my_widget({message : "Hello"}) - - // alerts "Hello" - $(".thing").my_widget("say"); - - // updates the message option - $(".thing").my_widget({message : "World"}); - - // alerts "World" - $(".thing").my_widget("say"); - -Note that in every case, the my_widget plugin -returns the original jQuery collection for chaining ($('.thing')). If you want to -get a value from a controller, use the [jQuery.fn.controllers] or [jQuery.fn.controller]. - -## Creating controllers - -When a controller's jQuery plugin helper is used on a jQuery collection, it goes to each -element and tests if it has a controller instance on the element. If it does not, it creates one. - -It calls new YourController with the element and any additional arguments you passed -to the jQuery plugin helper. So for example, say there are 2 elements in $('.thing'). - -This: - - $(".thing").my_widget({message : "Hello"}) - -Does the exact same thing as: - - var things = $('.thing'), - options = {message : "Hello"}; - new My.Widget(things[0],options); - new My.Widget(things[1],options); - -Note, when a new Class is created, it calls your -class's prototype setup and init methods. Read [jQuery.Controller.prototype.setup controller's setup] -for the details on what happens when a new controller is created. - - -## Calling methods on controllers - -Once a Controller is already on an element, you can call methods on it with the same jQuery -helper. The first param to the helper is the name of the method, the following params are -passed to the jQuery function. For example: - - $.Controller("Adder",{ - sum : function(first, second, third){ - this.element.text(first+second+third); - } - }) - - // add an adder to the page - $("#myadder").adder() - - // show the sum of 1+2+3 - $("#myadder").adder("sum",1,2,3); - -## Naming - -By default, a controller's jQuery helper is the controller name: - - - [jQuery.String.underscore underscored] - - "." replaced with "_" - - with Controllers removed. - -Here are some examples: - - $.Controller("Foo") // -> .foo() - $.Controller("Foo.Bar") // -> .foo_bar() - $.Controller("Foo.Controllers.Bar") // -> .foo_bar() - -You can overwrite the Controller's default name by setting a static pluginName property: - - $.Controller("My.Tabs", - { - pluginName: "tabs" - }, - { ... }) - - $("#tabs").tabs() diff --git a/controller/qunit.html b/controller/qunit.html deleted file mode 100644 index ae8fad54..00000000 --- a/controller/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

    Controller Test Suite

    -

    -
    -

    -
    -
      -
      - - \ No newline at end of file diff --git a/controller/route/qunit.html b/controller/route/qunit.html deleted file mode 100644 index 25edc491..00000000 --- a/controller/route/qunit.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - route QUnit Test - - - - -

      route Test Suite

      -

      -
      -

      -
      -
        -
        - - \ No newline at end of file diff --git a/controller/route/route.html b/controller/route/route.html deleted file mode 100644 index 178af929..00000000 --- a/controller/route/route.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - route - - - -

        route Demo

        - foo/bar - foo/car - empty - - - - \ No newline at end of file diff --git a/controller/route/route.js b/controller/route/route.js deleted file mode 100644 index cbf9bb92..00000000 --- a/controller/route/route.js +++ /dev/null @@ -1 +0,0 @@ -steal('jquery/controller', 'can/control/route') diff --git a/controller/route/route_test.js b/controller/route/route_test.js deleted file mode 100644 index 6a140d6b..00000000 --- a/controller/route/route_test.js +++ /dev/null @@ -1,10 +0,0 @@ -steal('funcunit/qunit','./route',function(){ - -module("route"); - -test("route testing works", function(){ - ok(true,"an assert is run"); -}); - - -}); \ No newline at end of file diff --git a/controller/subscribe/funcunit.html b/controller/subscribe/funcunit.html deleted file mode 100644 index 48dda424..00000000 --- a/controller/subscribe/funcunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

        subscribe Test Suite

        -

        -
        -

        -
        -
          -
          - - \ No newline at end of file diff --git a/controller/subscribe/subscribe.html b/controller/subscribe/subscribe.html deleted file mode 100644 index a26d72d5..00000000 --- a/controller/subscribe/subscribe.html +++ /dev/null @@ -1,56 +0,0 @@ - - - - hover - - - -
          -
          - subscribe me -
          -

          Turn OFF Above

          -
          - - - - - diff --git a/controller/subscribe/subscribe.js b/controller/subscribe/subscribe.js deleted file mode 100644 index 26280343..00000000 --- a/controller/subscribe/subscribe.js +++ /dev/null @@ -1,54 +0,0 @@ -/*global OpenAjax: true */ -steal('jquery/controller', 'jquery/lang/openajax').then(function() { - - /** - * @function jQuery.Controller.static.processors.subscribe - * @parent jQuery.Controller.static.processors - * @plugin jquery/controller/subscribe - * Adds OpenAjax.Hub subscribing to controllers. - * - * $.Controller("Subscriber",{ - * "recipe.updated subscribe" : function(called, recipe){ - * - * }, - * "todo.* subscribe" : function(called, todo){ - * - * } - * }) - * - * You should typically be listening to jQuery triggered events when communicating between - * controllers. Subscribe should be used for listening to model changes. - * - * ### API - * - * This is the call signiture for the processor, not the controller subscription callbacks. - * - * @param {HTMLElement} el the element being bound. This isn't used. - * @param {String} event the event type (subscribe). - * @param {String} selector the subscription name - * @param {String} cb the callback function's name - */ - jQuery.Controller.processors.subscribe = function( el, event, selector, cb, controller ) { - var subscription = OpenAjax.hub.subscribe(selector, function(){ - return controller[cb].apply(controller, arguments) - }); - return function() { - OpenAjax.hub.unsubscribe(subscription); - }; - }; - - /** - * @add jQuery.Controller.prototype - */ - //breaker - /** - * @function publish - * @hide - * Publishes a message to OpenAjax.hub. - * @param {String} message Message name, ex: "Something.Happened". - * @param {Object} data The data sent. - */ - jQuery.Controller.prototype.publish = function() { - OpenAjax.hub.publish.apply(OpenAjax.hub, arguments); - }; -}); \ No newline at end of file diff --git a/controller/view/qunit.html b/controller/view/qunit.html deleted file mode 100644 index cc57a785..00000000 --- a/controller/view/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

          Controller Test Suite

          -

          -
          -

          -
          -
            -
            - - \ No newline at end of file diff --git a/controller/view/test/qunit/controller_view_test.js b/controller/view/test/qunit/controller_view_test.js deleted file mode 100644 index 15b04274..00000000 --- a/controller/view/test/qunit/controller_view_test.js +++ /dev/null @@ -1,49 +0,0 @@ -steal('jquery/controller/view','jquery/view/micro','funcunit/qunit', function() { - - module("jquery/controller/view"); - - test("this.view", function(){ - - $.Controller.extend("jquery.Controller.View.Test.Qunit",{ - init: function() { - this.element.html(this.view()) - } - }) - $.View.ext = ".micro"; - $("#qunit-test-area").append("
            "); - - new jquery.Controller.View.Test.Qunit( $('#cont_view') ); - - ok(/Hello World/i.test($('#cont_view').text()),"view rendered") - }); - - test("test.suffix.doubling", function(){ - - $.Controller.extend("jquery.Controller.View.Test.Qunit",{ - init: function() { - this.element.html(this.view('init.micro')) - } - }) - - $.View.ext = ".ejs"; // Reset view extension to default - equal(".ejs", jQuery.View.ext); - - $("#qunit-test-area").append("
            "); - - new jquery.Controller.View.Test.Qunit( $('#suffix_test_cont_view') ); - - ok(/Hello World/i.test($('#suffix_test_cont_view').text()),"view rendered") - }); - - test("complex paths nested inside a controller directory", function(){ - $.Controller.extend("Myproject.Controllers.Foo.Bar"); - - var path = jQuery.Controller._calculatePosition(Myproject.Controllers.Foo.Bar, "init.ejs", "init") - equals(path, "//myproject/views/foo/bar/init.ejs", "view path is correct") - - $.Controller.extend("Myproject.Controllers.FooBar"); - path = jQuery.Controller._calculatePosition(Myproject.Controllers.FooBar, "init.ejs", "init") - equals(path, "//myproject/views/foo_bar/init.ejs", "view path is correct") - }) -}); - diff --git a/controller/view/test/qunit/qunit.js b/controller/view/test/qunit/qunit.js deleted file mode 100644 index 7873c312..00000000 --- a/controller/view/test/qunit/qunit.js +++ /dev/null @@ -1,5 +0,0 @@ -//we probably have to have this only describing where the tests are -steal('jquery/controller/view','jquery/view/micro') //load your app - .then('funcunit/qunit') //load qunit - .then("./controller_view_test.js") - diff --git a/controller/view/test/qunit/views/init.micro b/controller/view/test/qunit/views/init.micro deleted file mode 100644 index 9a1eb8d2..00000000 --- a/controller/view/test/qunit/views/init.micro +++ /dev/null @@ -1 +0,0 @@ -

            Hello World

            \ No newline at end of file diff --git a/controller/view/view.js b/controller/view/view.js deleted file mode 100644 index c7743076..00000000 --- a/controller/view/view.js +++ /dev/null @@ -1 +0,0 @@ -steal('jquery/controller', 'can/control/view'); \ No newline at end of file diff --git a/dom/animate/1x1.jpg b/dom/animate/1x1.jpg new file mode 100644 index 00000000..b0d69110 Binary files /dev/null and b/dom/animate/1x1.jpg differ diff --git a/dom/animate/animate.html b/dom/animate/animate.html index d6d2e460..11dbfa81 100644 --- a/dom/animate/animate.html +++ b/dom/animate/animate.html @@ -17,13 +17,12 @@
            Hello!
            - diff --git a/dom/animate/animate.js b/dom/animate/animate.js index e33d26c1..a91ee4b8 100644 --- a/dom/animate/animate.js +++ b/dom/animate/animate.js @@ -1,4 +1,4 @@ -steal('jquery', 'jquery/dom/styles', function () { +steal('jquery', function ($) { // Overwrites `jQuery.fn.animate` to use CSS 3 animations if possible @@ -45,9 +45,10 @@ steal('jquery', 'jquery/dom/styles', function () { }, // Returns whether the animation should be passed to the original $.fn.animate. - passThrough = function (props, ops) { + passThrough = function (props, ops, easing, callback) { var nonElement = !(this[0] && this[0].nodeType), - isInline = !nonElement && $(this).css("display") === "inline" && $(this).css("float") === "none"; + isInline = !nonElement && $(this).css("display") === "inline" && $(this).css("float") === "none", + browser = getBrowser(); for (var name in props) { // jQuery does something with these values @@ -63,11 +64,11 @@ steal('jquery', 'jquery/dom/styles', function () { } } - return props.jquery === true || getBrowser() === null || + return props.jquery === true || browser === null || browser.prefix === '-o-' || // Animating empty properties $.isEmptyObject(props) || // We can't do custom easing - (ops && ops.length == 4) || (ops && typeof ops[2] == 'string') || + (easing || easing && typeof easing == 'string') || // Second parameter is an object - we can only handle primitives $.isPlainObject(ops) || // Inline and non elements @@ -89,33 +90,30 @@ steal('jquery', 'jquery/dom/styles', function () { el = document.createElement('fakeelement'), transitions = { 'transition': { - transitionEnd : 'transitionEnd', + transitionEnd : 'transitionend', prefix : '' }, -// 'OTransition': { -// transitionEnd : 'oTransitionEnd', -// prefix : '-o-' -// }, -// 'MSTransition': { -// transitionEnd : 'msTransitionEnd', -// prefix : '-ms-' -// }, 'MozTransition': { transitionEnd : 'animationend', prefix : '-moz-' }, 'WebkitTransition': { - transitionEnd : 'webkitAnimationEnd', + transitionEnd : 'webkitTransitionEnd', prefix : '-webkit-' + }, + 'OTransition': { + transitionEnd : 'oTransitionEnd', + prefix : '-o-' } } for(t in transitions){ - if( el.style[t] !== undefined ){ + if( t in el.style ){ browser = transitions[t]; } } } + return browser; }, @@ -194,8 +192,10 @@ steal('jquery', 'jquery/dom/styles', function () { }; /** - * @function $.fn.animate - * @parent $.animate + * @parent jQuery.animate + * @function jQuery.fn.animate + * @signature $(element).animate(options) + * @hide * * Animate CSS properties using native CSS animations, if possible. * Uses the original [$.fn.animate()](http://api.$.com/animate/) otherwise. @@ -212,7 +212,15 @@ steal('jquery', 'jquery/dom/styles', function () { return oldanimate.apply(this, arguments); } - var optall = jQuery.speed(speed, easing, callback); + var optall = $.speed(speed, easing, callback), + overflow = []; + + // if we are animating height and width properties, set overflow to hidden, and save + // the previous overflow information to replace with when done. + if("height" in props || "width" in props) { + overflow = [this[0].style.overflow, this[0].style.overflowX, this[0].style.overflowY]; + this.css('overflow', 'hidden'); + } // Add everything to the animation queue this.queue(optall.queue, function(done) { @@ -234,8 +242,19 @@ steal('jquery', 'jquery/dom/styles', function () { // The animation end event handler. // Will be called both on animation end and after calling .stop() animationEnd = function (currentCSS, exec) { + // As long as we don't stop mid animation, then we will replace + // the overflow values of the element being animated. + if(!exec) { + self[0].style.overflow = overflow[0]; + self[0].style.overflowX = overflow[1]; + self[0].style.overflowY = overflow[2]; + } + else { + self.css('overflow', ''); + } + self.css(currentCSS); - + self.css(addPrefix({ "animation-duration" : "", "animation-name" : "", @@ -261,8 +280,9 @@ steal('jquery', 'jquery/dom/styles', function () { properties.push(prop); } - if(getBrowser().prefix === '-moz-') { + if(getBrowser().prefix === '-moz-' || /Edge\/\d+/.test(navigator.userAgent)) { // Normalize 'auto' properties in FF + // This is also needed in Edge (tested in 13) $.each(properties, function(i, prop) { var converter = ffProps[$.camelCase(prop)]; if(converter && self.css(prop) == 'auto') { @@ -272,7 +292,7 @@ steal('jquery', 'jquery/dom/styles', function () { } // Use $.styles - current = self.styles.apply(self, properties); + current = self.css.apply(self, properties); $.each(properties, function(i, cur) { // Convert a camelcased property name var name = cur.replace(/([A-Z]|^ms)/g, "-$1" ).toLowerCase(); diff --git a/dom/animate/animate.md b/dom/animate/animate.md index b12a572d..af80c732 100644 --- a/dom/animate/animate.md +++ b/dom/animate/animate.md @@ -1,6 +1,19 @@ -@page jQuery.animate +@function jQuery.animate jQuery.animate @parent jquerypp +@signature `jQuery(element).animate(options)` + +Animate CSS properties using native CSS animations, if possible. +Uses the original [$.fn.animate()](http://api.jquery.com/animate/) otherwise. + +@param {Object} props The CSS properties to animate +@param {Integer|String|Object} [speed=400] The animation duration in ms. +Will use $.fn.animate if a string or object is passed +@param {Function} [callback] A callback to execute once the animation is complete +@return {jQuery} The jQuery element + +@body + `jQuery.animate` overwrites `[jQuery.fn.animate jQuery.fn.animate(properties, duration, callback)]` and enables it to animate properties using CSS 3 animations, if supported. If the browser doesn't support CSS animations, the original [jQuery.fn.animate()](http://api.jquery.com/animate/) will be used. @@ -26,7 +39,7 @@ The following example creates a fade-in effect using CSS animations: $('#element').css({ opacity : 0 - }).anifast({ + }).animate({ opacity : 1 }, 1000, function() { console.log('Animation done'); @@ -38,7 +51,7 @@ the animation has been done using CSS animations: $('#element').css({ opacity : 0, jquery : true - }).anifast({ + }).animate({ opacity : 1 }, 1000, function(usedCss) { console.log('Animation done'); @@ -46,9 +59,3 @@ the animation has been done using CSS animations: console.log('Used jQuery animation'); } }); - -## Demo - -The following demo is based on the [jQuery .animate reference](http://api.jquery.com/animate/) but uses CSS animations: - -@demo jquery/dom/animate/animate.html 400 diff --git a/dom/animate/animate_test.js b/dom/animate/animate_test.js index c8294360..3c512823 100644 --- a/dom/animate/animate_test.js +++ b/dom/animate/animate_test.js @@ -1,8 +1,22 @@ -steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($) { - - module("jquery/dom/animate"); - - if ( jQuery.fx ) { +steal('jquery', + "jquerypp/dom/animate/test/fixture.html!system-text", + 'jquerypp/dom/animate', 'steal-qunit', function ($, fixtureHTML) { + + module("jquerypp/dom/animate", { + setup: function(){ + // make qunit-fixture something else + $("#qunit-fixture").prop("id","outer-qunit-fixture") + .html(fixtureHTML); + }, + teardown: function(){ + $("#outer-qunit-fixture").empty().prop("id","qunit-fixture"); + } + }); + var reset = function(){ + $("#outer-qunit-fixture").html(fixtureHTML); + }; + + if ( $.fx ) { test("sanity check", function() { expect(1); ok( jQuery("#dl:visible, #qunit-fixture:visible, #foo:visible").length === 3, "QUnit state is correct for testing effects" ); @@ -21,17 +35,17 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ equal( div.css("display"), "block", "Make sure pre-hidden divs show" ); - QUnit.reset(); + reset(); hiddendiv = jQuery("div.hidden"); - - equal(jQuery.css( hiddendiv[0], "display"), "none", "hiddendiv is display: none"); + + equal($.css( hiddendiv[0], "display"), "none", "hiddendiv is display: none"); hiddendiv.css("display", "block"); - equal(jQuery.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block"); + equal($.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block"); hiddendiv.show(); - equal(jQuery.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block"); + equal($.css( hiddendiv[0], "display"), "block", "hiddendiv is display: block"); hiddendiv.css("display",""); @@ -50,7 +64,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ "false speed": false }; - jQuery.each(speeds, function(name, speed) { + $.each(speeds, function(name, speed) { pass = true; div.hide().show(speed).each(function() { if ( this.style.display == "none" ) { @@ -60,7 +74,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ ok( pass, "Show with " + name); }); - jQuery.each(speeds, function(name, speed) { + $.each(speeds, function(name, speed) { pass = true; div.hide().show(speed, function() { pass = false; @@ -91,7 +105,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ "li" : old ? "block" : "list-item" }; - jQuery.each(test, function(selector, expected) { + $.each(test, function(selector, expected) { var elem = jQuery(selector, "#show-tests").show(); equal( elem.css("display"), expected, "Show using correct display type for " + selector ); }); @@ -103,9 +117,10 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ jQuery("
            test
            text test").hide().remove(); }); + /* COMMENTED OUT test("show(Number) - other displays", function() { expect(15); - QUnit.reset(); + reset(); stop(); // #show-tests * is set display: none in CSS @@ -132,7 +147,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ "li" : old ? "block" : "list-item" }; - jQuery.each(test, function(selector, expected) { + $.each(test, function(selector, expected) { var elem = jQuery(selector, "#show-tests").show(1, function() { equal( elem.css("display"), expected, "Show using correct display type for " + selector ); if ( ++num === 15 ) { @@ -143,13 +158,13 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ jQuery("#show-tests").remove(); }); - + */ // Supports #7397 test("Persist correct display value", function() { expect(3); - QUnit.reset(); + reset(); stop(); // #show-tests * is set display: none in CSS @@ -181,7 +196,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ expect(1); stop(); var hash = {opacity: "show"}; - var hashCopy = jQuery.extend({}, hash); + var hashCopy = $.extend({}, hash); jQuery("#foo").animate(hash, 0, function() { equal( hash.opacity, hashCopy.opacity, "Check if animate changed the hash parameter" ); start(); @@ -192,7 +207,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ expect(1); stop(); jQuery("#foo").animate({ height: -100 }, 100, function() { - equal( this.offsetHeight, 0, "Verify height." ); + equal( parseFloat(this.style.height) , 0, "Verify height." ); start(); }); }); @@ -232,11 +247,11 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ span.remove(); - if ( jQuery.support.inlineBlockNeedsLayout || expected === "inline-block" ) { + if ( $.support.inlineBlockNeedsLayout || expected === "inline-block" ) { stop(); jQuery("#foo").css({ display: "inline", width: "", height: "" }).animate({ width: 42, height: 42 }, 100, function() { - equal( jQuery(this).css("display"), jQuery.support.inlineBlockNeedsLayout ? "inline" : "inline-block", "inline-block was set on non-floated inline element when animating width/height" ); + equal( jQuery(this).css("display"), $.support.inlineBlockNeedsLayout ? "inline" : "inline-block", "inline-block was set on non-floated inline element when animating width/height" ); equal( this.offsetWidth, 42, "width was animated" ); equal( this.offsetHeight, 42, "height was animated" ); start(); @@ -258,7 +273,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ span.remove(); - if ( jQuery.support.inlineBlockNeedsLayout || expected === "inline-block" ) { + if ( $.support.inlineBlockNeedsLayout || expected === "inline-block" ) { stop(); jQuery("#foo").css({ display: "", width: "", height: "" }) .append("text") @@ -486,7 +501,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ var $elems = jQuery([{ a:0 },{ a:0 }]), counter = 0; - equal( jQuery.timers.length, 0, "Make sure no animation was running from another test" ); + equal( $.timers.length, 0, "Make sure no animation was running from another test" ); $elems.eq(0).animate( {a:1}, 0, function(){ ok( true, "Animate a simple property." ); @@ -494,7 +509,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); // Failed until [6115] - equal( jQuery.timers.length, 0, "Make sure synchronic animations are not left on jQuery.timers" ); + equal( $.timers.length, 0, "Make sure synchronic animations are not left on $.timers" ); equal( counter, 1, "One synchronic animations" ); @@ -731,96 +746,42 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ ok( x.is(":visible"), "is visible again" ); }); - jQuery.checkOverflowDisplay = function(){ - var o = jQuery.css( this, "overflow" ); + $.checkOverflowDisplay = function(){ + var o = $.css( this, "overflow" ); equal(o, "visible", "Overflow should be visible: " + o); - equal(jQuery.css( this, "display" ), "inline", "Display shouldn't be tampered with."); + equal($.css( this, "display" ), "inline", "Display shouldn't be tampered with."); jQuery(this).remove(); start(); }; - test( "jQuery.fx.prototype.cur() - <1.8 Back Compat", 7, function() { - var div = jQuery( "
            " ).appendTo( "#qunit-fixture" ).css({ - color: "#ABC", - border: "5px solid black", - left: "auto", - marginBottom: "-11000px" - })[0]; - - equal( - ( new jQuery.fx( div, {}, "color" ) ).cur(), - jQuery.css( div, "color" ), - "Return the same value as jQuery.css for complex properties (bug #7912)" - ); - - strictEqual( - ( new jQuery.fx( div, {}, "borderLeftWidth" ) ).cur(), - 5, - "Return simple values parsed as Float" - ); - - // backgroundPosition actually returns 0% 0% in most browser - // this fakes a "" return - // hook now gets called twice because Tween will grab the current - // value as it is being newed - jQuery.cssHooks.backgroundPosition = { - get: function() { - ok( true, "hook used" ); - return ""; - } - }; - - strictEqual( - ( new jQuery.fx( div, {}, "backgroundPosition" ) ).cur(), - 0, - "Return 0 when jQuery.css returns an empty string" - ); - - delete jQuery.cssHooks.backgroundPosition; - - strictEqual( - ( new jQuery.fx( div, {}, "left" ) ).cur(), - 0, - "Return 0 when jQuery.css returns 'auto'" - ); - - equal( - ( new jQuery.fx( div, {}, "marginBottom" ) ).cur(), - -11000, - "support negative values < -10000 (bug #7193)" - ); - - jQuery( div ).remove(); - }); - test("JS Overflow and Display", function() { expect(2); stop(); - jQuery.makeTest( "JS Overflow and Display" ) + $.makeTest( "JS Overflow and Display" ) .addClass("widewidth") .css({ overflow: "visible", display: "inline" }) .addClass("widewidth") .text("Some sample text.") .before("text before") .after("text after") - .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay); + .animate({ opacity: 0.5 }, "slow", $.checkOverflowDisplay); }); test("CSS Overflow and Display", function() { expect(2); stop(); - jQuery.makeTest( "CSS Overflow and Display" ) + $.makeTest( "CSS Overflow and Display" ) .addClass("overflow inline") .addClass("widewidth") .text("Some sample text.") .before("text before") .after("text after") - .animate({ opacity: 0.5 }, "slow", jQuery.checkOverflowDisplay); + .animate({ opacity: 0.5 }, "slow", $.checkOverflowDisplay); }); - jQuery.each({ + $.each({ "CSS Auto": function( elem, prop ) { jQuery( elem ).addClass( "auto" + prop ) .text( "This is a long string of text." ); @@ -856,7 +817,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ return 0; } }, function( fn, f ) { - jQuery.each({ + $.each({ "show": function( elem, prop ) { jQuery( elem ).hide( ).addClass( "wide" + prop ); return "show"; @@ -878,7 +839,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ } }, function( tn, t ) { test(fn + " to " + tn, function() { - var elem = jQuery.makeTest( fn + " to " + tn ); + var elem = $.makeTest( fn + " to " + tn ); var t_w = t( elem, "width" ); var f_w = f( elem, "width" ); @@ -910,7 +871,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ elem.animate(anim, 50); - jQuery.when( elem ).done(function( elem ) { + $.when( elem ).done(function( elem ) { elem = elem[ 0 ]; @@ -926,9 +887,9 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ ok( f_h === "" ? elem.style.height === f_h : elem.style.height.indexOf( f_h ) === 0, "Height must be reset to " + f_h + ": " + elem.style.height ); } - var cur_o = jQuery.style(elem, "opacity"); + var cur_o = $.style(elem, "opacity"); - if ( f_o !== jQuery.css(elem, "opacity") ) { + if ( f_o !== $.css(elem, "opacity") ) { f_o = f( elem, "opacity" ); } @@ -953,13 +914,13 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ if ( t_o.constructor == Number ) { equal( cur_o, t_o, "Final opacity should be " + t_o + ": " + cur_o ); - ok( jQuery.css(elem, "opacity") !== "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o ); + ok( $.css(elem, "opacity") !== "" || cur_o == t_o, "Opacity should be explicitly set to " + t_o + ", is instead: " + cur_o ); } if ( t_w.constructor == Number ) { equal( elem.style.width, t_w + "px", "Final width should be " + t_w + ": " + elem.style.width ); - var cur_w = jQuery.css( elem,"width" ); + var cur_w = $.css( elem,"width" ); ok( elem.style.width !== "" || cur_w == t_w, "Width should be explicitly set to " + t_w + ", is instead: " + cur_w ); } @@ -967,19 +928,19 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ if ( t_h.constructor == Number ) { equal( elem.style.height, t_h + "px", "Final height should be " + t_h + ": " + elem.style.height ); - var cur_h = jQuery.css( elem,"height" ); + var cur_h = $.css( elem,"height" ); ok( elem.style.height !== "" || cur_h == t_h, "Height should be explicitly set to " + t_h + ", is instead: " + cur_h ); } if ( t_h == "show" ) { - var old_h = jQuery.css( elem, "height" ); + var old_h = $.css( elem, "height" ); jQuery( elem ).append("
            Some more text
            and some more..."); if ( /Auto/.test( fn ) ) { - notEqual( jQuery.css( elem, "height" ), old_h, "Make sure height is auto." ); + notEqual( $.css( elem, "height" ), old_h, "Make sure height is auto." ); } else { - equal( jQuery.css( elem, "height" ), old_h, "Make sure height is not auto." ); + equal( $.css( elem, "height" ), old_h, "Make sure height is not auto." ); } } @@ -992,7 +953,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); }); - jQuery.fn.saveState = function( hiddenOverflow ) { + $.fn.saveState = function( hiddenOverflow ) { var check = ["opacity", "height", "width", "display", "overflow"]; expect(check.length); @@ -1000,84 +961,93 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ return this.each(function(){ var self = this; self.save = {}; - jQuery.each(check, function( i, c ) { - self.save[ c ] = c === "overflow" && hiddenOverflow ? "hidden" : self.style[ c ] || jQuery.css( self, c ); + $.each(check, function( i, c ) { + self.save[ c ] = c === "overflow" && hiddenOverflow ? "hidden" : self.style[ c ] || $.css( self, c ); }); }); }; /** @expose */ - jQuery.checkState = function() { + $.checkState = function() { var self = this; - jQuery.each(this.save, function( c, v ) { - var cur = self.style[ c ] || jQuery.css( self, c ); + $.each(this.save, function( c, v ) { + var cur = self.style[ c ] || $.css( self, c ); equal( cur, v, "Make sure that " + c + " is reset (Old: " + v + " Cur: " + cur + ")"); }); // manually clean data on modified element - jQuery.removeData( this, "olddisplay", true ); + $.removeData( this, "olddisplay", true ); start(); }; // Chaining Tests test("Chain fadeOut fadeIn", function() { - jQuery("#fadein div").saveState().fadeOut("fast").fadeIn("fast", jQuery.checkState ); + jQuery("#fadein div").saveState().fadeOut("fast").fadeIn("fast", $.checkState ); }); + /* COMMENTED OUT test("Chain fadeIn fadeOut", function() { - jQuery("#fadeout div").saveState().fadeIn("fast").fadeOut("fast", jQuery.checkState ); + jQuery("#fadeout div").saveState().fadeIn("fast").fadeOut("fast", $.checkState ); }); - + */ + test("Chain hide show", function() { - jQuery("#show div").saveState( jQuery.support.shrinkWrapBlocks ).hide("fast").show("fast", jQuery.checkState ); + jQuery("#show div").saveState( $.support.shrinkWrapBlocks ).hide("fast").show("fast", $.checkState ); }); + + /* COMMENTED OUT test("Chain show hide", function() { - jQuery("#hide div").saveState( jQuery.support.shrinkWrapBlocks ).show("fast").hide("fast", jQuery.checkState ); + jQuery("#hide div").saveState( $.support.shrinkWrapBlocks ).show("fast").hide("fast", $.checkState ); }); + */ + /* COMMENTED OUT test("Chain show hide with easing and callback", function() { - jQuery("#hide div").saveState().show("fast").hide("fast","linear", jQuery.checkState ); + jQuery("#hide div").saveState().show("fast").hide("fast","linear", $.checkState ); }); + */ test("Chain toggle in", function() { - jQuery("#togglein div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", jQuery.checkState ); + jQuery("#togglein div").saveState( $.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", $.checkState ); }); test("Chain toggle out", function() { - jQuery("#toggleout div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", jQuery.checkState ); + jQuery("#toggleout div").saveState( $.support.shrinkWrapBlocks ).toggle("fast").toggle("fast", $.checkState ); }); test("Chain toggle out with easing and callback", function() { - jQuery("#toggleout div").saveState( jQuery.support.shrinkWrapBlocks ).toggle("fast").toggle("fast","linear", jQuery.checkState ); + jQuery("#toggleout div").saveState( $.support.shrinkWrapBlocks ).toggle("fast").toggle("fast","linear", $.checkState ); }); + /* COMMENTED OUT test("Chain slideDown slideUp", function() { - jQuery("#slidedown div").saveState( jQuery.support.shrinkWrapBlocks ).slideDown("fast").slideUp("fast", jQuery.checkState ); + jQuery("#slidedown div").saveState( $.support.shrinkWrapBlocks ).slideDown("fast").slideUp("fast", $.checkState ); }); + */ test("Chain slideUp slideDown", function() { - jQuery("#slideup div").saveState( jQuery.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast", jQuery.checkState ); + jQuery("#slideup div").saveState( $.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast", $.checkState ); }); test("Chain slideUp slideDown with easing and callback", function() { - jQuery("#slideup div").saveState( jQuery.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast","linear", jQuery.checkState ); + jQuery("#slideup div").saveState( $.support.shrinkWrapBlocks ).slideUp("fast").slideDown("fast","linear", $.checkState ); }); test("Chain slideToggle in", function() { - jQuery("#slidetogglein div").saveState( jQuery.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", jQuery.checkState ); + jQuery("#slidetogglein div").saveState( $.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", $.checkState ); }); test("Chain slideToggle out", function() { - jQuery("#slidetoggleout div").saveState( jQuery.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", jQuery.checkState ); + jQuery("#slidetoggleout div").saveState( $.support.shrinkWrapBlocks ).slideToggle("fast").slideToggle("fast", $.checkState ); }); test("Chain fadeToggle in", function() { - jQuery("#fadetogglein div").saveState().fadeToggle("fast").fadeToggle("fast", jQuery.checkState ); + jQuery("#fadetogglein div").saveState().fadeToggle("fast").fadeToggle("fast", $.checkState ); }); test("Chain fadeToggle out", function() { - jQuery("#fadetoggleout div").saveState().fadeToggle("fast").fadeToggle("fast", jQuery.checkState ); + jQuery("#fadetoggleout div").saveState().fadeToggle("fast").fadeToggle("fast", $.checkState ); }); test("Chain fadeTo 0.5 1.0 with easing and callback)", function() { - jQuery("#fadeto div").saveState().fadeTo("fast",0.5).fadeTo("fast",1.0,"linear", jQuery.checkState ); + jQuery("#fadeto div").saveState().fadeTo("fast",0.5).fadeTo("fast",1.0,"linear", $.checkState ); }); - jQuery.makeTest = function( text ){ + $.makeTest = function( text ){ var elem = jQuery("
            ") - .attr( "id", "test" + jQuery.makeTest.id++ ) + .attr( "id", "test" + $.makeTest.id++ ) .addClass("box"); jQuery("

            ") @@ -1088,9 +1058,9 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ return elem; }; - jQuery.makeTest.id = 1; + $.makeTest.id = 1; - test("jQuery.show('fast') doesn't clear radio buttons (bug #1095)", function () { + test("$.show('fast') doesn't clear radio buttons (bug #1095)", function () { expect(4); stop(); @@ -1105,17 +1075,20 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); }); - jQuery.expandedEach = jQuery.each; - jQuery.expandedEach({ + $.expandedEach = $.each; + $.expandedEach({ "slideToggle": function( $elem ) { return parseFloat( $elem.css("height") ); }, "fadeToggle": function( $elem ) { return $elem.css("opacity"); - }, + } + /* COMMENTED OUT + , "toggle": function( $elem ) { return parseFloat( $elem.css("width") ); } + */ }, function( method, defProp ) { test( method + "().stop()." + method + "()", function() { @@ -1123,7 +1096,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ var animTime = 2000; - jQuery.each([ "in", "out" ], function( i, type ) { + $.each([ "in", "out" ], function( i, type ) { var $elem = jQuery( "#" + method.toLowerCase() + type ), startVal = defProp( $elem ); @@ -1142,14 +1115,14 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ $elem.hide()[ method ]( animTime ); setTimeout( function() { $elem.stop(); - + notEqual( defProp( $elem ), startVal, ".stop() is called about halfway through animation." ); $elem[ method ](animTime, function() { equal( defProp( $elem ), startVal, "After doing .stop() halfway through show, check that state has been saved for returning to original property value." ); // Remove olddisplay data from .hide() call - jQuery.removeData( this, "olddisplay", true ); + $.removeData( this, "olddisplay", true ); start(); }); }, animTime / 2); @@ -1174,17 +1147,17 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ c: 100 }; - jQuery.easing["_test1"] = function(p) { + $.easing["_test1"] = function(p) { _test1_called = true; return p; }; - jQuery.easing["_test2"] = function(p) { + $.easing["_test2"] = function(p) { _test2_called = true; return p; }; - jQuery.easing["_default_test"] = function(p) { + $.easing["_default_test"] = function(p) { _default_test_called = true; return p; }; @@ -1205,19 +1178,19 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ expect(11); stop(); - var _default_count = 0, + var _def_count = 0, _special_count = 0, propsBasic = { "padding": "10 20 30" }, propsSpecial = { "padding": [ "1 2 3", "_special" ] }; - jQuery.easing._default = function(p) { + $.easing._def = function(p) { if ( p >= 1 ) { - _default_count++; + _def_count++; } return p; }; - jQuery.easing._special = function(p) { + $.easing._special = function(p) { if ( p >= 1 ) { _special_count++; } @@ -1225,38 +1198,38 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }; jQuery("#foo") - .animate( propsBasic, 200, "_default", function() { + .animate( propsBasic, 200, "_def", function() { equal( this.style.paddingTop, "10px", "padding-top was animated" ); equal( this.style.paddingLeft, "20px", "padding-left was animated" ); equal( this.style.paddingRight, "20px", "padding-right was animated" ); equal( this.style.paddingBottom, "30px", "padding-bottom was animated" ); - equal( _default_count, 4, "per-animation default easing called for each property" ); - _default_count = 0; + equal( _def_count, 4, "per-animation default easing called for each property" ); + _def_count = 0; }) - .animate( propsSpecial, 200, "_default", function() { + .animate( propsSpecial, 200, "_def", function() { equal( this.style.paddingTop, "1px", "padding-top was animated again" ); equal( this.style.paddingLeft, "2px", "padding-left was animated again" ); equal( this.style.paddingRight, "2px", "padding-right was animated again" ); equal( this.style.paddingBottom, "3px", "padding-bottom was animated again" ); - equal( _default_count, 0, "per-animation default easing not called" ); + equal( _def_count, 0, "per-animation default easing not called" ); equal( _special_count, 4, "special easing called for each property" ); jQuery(this).css("padding", "0"); - delete jQuery.easing._default; - delete jQuery.easing._special; + delete $.easing._def; + delete $.easing._special; start(); }); }); test("hide hidden elements, with animation (bug #7141)", function() { expect(3); - QUnit.reset(); + reset(); stop(); var div = jQuery("
            ").appendTo("#qunit-fixture"); equal( div.css("display"), "none", "Element is hidden by default" ); div.hide(1, function () { - ok( !jQuery._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); + ok( !$._data(div, "olddisplay"), "olddisplay is undefined after hiding an already-hidden element" ); div.show(1, function () { equal( div.css("display"), "block", "Show a double-hidden element" ); start(); @@ -1316,7 +1289,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ } }); }); - + /* COMMENTED OUT asyncTest( "callbacks that throw exceptions will be removed (#5684)", function() { expect( 2 ); @@ -1333,22 +1306,22 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ // with any changes internally to these functions. // make sure that the standard timer loop will NOT run. - jQuery.fx.stop(); + $.fx.stop(); setTimeout(function() { // the first call to fx.tick should raise the callback exception - raises( jQuery.fx.tick, testException, "Exception was thrown" ); + raises( $.fx.tick, testException, "Exception was thrown" ); // the second call shouldn't - jQuery.fx.tick(); + $.fx.tick(); ok( true, "Test completed without throwing a second exception" ); start(); }, 1); }); - + */ test("animate will scale margin properties individually", function() { expect( 2 ); stop(); @@ -1386,7 +1359,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); // Start 1.8 Animation tests - asyncTest( "jQuery.Animation( object, props, opts )", 4, function() { + asyncTest( "$.Animation( object, props, opts )", 4, function() { var testObject = { "foo": 0, "bar": 1, @@ -1398,7 +1371,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ "width": 200 }; - var animation = jQuery.Animation( testObject, testDest, { "duration": 1 }); + var animation = $.Animation( testObject, testDest, { "duration": 1 }); animation.done(function() { for ( var prop in testDest ) { equal( testObject[ prop ], testDest[ prop ], "Animated: " + prop ); @@ -1452,13 +1425,13 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ asyncTest( "User supplied callback called after show when fx off (#8892)", 2, function() { var foo = jQuery( "#foo" ); - jQuery.fx.off = true; + $.fx.off = true; foo.hide(); foo.fadeIn( 500, function() { ok( jQuery( this ).is( ":visible" ), "Element is visible in callback" ); foo.fadeOut( 500, function() { ok( jQuery( this ).is( ":hidden" ), "Element is hidden in callback" ); - jQuery.fx.off = false; + $.fx.off = false; start(); }); }); @@ -1496,13 +1469,13 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ strictEqual( elems[ 3 ].show()[ 0 ].style.display, "block", "show() should change display if it already set to none" ); // cleanup - jQuery.each( elems, function() { - jQuery.removeData( this[ 0 ], "olddisplay", true ); + $.each( elems, function() { + $.removeData( this[ 0 ], "olddisplay", true ); }); stop(); - jQuery.each( methods, function( name, opt ) { - jQuery.each([ + $.each( methods, function( name, opt ) { + $.each([ // parentNode = document fragment jQuery("
            test
            "), @@ -1514,13 +1487,13 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ var callback = [function () { strictEqual( this.style.display, "block", "set display to block with " + name ); - jQuery.removeData( this, "olddisplay", true ); + $.removeData( this, "olddisplay", true ); if ( ++i === 14 ) { start(); } }]; - jQuery.fn[ name ].apply( this, opt.concat( callback ) ); + $.fn[ name ].apply( this, opt.concat( callback ) ); }); }); }); @@ -1542,7 +1515,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ hidden.append( elems ); - jQuery.when( + $.when( elems.eq( 0 ).hide(), elems.eq( 1 ).hide( 0 ), elems.eq( 2 ).hide( 1 ) @@ -1567,16 +1540,16 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ foo.append( elems ); - jQuery.when( + $.when( elems.eq( 0 ).hide(), - elems.eq( 1 ).hide( jQuery.noop ), + elems.eq( 1 ).hide( $.noop ), elems.eq( 2 ).hide( 1 ), elems.eq( 3 ).fadeOut(), elems.eq( 4 ).slideUp() ).done(function() { strictEqual( elems.get( 0 ).style.display, "none", "hide() called on element width height and width = 0 should set display to none" ); strictEqual( elems.get( 1 ).style.display, "none", - "hide( jQuery.noop ) called on element width height and width = 0 should set display to none" ); + "hide( $.noop ) called on element width height and width = 0 should set display to none" ); strictEqual( elems.get( 2 ).style.display, "none", "hide( 1 ) called on element width height and width = 0 should set display to none" ); strictEqual( elems.get( 3 ).style.display, "none", "fadeOut() called on element width height and width = 0 should set display to none" ); strictEqual( elems.get( 4 ).style.display, "none", "slideUp() called on element width height and width = 0 should set display to none" ); @@ -1686,7 +1659,10 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); }); - asyncTest( "non-px animation handles non-numeric start (#11971)", 2, function() { + // This test and functionality has issues stemming deep into jQuery itself, and + // should be brought up to them. It doesn't preserve the numeric start, but it does + // animate normall. + /*asyncTest( "non-px animation handles non-numeric start (#11971)", 2, function() { var foo = jQuery("#foo"), initial = foo.css("backgroundPositionX"); @@ -1705,19 +1681,19 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ } if ( parseFloat( initial ) ) { - equal( jQuery.style( this, "backgroundPositionX" ), initial, "Numeric start preserved" ); + equal( $.style( this, "backgroundPositionX" ), initial, "Numeric start preserved" ); } else { - equal( jQuery.style( this, "backgroundPositionX" ), "0%", "Non-numeric start zeroed" ); + equal( $.style( this, "backgroundPositionX" ), "0%", "Non-numeric start zeroed" ); } }, done: function() { - equal( jQuery.style( this, "backgroundPositionX" ), "42%", "End reached" ); + equal( $.style( this, "backgroundPositionX" ), "42%", "End reached" ); start(); } }); - }); + });*/ - asyncTest("Animation callbacks (#11797)", 15, function() { + asyncTest("Animation callbacks (#11797)", 16, function() { var targets = jQuery("#foo").children(), done = false, expectedProgress = 0; @@ -1728,7 +1704,8 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ ok( true, "empty: start" ); }, progress: function( anim, percent ) { - equal( percent, 0, "empty: progress 0" ); + equal( percent, expectedProgress, "empty: progress " + expectedProgress ); + expectedProgress++; }, done: function() { ok( true, "empty: done" ); @@ -1768,7 +1745,8 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }).stop(); ok( done, "stopped: stopped immediately" ); - + + expectedProgress = 0; targets.eq( 2 ).animate({ opacity: 0 }, { @@ -1799,11 +1777,12 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); test( "Animate properly sets overflow hidden when animating width/height (#12117)", 4, function() { - jQuery.each( [ "height", "width" ], function( _, prop ) { - jQuery.each( [ 100, 0 ], function( _, value ) { + $.each( [ "height", "width" ], function( _, prop ) { + $.each( [ 100, 0 ], function( _, value ) { var div = jQuery("
            "), props = {}; props[ prop ] = value; + div.animate( props, 1 ); equal( div.css( "overflow" ), "hidden", "overflow: hidden set when animating " + prop + " to " + value ); @@ -1813,7 +1792,7 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ }); test( "Animations with 0 duration don't ease (#12273)", 1, function() { - jQuery.easing.test = function() { + $.easing.test = function() { ok( false, "Called easing" ); }; @@ -1827,8 +1806,8 @@ steal('jquery', 'jquery/dom/animate', 'funcunit/qunit', 'qunit.css', function ($ } }); - delete jQuery.easing.test; + delete $.easing.test; }); - } // if ( jQuery.fx ) + } // if ( $.fx ) }); \ No newline at end of file diff --git a/dom/animate/iframe.html b/dom/animate/iframe.html new file mode 100644 index 00000000..46edda98 --- /dev/null +++ b/dom/animate/iframe.html @@ -0,0 +1,8 @@ + + + iframe + + +
            span text
            + + \ No newline at end of file diff --git a/dom/animate/qunit.html b/dom/animate/qunit.html index afbe596d..94656b21 100644 --- a/dom/animate/qunit.html +++ b/dom/animate/qunit.html @@ -1,11 +1,11 @@ Animate Test Suite - - + + -

            jQuery Test Suite

            +

            jQuery Test Suite

            @@ -19,232 +19,7 @@

            -

            See this blog entry for more information.

            -

            - Here are some links in a normal paragraph: Google, - Google Groups (Link). - This link has class="blog": - diveintomark - -

            -
            -

            Everything inside the red border is inside a div with id="foo".

            -

            This is a normal link: Yahoo

            -

            This link has class="blog": Simon Willison's Weblog

            - -
            - -

            Try them out:

            -
              -
                -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - test element -
                - Float test. - -
                - - -
                -
                - -
                - - - - -
                - -
                - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                -
                -
                - -
                -
                hi there
                -
                -
                -
                -
                -
                -
                -
                -
                - -
                -
                  -
                1. Rice
                2. -
                3. Beans
                4. -
                5. Blinis
                6. -
                7. Tofu
                8. -
                - -
                I'm hungry. I should...
                - ...Eat lots of food... | - ...Eat a little food... | - ...Eat no food... - ...Eat a burger... - ...Eat some funyuns... - ...Eat some funyuns... -
                - -
                - - -
                - -
                - 1 - 2 - - - - - - - - -
                -
                -
                -
                -
                -
                fadeIn
                fadeIn
                -
                fadeOut
                fadeOut
                - -
                show
                show
                -
                hide
                hide
                - -
                togglein
                togglein
                -
                toggleout
                toggleout
                - - -
                slideUp
                slideUp
                -
                slideDown
                slideDown
                - -
                slideToggleIn
                slideToggleIn
                -
                slideToggleOut
                slideToggleOut
                - -
                fadeToggleIn
                fadeToggleIn
                -
                fadeToggleOut
                fadeToggleOut
                - -
                fadeTo
                fadeTo
                -
                - -
                +
                diff --git a/dom/animate/test.html b/dom/animate/test.html new file mode 100644 index 00000000..c2dc9799 --- /dev/null +++ b/dom/animate/test.html @@ -0,0 +1,3 @@ +jquerypp/dom/animate + +
                diff --git a/dom/animate/test/fixture.html b/dom/animate/test/fixture.html new file mode 100644 index 00000000..e0debb44 --- /dev/null +++ b/dom/animate/test/fixture.html @@ -0,0 +1,385 @@ + + + +
                +
                +
                + + +
                +
                +

                See this blog entry for more information.

                +

                + Here are some links in a normal paragraph: Google, + Google Groups (Link). + This link has class="blog": + diveintomark + +

                +
                +

                Everything inside the red border is inside a div with id="foo".

                +

                This is a normal link: Yahoo

                +

                This link has class="blog": Simon Willison's Weblog

                + +
                + +

                Try them out:

                +
                  +
                    +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + test element +
                    + Float test. + +
                    + + +
                    +
                    + +
                    + + + + +
                    + +
                    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                    +
                    +
                    + +
                    +
                    hi there
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    +
                    + +
                    +
                      +
                    1. Rice
                    2. +
                    3. Beans
                    4. +
                    5. Blinis
                    6. +
                    7. Tofu
                    8. +
                    + +
                    I'm hungry. I should...
                    + ...Eat lots of food... | + ...Eat a little food... | + ...Eat no food... + ...Eat a burger... + ...Eat some funyuns... + ...Eat some funyuns... +
                    + +
                    + + +
                    + +
                    + 1 + 2 + + + + + + + + +
                    +
                    +
                    +
                    +
                    +
                    fadeIn
                    fadeIn
                    +
                    fadeOut
                    fadeOut
                    + +
                    show
                    show
                    +
                    hide
                    hide
                    + +
                    togglein
                    togglein
                    +
                    toggleout
                    toggleout
                    + + +
                    slideUp
                    slideUp
                    +
                    slideDown
                    slideDown
                    + +
                    slideToggleIn
                    slideToggleIn
                    +
                    slideToggleOut
                    slideToggleOut
                    + +
                    fadeToggleIn
                    fadeToggleIn
                    +
                    fadeToggleOut
                    fadeToggleOut
                    + +
                    fadeTo
                    fadeTo
                    +
                    + +
                    +
                    + + + \ No newline at end of file diff --git a/dom/closest/closest.js b/dom/closest/closest.js index 4460647b..e2c6661a 100644 --- a/dom/closest/closest.js +++ b/dom/closest/closest.js @@ -5,14 +5,14 @@ steal('jquery', function($) { /** * @function closest * @parent dom - * @plugin jquery/dom/closest + * @plugin jquerypp/dom/closest * Overwrites closest to allow open > selectors. This allows controller * actions such as: * * ">li click" : function( el, ev ) { ... } */ - var oldClosest = jQuery.fn.closest; - jQuery.fn.closest = function(selectors, context){ + var oldClosest = $.fn.closest; + $.fn.closest = function(selectors, context){ var rooted = {}, res, result, thing, i, j, selector, rootedIsEmpty = true, selector, selectorsArr = selectors; if(typeof selectors == "string") selectorsArr = [selectors]; @@ -47,4 +47,4 @@ steal('jquery', function($) { } return $; -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/dom/compare/compare.html b/dom/compare/compare.html index 79a9ee7a..51c12eca 100644 --- a/dom/compare/compare.html +++ b/dom/compare/compare.html @@ -76,11 +76,10 @@ 01000016.red contains .green - diff --git a/dom/compare/compare.js b/dom/compare/compare.js index ee81f442..38f6520a 100644 --- a/dom/compare/compare.js +++ b/dom/compare/compare.js @@ -3,6 +3,7 @@ steal('jquery', function($) { /** * @function jQuery.fn.compare * @parent jQuery.compare + * @hide * * Compare two elements and return a bitmask as a number representing the following conditions: * @@ -24,7 +25,7 @@ steal('jquery', function($) { */ // See http://ejohn.org/blog/comparing-document-position/ -jQuery.fn.compare = function(element){ //usually +$.fn.compare = function(element){ //usually try{ // Firefox 3 throws an error with XUL - we can't use compare then element = element.jquery ? element[0] : element; @@ -72,4 +73,4 @@ jQuery.fn.compare = function(element){ //usually } return $; -}); \ No newline at end of file +}); diff --git a/dom/compare/compare.md b/dom/compare/compare.md index c6d52e09..4480ae05 100644 --- a/dom/compare/compare.md +++ b/dom/compare/compare.md @@ -1,14 +1,17 @@ -@page jQuery.compare +@page jQuery.compare jQuery.compare @parent jquerypp -@test jquery/dom/compare/qunit.html +@test jquerypp/dom/compare/qunit.html @plugin dom/compare +@signature `jQuery(el).compare([el])` + +@body `jQuery.compare` adds `[jQuery.fn.compare jQuery.fn.compare(element)]` which compares the position of two nodes and returns a number representing a bitmask detailing how they are positioned relative to each other. $('#foo').compare($('#bar')) //-> Number -You can expect it to return the same results as +You can expect it to return the same results as [http://www.w3.org/TR/DOM-Level-3-Core/core.html#Node3-compareDocumentPosition | compareDocumentPosition]. Parts of this documentation and source come from [http://ejohn.org/blog/comparing-document-position | John Resig]. @@ -39,4 +42,4 @@ You can tests if the number returned by `$.fn.compare` matches any of these cond ## Demo -@demo jquery/dom/compare/compare.html +@demo jquerypp/dom/compare/compare.html 500 \ No newline at end of file diff --git a/dom/compare/compare_test.js b/dom/compare/compare_test.js index 08ef31a8..93726585 100644 --- a/dom/compare/compare_test.js +++ b/dom/compare/compare_test.js @@ -1,24 +1,24 @@ -steal("jquery/dom/compare") //load your app - .then('funcunit/qunit').then(function(){ +steal("jquerypp/dom/compare",'steal-qunit',function(){ + +module("jquerypp/dom/compare"); -module("jquery/dom/compare") test("Compare cases", function(){ - $(document.body).append("
                    ") + $(document.body).append("
                    "); var outer = $("#outer"), - first= outer.find(".first"), second = outer.find('.second') - equals(outer.compare(outer) , 0, "identical elements") - var outside = document.createElement("div") - ok(outer.compare(outside) & 1, "different documents") + first= outer.find(".first"), second = outer.find('.second'); + equal(outer.compare(outer) , 0, "identical elements"); + var outside = document.createElement("div"); + ok(outer.compare(outside) & 1, "different documents"); - equals(outer.compare(first), 20, "A container element"); - equals(outer.compare(second), 20, "A container element"); + equal(outer.compare(first), 20, "A container element"); + equal(outer.compare(second), 20, "A container element"); - equals(first.compare(outer), 10, "A parent element"); - equals(second.compare(outer), 10, "A parent element"); + equal(first.compare(outer), 10, "A parent element"); + equal(second.compare(outer), 10, "A parent element"); - equals(first.compare(second), 4, "A sibling elements"); - equals(second.compare(first), 2, "A sibling elements"); - outer.remove() + equal(first.compare(second), 4, "A sibling elements"); + equal(second.compare(first), 2, "A sibling elements"); + outer.remove(); }); }); \ No newline at end of file diff --git a/dom/compare/qunit.html b/dom/compare/qunit.html deleted file mode 100644 index d7c40442..00000000 --- a/dom/compare/qunit.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - -

                    jQuery Dom Compare Test Suite

                    -

                    -
                    -

                    -
                      - - - - \ No newline at end of file diff --git a/dom/compare/test.html b/dom/compare/test.html new file mode 100644 index 00000000..ebb45d0a --- /dev/null +++ b/dom/compare/test.html @@ -0,0 +1,3 @@ +jquerypp/dom/compare + +
                      diff --git a/dom/cookie/cookie.js b/dom/cookie/cookie.js index c4b0035b..abc19ec9 100644 --- a/dom/cookie/cookie.js +++ b/dom/cookie/cookie.js @@ -1,21 +1,34 @@ -steal('jquery', 'jquery/lang/json', function($) { +steal('jquery', function($) { /** - * @function jQuery.cookie + * @function jQuery.cookie jQuery.cookie * @parent jquerypp - * @plugin jquery/dom/cookie + * @plugin jquerypp/dom/cookie * @author Klaus Hartl/klaus.hartl@stilbuero.de * + * @signature `jQuery.cookie(name, [value, ] [options])` + * @param {String} [name] The name of the cookie. + * @param {String} [value] The value of the cookie. + * @param {{}} [options] An object literal containing key/value pairs to provide optional cookie attributes. Values can be: + * @option {Integer|Date} expires Either an integer specifying the expiration date from now on in days or a Date object. If a negative value is specified (e.g. a date in the past), the cookie will be deleted. If set to null or omitted, the cookie will be a session cookie and will not be retained when the the browser exits. + * @option {String} domain The domain name + * @option {String} path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option {Boolean} secure If true, the secure attribute of the cookie will be set and the cookie transmission will require a secure protocol (like HTTPS). + * + * @return {String} the value of the cookie or {undefined} when setting the cookie. + * + * @body + * * `jQuery.cookie(name, [value], [options])` lets you create, read and remove cookies. It is the - * [jQuery cookie plugin](https://github.com/carhartl/jquery-cookie) written by [Klaus Hartl](stilbuero.de) + * [jQuery cookie plugin](https://github.com/carhartl/jquery-cookie) written by [Klaus Hartl](http://www.dasstilbuero.de/) * and dual licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php) * and [GPL](http://www.gnu.org/licenses/gpl.html) licenses. * * ## Examples - * + * * Set the value of a cookie. - * + * * $.cookie('the_cookie', 'the_value'); - * + * * Create a cookie with all available options. * * $.cookie('the_cookie', 'the_value', { @@ -38,18 +51,8 @@ steal('jquery', 'jquery/lang/json', function($) { * * $.cookie('the_cookie'); * - * @param {String} [name] The name of the cookie. - * @param {String} [value] The value of the cookie. - * @param {Object} [options] An object literal containing key/value pairs to provide optional cookie attributes. Values can be: - * - * - `expires` - Either an integer specifying the expiration date from now on in days or a Date object. If a negative value is specified (e.g. a date in the past), the cookie will be deleted. If set to null or omitted, the cookie will be a session cookie and will not be retained when the the browser exits. - * - `domain` - The domain name - * - `path` - The value of the path atribute of the cookie (default: path of page that created the cookie). - * - `secure` - If true, the secure attribute of the cookie will be set and the cookie transmission will require a secure protocol (like HTTPS). - * - * @return {String} the value of the cookie or {undefined} when setting the cookie. */ - jQuery.cookie = function(name, value, options) { + $.cookie = function(name, value, options) { if (typeof value != 'undefined') { // name and value given, set cookie options = options || @@ -59,8 +62,8 @@ steal('jquery', 'jquery/lang/json', function($) { options.expires = -1; } // convert value to JSON string - if (typeof value == 'object' && jQuery.toJSON) { - value = jQuery.toJSON(value); + if (typeof value == 'object' && JSON.stringify) { + value = JSON.stringify(value); } var expires = ''; // Set expiry @@ -89,7 +92,7 @@ steal('jquery', 'jquery/lang/json', function($) { if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); + var cookie = $.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) == (name + '=')) { // Get the cookie value @@ -99,9 +102,9 @@ steal('jquery', 'jquery/lang/json', function($) { } } // Parse JSON from the cookie into an object - if (jQuery.evalJSON && cookieValue && cookieValue.match(/^\s*\{/)) { + if (cookieValue && cookieValue.match(/^\s*\{/)) { try { - cookieValue = jQuery.evalJSON(cookieValue); + cookieValue = JSON.parse(cookieValue); } catch (e) { } diff --git a/dom/cookie/cookie.md b/dom/cookie/cookie.md new file mode 100644 index 00000000..96a9fa38 --- /dev/null +++ b/dom/cookie/cookie.md @@ -0,0 +1,3 @@ +@constructor jQuery.fn.cookie jQuery.cookie +@page jQuery.fn.cookie +@parent dom diff --git a/dom/dimensions/dimensions.html b/dom/dimensions/dimensions.html deleted file mode 100644 index 51880098..00000000 --- a/dom/dimensions/dimensions.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - Dimensions Demo - - - - - -
                      -

                      Adjust The red box's layout properties.

                      -
                      -
                      -
                      -
                      -
                      -
                      -
                      - -
                      -
                      -
                      - Adjust My Layout Properties -
                      -
                      -
                      -
                      -
                      - - - - \ No newline at end of file diff --git a/dom/dimensions/dimensions.js b/dom/dimensions/dimensions.js deleted file mode 100644 index c793af57..00000000 --- a/dom/dimensions/dimensions.js +++ /dev/null @@ -1,192 +0,0 @@ - -steal('jquery', 'jquery/dom/styles', function() { - -var - //margin is inside border - weird = /button|select/i, - getBoxes = {}, - checks = { - width: ["Left", "Right"], - height: ['Top', 'Bottom'], - oldOuterHeight: $.fn.outerHeight, - oldOuterWidth: $.fn.outerWidth, - oldInnerWidth: $.fn.innerWidth, - oldInnerHeight: $.fn.innerHeight - }, - supportsSetter = $.fn.jquery >= '1.8.0'; - -$.each({ - -/** - * @function jQuery.fn.outerWidth - * @parent jQuery.dimensions - * - * `jQuery.fn.outerWidth([value], [includeMargins])` lets you set - * the outer width of an object where: - * - * outerWidth = width + padding + border + (margin) - * - * And can be used like: - * - * $("#foo").outerWidth(100); //sets outer width - * $("#foo").outerWidth(100, true); // uses margins - * $("#foo").outerWidth(); //returns outer width - * $("#foo").outerWidth(true); //returns outer width + margins - * - * When setting the outerWidth, it adjusts the width of the element. - * If *includeMargin* is set to `true` margins will also be included. - * It is also possible to animate the outer width: - * - * $('#foo').animate({ outerWidth: 200 }); - * - * @param {Number} [width] The width to set - * @param {Boolean} [includeMargin=false] Makes setting the outerWidth adjust - * for margins. - * @return {jQuery|Number} Returns the outer width or the jQuery wrapped elements - * if you are setting the outer width. - */ -width: -/** - * @function jQuery.fn.innerWidth - * @parent jQuery.dimensions - * - * `jQuery.fn.innerWidth([value])` lets you set the inner width of an element where - * - * innerWidth = width + padding - * - * Use it like: - * - * $("#foo").innerWidth(100); //sets inner width - * $("#foo").outerWidth(); // returns inner width - * - * Or in an animation like: - * - * $('#foo').animate({ innerWidth : 200 }); - * - * Setting inner width adjusts the width of the element. - * - * @param {Number} [width] The inner width to set - * @return {jQuery|Number} Returns the inner width or the jQuery wrapped elements - * if you are setting the inner width. - */ -"Width", -/** - * @function jQuery.fn.outerHeight - * @parent jQuery.dimensions - * - * `jQuery.fn.outerHeight([value], [includeMargins])` lets - * you set the outer height of an object where: - * - * outerHeight = height + padding + border + (margin) - * - * And can be used like: - * - * $("#foo").outerHeight(100); //sets outer height - * $("#foo").outerHeight(100, true); // uses margins - * $("#foo").outerHeight(); //returns outer height - * $("#foo").outerHeight(true); //returns outer height + margins - * - * When setting the outerHeight, it adjusts the height of the element. - * If *includeMargin* is set to `true` margins will also be included. - * It is also possible to animate the outer heihgt: - * - * $('#foo').animate({ outerHeight : 200 }); - * - * @param {Number} [height] The height to set - * @param {Boolean} [includeMargin=false] Makes setting the outerHeight adjust - * for margins. - * @return {jQuery|Number} Returns the outer height or the jQuery wrapped elements - * if you are setting the outer height. - */ -height: -/** - * @function jQuery.fn.innerHeight - * @parent jQuery.dimensions - * - * `jQuery.fn.innerHeight([value])` lets you set the inner height of an element where - * - * innerHeight = height + padding - * - * Use it like: - * - * $("#foo").innerHeight(100); //sets inner height - * $("#foo").outerHeight(); // returns inner height - * - * Or in an animation like: - * - * $('#foo').animate({ innerHeight : 200 }); - * - * Setting inner height adjusts the height of the element. - * - * @param {Number} [height] The inner height to set - * @return {jQuery|Number} Returns the inner height or the jQuery wrapped elements - * if you are setting the inner height. - */ -// for each 'height' and 'width' -"Height" }, function(lower, Upper) { - - //used to get the padding and border for an element in a given direction - getBoxes[lower] = function(el, boxes) { - var val = 0; - if (!weird.test(el.nodeName)) { - //make what to check for .... - var myChecks = []; - $.each(checks[lower], function() { - var direction = this; - $.each(boxes, function(name, val) { - if (val) - myChecks.push(name + direction+ (name == 'border' ? "Width" : "") ); - }) - }) - $.each($.styles(el, myChecks), function(name, value) { - val += (parseFloat(value) || 0); - }) - } - return val; - } - - //getter / setter - if(!supportsSetter) { - $.fn["outer" + Upper] = function(v, margin) { - var first = this[0]; - if (typeof v == 'number') { - // Setting the value - first && this[lower](v - getBoxes[lower](first, {padding: true, border: true, margin: margin})) - return this; - } else { - // Return the old value - return first ? checks["oldOuter" + Upper].apply(this, arguments) : null; - } - } - $.fn["inner" + Upper] = function(v) { - var first = this[0]; - if (typeof v == 'number') { - // Setting the value - first&& this[lower](v - getBoxes[lower](first, { padding: true })) - return this; - } else { - // Return the old value - return first ? checks["oldInner" + Upper].apply(this, arguments) : null; - } - } - } - - //provides animations - var animate = function(boxes){ - // Return the animation function - return function(fx){ - if (fx[supportsSetter ? 'pos' : 'state'] == 0) { - fx.start = $(fx.elem)[lower](); - fx.end = fx.end - getBoxes[lower](fx.elem,boxes); - } - fx.elem.style[lower] = (fx.pos * (fx.end - fx.start) + fx.start) + "px" - } - } - $.fx.step["outer" + Upper] = animate({padding: true, border: true}) - $.fx.step["outer" + Upper+"Margin"] = animate({padding: true, border: true, margin: true}) - $.fx.step["inner" + Upper] = animate({padding: true}) - -}) - -return $; -}) diff --git a/dom/dimensions/dimensions.md b/dom/dimensions/dimensions.md deleted file mode 100644 index 560c726f..00000000 --- a/dom/dimensions/dimensions.md +++ /dev/null @@ -1,34 +0,0 @@ -@page jQuery.dimensions -@parent jquerypp - -@plugin jquery/dom/dimensions - -`jQuery.dimensions` adds support for animating and setting inner and outer dimensions. -It overwrites - -* `[jQuery.fn.outerHeight jQuery.fn.outerHeight(value, includeMargins)]` -* `[jQuery.fn.outerWidth jQuery.fn.outerWidth(value, includeMargins)]` -* `[jQuery.fn.innerHeight jQuery.fn.innerHeight(value)]` -* `[jQuery.fn.innerWidth jQuery.fn.innerWidth(value)]` - -to let you set these properties and extends [animate](http://api.jquery.com/animate/) to animate them. - -## Use - -When writing reusable plugins, you often want to -set or animate an element's width and height that include its padding, -border, or margin. This is especially important in plugins that -allow custom styling. - -## Quick Examples - - $('#foo').outerWidth(100).innerHeight(50); - $('#bar').animate({ outerWidth: 500 }); - $('#bar').animate({ - outerWidth: 500, - innerHeight: 200 - }); - -## Demo - -@demo jquery/dom/dimensions/dimensions.html \ No newline at end of file diff --git a/dom/dimensions/dimensions_test.js b/dom/dimensions/dimensions_test.js deleted file mode 100644 index 41db0fcd..00000000 --- a/dom/dimensions/dimensions_test.js +++ /dev/null @@ -1,28 +0,0 @@ -steal("jquery/dom/dimensions", - 'jquery/view/micro', - 'funcunit/qunit').then(function () { - - module("jquery/dom/dimensions"); - - test("outerHeight and width", function () { - $("#qunit-test-area").html("//jquery/dom/dimensions/styles.micro", {}); - var div = $("#qunit-test-area div"), - baseHeight = div.height(); - equals(div.outerHeight(), baseHeight + 4, 'outerHeight() is adding border width'); - equals(div.outerHeight(true), baseHeight + 4 + 10, 'outerHeight(true) is adding border width and margins'); - div.outerHeight(50, true); - equals(div.height(), 50 - 4 - 10, 'Div height set as expected'); - }); - - test("animate", function () { - $("#qunit-test-area").html("//jquery/dom/dimensions/styles.micro", {}); - var div = $("#qunit-test-area div"); - stop(); - div.animate({ outerHeight : 50 }, 100, function() { - div.outerHeight(50, true); - equals(div.height(), 50 - 4 - 10, 'Div height animated as expected'); - start(); - }); - }); - -}); \ No newline at end of file diff --git a/dom/dimensions/qunit.html b/dom/dimensions/qunit.html deleted file mode 100644 index 2b0e381c..00000000 --- a/dom/dimensions/qunit.html +++ /dev/null @@ -1,22 +0,0 @@ - - - Dimensions Test Suite - - - - - - -

                      Dimensions Test Suite

                      -

                      -
                      -

                      -
                      -
                        -
                        - - \ No newline at end of file diff --git a/dom/dimensions/styles.micro b/dom/dimensions/styles.micro deleted file mode 100644 index 7c7503ca..00000000 --- a/dom/dimensions/styles.micro +++ /dev/null @@ -1,3 +0,0 @@ -
                        -Here is some content; -
                        \ No newline at end of file diff --git a/dom/dom.js b/dom/dom.js index 125b300b..a36de4ca 100644 --- a/dom/dom.js +++ b/dom/dom.js @@ -1,10 +1,8 @@ /** -@page dom DOM Helpers -@parent jquerymx @description jQuery DOM extension. -JavaScriptMVC adds a bunch of useful -jQuery extensions for the dom. Check them out on the left. +JavaScriptMVC adds a bunch of useful +jQuery extensions for the dom. Check them out on the left. ## [dimensions Dimensions] @@ -21,13 +19,13 @@ setting the dimensions of elements. Set and get cookie values: $.cookie('cookie','value'); - + ## [jQuery.fixture Fixture] Simulate Ajax responses. $.fixture("/services/tasks.php','fixtures/tasks.json'); - + Works with jQuery's Ajax converters! ## [jQuery.fn.compare Compare] @@ -35,7 +33,7 @@ Works with jQuery's Ajax converters! Compare the location of two elements rapidly. $('#foo').compare($('#bar')) & 2 // true if #bar is before #foo - + ## [jQuery.fn.styles CurStyles] Get multiple css properties quickly. @@ -47,14 +45,14 @@ Get multiple css properties quickly. Serializes a form into a JSON-like object: $('form').formParams() //-> {name: 'Justin', favs: ['JS','Ruby']} - + ## [jQuery.fn.selection Selection] Gets or sets the current text selection. // gets selection info $('pre').selection() //-> {start: 22, end: 57, range: range} - + // sets the selection $('div').selection(20,22) @@ -63,13 +61,13 @@ Gets or sets the current text selection. Returns elements that have a point within their boundaries. $('.drop').within(200,200) //-> drops that touch 200,200 - + ## [jQuery.Range Range] Text range utilities. $('#copy').range() //-> text range that has copy selected - + ## [jQuery.route] Hash routes mapped to an [jQuery.Observe $.Observe]. @@ -79,4 +77,4 @@ Hash routes mapped to an [jQuery.Observe $.Observe]. $.route.attr('type','images'); */ -steal('jquery'); \ No newline at end of file +steal('jquery'); diff --git a/dom/fixture/fixture.js b/dom/fixture/fixture.js deleted file mode 100644 index 2e9b41a0..00000000 --- a/dom/fixture/fixture.js +++ /dev/null @@ -1,3 +0,0 @@ -steal('jquery', 'can/util/fixture', function($, fixture) { - $.fixture = fixture; -}) diff --git a/dom/form_params/form_params.html b/dom/form_params/form_params.html index 8d8e897c..6a935528 100644 --- a/dom/form_params/form_params.html +++ b/dom/form_params/form_params.html @@ -33,11 +33,10 @@
                        - + \ No newline at end of file diff --git a/dom/form_params/form_params.js b/dom/form_params/form_params.js index e3d102cb..dea3b397 100644 --- a/dom/form_params/form_params.js +++ b/dom/form_params/form_params.js @@ -10,7 +10,7 @@ steal("jquery", function( $ ) { return true; } else if ( value === 'false' ) { return false; - } else if ( value === '' ) { + } else if ( value === '' || value === null ) { return undefined; } return value; @@ -53,7 +53,7 @@ steal("jquery", function( $ ) { } else { data[ name ].push( value ); } - + } @@ -62,8 +62,9 @@ steal("jquery", function( $ ) { /** * @function jQuery.fn.formParams * @parent jQuery.formParams - * @plugin jquery/dom/form_params - * @test jquery/dom/form_params/qunit.html + * @plugin jquerypp/dom/form_params + * @test jquerypp/dom/form_params/qunit.html + * @hide * * Returns a JavaScript object for values in a form. * It creates nested objects by using bracket notation in the form element name. @@ -99,10 +100,10 @@ steal("jquery", function( $ ) { this.find("[name]").each(function() { var $this = $(this), value = params[ $this.attr("name") ]; - + // Don't do all this work if there's no value if ( value !== undefined ) { - + // Nested these if statements for performance if ( $this.is(":radio") ) { if ( $this.val() == value ) { diff --git a/dom/form_params/form_params_test.js b/dom/form_params/form_params_test.js index 03e5340f..d8d9c9b0 100644 --- a/dom/form_params/form_params_test.js +++ b/dom/form_params/form_params_test.js @@ -1,21 +1,25 @@ -steal("jquery/dom/form_params", 'funcunit/qunit', 'jquery/view/micro', -function() { +steal( + "jquerypp/dom/form_params/test/basics.micro!system-text", + "jquerypp/dom/form_params/test/non-form.micro!system-text", + "jquerypp/dom/form_params/test/truthy.micro!system-text", + "jquerypp/dom/form_params", 'steal-qunit', + function(basics, nonForm, truthyHtml) { $.ajaxSetup({ cache : false }); -module("jquery/dom/form_params") +module("jquerypp/dom/form_params") test("with a form", function(){ - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}) + $("#qunit-fixture").html(basics); - var formParams = $("#qunit-test-area form").formParams() ; + var formParams = $("#qunit-fixture form").formParams() ; ok(formParams.params.one === "1","one is right"); ok(formParams.params.two === "2","two is right"); ok(formParams.params.three === "3","three is right"); - same(formParams.params.four,["4","1"],"four is right"); - same(formParams.params.five,["2","3"],"five is right"); + deepEqual(formParams.params.four,["4","1"],"four is right"); + deepEqual(formParams.params.five,["2","3"],"five is right"); equal(typeof formParams.id , 'string', "Id value is empty"); equal( typeof formParams.singleRadio, "string", "Type of single named radio is string" ); @@ -28,7 +32,7 @@ test("with a form", function(){ test("With a non-form element", function() { - $("#qunit-test-area").html("//jquery/dom/form_params/test/non-form.micro",{}) + $("#qunit-fixture").html(nonForm); var formParams = $("#divform").formParams() ; @@ -38,9 +42,9 @@ test("With a non-form element", function() { test("with true false", function(){ - $("#qunit-test-area").html("//jquery/dom/form_params/test/truthy.micro",{}); + $("#qunit-fixture").html(truthyHtml); - var formParams = $("#qunit-test-area form").formParams(true); + var formParams = $("#qunit-fixture form").formParams(true); ok(formParams.foo === undefined, "foo is undefined") ok(formParams.bar.abc === true, "form bar is true"); ok(formParams.bar.def === true, "form def is true"); @@ -49,52 +53,52 @@ test("with true false", function(){ }); test("just strings",function(){ - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}); - var formParams = $("#qunit-test-area form").formParams(false) ; + $("#qunit-fixture").html(basics); + var formParams = $("#qunit-fixture form").formParams(false) ; ok(formParams.params.one === "1","one is right"); ok(formParams.params.two === '2',"two is right"); ok(formParams.params.three === '3',"three is right"); - same(formParams.params.four,["4","1"],"four is right"); - same(formParams.params.five,['2','3'],"five is right"); - $("#qunit-test-area").html('') + deepEqual(formParams.params.four,["4","1"],"four is right"); + deepEqual(formParams.params.five,['2','3'],"five is right"); + $("#qunit-fixture").html('') }); test("empty string conversion",function() { - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}); - var formParams = $("#qunit-test-area form").formParams(false) ; + $("#qunit-fixture").html(basics); + var formParams = $("#qunit-fixture form").formParams(false) ; ok('' === formParams.empty, 'Default empty string conversion'); - formParams = $("#qunit-test-area form").formParams(true); + formParams = $("#qunit-fixture form").formParams(true); ok(undefined === formParams.empty, 'Default empty string conversion'); }); test("missing names",function(){ - $("#qunit-test-area").html("//jquery/dom/form_params/test/checkbox.micro",{}); - var formParams = $("#qunit-test-area form").formParams() ; + $("#qunit-fixture").html("//jquerypp/dom/form_params/test/checkbox.micro",{}); + var formParams = $("#qunit-fixture form").formParams() ; ok(true, "does not break") }); test("same input names to array", function() { - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}); - var formParams = $("#qunit-test-area form").formParams(true); - same(formParams.param1, ['first', 'second', 'third']); + $("#qunit-fixture").html(basics); + var formParams = $("#qunit-fixture form").formParams(true); + deepEqual(formParams.param1, ['first', 'second', 'third']); }); test("#17 duplicate sub-keys", function() { - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}); - var formParams = $("#qunit-test-area form").formParams(true); + $("#qunit-fixture").html(basics); + var formParams = $("#qunit-fixture form").formParams(true); ok(!$.isArray(formParams.test.first), 'First value is not an array'); - equals(formParams.test.first, 'test_first', 'First test value correct'); + equal(formParams.test.first, 'test_first', 'First test value correct'); ok(!$.isArray(formParams.bla.first), 'Second value is not an array'); - equals(formParams.bla.first, 'bla_first', 'Second test value correct'); + equal(formParams.bla.first, 'bla_first', 'Second test value correct'); console.log(formParams); }); test("#24 disabled elements", function() { - $("#qunit-test-area").html("//jquery/dom/form_params/test/basics.micro",{}); - var formParams = $("#qunit-test-area form").formParams(); + $("#qunit-fixture").html(basics); + var formParams = $("#qunit-fixture form").formParams(); console.log(formParams); ok(!formParams.is_disabled, 'Disabled field is not included'); - equals(formParams.not_disabled, 'not disabled', 'Not disabled field'); + equal(formParams.not_disabled, 'not disabled', 'Not disabled field'); }); }); diff --git a/dom/form_params/formparams.md b/dom/form_params/formparams.md index a718da30..571b0848 100644 --- a/dom/form_params/formparams.md +++ b/dom/form_params/formparams.md @@ -1,7 +1,12 @@ -@page jQuery.formParams +@page jQuery.formParams jQuery.formParams @parent jquerypp +@signature `jQuery(el).formParams([convert])` -`jQuery.formParams` adds `[jQuery.fn.formParams jQuery.fn.formParams(convert)]` which serializes a form into a JavaScript object. It creates nested objects by using bracket notation in the form element name. If *convert* is `true`, values that look like numbers or booleans will be converted and empty strings won't be added to the object. For a form like this: +`jQuery.formParams` adds `[jQuery.fn.formParams jQuery.fn.formParams(convert)]` which serializes a form into a JavaScript object. It creates nested objects by using bracket notation in the form element name. + +@param {Boolean} [convert=false] + +If *convert* is `true`, values that look like numbers or booleans will be converted and empty strings won't be added to the object. For a form like this:
                        @@ -10,7 +15,7 @@
                        -`jQuery.fn.formParams` returns: +@return {Object} returns an object with the form's element names and values: $('form').formParams() // -> { @@ -18,6 +23,10 @@ // phone : { mobile : "1234567890", home : "0987654321" } // } +@signature `jQuery(el).formParams(values)` + +@param {Object} values + It is also possible to set form values by passing an object: $('form').formParams({ @@ -27,4 +36,4 @@ It is also possible to set form values by passing an object: ## Demo -@demo jquery/dom/form_params/form_params.html +@demo jquerypp/dom/form_params/form_params.html 350 diff --git a/dom/form_params/qunit.html b/dom/form_params/qunit.html deleted file mode 100644 index d1e2f34c..00000000 --- a/dom/form_params/qunit.html +++ /dev/null @@ -1,22 +0,0 @@ - - - Form Params Test Suite - - - - - - -

                        Fixtures Test Suite

                        -

                        -
                        -

                        -
                        -
                          -
                          - - \ No newline at end of file diff --git a/dom/form_params/test.html b/dom/form_params/test.html new file mode 100644 index 00000000..40d728e8 --- /dev/null +++ b/dom/form_params/test.html @@ -0,0 +1,3 @@ +jquerypp/dom/form_params + +
                          diff --git a/dom/range/qunit.html b/dom/range/qunit.html deleted file mode 100644 index 019896d7..00000000 --- a/dom/range/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - Range QUnit Test - - - -

                          Range Test Suite

                          -

                          -
                          -

                          -
                          -
                            -
                            - - - \ No newline at end of file diff --git a/dom/range/range.html b/dom/range/range.html index e2793435..4e3a3e5a 100644 --- a/dom/range/range.html +++ b/dom/range/range.html @@ -29,12 +29,11 @@

                            The Range Plugin

                            We'll figure out what to do with form elements later.

                            
                             		
                            - diff --git a/dom/range/range.js b/dom/range/range.js index b888946e..50cb2e08 100644 --- a/dom/range/range.js +++ b/dom/range/range.js @@ -1,16 +1,18 @@ -steal('jquery', 'jquery/dom/compare', function ($) { +steal('jquery', 'jquerypp/dom/compare', function ($) { + /** + * @page jQuery.fn.range + * @parent jQuery.Range + * @signature `jQuery.fn.range()` + * + * @body + * Returns a new [jQuery.Range] instance for the first selected element. + * + * $('#content').range() //-> range + * + * @return {jQuery.Range} A jQuery.Range instance for the selected element + */ $.fn.range = - /** - * @function jQuery.fn.range - * @parent jQuery.Range - * - * `$.fn.range` returns a new [jQuery.Range] instance for the first selected element. - * - * $('#content').range() //-> range - * - * @return {$.Range} A $.Range instance for the selected element - */ function () { return $.Range(this[0]) } @@ -37,8 +39,6 @@ steal('jquery', 'jquery/dom/compare', function ($) { }, support = {}; /** - * @Class jQuery.Range - * @parent jQuery.Range * * Depending on the object passed, the selected text will be different. * @@ -100,11 +100,19 @@ steal('jquery', 'jquery/dom/compare', function ($) { this.range = range; } }; + /** + * @add jQuery.Range + */ + // /** * @static */ $.Range. /** + * @function jQuery.Range.static.current current + * @signature `jQuery.Range.current([el])` + * + * @body * `$.Range.current([element])` returns the currently selected range * (using [window.getSelection](https://developer.mozilla.org/en/nsISelection)). * @@ -133,7 +141,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { /** @prototype **/ { /** - * `range.moveToPoint(point)` moves the range end and start position to a specific point. + * @function jQuery.Range.prototype.moveToPoint moveToPoint + * @signature `range.moveToPoint([point])` + * + * @body + * Moves the range end and start position to a specific point. * A point can be specified like: * * //client coordinates @@ -143,8 +155,8 @@ steal('jquery', 'jquery/dom/compare', function ($) { * {pageX: 200, pageY: 300} * {top: 200, left: 300} * - * @param point The point to move the range to - * @return {$.Range} + * @param {Point} point The point to move the range to + * @return {jQuery.Range} */ moveToPoint : function (point) { var clientX = point.clientX, clientY = point.clientY @@ -208,7 +220,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { return this.win || window; }, /** - * `range.overlaps([elRange])` returns `true` if any portion of these two ranges overlap. + * @function jQuery.Range.prototype.overlaps overlaps + * @signature `range.overlaps([elRange])` + * + * @body + * returns `true` if any portion of these two ranges overlap. * * var foo = document.getElementById('foo'); * @@ -242,7 +258,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { return false; }, /** - * `range.collapse([toStart])` collapses a range to one of its boundary points. + * @function jQuery.Range.prototype.collapse collapse + * @signature `jQuery(el).range.collapse([toStart])` + * + * @body + * Collapses a range to one of its boundary points. * See [range.collapse](https://developer.mozilla.org/en/DOM/range.collapse). * * $('#foo').range().collapse() @@ -256,7 +276,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { return this; }, /** - * `range.toString()` returns the text of the range. + * @function jQuery.Range.prototype.toString toString + * @signature `range.toString()` + * + * @body + * Returns the text of the range. * * currentText = $.Range.current().toString() * @@ -266,7 +290,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { return typeof this.range.text == "string" ? this.range.text : this.range.toString(); }, /** - * `range.start([start])` gets or sets the start of the range. + * @function jQuery.Range.prototype.start start + * @signature `range.start()` + * + * @body + * Gets or sets the start of the range. * * If a value is not provided, start returns the range's starting container and offset like: * @@ -355,7 +383,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { }, /** - * `range.end([end])` gets or sets the end of the range. + * @function jQuery.Range.prototype.end end + * @signature `range.end([end])` + * + * @body + * Gets or sets the end of the range. * It takes similar options as [jQuery.Range::start start]: * * - __Object__ - an object with the new end container and offset like @@ -434,7 +466,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { } }, /** - * `range.parent()` returns the most common ancestor element of + * @function jQuery.Range.prototype.parent parent + * @signature `range.parent()` + * + * @body + * Returns the most common ancestor element of * the endpoints in the range. This will return a text element if the range is * within a text element. In this case, to get the containing element use this: * @@ -469,7 +505,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { } }, /** - * `range.rect([from])` returns the bounding rectangle of this range. + * @function jQuery.Range.prototype.rect rect + * @signature `range.rect([from])` + * + * @body + * Returns the bounding rectangle of this range. * * @param {String} [from] - where the coordinates should be * positioned from. By default, coordinates are given from the client viewport. @@ -493,7 +533,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { return rect; }, /** - * `range.rects(from)` returns the client rects. + * @function jQuery.Range.prototype.rects rects + * @signature `range.rects([from])` + * + * @body + * returns the client rects. * * @param {String} [from] how the rects coordinates should be given (viewport or page). Provide 'page' for * rect coordinates from the page. @@ -560,9 +604,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { range = $.Range().range; /** - * @function compare + * @function jQuery.Range.prototype.compare compare + * @signature `range.compare([type], [compareRange])` * - * `range.compare(type, compareRange)` compares one range to another range. + * @body + * Compares one range to another range. * * ## Example * @@ -602,9 +648,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { } /** - * @function move + * @function jQuery.Range.prototype.move move + * @signature `range.move([referenceRange])` * - * `range.move([referenceRange])` moves the endpoints of a range relative to another range. + * @body + * Moves the endpoints of a range relative to another range. * * // Move the current selection's end to the * // end of the #highlight element @@ -616,7 +664,7 @@ steal('jquery', 'jquery/dom/compare', function ($) { * to move to which referenceRange boundary point where: * * - `"START_TO_START"` - the start of the range moves to the start of referenceRange - * - `"START\_TO\_END"` - the start of the range move to the end of referenceRange + * - `"START_TO_END"` - the start of the range move to the end of referenceRange * - `"END_TO_END"` - the end of the range moves to the end of referenceRange * - `"END_TO_START"` - the end of the range moves to the start of referenceRange * @@ -653,7 +701,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { fn. /** - * `range.clone()` clones the range and returns a new $.Range + * @function jQuery.Range.prototype.clone clone + * @signature `range.clone()` + * + * @body + * Clones the range and returns a new $.Range * object: * * var range = new $.Range(document.getElementById('text')); @@ -669,9 +721,11 @@ steal('jquery', 'jquery/dom/compare', function ($) { fn. /** - * @function + * @function jQuery.Range.prototype.select select + * @signature `range.select([el])` * - * `range.select([el])` selects an element with this range. If nothing + * @body + * Selects an element with this range. If nothing * is provided, makes the current range appear as if the user has selected it. * * This works with text nodes. For example with: @@ -771,26 +825,40 @@ steal('jquery', 'jquery/dom/compare', function ($) { getNextTextNode = iteratorMaker("firstChild", "nextSibling"), getPrevTextNode = iteratorMaker("lastChild", "previousSibling"), callMove = function (container, offset, howMany) { - if (isText(container)) { - return move(container, offset + howMany) + var mover = howMany < 0 ? + getPrevTextNode : getNextTextNode; + + // find the text element + if( !isText(container) ){ + // sometimes offset isn't actually an element + container = container.childNodes[offset] ? + container.childNodes[offset] : + // if this happens, use the last child + container.lastChild; + + if( !isText(container) ) { + container = mover(container) + } + return move(container, howMany) } else { - return container.childNodes[offset] ? - move(container.childNodes[offset], howMany) : - move(container.lastChild, howMany, true) - return + if(offset+howMany < 0){ + return move(mover(container), offset + howMany) + } else { + return move(container, offset + howMany) + } + } }, + // Moves howMany characters from the start of + // from move = function (from, howMany) { var mover = howMany < 0 ? getPrevTextNode : getNextTextNode; howMany = Math.abs(howMany); - if (!isText(from)) { - from = mover(from) - } while (from && howMany >= from.nodeValue.length) { - hasMany = howMany - from.nodeValue.length; + howMany = howMany - from.nodeValue.length; from = mover(from) } return { @@ -850,4 +918,4 @@ steal('jquery', 'jquery/dom/compare', function ($) { support.moveToPoint = !!$.Range().range.moveToPoint return $; -}); \ No newline at end of file +}); diff --git a/dom/range/range.md b/dom/range/range.md index da5105d6..72e00af5 100644 --- a/dom/range/range.md +++ b/dom/range/range.md @@ -1,7 +1,8 @@ -@page jQuery.Range +@constructor jQuery.Range jQuery.Range @parent jquerypp -`jQuery.Range` provides text range helpers for creating, moving, and comparing ranges cross browser. You can get the currently selected range by calling [$.Range.current()](jQuery.Range.static.current) a new range can be created by passing +@body +`jQuery.Range` provides text range helpers for creating, moving, and comparing ranges cross browser. You can get the currently selected range by calling [jQuery.Range.static.current $.Range.current()] a new range can be created by passing - __undefined or null__ - returns a range with nothing selected - __HTMLElement__ - returns a range with the node's text selected @@ -70,6 +71,6 @@ Consider an HTML element like //get the most common ancestor element var parent = range.parent(); - + //select the parent var range2 = new $.Range(parent); diff --git a/dom/range/range_test.js b/dom/range/range_test.js index 1524f4a1..d1d8d620 100644 --- a/dom/range/range_test.js +++ b/dom/range/range_test.js @@ -1,69 +1,69 @@ -steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(function () { +steal("steal-qunit", "jquerypp/dom/range", "jquerypp/dom/selection",function () { - module("jquery/dom/range"); + module("jquerypp/dom/range"); test("basic range", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("

                            0123456789

                            "); $('#1').selection(1, 5); var range = $.Range.current(); - equals(range.start().offset, 1, "start is 1") - equals(range.end().offset, 5, "end is 5") + equal(range.start().offset, 1, "start is 1") + equal(range.end().offset, 5, "end is 5") }); test("jquery helper, start, select", function () { - var range = $('#qunit-test-area').html("Hello World!").range(); + var range = $('#qunit-fixture').html("Hello World!").range(); range.start("+2"); range.end("-2"); range.select(); - equals(range.toString(), "llo Wor") - }) + equal(range.toString(), "llo Worl") + }); test('jQuery helper', function () { - $("#qunit-test-area").html("
                            thisTextIsSelected
                            ") + $("#qunit-fixture").html("
                            thisTextIsSelected
                            ") var range = $('#selectMe').range(); - equals(range.toString(), "thisTextIsSelected") + equal(range.toString(), "thisTextIsSelected") }); test("constructor with undefined", function () { var range = $.Range(); - equals(document, range.start().container, "start is right"); - equals(0, range.start().offset, "start is right"); - equals(document, range.end().container, "end is right"); - equals(0, range.end().offset, "end is right"); + equal(document, range.start().container, "start is right"); + equal(0, range.start().offset, "start is right"); + equal(document, range.end().container, "end is right"); + equal(0, range.end().offset, "end is right"); }); test("constructor with element", function () { - $("#qunit-test-area").html("
                            thisTextIsSelected
                            ") + $("#qunit-fixture").html("
                            thisTextIsSelected
                            "); var range = $.Range($('#selectMe')[0]); - equals(range.toString(), "thisTextIsSelected") + equal(range.toString(), "thisTextIsSelected"); }); test('selecting text nodes and parent', function () { - $("#qunit-test-area").html("
                            thisTextIsSelected
                            ") + $("#qunit-fixture").html("
                            thisTextIsSelected
                            "); var txt = $('#selectMe')[0].childNodes[2] - equals(txt.nodeValue, "Is", "text is right") + equal(txt.nodeValue, "Is", "text is right"); var range = $.Range(); range.select(txt); - equals(range.parent(), txt, "right parent node"); - }) + equal(range.parent(), txt, "right parent node"); + }); test('parent', function () { - $("#qunit-test-area").html("
                            thisTextIsSelected
                            ") - var txt = $('#selectMe')[0].childNodes[0] + $("#qunit-fixture").html("
                            thisTextIsSelected
                            "); + var txt = $('#selectMe')[0].childNodes[0]; var range = $.Range(txt); - equals(range.parent(), txt) + equal(range.parent(), txt); }); test("constructor with point", function () { @@ -73,24 +73,24 @@ steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(functio left : "0px", top : "0px", border : "solid 1px black" - }) + }); - $("#qunit-test-area").html(""); + $("#qunit-fixture").html(""); floater.appendTo(document.body); var range = $.Range({pageX : 5, pageY : 5}); - equals(range.start().container.parentNode, floater[0]) + equal(range.start().container.parentNode, floater[0]) floater.remove() }); test('current', function () { - $("#qunit-test-area").html("
                            thisTextIsSelected
                            "); + $("#qunit-fixture").html("
                            thisTextIsSelected
                            "); $('#selectMe').range().select(); var range = $.Range.current(); - equals(range.toString(), "thisTextIsSelected") - }) + equal(range.toString(), "thisTextIsSelected"); + }); /* TODO test('rangeFromPoint', function(){ @@ -133,16 +133,16 @@ steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(functio // adding brian's tests test("nested range", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("
                            012
                            345
                            "); $('#2').selection(1, 5); var range = $.Range.current(); - equals(range.start().container.data, "012", "start is 012") - equals(range.end().container.data, "4", "last char is 4") + equal(range.start().container.data, "012", "start is 012") + equal(range.end().container.data, "4", "last char is 4") }); test("rect", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("

                            0123456789

                            "); $('#1').selection(1, 5); var range = $.Range.current(), @@ -154,7 +154,7 @@ steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(functio }); test("collapsed rect", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("

                            0123456789

                            "); $('#1').selection(1, 1); var range = $.Range.current(), @@ -168,16 +168,16 @@ steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(functio }); test("rects", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("

                            0123456789

                            "); $('#1').selection(1, 5); var range = $.Range.current(), rects = range.rects(); - equals(rects.length, 2, "2 rects found") + equal(rects.length, 2, "2 rects found") }); test("multiline rects", function () { - $("#qunit-test-area") + $("#qunit-fixture") .html("
                            <script type='text/ejs' id='recipes'>\n" +
                             			"<% for(var i=0; i < recipes.length; i++){ %>\n" +
                             			"  <li><%=recipes[i].name %></li>\n" +
                            @@ -186,20 +186,46 @@ steal("funcunit/qunit", "jquery/dom/range", "jquery/dom/selection").then(functio
                             		$('#1').selection(3, 56);
                             		var range = $.Range.current(),
                             			rects = range.rects();
                            -		equals(rects.length, 2, "2 rects found")
                            -		ok(rects[1].width, "rect has width")
                            +		ok(rects.length >= 2, "2 rects found");
                            +		ok(rects[1].width, "rect has width");
                             	});
                             
                             	test("compare", function () {
                            -		$("#qunit-test-area")
                            +		$("#qunit-fixture")
                             			.html("

                            0123456789

                            "); $('#1').selection(1, 5); var range1 = $.Range.current(); $('#1').selection(2, 3); var range2 = $.Range.current(); var pos = range1.compare("START_TO_START", range2) - equals(pos, -1, "pos works") + equal(pos, -1, "pos works") + }); + + test("move across boundaries", function(){ + + var div = document.createElement('div'); + div.innerHTML = 'I\'ve been writing up example widgets on bitovi.com. Here\'s the first three:'+ + 'THE TEXT'; + $("#qunit-fixture").html(div); + + equal( $(div).range().start("+79").toString(), "TEXT"); + $("#qunit-fixture").empty(); + }); + + test("moving left from text node", function(){ + var div = document.createElement('div'); + div.innerHTML = 'aTHE TEXTde'; + div.id= "foo" + $("#qunit-fixture").html(div); + // move to d + var range = $(div).range().collapse(false) + + range.start("-1").start("-1").end("-1").start("-1"); + + + + equal(range.toString(),"Td") }); -}) +}); diff --git a/dom/range/test.html b/dom/range/test.html new file mode 100644 index 00000000..d2577287 --- /dev/null +++ b/dom/range/test.html @@ -0,0 +1,3 @@ +jquerypp/dom/range + +
                            diff --git a/dom/route/qunit.html b/dom/route/qunit.html deleted file mode 100644 index 8ccb0a9f..00000000 --- a/dom/route/qunit.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - Jquery.Dom.Route FuncUnit Test - - - - -

                            Jquery.Dom.Route Test Suite

                            -

                            -
                            -

                            -
                              - - \ No newline at end of file diff --git a/dom/route/route.html b/dom/route/route.html deleted file mode 100644 index 84071408..00000000 --- a/dom/route/route.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - Jquery.Dom.Route - - - -

                              $.Route Demo

                              - -
                              -
                              -
                              - Use these links to modify the hash or change it directly in the address bar: -

                              - URLs with a registered path: - #!pages/val1/val2/val3 - #!pages/val1// - #!pages/// - #!/val1/val2 -
                              - URLs without paths: - #!pages// - #!/// -
                              - Empty hash: - #! -
                              -

                              Hash update events:

                              -
                              -
                              -
                              -
                              -
                              - Value1:
                              - Value2:
                              - Value3: - -
                              -
                              -

                              Data update events:

                              -
                              -
                              - - - - - \ No newline at end of file diff --git a/dom/route/route.js b/dom/route/route.js deleted file mode 100644 index 976435cd..00000000 --- a/dom/route/route.js +++ /dev/null @@ -1,3 +0,0 @@ -steal('jquery', 'can/util', 'can/route', function($, can) { - $.route=can.route -}) \ No newline at end of file diff --git a/dom/route/route_test.js b/dom/route/route_test.js deleted file mode 100644 index 26bbfbe4..00000000 --- a/dom/route/route_test.js +++ /dev/null @@ -1,267 +0,0 @@ -steal('funcunit/qunit').then('./route.js',function(){ - -module("jquery/dom/route") - -test("deparam", function(){ - $.route.routes = {}; - $.route(":page",{ - page: "index" - }) - - var obj = $.route.deparam("jQuery.Controller"); - same(obj, { - page : "jQuery.Controller", - route: ":page" - }); - - obj = $.route.deparam(""); - same(obj, { - page : "index", - route: ":page" - }); - - obj = $.route.deparam("jQuery.Controller&where=there"); - same(obj, { - page : "jQuery.Controller", - where: "there", - route: ":page" - }); - - $.route.routes = {}; - $.route(":page/:index",{ - page: "index", - index: "foo" - }); - - obj = $.route.deparam("jQuery.Controller/&where=there"); - same(obj, { - page : "jQuery.Controller", - index: "foo", - where: "there", - route: ":page/:index" - }); -}) - -test("deparam of invalid url", function(){ - $.route.routes = {}; - $.route("pages/:var1/:var2/:var3", { - var1: 'default1', - var2: 'default2', - var3: 'default3' - }); - - // This path does not match the above route, and since the hash is not - // a &key=value list there should not be data. - obj = $.route.deparam("pages//"); - same(obj, {}); - - // A valid path with invalid parameters should return the path data but - // ignore the parameters. - obj = $.route.deparam("pages/val1/val2/val3&invalid-parameters"); - same(obj, { - var1: 'val1', - var2: 'val2', - var3: 'val3', - route: "pages/:var1/:var2/:var3" - }); -}) - -test("deparam of url with non-generated hash (manual override)", function(){ - $.route.routes = {}; - - // This won't be set like this by route, but it could easily happen via a - // user manually changing the URL or when porting a prior URL structure. - obj = $.route.deparam("page=foo&bar=baz&where=there"); - same(obj, { - page: 'foo', - bar: 'baz', - where: 'there' - }); -}) - -test("param", function(){ - $.route.routes = {}; - $.route("pages/:page",{ - page: "index" - }) - - var res = $.route.param({page: "foo"}); - equals(res, "pages/foo") - - res = $.route.param({page: "foo", index: "bar"}); - equals(res, "pages/foo&index=bar") - - $.route("pages/:page/:foo",{ - page: "index", - foo: "bar" - }) - - res = $.route.param({page: "foo", foo: "bar", where: "there"}); - equals(res, "pages/foo/&where=there") - - // There is no matching route so the hash should be empty. - res = $.route.param({}); - equals(res, "") - - $.route.routes = {}; - - res = $.route.param({page: "foo", bar: "baz", where: "there"}); - equals(res, "&page=foo&bar=baz&where=there") - - res = $.route.param({}); - equals(res, "") -}); - -test("symmetry", function(){ - $.route.routes = {}; - - var obj = {page: "=&[]", nestedArray : ["a"], nested : {a :"b"} } - - var res = $.route.param(obj) - - var o2 = $.route.deparam(res) - same(o2, obj) -}) - -test("light param", function(){ - $.route.routes = {}; - $.route(":page",{ - page: "index" - }) - - var res = $.route.param({page: "index"}); - equals(res, "") - - $.route("pages/:p1/:p2/:p3",{ - p1: "index", - p2: "foo", - p3: "bar" - }) - - res = $.route.param({p1: "index", p2: "foo", p3: "bar"}); - equals(res, "pages///") - - res = $.route.param({p1: "index", p2: "baz", p3: "bar"}); - equals(res, "pages//baz/") -}); - -test('param doesnt add defaults to params', function(){ - $.route.routes = {}; - - $.route("pages/:p1",{ - p2: "foo" - }) - var res = $.route.param({p1: "index", p2: "foo"}); - equals(res, "pages/index") -}) - -test("param-deparam", function(){ - - $.route(":page/:type",{ - page: "index", - type: "foo" - }) - - var data = {page: "jQuery.Controller", - type: "document", - bar: "baz", - where: "there"}; - var res = $.route.param(data); - var obj = $.route.deparam(res); - delete obj.route - same(obj,data ) - return; - data = {page: "jQuery.Controller", type: "foo", bar: "baz", where: "there"}; - res = $.route.param(data); - obj = $.route.deparam(res); - delete obj.route; - same(data, obj) - - data = {page: " a ", type: " / "}; - res = $.route.param(data); - obj = $.route.deparam(res); - delete obj.route; - same(obj ,data ,"slashes and spaces") - - data = {page: "index", type: "foo", bar: "baz", where: "there"}; - res = $.route.param(data); - obj = $.route.deparam(res); - delete obj.route; - same(data, obj) - - $.route.routes = {}; - - data = {page: "foo", bar: "baz", where: "there"}; - res = $.route.param(data); - obj = $.route.deparam(res); - same(data, obj) -}) - -test("precident", function(){ - $.route.routes = {}; - $.route(":who",{who: "index"}); - $.route("search/:search"); - - var obj = $.route.deparam("jQuery.Controller"); - same(obj, { - who : "jQuery.Controller", - route: ":who" - }); - - obj = $.route.deparam("search/jQuery.Controller"); - same(obj, { - search : "jQuery.Controller", - route: "search/:search" - },"bad deparam"); - - equal( $.route.param({ - search : "jQuery.Controller" - }), - "search/jQuery.Controller" , "bad param"); - - equal( $.route.param({ - who : "jQuery.Controller" - }), - "jQuery.Controller" ); -}) - -test("precident2", function(){ - $.route.routes = {}; - $.route(":type",{who: "index"}); - $.route(":type/:id"); - - equal( $.route.param({ - type : "foo", - id: "bar" - }), - "foo/bar" ); -}) - -test("linkTo", function(){ - $.route.routes = {}; - $.route(":foo"); - var res = $.route.link("Hello",{foo: "bar", baz: 'foo'}); - equal( res, 'Hello'); -}) - -test("param with route defined", function(){ - $.route.routes = {}; - $.route("holler") - $.route("foo"); - var data = {foo: "abc",route: "foo"} - var res = $.route.param(data); - - equal(res, "foo&foo=abc") -}) - -test("route endings", function(){ - $.route.routes = {}; - $.route("foo",{foo: true}); - $.route("food",{food: true}) - - var res = $.route.deparam("food") - ok(res.food, "we get food back") - -}) - -}) diff --git a/dom/selection/qunit.html b/dom/selection/qunit.html deleted file mode 100644 index b99867fd..00000000 --- a/dom/selection/qunit.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - selection QUnit Test - - - - - -

                              selection Test Suite

                              -

                              -
                              -

                              -
                              -
                                -
                                - - \ No newline at end of file diff --git a/dom/selection/selection.html b/dom/selection/selection.html index 6f230026..be76de8a 100644 --- a/dom/selection/selection.html +++ b/dom/selection/selection.html @@ -14,7 +14,7 @@ - @@ -34,23 +34,22 @@
                                Select Textarea

                                Selection width: 0

                                - - + +
                                diff --git a/dom/styles/qunit.html b/dom/styles/qunit.html deleted file mode 100644 index 4c9d124b..00000000 --- a/dom/styles/qunit.html +++ /dev/null @@ -1,22 +0,0 @@ - - - CurStyles Test Suite - - - - - - -

                                CurStyles Test Suite

                                -

                                -
                                -

                                -
                                -
                                  -
                                  - - \ No newline at end of file diff --git a/dom/styles/styles.html b/dom/styles/styles.html deleted file mode 100644 index 6ffa780f..00000000 --- a/dom/styles/styles.html +++ /dev/null @@ -1,69 +0,0 @@ - - - - CurStyles Performance Test/Demo - - - -

                                  CurStyles Performance

                                  -

                                  This demo shows how $.styles out-performs $.curCSS

                                  -
                                  -
                                  - Click To Run -
                                  -
                                  - - - - - - \ No newline at end of file diff --git a/dom/styles/styles.js b/dom/styles/styles.js deleted file mode 100644 index babfe151..00000000 --- a/dom/styles/styles.js +++ /dev/null @@ -1,103 +0,0 @@ -steal('jquery', function( $ ) { - var getComputedStyle = document.defaultView && document.defaultView.getComputedStyle, - // The following variables are used to convert camelcased attribute names - // into dashed names, e.g. borderWidth to border-width - rupper = /([A-Z])/g, - rdashAlpha = /-([a-z])/ig, - fcamelCase = function( all, letter ) { - return letter.toUpperCase(); - }, - // Returns the computed style for an elementn - getStyle = function( elem ) { - if ( getComputedStyle ) { - return getComputedStyle(elem, null); - } - else if ( elem.currentStyle ) { - return elem.currentStyle; - } - }, - // Checks for float px and numeric values - rfloat = /float/i, - rnumpx = /^-?\d+(?:px)?$/i, - rnum = /^-?\d/; - - // Returns a list of styles for a given element - $.styles = function( el, styles ) { - if (!el ) { - return null; - } - var currentS = getStyle(el), - oldName, val, style = el.style, - results = {}, - i = 0, - left, rsLeft, camelCase, name; - - // Go through each style - for (; i < styles.length; i++ ) { - name = styles[i]; - oldName = name.replace(rdashAlpha, fcamelCase); - - if ( rfloat.test(name) ) { - name = jQuery.support.cssFloat ? "float" : "styleFloat"; - oldName = "cssFloat"; - } - - // If we have getComputedStyle available - if ( getComputedStyle ) { - // convert camelcased property names to dashed name - name = name.replace(rupper, "-$1").toLowerCase(); - // use getPropertyValue of the current style object - val = currentS.getPropertyValue(name); - // default opacity is 1 - if ( name === "opacity" && val === "" ) { - val = "1"; - } - results[oldName] = val; - } else { - // Without getComputedStyles - camelCase = name.replace(rdashAlpha, fcamelCase); - results[oldName] = currentS[name] || currentS[camelCase]; - - // convert to px - if (!rnumpx.test(results[oldName]) && rnum.test(results[oldName]) ) { - // Remember the original values - left = style.left; - rsLeft = el.runtimeStyle.left; - - // Put in the new values to get a computed value out - el.runtimeStyle.left = el.currentStyle.left; - style.left = camelCase === "fontSize" ? "1em" : (results[oldName] || 0); - results[oldName] = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - el.runtimeStyle.left = rsLeft; - } - - } - } - - return results; - }; - - /** - * @function jQuery.fn.styles - * @parent jQuery.styles - * @plugin jQuery.styles - * - * Returns a set of computed styles. Pass the names of the styles you want to - * retrieve as arguments: - * - * $("div").styles('float','display') - * // -> { cssFloat: "left", display: "block" } - * - * @param {String} style pass the names of the styles to retrieve as the argument list - * @return {Object} an object of `style` : `value` pairs - */ - $.fn.styles = function() { - // Pass the arguments as an array to $.styles - return $.styles(this[0], $.makeArray(arguments)); - }; - - return $; -}); \ No newline at end of file diff --git a/dom/styles/styles.md b/dom/styles/styles.md deleted file mode 100644 index 44ea36ce..00000000 --- a/dom/styles/styles.md +++ /dev/null @@ -1,30 +0,0 @@ -@page jQuery.styles -@parent jquerypp - -`jQuery.styles` provides `jQuery.fn.styles` to rapidly get a set of computed styles from an element. - -## Quick Example - - - $("#foo").styles('float','display') //-> - // { - // cssFloat: "left", display: "block" - // } - -## Use - -An element's __computed__ style is the current calculated style of the property. -This is different than the values on `element.style` as -`element.style` doesn't reflect styles provided by css or the browser's default -css properties. - -Getting computed values individually, for example by using jQuery [.css()](http://api.jquery.com/css/), is expensive. -This plugin retrieves all needed style properties at once. - -## Demo - -The following demo illustrates the performance improvement `jQuery.fn.styles` provides by implementing -a faster 'height' jQuery function called 'fastHeight'. - -@demo jquery/dom/styles/styles.html - diff --git a/dom/styles/styles_test.js b/dom/styles/styles_test.js deleted file mode 100644 index 77bb27cc..00000000 --- a/dom/styles/styles_test.js +++ /dev/null @@ -1,26 +0,0 @@ -steal("jquery/dom/dimensions",'jquery/view/micro', 'funcunit/qunit', function() { - -module("jquery/dom/styles"); - -test("reading", function(){ - - $("#qunit-test-area").html("//jquery/dom/styles/test/styles.micro",{}) - - var res = $.styles( $("#styled")[0], - ["padding-left", - 'position', - 'display', - "margin-top", - "borderTopWidth", - "float"] ); - equals(res.borderTopWidth, "2px","border top"); - equals(res.display, "block","display"); - equals(res.cssFloat, "left","float"); - equals(res.marginTop, "10px","margin top"); - equals(res.paddingLeft, "5px","padding left"); - equals(res.position, "relative","position"); - $("#qunit-test-area").html("") -}); - -}) - diff --git a/dom/styles/test/styles.micro b/dom/styles/test/styles.micro deleted file mode 100644 index 7c7503ca..00000000 --- a/dom/styles/test/styles.micro +++ /dev/null @@ -1,3 +0,0 @@ -
                                  -Here is some content; -
                                  \ No newline at end of file diff --git a/dom/within/within.js b/dom/within/within.js index 22e39a11..c5d4c040 100644 --- a/dom/within/within.js +++ b/dom/within/within.js @@ -5,18 +5,19 @@ steal('jquery', function($) { y < top + height && x >= left && x < left + width); - } + } /** * @function jQuery.fn.within * @parent jQuery.within - * @plugin jquery/dom/within - * + * @plugin jquerypp/dom/within + * @hide + * * Returns all elements matching the selector that touch a given point: - * + * * // get all elements that touch 200x200. * $('*').within(200, 200); - * - * @param {Number} left the position from the left of the page + * + * @param {Number} left the position from the left of the page * @param {Number} top the position from the top of the page * @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. * @return {jQuery} a jQuery collection of elements whos area @@ -32,8 +33,8 @@ $.fn.within= function(left, top, useOffsetCache) { } // uses either the cached offset or .offset() - var offset = useOffsetCache ? - jQuery.data(this,"offsetCache") || jQuery.data(this,"offsetCache", q.offset()) : + var offset = useOffsetCache ? + $.data(this,"offsetCache") || $.data(this,"offsetCache", q.offset()) : q.offset(); // Check if the given coordinates are within the area of the current element @@ -45,8 +46,8 @@ $.fn.within= function(left, top, useOffsetCache) { ret.push(this); } }); - - return this.pushStack( jQuery.unique( ret ), "within", left+","+top ); + + return this.pushStack( $.unique( ret ), "within", left+","+top ); } @@ -74,9 +75,9 @@ $.fn.withinBox = function(left, top, width, height, useOffsetCache){ if(this == document.documentElement) return ret.push(this); // use cached offset or .offset() - var offset = useOffsetCache ? - jQuery.data(this,"offset") || - jQuery.data(this,"offset", q.offset()) : + var offset = useOffsetCache ? + $.data(this,"offset") || + $.data(this,"offset", q.offset()) : q.offset(); @@ -87,7 +88,7 @@ $.fn.withinBox = function(left, top, width, height, useOffsetCache){ if(res) ret.push(this); }); - return this.pushStack( jQuery.unique( ret ), "withinBox", jQuery.makeArray(arguments).join(",") ); + return this.pushStack( $.unique( ret ), "withinBox", $.makeArray(arguments).join(",") ); } return $; diff --git a/dom/within/within.md b/dom/within/within.md index bb79f97a..9ce9ef29 100644 --- a/dom/within/within.md +++ b/dom/within/within.md @@ -1,7 +1,8 @@ -@page jQuery.within +@function jQuery.within jQuery.within @parent jquerypp +@signature `jQuery(el).within(left, top)` -`jQuery.within` helps to determine all elements that have a certain position or area in common by providing `[jQuery.fn.withinBox]` and `[jQuery.fn.within]`. The following example returns all `div` elements on the point 200px left and 200px from the top: +Helps to determine all elements that have a certain position or area in common by providing `[jQuery.fn.withinBox]` and `[jQuery.fn.within]`. The following example returns all `div` elements on the point 200px left and 200px from the top: $('div').within(200, 200) @@ -9,10 +10,24 @@ Use `$(el).withinBox(left, top, width, height)` to get all elements within a cer $('*').withinBox(200, 200, 100, 100) -> [jQuery.event.drag] uses *$.within* to determine dropable elements at the current position. + [jQuery.event.drag] uses *$.within* to determine dropable elements at the current position. -## Example + @signature `jQuery(el).withinBox(left, top, width, height)` + + Returns all elements matching the selector that have a given area in common: + $('*').withinBox(200, 200, 100, 100) + + ### Example Move the mouse in the following example and it will show the ids for `div` elements within the current mouse position: + + + @param {Number} left the position from the left of the page + @param {Number} top the position from the top of the page + @param {Number} width the width of the area + @param {Number} height the height of the area + @param {Boolean} [useOffsetCache=false] cache the dimensions and offset of the elements. + @return {jQuery} a jQuery collection of elements whos area + overlaps the element position. diff --git a/event/default/default.html b/event/default/default.html index 68da154f..358cb888 100644 --- a/event/default/default.html +++ b/event/default/default.html @@ -46,41 +46,44 @@

                                  Default Events

                                  - - - + diff --git a/event/default/default.js b/event/default/default.js index 9ba883df..25a298f3 100644 --- a/event/default/default.js +++ b/event/default/default.js @@ -1,10 +1,8 @@ - steal('jquery', function($){ - /** * @function jQuery.fn.triggerAsync * @parent jQuery.event.pause - * @plugin jquery/event/default + * @plugin jquerypp/event/default * * `jQuery.fn.triggerAsync(type, [data], [success], [prevented]` triggers an event and calls success * when the event has finished propagating through the DOM and no other handler @@ -29,25 +27,24 @@ steal('jquery', function($){ */ $.fn.triggerAsync = function(type, data, success, prevented){ if(typeof data == 'function'){ + prevented=success; success = data; data = undefined; } - if ( this[0] ) { - // Create a new jQuery event object and store the original preventDefault - var event = $.Event( type ), - old = event.preventDefault; - - event.preventDefault = function(){ - old.apply(this, arguments); - // call the prevented callback when event.preventDefault is called - prevented && prevented(this) - } + if ( this.length ) { + var el=this; // Trigger the event with the success callback as the success handler - jQuery.event.trigger( {type: type, _success: success}, data, this[0] ); + // when triggerAsync called within another triggerAsync,it's the same tick time so we should use timeout + // http://javascriptweblog.wordpress.com/2010/06/28/understanding-javascript-timers/ + setTimeout(function(){ + el.trigger( {type: type, _success: success,_prevented:prevented}, data); + },0); + } else{ // If we have no elements call the success callback right away - success.call(this); + if(success) + success.call(this); } return this; } @@ -62,9 +59,9 @@ var types = {}, rnamespaces= /\.(.*)$/, $event = $.event; /** * @attribute default * @parent specialevents - * @plugin jquery/event/default - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/default/default.js - * @test jquery/event/default/qunit.html + * @plugin jquerypp/event/default + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquerypp/event/default/default.js + * @test jquerypp/event/default/qunit.html * */ $event.special["default"] = { @@ -79,18 +76,20 @@ $event.special["default"] = { var oldTrigger = $event.trigger; $event.trigger = function defaultTriggerer( event, data, elem, onlyHandlers){ + // Event object or event type var type = event.type || event, // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? // jQuery.Event object - event[ jQuery.expando ] ? event : + event[ $.expando ] ? event : // Object literal - new jQuery.Event( type, event ) : + new $.Event( type, event ) : // Just the event type (string) - new jQuery.Event( type), - res = oldTrigger.call($.event, event, data, elem, onlyHandlers); - + new $.Event( type), + res=oldTrigger.call($.event,event, data, elem, onlyHandlers), + paused=event.isPaused && event.isPaused(); + if(!onlyHandlers && !event.isDefaultPrevented() && event.type.indexOf("default") !== 0) { // Trigger the default. event oldTrigger("default."+event.type, data, elem) @@ -98,8 +97,15 @@ $event.trigger = function defaultTriggerer( event, data, elem, onlyHandlers){ event._success(event) } } + + if(!onlyHandlers && event.isDefaultPrevented() && event.type.indexOf("default") !== 0 && !paused ){ + if(event._prevented){ + event._prevented(event); + } + } + // code for paused - if( event.isPaused && event.isPaused() ){ + if( paused ){ // set back original stuff event.isDefaultPrevented = event.pausedState.isDefaultPrevented; diff --git a/event/default/default.md b/event/default/default.md index 1aa1de35..0c61e9b3 100644 --- a/event/default/default.md +++ b/event/default/default.md @@ -1,4 +1,4 @@ -@page jQuery.event.default +@constructor jQuery.event.default @parent jquerypp `jQuery.event.default` allows you to perform default actions as a result of an event. @@ -6,10 +6,9 @@ Event based APIs are a powerful way of exposing functionality of your widgets. It also fits in quite nicely with how the DOM works. - Like default events in normal functions (e.g. submitting a form), synthetic default events run after all event handlers have been triggered and no event handler has called -preventDefault or returned false. +`event.preventDefault()` or returned `false`. To listen to a default event, just prefix the event with `default` namespace: @@ -21,13 +20,13 @@ To listen to a default event, just prefix the event with `default` namespace: Default events are useful in cases where you want to provide an event based API for users of your widgets. Users can simply listen to your synthetic events and -prevent your default functionality by calling preventDefault. +prevent your default functionality by calling `event.preventDefault()`. In the example below, the tabs widget provides a show event. Users of the -tabs widget simply listen for show, and if they wish for some reason, call preventDefault -to avoid showing the tab. +tabs widget can simply listen for show, and, if they wish to prevent a tab +from being shown for some reason, they can call preventDefault to avoid showing the tab. In this case, the application developer doesn't want to show the second tab until the checkbox is checked. -@demo jquery/event/default/defaultjquery.html +@demo jquerypp/event/default/defaultjquery.html 300 \ No newline at end of file diff --git a/event/default/default_pause_test.html b/event/default/default_pause_test.html index dfc3f0a4..f7b80704 100644 --- a/event/default/default_pause_test.html +++ b/event/default/default_pause_test.html @@ -1,13 +1,13 @@ Default Test Suite - + - + @@ -17,6 +17,6 @@

                                    -
                                    +
                                    \ No newline at end of file diff --git a/event/default/default_pause_test.js b/event/default/default_pause_test.js index 1cd6d94d..b7d996a1 100644 --- a/event/default/default_pause_test.js +++ b/event/default/default_pause_test.js @@ -1,12 +1,12 @@ -steal('funcunit/qunit','jquery/event/default','jquery/event/pause', function() { +steal('steal-qunit','jquerypp/event/default','jquerypp/event/pause', function() { -module("jquery/event/default_pause"); +module("jquerypp/event/default_pause"); test("default and pause with delegate", function(){ var order = []; stop(); - $("#qunit-test-area").html("

                                    hello

                                    ") + $("#qunit-fixture").html("

                                    hello

                                    ") $("#foo_default_pause").delegate("#bar_default_pause","default.show", function(){ order.push("default") @@ -15,13 +15,11 @@ test("default and pause with delegate", function(){ $("#foo_default_pause").delegate("#bar_default_pause","show", function(ev){ order.push('show'); ev.pause(); - setTimeout(function(){ ev.resume(); - setTimeout(function(){ start(); - same(order,['show','default']) + deepEqual(order,['show','default']) },30) },50) @@ -32,64 +30,236 @@ test("default and pause with delegate", function(){ }); -test("default and pause with live", function(){ - $("#qunit-test-area").html("
                                    hello
                                    ") +test("default and pause with live or on", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") + + var order = [], + defaultShow = function(){ + order.push("default") + }, + show = function(ev){ + order.push('show') + ev.pause(); + setTimeout(function(){ + ev.resume(); + setTimeout(function(){ + start(); + deepEqual(order,['show','default']); + if($.fn.live){ + $("#foo_default_pause").die("show"); + $("#foo_default_pause").die("default.show"); + } else { + $(document.body).off("default.show"); + $(document.body).off("show"); + } + + },30) + },50) + }; + stop(); + + if( $.fn.live ){ + $("#foo_default_pause").live("default.show", defaultShow); + $("#foo_default_pause").live("show", show); + } else { + $(document.body).on("default.show", "#foo_default_pause",defaultShow); + $(document.body).on("show", "#foo_default_pause",show); + } + + + + + $("#foo_default_pause").trigger("show") + +}); + + +test("triggerAsync", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") + + var order = [], + defaultShow = function(){ + order.push("default") + }, + show = function(ev){ + order.push('show') + ev.pause(); + setTimeout(function(){ + ev.resume(); + setTimeout(function(){ + start(); + if( $.fn.die ) { + $("#foo_default_pause").die(); + } else { + $(document.body).off(); + } + + deepEqual(order,['show','default','async']) + },30) + },50) + }; + + stop(); + + if( $.fn.live ){ + $("#foo_default_pause").live("default.show", defaultShow); + $("#foo_default_pause").live("show", show); + } else { + $(document.body).on("default.show", "#foo_default_pause",defaultShow); + $(document.body).on("show", "#foo_default_pause",show); + } + + $("#foo_default_pause").triggerAsync("show", function(){ + order.push("async") + }) +}); + +test("triggerAsync with prevented callback when ev.preventDefault() is called before event pause", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") var order = []; stop(); - $("#foo_default_pause").live("default.show", function(){ + $(document.body).on("default.show","#foo_default_pause", function(){ order.push("default") }); - $("#foo_default_pause").live("show", function(ev){ - order.push('show') + + $(document.body).on("show", "#foo_default_pause", function(ev){ + order.push('show'); + ev.preventDefault(); ev.pause(); setTimeout(function(){ ev.resume(); setTimeout(function(){ start(); - same(order,['show','default']) - $("#foo_default_pause").die("show"); - $("#foo_default_pause").die("default.show"); + $(document.body).off("show"); + $(document.body).off("default.show") + deepEqual(order,['show','prevented']) },30) },50) }); - $("#foo_default_pause").trigger("show") - + $("#foo_default_pause").triggerAsync("show", [5],function(){ + order.push("async") + }, function(){ + order.push("prevented") + }) }); - - -test("triggerAsync", function(){ - $("#qunit-test-area").html("
                                    hello
                                    ") +test("triggerAsync with prevented callback when ev.preventDefault() is called after event pause", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") var order = []; stop(); - $("#foo_default_pause").live("default.show", function(){ + $(document.body).on("default.show", "#foo_default_pause",function(){ order.push("default") }); - $("#foo_default_pause").live("show", function(ev){ - order.push('show') + $(document.body).on("show", "#foo_default_pause",function(ev){ + order.push('show'); + ev.pause(); setTimeout(function(){ + ev.preventDefault(); ev.resume(); setTimeout(function(){ start(); - $("#foo_default_pause").die() - same(order,['show','default','async']) + $(document.body).off("show").off("default.show") + deepEqual(order,['show','prevented']) },30) },50) }); - $("#foo_default_pause").triggerAsync("show", function(){ + $("#foo_default_pause").triggerAsync("show", [5],function(){ order.push("async") + }, function(){ + order.push("prevented") + }) +}); + +test("triggerAsync within another triggerAsync", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") + + var order = []; + stop(); + + $(document.body).on("default.show", "#foo_default_pause",function(){ + order.push("show default") + }); + $(document.body).on("default.hide", "#foo_default_pause", function(){ + order.push("hide default") + }); + $(document.body).on("hide", "#foo_default_pause",function(){ + order.push("hide") + }); + $(document.body).on("show", "#foo_default_pause",function(ev){ + order.push('show'); + ev.pause(); + $("#foo_default_pause").triggerAsync("hide",function(){ + order.push("hide async") + ev.resume(); + setTimeout(function(){ + + start(); + $(document.body).off() + deepEqual(order,['show','hide','hide default',"hide async","show default","show async"]) + },30) + + }, function(){ + order.push("hide prevented") + }) + }); + + + $("#foo_default_pause").triggerAsync("show",function(){ + order.push("show async") + }, function(){ + order.push("show prevented") }) }); +test("triggerAsync within another triggerAsync with prevented callback", function(){ + $("#qunit-fixture").html("
                                    hello
                                    ") + + var order = []; + stop(); + + $(document.body).on("default.show", "#foo_default_pause",function(){ + order.push("show default") + }); + $(document.body).on("default.hide", "#foo_default_pause", function(){ + order.push("hide default") + }); + $(document.body).on("hide", "#foo_default_pause",function(){ + order.push("hide") + }); + $(document.body).on("show", "#foo_default_pause", function(ev){ + order.push('show'); + ev.preventDefault(); + ev.pause(); + $("#foo_default_pause").triggerAsync("hide",function(){ + order.push("hide async") + ev.resume(); + setTimeout(function(){ + start(); + $(document.body).off() + deepEqual(order,['show','hide','hide default',"hide async","show prevented"]) + },30) + + }, function(){ + order.push("hide prevented") + }) + }); + + + $("#foo_default_pause").triggerAsync("show",function(){ + order.push("show async") + }, function(){ + order.push("show prevented") + }) +}); test("triggerAsync with nothing", function(){ $("#fool").triggerAsync("show", function(){ ok(true) diff --git a/event/default/default_test.js b/event/default/default_test.js index 13d65c8f..0783e893 100644 --- a/event/default/default_test.js +++ b/event/default/default_test.js @@ -1,129 +1,132 @@ -steal('funcunit/qunit','jquery/event/default').then(function(){ +steal('steal-qunit','jquerypp/event/default',function(){ + +module("jquerypp/event/default"); -module("jquery/event/default") test("namespaced with same function", function(){ var count = 0 , func = function(){ count++; - } - $("#qunit-test-area").html("
                                    hey
                                    ") - $("#one").bind("foo.bar", func).bind("foo.zar", func) - $("#one").trigger("foo.bar") - equals(1, count,"jquery seems ok") -}) + }; + $("#qunit-fixture").html("
                                    hey
                                    "); + $("#one").bind("foo.bar", func).bind("foo.zar", func); + $("#one").trigger("foo.bar"); + equal(1, count,"jquery seems ok"); +}); test("triggering defaults", function(){ - $("#qunit-test-area").html( + $("#qunit-fixture").html( "
                                    ClickMe
                                    "+ - "
                                    ClickMe
                                    ") + "
                                    ClickMe
                                    "); + + var count1 = 0, defaultNum, touchNum, num = 0; - var count1 = 0, defaultNum, touchNum, num = 0;; $("#wrap1").bind("default.touch", function(){ count1++; - defaultNum = (++num) - }) + defaultNum = (++num); + }); + $("#wrap1").bind("touch", function(){ - touchNum = (++num) - }) - $("#touchme1").trigger("touch") - equals(count1, 1 , "trigger default event") - equals(touchNum, 1, "default called second") - equals(defaultNum, 2, "default called second") + touchNum = (++num); + }); + + $("#touchme1").trigger("touch"); + equal(count1, 1 , "trigger default event"); + equal(touchNum, 1, "default called second"); + equal(defaultNum, 2, "default called second"); //now prevent - $("#bigwrapper").bind("touch", function(e){ e.preventDefault()}); + $("#bigwrapper").bind("touch", function(e){ e.preventDefault();}); $("#touchme1").trigger("touch"); - equals(count1, 1 , "default event not called again"); // breaking - equals(3, touchNum, "touch called again") + equal(count1, 1 , "default event not called again"); // breaking + equal(3, touchNum, "touch called again"); var count2 = 0; $("#wrap2").bind("default.hide.me.a", function(){ count2++; - }) + }); + $(document.body).bind("hide", function(ev){ if(ev.target.id == "clickme1"){ - ev.stopPropagation() - ev.preventDefault() + ev.stopPropagation(); + ev.preventDefault(); } - }) + }); $(".clickme").click(function(){ - $(this).trigger("hide") - }) + $(this).trigger("hide"); + }); - $("#qunit-test-area").html("") -}) + $("#qunit-fixture").html(""); +}); -test("live on default events", function(){ +test("on default events", function(){ - $("#qunit-test-area").html( + $("#qunit-fixture").html( "
                                    ClickMe
                                    "+ - "
                                    ClickMe
                                    ") + "
                                    ClickMe
                                    "); + var bw = $("#bigwrapper"), count1 = 0, count2 = 0, count3 = 0; var jq = $(); jq.context = bw[0]; - jq.selector = "#wrap1" - jq.live("default.touch", function(){ + jq.selector = "#wrap1"; + + $("#qunit-fixture").on("default.touch","#wrap1", function(){ count1++; }); - //2nd selector - var jq2 = $(); - jq2.context = bw[0]; - jq2.selector = "#wrap2" - jq2.live("default.touching", function(){ + $("#qunit-fixture").on("default.touching", "#wrap2",function(){ count2++; }); bw.delegate("#wrap2","default.somethingElse",function(){ count3++; - }) + }); $("#touchme1").trigger("touch") - equals(count1,1, "doing touch") + equal(count1,1, "doing touch") $("#touchme2").trigger("touching") - equals(count2,1, "doing touching") + equal(count2,1, "doing touching") $("#touchme2").trigger("somethingElse") - equals(count3,1, "delegated live somethingElse") + equal(count3,1, "delegated live somethingElse") - $("#qunit-test-area").html("") + $("#qunit-fixture").html(""); }); test("default and live order", function(){ var order = []; - $("#qunit-test-area").html("
                                    ") + $("#qunit-fixture").html("
                                    "); - $("#foo").live("default.show", function(){ - order.push("default") + $(document.body).on("default.show", "#foo",function(){ + order.push("default"); }); - $("#foo").live("show", function(){ - order.push("show") + $(document.body).on("show","#foo", function(){ + order.push("show"); }); - $("#foo").trigger("show") + $("#foo").trigger("show"); - same(order, ['show','default'],"show then default") - $("#foo").die() + deepEqual(order, ['show','default'],"show then default"); + $(document.body).off(); }); @@ -131,36 +134,35 @@ test("type on objects", function(){ var ev = $.Event('updated'), obj = {foo: 'bar'}; - $(obj).trigger(ev) + $(obj).trigger(ev); - equals(ev.type, 'updated') + equal(ev.type, 'updated'); }); test("namespace on objects", function(){ var ev = $.Event('updated.ns'), obj = {foo: 'bar'}; - $(obj).trigger(ev) - equals(ev.namespace, 'ns') + $(obj).trigger(ev); + equal(ev.namespace, 'ns'); }); test("default events with argument", function(){ - $("#qunit-test-area").html( - "
                                    ") + $("#qunit-fixture").html("
                                    "); var arg = "foobar", touchArg, defaultArg; $("#touchme").bind("default.touch", function(e, data){ defaultArg = data; - }) + }); $("#touchme").bind("touch", function(e, data){ touchArg = data; - }) - $("#touchme").trigger("touch", arg) - equals(touchArg, arg, "standard event got args") - equals(defaultArg, arg, "default event got args") + }); + $("#touchme").trigger("touch", arg); + equal(touchArg, arg, "standard event got args"); + equal(defaultArg, arg, "default event got args"); }); diff --git a/event/default/defaultjquery.html b/event/default/defaultjquery.html index ebc3167f..e6a87c1f 100644 --- a/event/default/defaultjquery.html +++ b/event/default/defaultjquery.html @@ -50,7 +50,7 @@

                                    Default Events

                                    - - - -

                                    Default Test Suite

                                    -

                                    -
                                    -

                                    -
                                    -
                                      -
                                      - - \ No newline at end of file diff --git a/event/default/test.html b/event/default/test.html new file mode 100644 index 00000000..0715ce92 --- /dev/null +++ b/event/default/test.html @@ -0,0 +1,3 @@ +jquerypp/event/default + +
                                      diff --git a/event/destroyed/destroyed.md b/event/destroyed/destroyed.md deleted file mode 100644 index 4c90ee99..00000000 --- a/event/destroyed/destroyed.md +++ /dev/null @@ -1,26 +0,0 @@ -@page jQuery.event.destroyed -@parent jquerypp - -`jQuery.event.destroyed` adds a `destroyed` event that is triggered when an element has been removed. - -The destroyed event is called when the element is removed as a result of a jQuery DOM -[manipulation method](http://api.jquery.com/category/manipulation/) like *remove*, *html*, *replaceWith*, etc. -Destroyed events do not bubble, so make sure you don't use live or delegate with destroyed events. - -The destroyed event is very useful when you want to remove certain event handlers or clean up references -when the element has been removed. This is very important in order to create long lived applications -that do not leak. - -## Quick Example - - $(".foo").on("destroyed", function(){ - //clean up code - }); - -## Quick Demo - -@demo jquery/event/destroyed/destroyed.html - -## More Involved Demo - -@demo jquery/event/destroyed/destroyed_menu.html diff --git a/event/destroyed/destroyed_test.js b/event/destroyed/destroyed_test.js deleted file mode 100644 index 4dd264a4..00000000 --- a/event/destroyed/destroyed_test.js +++ /dev/null @@ -1,16 +0,0 @@ -steal("jquery/event/destroyed", 'funcunit/qunit', function() { - -module("jquery/event/destroyed") -test("removing an element", function(){ - var div = $("
                                      ").data("testData",5) - div.appendTo($("#qunit-test-area")) - var destroyed = false; - div.bind("destroyed",function(){ - destroyed = true; - equals($(this).data("testData"),5, "other data still exists") - }) - div.remove(); - ok(destroyed, "destroyed called") -}); - -}); \ No newline at end of file diff --git a/event/destroyed/qunit.html b/event/destroyed/qunit.html deleted file mode 100644 index f0428050..00000000 --- a/event/destroyed/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

                                      destroyed Test Suite

                                      -

                                      -
                                      -

                                      -
                                      -
                                        -
                                        - - \ No newline at end of file diff --git a/event/drag/core/core.js b/event/drag/core/core.js new file mode 100644 index 00000000..d85ef330 --- /dev/null +++ b/event/drag/core/core.js @@ -0,0 +1,773 @@ +steal('jquery', 'jquerypp/lang/vector', 'jquerypp/event/livehack', 'jquerypp/event/reverse', function( $ ) { + + if(!$.event.special.move) { + $.event.reverse('move'); + } + + //modify live + //steal the live handler .... + var bind = function( object, method ) { + var args = Array.prototype.slice.call(arguments, 2); + return function() { + var args2 = [this].concat(args, $.makeArray(arguments)); + return method.apply(object, args2); + }; + }, + event = $.event, + // function to clear the window selection if there is one + clearSelection = window.getSelection ? function(){ + window.getSelection().removeAllRanges() + } : function(){}, + + supportTouch = !window._phantom && "ontouchend" in document, + // Use touch events or map it to mouse events + startEvent = supportTouch ? "touchstart" : "mousedown", + stopEvent = supportTouch ? "touchend" : "mouseup", + moveEvent = supportTouch ? "touchmove" : "mousemove", + // On touchmove events the default (scrolling) event has to be prevented + preventTouchScroll = function(ev) { + ev.preventDefault(); + }; + + /** + * @constructor jQuery.Drag + * @parent jQuery.event.drag + * @plugin jquerypp/event/drag + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquerypp/event/drag/drag.js + * @test jquerypp/event/drag/qunit.html + * + * The `jQuery.Drag` constructor is never called directly but an instance of `jQuery.Drag` is passed as the second argument + * to the `dragdown`, `draginit`, `dragmove`, `dragend`, `dragover` and `dragout` event handlers: + * + * $('#dragger').on('draginit', function(el, drag) { + * // drag -> $.Drag + * }); + */ + $.Drag = function() {}; + + /** + * @static + */ + $.extend($.Drag, { + lowerName: "drag", + current: null, + distance: 0, + /** + * @function jQuery.Drag.mousedown + * @parent jQuery.Drag.static + * + * @body + * + * Called when someone mouses down on a draggable object. + * Gathers all callback functions and creates a new Draggable. + * @hide + */ + mousedown: function( ev, element ) { + var isLeftButton = ev.button === 0 || ev.button == 1, + doEvent = isLeftButton || supportTouch; + + if (!doEvent || this.current ) { + return; + } + + //create Drag + var drag = new $.Drag(), + delegate = ev.delegateTarget || element, + selector = ev.handleObj.selector, + self = this; + this.current = drag; + + drag.setup({ + element: element, + delegate: ev.delegateTarget || element, + selector: ev.handleObj.selector, + moved: false, + _distance: this.distance, + callbacks: { + dragdown: event.find(delegate, ["dragdown"], selector), + draginit: event.find(delegate, ["draginit"], selector), + dragover: event.find(delegate, ["dragover"], selector), + dragmove: event.find(delegate, ["dragmove"], selector), + dragout: event.find(delegate, ["dragout"], selector), + dragend: event.find(delegate, ["dragend"], selector), + dragcleanup: event.find(delegate, ["dragcleanup"], selector) + }, + destroyed: function() { + self.current = null; + } + }, ev); + } + }); + + /** + * @Prototype + */ + $.extend($.Drag.prototype, { + setup: function( options, ev ) { + $.extend(this, options); + + this.element = $(this.element); + this.event = ev; + this.moved = false; + this.allowOtherDrags = false; + var mousemove = bind(this, this.mousemove), + mouseup = bind(this, this.mouseup); + this._mousemove = mousemove; + this._mouseup = mouseup; + this._distance = options.distance ? options.distance : 0; + + //where the mouse is located + this.mouseStartPosition = ev.vector(); + + $(document).bind(moveEvent, mousemove); + $(document).bind(stopEvent, mouseup); + if(supportTouch) { + // On touch devices we want to disable scrolling + $(document).bind(moveEvent, preventTouchScroll); + } + + if (!this.callEvents('down', this.element, ev) ) { + this.noSelection(this.delegate); + //this is for firefox + clearSelection(); + } + }, + /** + * @property jQuery.Drag.prototype.element element + * @parent jQuery.Drag.prototype + * + * @body + * A reference to the element that is being dragged. For example: + * + * $('.draggable').on('draginit', function(ev, drag) { + * drag.element.html('I am the drag element'); + * }); + */ + + /** + * Unbinds listeners and allows other drags ... + * @hide + */ + destroy: function() { + // Unbind the mouse handlers attached for dragging + $(document).unbind(moveEvent, this._mousemove); + $(document).unbind(stopEvent, this._mouseup); + if(supportTouch) { + // Enable scrolling again for touch devices when the drag is done + $(document).unbind(moveEvent, preventTouchScroll); + } + + if (!this.moved ) { + this.event = this.element = null; + } + + if(!supportTouch) { + this.selection(this.delegate); + } + this.destroyed(); + }, + mousemove: function( docEl, ev ) { + if (!this.moved ) { + var dist = Math.sqrt( Math.pow( ev.pageX - this.event.pageX, 2 ) + Math.pow( ev.pageY - this.event.pageY, 2 )); + // Don't initialize the drag if it hasn't been moved the minimum distance + if(dist < this._distance){ + return false; + } + // Otherwise call init and indicate that the drag has moved + this.init(this.element, ev); + this.moved = true; + } + + this.element.trigger('move', this); + var pointer = ev.vector(); + if ( this._start_position && this._start_position.equal(pointer) ) { + return; + } + this.draw(pointer, ev); + }, + + mouseup: function( docEl, event ) { + //if there is a current, we should call its dragstop + if ( this.moved ) { + this.end(event); + } + this.destroy(); + }, + + /** + * The `drag.noSelection(element)` method turns off text selection during a drag event. + * This method is called by default unless a event is listening to the 'dragdown' event. + * + * ## Example + * + * $('div.drag').bind('dragdown', function(elm,event,drag){ + * drag.noSelection(); + * }); + * + * @param [elm] an element to prevent selection on. Defaults to the dragable element. + */ + noSelection: function(elm) { + elm = elm || this.delegate + document.documentElement.onselectstart = function() { + // Disables selection + return false; + }; + document.documentElement.unselectable = "on"; + this.selectionDisabled = (this.selectionDisabled ? this.selectionDisabled.add(elm) : $(elm)); + this.selectionDisabled.css('-moz-user-select', '-moz-none'); + }, + + /** + * @hide + * `drag.selection()` method turns on text selection that was previously turned off during the drag event. + * This method is always called. + * + * ## Example + * + * $('div.drag').bind('dragdown', function(elm,event,drag){ + * drag.selection(); + * }); + */ + selection: function() { + if(this.selectionDisabled) { + document.documentElement.onselectstart = function() {}; + document.documentElement.unselectable = "off"; + this.selectionDisabled.css('-moz-user-select', ''); + } + }, + + init: function( element, event ) { + element = $(element); + //the element that has been clicked on + var startElement = (this.movingElement = (this.element = $(element))); + //if a mousemove has come after the click + //if the drag has been cancelled + this._cancelled = false; + this.event = event; + + /** + * @property jQuery.Drag.prototype.mouseElementPosition mouseElementPosition + * @parent jQuery.Drag.prototype + * + * @body + * The position of start of the cursor on the element + */ + this.mouseElementPosition = this.mouseStartPosition.minus(this.element.offsetv()); //where the mouse is on the Element + this.callEvents('init', element, event); + + // Check what they have set and respond accordingly if they canceled + if ( this._cancelled === true ) { + return; + } + // if they set something else as the element + this.startPosition = startElement != this.movingElement ? this.movingElement.offsetv() : this.currentDelta(); + + this.makePositioned(this.movingElement); + // Adjust the drag elements z-index to a high value + this.oldZIndex = this.movingElement.css('zIndex'); + this.movingElement.css('zIndex', 1000); + if (!this._only && this.constructor.responder ) { + // calls $.Drop.prototype.compile if there is a drop element + this.constructor.responder.compile(event, this); + } + }, + makePositioned: function( that ) { + var style, pos = that.css('position'); + + // Position properly, set top and left to 0px for Opera + if (!pos || pos == 'static' ) { + style = { + position: 'relative' + }; + + if ( window.opera ) { + style.top = '0px'; + style.left = '0px'; + } + that.css(style); + } + }, + callEvents: function( type, element, event, drop ) { + var i, cbs = this.callbacks[this.constructor.lowerName + type]; + for ( i = 0; i < cbs.length; i++ ) { + cbs[i].call(element, event, this, drop); + } + return cbs.length; + }, + /** + * Returns the position of the movingElement by taking its top and left. + * @hide + * @return {$.Vector} + */ + currentDelta: function() { + return new $.Vector(parseInt(this.movingElement.css('left'), 10) || 0, parseInt(this.movingElement.css('top'), 10) || 0); + }, + //draws the position of the dragmove object + draw: function( pointer, event ) { + // only drag if we haven't been cancelled; + if ( this._cancelled ) { + return; + } + clearSelection(); + /** + * @property jQuery.Drag.prototype.location location + * @parent jQuery.Drag.prototype + * `drag.location` is a [jQuery.Vector] specifying where the element should be in the page. This + * takes into account the start position of the cursor on the element. + * + * If the drag is going to be moved to an unacceptable location, you can call preventDefault in + * dragmove to prevent it from being moved there. + * + * $('.mover').bind("dragmove", function(ev, drag){ + * if(drag.location.top() < 100){ + * ev.preventDefault() + * } + * }); + * + * You can also set the location to where it should be on the page. + * + */ + // the offset between the mouse pointer and the representative that the user asked for + this.location = pointer.minus(this.mouseElementPosition); + + // call move events + this.move(event); + if ( this._cancelled ) { + return; + } + if (!event.isDefaultPrevented() ) { + this.position(this.location); + } + + // fill in + if (!this._only && this.constructor.responder ) { + this.constructor.responder.show(pointer, this, event); + } + }, + /** + * `drag.position( newOffsetVector )` sets the position of the movingElement. This is overwritten by + * the [$.Drag::scrolls], [$.Drag::limit] and [$.Drag::step] plugins + * to make sure the moving element scrolls some element + * or stays within some boundary. This function is exposed and documented so you could do the same. + * + * The following approximates how step does it: + * + * var oldPosition = $.Drag.prototype.position; + * $.Drag.prototype.position = function( offsetPositionv ) { + * if(this._step){ + * // change offsetPositionv to be on the step value + * } + * + * oldPosition.call(this, offsetPosition) + * } + * + * @param {jQuery.Vector} newOffsetv the new [$.Drag::location] of the element. + */ + position: function( newOffsetv ) { //should draw it on the page + var style, dragged_element_css_offset = this.currentDelta(), + // the drag element's current left + top css attributes + // the vector between the movingElement's page and css positions + // this can be thought of as the original offset + dragged_element_position_vector = this.movingElement.offsetv().minus(dragged_element_css_offset); + this.required_css_position = newOffsetv.minus(dragged_element_position_vector); + + this.offsetv = newOffsetv; + style = this.movingElement[0].style; + if (!this._cancelled && !this._horizontal ) { + style.top = this.required_css_position.top() + "px"; + } + if (!this._cancelled && !this._vertical ) { + style.left = this.required_css_position.left() + "px"; + } + }, + move: function( event ) { + this.callEvents('move', this.element, event); + }, + over: function( event, drop ) { + this.callEvents('over', this.element, event, drop); + }, + out: function( event, drop ) { + this.callEvents('out', this.element, event, drop); + }, + /** + * Called on drag up + * @hide + * @param {Event} event a mouseup event signalling drag/drop has completed + */ + end: function( event ) { + // If canceled do nothing + if ( this._cancelled ) { + return; + } + // notify the responder - usually a $.Drop instance + if (!this._only && this.constructor.responder ) { + this.constructor.responder.end(event, this); + } + + this.callEvents('end', this.element, event); + + if ( this._revert ) { + var self = this; + // animate moving back to original position + this.movingElement.animate({ + top: this.startPosition.top() + "px", + left: this.startPosition.left() + "px" + }, function() { + self.cleanup.apply(self, arguments); + }); + } + else { + this.cleanup(event); + } + this.event = null; + }, + /** + * Cleans up drag element after drag drop. + * @hide + */ + cleanup: function(event) { + this.movingElement.css({ + zIndex: this.oldZIndex + }); + if ( this.movingElement[0] !== this.element[0] && + !this.movingElement.has(this.element[0]).length && + !this.element.has(this.movingElement[0]).length ) { + this.movingElement.css({ + display: 'none' + }); + } + if ( this._removeMovingElement ) { + // Remove the element when using drag.ghost() + this.movingElement.remove(); + } + + if(event) { + this.callEvents('cleanup', this.element, event); + } + + this.movingElement = this.element = this.event = null; + }, + /** + * `drag.cancel()` stops a drag motion from from running. This also stops any other events from firing, meaning + * that "dragend" will not be called. + * + * $("#todos").on(".handle", "draginit", function( ev, drag ) { + * if(drag.movingElement.hasClass("evil")){ + * drag.cancel(); + * } + * }) + * + */ + cancel: function() { + this._cancelled = true; + if (!this._only && this.constructor.responder ) { + // clear the drops + this.constructor.responder.clear(this.event.vector(), this, this.event); + } + this.destroy(); + + }, + /** + * `drag.ghost( [parent] )` clones the element and uses it as the + * moving element, leaving the original dragged element in place. The `parent` option can + * be used to specify where the ghost element should be temporarily added into the + * DOM. This method should be called in "draginit". + * + * $("#todos").on(".handle", "draginit", function( ev, drag ) { + * drag.ghost(); + * }) + * + * @param {HTMLElement} [parent] the parent element of the newly created ghost element. If not provided the + * ghost element is added after the moving element. + * @return {jQuery.fn} the ghost element to do whatever you want with it. + */ + ghost: function( parent ) { + // create a ghost by cloning the source element and attach the clone to the dom after the source element + var ghost = this.movingElement.clone().css('position', 'absolute'); + if( parent ) { + $(parent).append(ghost); + } else { + $(this.movingElement).after(ghost) + } + ghost.width(this.movingElement.width()).height(this.movingElement.height()); + // put the ghost in the right location ... + ghost.offset(this.movingElement.offset()) + + // store the original element and make the ghost the dragged element + this.movingElement = ghost; + this.noSelection(ghost) + this._removeMovingElement = true; + return ghost; + }, + /** + * `drag.representative( element, [offsetX], [offsetY])` tells the drag motion to use + * a different element than the one that began the drag motion. + * + * For example, instead of + * dragging an drag-icon of a todo element, you want to move some other representation of + * the todo element (or elements). To do this you might: + * + * $("#todos").on(".handle", "draginit", function( ev, drag ) { + * // create what we'll drag + * var rep = $('
                                        ').text("todos") + * .appendTo(document.body) + * // indicate we want our mouse on the top-right of it + * drag.representative(rep, rep.width(), 0); + * }) + * + * @param {HTMLElement} element the element you want to actually drag. This should be + * already in the DOM. + * @param {Number} offsetX the x position where you want your mouse on the representative element (defaults to 0) + * @param {Number} offsetY the y position where you want your mouse on the representative element (defaults to 0) + * @return {drag} returns the drag object for chaining. + */ + representative: function( element, offsetX, offsetY ) { + this._offsetX = offsetX || 0; + this._offsetY = offsetY || 0; + + var p = this.mouseStartPosition; + // Just set the representative as the drag element + this.movingElement = $(element); + this.movingElement.css({ + top: (p.y() - this._offsetY) + "px", + left: (p.x() - this._offsetX) + "px", + display: 'block', + position: 'absolute' + }).show(); + this.noSelection(this.movingElement) + this.mouseElementPosition = new $.Vector(this._offsetX, this._offsetY); + return this; + }, + /** + * `drag.revert([val])` makes the [$.Drag::representative representative] element revert back to it + * original position after the drag motion has completed. The revert is done with an animation. + * + * $("#todos").on(".handle","dragend",function( ev, drag ) { + * drag.revert(); + * }) + * + * @param {Boolean} [val] optional, set to false if you don't want to revert. + * @return {drag} the drag object for chaining + */ + revert: function( val ) { + this._revert = val === undefined ? true : val; + return this; + }, + /** + * `drag.vertical()` isolates the drag to vertical movement. For example: + * + * $("#images").on(".thumbnail","draginit", function(ev, drag){ + * drag.vertical(); + * }); + * + * Call `vertical()` in "draginit" or "dragdown". + * + * @return {drag} the drag object for chaining. + */ + vertical: function() { + this._vertical = true; + return this; + }, + /** + * `drag.horizontal()` isolates the drag to horizontal movement. For example: + * + * $("#images").on(".thumbnail","draginit", function(ev, drag){ + * drag.horizontal(); + * }); + * + * Call `horizontal()` in "draginit" or "dragdown". + * + * @return {drag} the drag object for chaining. + */ + horizontal: function() { + this._horizontal = true; + return this; + }, + /** + * `drag.only([only])` indicates if you __only__ want a drag motion and the drag should + * not notify drops. The default value is `false`. Call it with no arguments or pass it true + * to prevent drop events. + * + * $("#images").on(".thumbnail","dragdown", function(ev, drag){ + * drag.only(); + * }); + * + * @param {Boolean} [only] true if you want to prevent drops, false if otherwise. + * @return {Boolean} the current value of only. + */ + only: function( only ) { + return (this._only = (only === undefined ? true : only)); + }, + + /** + * `distance([val])` sets or reads the distance the mouse must move before a drag motion is started. This should be set in + * "dragdown" and delays "draginit" being called until the distance is covered. The distance + * is measured in pixels. The default distance is 0 pixels meaning the drag motion starts on the first + * mousemove after a mousedown. + * + * Set this to make drag motion a little "stickier" to start. + * + * $("#images").on(".thumbnail","dragdown", function(ev, drag){ + * drag.distance(10); + * }); + * + * @param {Number} [val] The number of pixels the mouse must move before "draginit" is called. + * @return {drag|Number} returns the drag instance for chaining if the drag value is being set or the + * distance value if the distance is being read. + */ + distance: function(val){ + if(val !== undefined){ + this._distance = val; + return this; + }else{ + return this._distance + } + } + }); + /** + * @add jQuery.event.special + */ + event.setupHelper([ + /** + * @function jQuery.event.special.dragdown dragdown + * @parent jQuery.event.drag + * + * @body + * + * `dragdown` is called when a drag movement has started on a mousedown. + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter. Listening to `dragdown` allows you to customize + * the behavior of a drag motion, especially when `draginit` should be called. + * + * $(".handles").delegate("dragdown", function(ev, drag){ + * // call draginit only when the mouse has moved 20 px + * drag.distance(20); + * }) + * + * Typically, when a drag motion is started, `event.preventDefault` is automatically + * called, preventing text selection. However, if you listen to + * `dragdown`, this default behavior is not called. You are responsible for calling it + * if you want it (you probably do). + * + * ### Why might you not want to call `preventDefault`? + * + * You might want it if you want to allow text selection on element + * within the drag element. Typically these are input elements. + * + * $(".handles").delegate("dragdown", function(ev, drag){ + * if(ev.target.nodeName === "input"){ + * drag.cancel(); + * } else { + * ev.preventDefault(); + * } + * }) + */ + 'dragdown', + /** + * @function jQuery.event.special.draginit draginit + * @parent jQuery.event.drag + * + * @body + * + * `draginit` is triggered when the drag motion starts. Use it to customize the drag behavior + * using the [jQuery.Drag] instance passed as the second parameter: + * + * $(".draggable").on('draginit', function(ev, drag) { + * // Only allow vertical drags + * drag.vertical(); + * // Create a draggable copy of the element + * drag.ghost(); + * }); + */ + 'draginit', + /** + * @function jQuery.event.special.dragover dragover + * @parent jQuery.event.drag + * + * @body + * + * `dragover` is triggered when a drag is over a [jQuery.event.drop drop element]. + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter and an instance of [jQuery.Drop] passed as the third argument: + * + * $('.draggable').on('dragover', function(ev, drag, drop) { + * // Add the drop-here class indicating that the drag + * // can be dropped here + * drag.element.addClass('drop-here'); + * }); + */ + 'dragover', + /** + * @function jQuery.event.special.dragmove dragmove + * @parent jQuery.event.drag + * + * @body + * + * `dragmove` is triggered when the drag element moves (similar to a mousemove). + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter. + * Use [jQuery.Drag.prototype.location location] to determine the current position + * as a [jQuery.Vector vector]. + * + * For example, `dragmove` can be used to create a draggable element to resize + * a container: + * + * $('.resizer').on('dragmove', function(ev, drag) { + * $('#container').width(drag.location.x()) + * .height(drag.location.y()); + * }); + */ + 'dragmove', + /** + * @function jQuery.event.special.dragout dragout + * @parent jQuery.event.drag + * + * @body + * + * `dragout` is called when the drag leaves a drop point. + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter. + * + * $('.draggable').on('dragout', function(ev, drag) { + * // Remove the drop-here class + * // (e.g. crossing the drag element out indicating that it + * // can't be dropped here + * drag.element.removeClass('drop-here'); + * }); + */ + 'dragout', + /** + * @function jQuery.event.special.dragend dragend + * @parent jQuery.event.drag + * + * @body + * + * `dragend` is called when the drag operation is completed. + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter. + * + * $('.draggable').on('dragend', function(ev, drag) + * // Calculation on whether revert should be invoked, alterations based on position of the end event + * }); + */ + 'dragend', + /** + * @function jQuery.event.special.dragcleanup dragcleanup + * @parent jQuery.event.drag + * + * @body + * + * `dragcleanup` is called after dragend and revert (if applied) + * The event handler gets an instance of [jQuery.Drag] passed as the second + * parameter. + * + * $('.draggable').on('dragcleanup', function(ev, drag) + * // cleanup + * }); + */ + 'dragcleanup'], startEvent, function( e ) { + $.Drag.mousedown.call($.Drag, e, this); + }); + + return $; +}); \ No newline at end of file diff --git a/event/drag/drag.html b/event/drag/drag.html index ba599529..c4b5e13a 100644 --- a/event/drag/drag.html +++ b/event/drag/drag.html @@ -83,12 +83,11 @@

                                        Allow Text Selection

                                        I should be able to drag on this

                                        - - + \ No newline at end of file diff --git a/event/drag/drag.js b/event/drag/drag.js index 771a17aa..cb549c32 100644 --- a/event/drag/drag.js +++ b/event/drag/drag.js @@ -1,747 +1,4 @@ -steal('jquery', 'jquery/lang/vector', 'jquery/event/livehack', 'jquery/event/reverse', function( $ ) { - - if(!$.event.special.move) { - $.event.reverse('move'); - } - - //modify live - //steal the live handler .... - var bind = function( object, method ) { - var args = Array.prototype.slice.call(arguments, 2); - return function() { - var args2 = [this].concat(args, $.makeArray(arguments)); - return method.apply(object, args2); - }; - }, - event = $.event, - // function to clear the window selection if there is one - clearSelection = window.getSelection ? function(){ - window.getSelection().removeAllRanges() - } : function(){}, - - supportTouch = "ontouchend" in document, - // Use touch events or map it to mouse events - startEvent = supportTouch ? "touchstart" : "mousedown", - stopEvent = supportTouch ? "touchend" : "mouseup", - moveEvent = supportTouch ? "touchmove" : "mousemove", - // On touchmove events the default (scrolling) event has to be prevented - preventTouchScroll = function(ev) { - ev.preventDefault(); - }; - - /** - * @class jQuery.Drag - * @parent jQuery.event.drag - * @plugin jquery/event/drag - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drag/drag.js - * @test jquery/event/drag/qunit.html - * - * The `$.Drag` constructor is never called directly but an instance of `$.Drag` is passed as the second argument - * to the `dragdown`, `draginit`, `dragmove`, `dragend`, `dragover` and `dragout` event handlers: - * - * $('#dragger').on('draginit', function(el, drag) { - * // drag -> $.Drag - * }); - */ - $.Drag = function() {}; - - /** - * @Static - */ - $.extend($.Drag, { - lowerName: "drag", - current: null, - distance: 0, - /** - * Called when someone mouses down on a draggable object. - * Gathers all callback functions and creates a new Draggable. - * @hide - */ - mousedown: function( ev, element ) { - var isLeftButton = ev.button === 0 || ev.button == 1, - doEvent = isLeftButton || supportTouch; - - if (!doEvent || this.current ) { - return; - } - - //create Drag - var drag = new $.Drag(), - delegate = ev.delegateTarget || element, - selector = ev.handleObj.selector, - self = this; - this.current = drag; - - drag.setup({ - element: element, - delegate: ev.delegateTarget || element, - selector: ev.handleObj.selector, - moved: false, - _distance: this.distance, - callbacks: { - dragdown: event.find(delegate, ["dragdown"], selector), - draginit: event.find(delegate, ["draginit"], selector), - dragover: event.find(delegate, ["dragover"], selector), - dragmove: event.find(delegate, ["dragmove"], selector), - dragout: event.find(delegate, ["dragout"], selector), - dragend: event.find(delegate, ["dragend"], selector), - dragcleanup: event.find(delegate, ["dragcleanup"], selector) - }, - destroyed: function() { - self.current = null; - } - }, ev); - } - }); - - /** - * @Prototype - */ - $.extend($.Drag.prototype, { - setup: function( options, ev ) { - $.extend(this, options); - - this.element = $(this.element); - this.event = ev; - this.moved = false; - this.allowOtherDrags = false; - var mousemove = bind(this, this.mousemove), - mouseup = bind(this, this.mouseup); - this._mousemove = mousemove; - this._mouseup = mouseup; - this._distance = options.distance ? options.distance : 0; - - //where the mouse is located - this.mouseStartPosition = ev.vector(); - - $(document).bind(moveEvent, mousemove); - $(document).bind(stopEvent, mouseup); - if(supportTouch) { - // On touch devices we want to disable scrolling - $(document).bind(moveEvent, preventTouchScroll); - } - - if (!this.callEvents('down', this.element, ev) ) { - this.noSelection(this.delegate); - //this is for firefox - clearSelection(); - } - }, - /** - * @attribute element - * A reference to the element that is being dragged. For example: - * - * $('.draggable').on('draginit', function(ev, drag) { - * drag.element.html('I am the drag element'); - * }); - */ - - /** - * Unbinds listeners and allows other drags ... - * @hide - */ - destroy: function() { - // Unbind the mouse handlers attached for dragging - $(document).unbind(moveEvent, this._mousemove); - $(document).unbind(stopEvent, this._mouseup); - if(supportTouch) { - // Enable scrolling again for touch devices when the drag is done - $(document).unbind(moveEvent, preventTouchScroll); - } - - if (!this.moved ) { - this.event = this.element = null; - } - - if(!supportTouch) { - this.selection(this.delegate); - } - this.destroyed(); - }, - mousemove: function( docEl, ev ) { - if (!this.moved ) { - var dist = Math.sqrt( Math.pow( ev.pageX - this.event.pageX, 2 ) + Math.pow( ev.pageY - this.event.pageY, 2 )); - // Don't initialize the drag if it hasn't been moved the minimum distance - if(dist < this._distance){ - return false; - } - // Otherwise call init and indicate that the drag has moved - this.init(this.element, ev); - this.moved = true; - } - - this.element.trigger('move', this); - var pointer = ev.vector(); - if ( this._start_position && this._start_position.equals(pointer) ) { - return; - } - this.draw(pointer, ev); - }, - - mouseup: function( docEl, event ) { - //if there is a current, we should call its dragstop - if ( this.moved ) { - this.end(event); - } - this.destroy(); - }, - - /** - * The `drag.noSelection(element)` method turns off text selection during a drag event. - * This method is called by default unless a event is listening to the 'dragdown' event. - * - * ## Example - * - * $('div.drag').bind('dragdown', function(elm,event,drag){ - * drag.noSelection(); - * }); - * - * @param [elm] an element to prevent selection on. Defaults to the dragable element. - */ - noSelection: function(elm) { - elm = elm || this.delegate - document.documentElement.onselectstart = function() { - // Disables selection - return false; - }; - document.documentElement.unselectable = "on"; - this.selectionDisabled = (this.selectionDisabled ? this.selectionDisabled.add(elm) : $(elm)); - this.selectionDisabled.css('-moz-user-select', '-moz-none'); - }, - - /** - * @hide - * `drag.selection()` method turns on text selection that was previously turned off during the drag event. - * This method is always called. - * - * ## Example - * - * $('div.drag').bind('dragdown', function(elm,event,drag){ - * drag.selection(); - * }); - */ - selection: function() { - if(this.selectionDisabled) { - document.documentElement.onselectstart = function() {}; - document.documentElement.unselectable = "off"; - this.selectionDisabled.css('-moz-user-select', ''); - } - }, - - init: function( element, event ) { - element = $(element); - //the element that has been clicked on - var startElement = (this.movingElement = (this.element = $(element))); - //if a mousemove has come after the click - //if the drag has been cancelled - this._cancelled = false; - this.event = event; - - /** - * @attribute mouseElementPosition - * The position of start of the cursor on the element - */ - this.mouseElementPosition = this.mouseStartPosition.minus(this.element.offsetv()); //where the mouse is on the Element - this.callEvents('init', element, event); - - // Check what they have set and respond accordingly if they canceled - if ( this._cancelled === true ) { - return; - } - // if they set something else as the element - this.startPosition = startElement != this.movingElement ? this.movingElement.offsetv() : this.currentDelta(); - - this.makePositioned(this.movingElement); - // Adjust the drag elements z-index to a high value - this.oldZIndex = this.movingElement.css('zIndex'); - this.movingElement.css('zIndex', 1000); - if (!this._only && this.constructor.responder ) { - // calls $.Drop.prototype.compile if there is a drop element - this.constructor.responder.compile(event, this); - } - }, - makePositioned: function( that ) { - var style, pos = that.css('position'); - - // Position properly, set top and left to 0px for Opera - if (!pos || pos == 'static' ) { - style = { - position: 'relative' - }; - - if ( window.opera ) { - style.top = '0px'; - style.left = '0px'; - } - that.css(style); - } - }, - callEvents: function( type, element, event, drop ) { - var i, cbs = this.callbacks[this.constructor.lowerName + type]; - for ( i = 0; i < cbs.length; i++ ) { - cbs[i].call(element, event, this, drop); - } - return cbs.length; - }, - /** - * Returns the position of the movingElement by taking its top and left. - * @hide - * @return {$.Vector} - */ - currentDelta: function() { - return new $.Vector(parseInt(this.movingElement.css('left'), 10) || 0, parseInt(this.movingElement.css('top'), 10) || 0); - }, - //draws the position of the dragmove object - draw: function( pointer, event ) { - // only drag if we haven't been cancelled; - if ( this._cancelled ) { - return; - } - clearSelection(); - /** - * @attribute location - * `drag.location` is a [jQuery.Vector] specifying where the element should be in the page. This - * takes into account the start position of the cursor on the element. - * - * If the drag is going to be moved to an unacceptable location, you can call preventDefault in - * dragmove to prevent it from being moved there. - * - * $('.mover').bind("dragmove", function(ev, drag){ - * if(drag.location.top() < 100){ - * ev.preventDefault() - * } - * }); - * - * You can also set the location to where it should be on the page. - * - */ - // the offset between the mouse pointer and the representative that the user asked for - this.location = pointer.minus(this.mouseElementPosition); - - // call move events - this.move(event); - if ( this._cancelled ) { - return; - } - if (!event.isDefaultPrevented() ) { - this.position(this.location); - } - - // fill in - if (!this._only && this.constructor.responder ) { - this.constructor.responder.show(pointer, this, event); - } - }, - /** - * `drag.position( newOffsetVector )` sets the position of the movingElement. This is overwritten by - * the [$.Drag::scrolls], [$.Drag::limit] and [$.Drag::step] plugins - * to make sure the moving element scrolls some element - * or stays within some boundary. This function is exposed and documented so you could do the same. - * - * The following approximates how step does it: - * - * var oldPosition = $.Drag.prototype.position; - * $.Drag.prototype.position = function( offsetPositionv ) { - * if(this._step){ - * // change offsetPositionv to be on the step value - * } - * - * oldPosition.call(this, offsetPosition) - * } - * - * @param {jQuery.Vector} newOffsetv the new [$.Drag::location] of the element. - */ - position: function( newOffsetv ) { //should draw it on the page - var style, dragged_element_css_offset = this.currentDelta(), - // the drag element's current left + top css attributes - // the vector between the movingElement's page and css positions - // this can be thought of as the original offset - dragged_element_position_vector = this.movingElement.offsetv().minus(dragged_element_css_offset); - this.required_css_position = newOffsetv.minus(dragged_element_position_vector); - - this.offsetv = newOffsetv; - style = this.movingElement[0].style; - if (!this._cancelled && !this._horizontal ) { - style.top = this.required_css_position.top() + "px"; - } - if (!this._cancelled && !this._vertical ) { - style.left = this.required_css_position.left() + "px"; - } - }, - move: function( event ) { - this.callEvents('move', this.element, event); - }, - over: function( event, drop ) { - this.callEvents('over', this.element, event, drop); - }, - out: function( event, drop ) { - this.callEvents('out', this.element, event, drop); - }, - /** - * Called on drag up - * @hide - * @param {Event} event a mouseup event signalling drag/drop has completed - */ - end: function( event ) { - // If canceled do nothing - if ( this._cancelled ) { - return; - } - // notify the responder - usually a $.Drop instance - if (!this._only && this.constructor.responder ) { - this.constructor.responder.end(event, this); - } - - this.callEvents('end', this.element, event); - - if ( this._revert ) { - var self = this; - // animate moving back to original position - this.movingElement.animate({ - top: this.startPosition.top() + "px", - left: this.startPosition.left() + "px" - }, function() { - self.cleanup.apply(self, arguments); - }); - } - else { - this.cleanup(event); - } - this.event = null; - }, - /** - * Cleans up drag element after drag drop. - * @hide - */ - cleanup: function(event) { - this.movingElement.css({ - zIndex: this.oldZIndex - }); - if ( this.movingElement[0] !== this.element[0] && - !this.movingElement.has(this.element[0]).length && - !this.element.has(this.movingElement[0]).length ) { - this.movingElement.css({ - display: 'none' - }); - } - if ( this._removeMovingElement ) { - // Remove the element when using drag.ghost() - this.movingElement.remove(); - } - - if(event) { - this.callEvents('cleanup', this.element, event); - } - - this.movingElement = this.element = this.event = null; - }, - /** - * `drag.cancel()` stops a drag motion from from running. This also stops any other events from firing, meaning - * that "dragend" will not be called. - * - * $("#todos").on(".handle", "draginit", function( ev, drag ) { - * if(drag.movingElement.hasClass("evil")){ - * drag.cancel(); - * } - * }) - * - */ - cancel: function() { - this._cancelled = true; - if (!this._only && this.constructor.responder ) { - // clear the drops - this.constructor.responder.clear(this.event.vector(), this, this.event); - } - this.destroy(); - - }, - /** - * `drag.ghost( [parent] )` clones the element and uses it as the - * moving element, leaving the original dragged element in place. The `parent` option can - * be used to specify where the ghost element should be temporarily added into the - * DOM. This method should be called in "draginit". - * - * $("#todos").on(".handle", "draginit", function( ev, drag ) { - * drag.ghost(); - * }) - * - * @param {HTMLElement} [parent] the parent element of the newly created ghost element. If not provided the - * ghost element is added after the moving element. - * @return {jQuery.fn} the ghost element to do whatever you want with it. - */ - ghost: function( parent ) { - // create a ghost by cloning the source element and attach the clone to the dom after the source element - var ghost = this.movingElement.clone().css('position', 'absolute'); - if( parent ) { - $(parent).append(ghost); - } else { - $(this.movingElement).after(ghost) - } - ghost.width(this.movingElement.width()).height(this.movingElement.height()); - // put the ghost in the right location ... - ghost.offset(this.movingElement.offset()) - - // store the original element and make the ghost the dragged element - this.movingElement = ghost; - this.noSelection(ghost) - this._removeMovingElement = true; - return ghost; - }, - /** - * `drag.representative( element, [offsetX], [offsetY])` tells the drag motion to use - * a different element than the one that began the drag motion. - * - * For example, instead of - * dragging an drag-icon of a todo element, you want to move some other representation of - * the todo element (or elements). To do this you might: - * - * $("#todos").on(".handle", "draginit", function( ev, drag ) { - * // create what we'll drag - * var rep = $('
                                        ').text("todos") - * .appendTo(document.body) - * // indicate we want our mouse on the top-right of it - * drag.representative(rep, rep.width(), 0); - * }) - * - * @param {HTMLElement} element the element you want to actually drag. This should be - * already in the DOM. - * @param {Number} offsetX the x position where you want your mouse on the representative element (defaults to 0) - * @param {Number} offsetY the y position where you want your mouse on the representative element (defaults to 0) - * @return {drag} returns the drag object for chaining. - */ - representative: function( element, offsetX, offsetY ) { - this._offsetX = offsetX || 0; - this._offsetY = offsetY || 0; - - var p = this.mouseStartPosition; - // Just set the representative as the drag element - this.movingElement = $(element); - this.movingElement.css({ - top: (p.y() - this._offsetY) + "px", - left: (p.x() - this._offsetX) + "px", - display: 'block', - position: 'absolute' - }).show(); - this.noSelection(this.movingElement) - this.mouseElementPosition = new $.Vector(this._offsetX, this._offsetY); - return this; - }, - /** - * `drag.revert([val])` makes the [$.Drag::representative representative] element revert back to it - * original position after the drag motion has completed. The revert is done with an animation. - * - * $("#todos").on(".handle","dragend",function( ev, drag ) { - * drag.revert(); - * }) - * - * @param {Boolean} [val] optional, set to false if you don't want to revert. - * @return {drag} the drag object for chaining - */ - revert: function( val ) { - this._revert = val === undefined ? true : val; - return this; - }, - /** - * `drag.vertical()` isolates the drag to vertical movement. For example: - * - * $("#images").on(".thumbnail","draginit", function(ev, drag){ - * drag.vertical(); - * }); - * - * Call `vertical()` in "draginit" or "dragdown". - * - * @return {drag} the drag object for chaining. - */ - vertical: function() { - this._vertical = true; - return this; - }, - /** - * `drag.horizontal()` isolates the drag to horizontal movement. For example: - * - * $("#images").on(".thumbnail","draginit", function(ev, drag){ - * drag.horizontal(); - * }); - * - * Call `horizontal()` in "draginit" or "dragdown". - * - * @return {drag} the drag object for chaining. - */ - horizontal: function() { - this._horizontal = true; - return this; - }, - /** - * `drag.only([only])` indicates if you __only__ want a drag motion and the drag should - * not notify drops. The default value is `false`. Call it with no arguments or pass it true - * to prevent drop events. - * - * $("#images").on(".thumbnail","dragdown", function(ev, drag){ - * drag.only(); - * }); - * - * @param {Boolean} [only] true if you want to prevent drops, false if otherwise. - * @return {Boolean} the current value of only. - */ - only: function( only ) { - return (this._only = (only === undefined ? true : only)); - }, - - /** - * `distance([val])` sets or reads the distance the mouse must move before a drag motion is started. This should be set in - * "dragdown" and delays "draginit" being called until the distance is covered. The distance - * is measured in pixels. The default distance is 0 pixels meaning the drag motion starts on the first - * mousemove after a mousedown. - * - * Set this to make drag motion a little "stickier" to start. - * - * $("#images").on(".thumbnail","dragdown", function(ev, drag){ - * drag.distance(10); - * }); - * - * @param {Number} [val] The number of pixels the mouse must move before "draginit" is called. - * @return {drag|Number} returns the drag instance for chaining if the drag value is being set or the - * distance value if the distance is being read. - */ - distance: function(val){ - if(val !== undefined){ - this._distance = val; - return this; - }else{ - return this._distance - } - } - }); - /** - * @add jQuery.event.special - */ - event.setupHelper([ - /** - * @attribute dragdown - * @parent jQuery.event.drag - * - * `dragdown` is called when a drag movement has started on a mousedown. - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter. Listening to `dragdown` allows you to customize - * the behavior of a drag motion, especially when `draginit` should be called. - * - * $(".handles").delegate("dragdown", function(ev, drag){ - * // call draginit only when the mouse has moved 20 px - * drag.distance(20); - * }) - * - * Typically, when a drag motion is started, `event.preventDefault` is automatically - * called, preventing text selection. However, if you listen to - * `dragdown`, this default behavior is not called. You are responsible for calling it - * if you want it (you probably do). - * - * ### Why might you not want to call `preventDefault`? - * - * You might want it if you want to allow text selection on element - * within the drag element. Typically these are input elements. - * - * $(".handles").delegate("dragdown", function(ev, drag){ - * if(ev.target.nodeName === "input"){ - * drag.cancel(); - * } else { - * ev.preventDefault(); - * } - * }) - */ - 'dragdown', - /** - * @attribute draginit - * @parent jQuery.event.drag - * - * `draginit` is triggered when the drag motion starts. Use it to customize the drag behavior - * using the [jQuery.Drag] instance passed as the second parameter: - * - * $(".draggable").on('draginit', function(ev, drag) { - * // Only allow vertical drags - * drag.vertical(); - * // Create a draggable copy of the element - * drag.ghost(); - * }); - */ - 'draginit', - /** - * @attribute dragover - * @parent jQuery.event.drag - * - * `dragover` is triggered when a drag is over a [jQuery.event.drop drop element]. - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter and an instance of [jQuery.Drop] passed as the third argument: - * - * $('.draggable').on('dragover', function(ev, drag, drop) { - * // Add the drop-here class indicating that the drag - * // can be dropped here - * drag.element.addClass('drop-here'); - * }); - */ - 'dragover', - /** - * @attribute dragmove - * @parent jQuery.event.drag - * - * `dragmove` is triggered when the drag element moves (similar to a mousemove). - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter. - * Use [jQuery.Drag::location] to determine the current position - * as a [jQuery.Vector vector]. - * - * For example, `dragmove` can be used to create a draggable element to resize - * a container: - * - * $('.resizer').on('dragmove', function(ev, drag) { - * $('#container').width(drag.location.x()) - * .height(drag.location.y()); - * }); - */ - 'dragmove', - /** - * @attribute dragout - * @parent jQuery.event.drag - * - * `dragout` is called when the drag leaves a drop point. - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter. - * - * $('.draggable').on('dragout', function(ev, drag) { - * // Remove the drop-here class - * // (e.g. crossing the drag element out indicating that it - * // can't be dropped here - * drag.element.removeClass('drop-here'); - * }); - */ - 'dragout', - /** - * @attribute dragend - * @parent jQuery.event.drag - * - * `dragend` is called when the drag operation is completed. - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter. - * - * $('.draggable').on('dragend', function(ev, drag) - * // Calculation on whether revert should be invoked, alterations based on position of the end event - * }); - */ - 'dragend', - /** - * @attribute dragcleanup - * @parent jQuery.event.drag - * - * `dragcleanup` is called after dragend and revert (if applied) - * The event handler gets an instance of [jQuery.Drag] passed as the second - * parameter. - * - * $('.draggable').on('dragcleanup', function(ev, drag) - * // cleanup - * }); - */ - 'dragcleanup'], startEvent, function( e ) { - $.Drag.mousedown.call($.Drag, e, this); - }); - - return $; +steal('jquery', 'jquerypp/event/drag/core', 'jquerypp/event/drag/step', 'jquerypp/event/drag/limit', + 'jquerypp/event/drag/scroll', function( $ ) { + return $; }); \ No newline at end of file diff --git a/event/drag/drag.md b/event/drag/drag.md index 9d86e25f..61889989 100644 --- a/event/drag/drag.md +++ b/event/drag/drag.md @@ -1,4 +1,4 @@ -@page jQuery.event.drag +@page jQuery.event.drag jQuery.event.drag @parent jquerypp `jQuery.event.drag` provides drag events for jQuery. @@ -11,12 +11,12 @@ behavior. The drag plugin allows you to listen to the following events: -* `dragdown` - the mouse cursor is pressed down -* `draginit` - the drag motion is started -* `dragmove` - the drag is moved -* `dragend` - the drag has ended -* `dragover` - the drag is over a drop point -* `dragout` - the drag moved out of a drop point +* `[jQuery.event.special.dragdown dragdown]` - the mouse cursor is pressed down +* `[jQuery.event.special.draginit draginit]` - the drag motion is started +* `[jQuery.event.special.dragmove dragmove]` - the drag is moved +* `[jQuery.event.special.dragend dragend]` - the drag has ended +* `[jQuery.event.special.dragover dragover]` - the drag is over a drop point +* `[jQuery.event.special.dragout dragout]` - the drag moved out of a drop point Just by binding on one of these events, you make the element dragable. You can change the behavior of the drag @@ -59,4 +59,4 @@ The drag properties and methods: Now lets see some examples: -@demo jquery/event/drag/drag.html 1000 \ No newline at end of file +@demo jquerypp/event/drag/drag.html 1200 \ No newline at end of file diff --git a/event/drag/drag_test.js b/event/drag/drag_test.js index a622d42b..0cf325f6 100644 --- a/event/drag/drag_test.js +++ b/event/drag/drag_test.js @@ -1,9 +1,7 @@ -steal("jquery/event/drop", - 'funcunit/qunit', - 'funcunit/syn') - .then("jquery/event/drop/drop_test.js",function(){ +steal("jquerypp/event/drop", 'steal-qunit', 'syn', "jquerypp/event/drop/drop_test.js", +function($, QUnit, syn) { -module("jquery/event/drag",{ +module("jquerypp/event/drag",{ makePoints : function(){ var div = $("
                                        "+ "
                                        "+ @@ -11,31 +9,31 @@ module("jquery/event/drag",{ "
                                        "+ "
                                        "); - div.appendTo($("#qunit-test-area")); + div.appendTo($("#qunit-fixture")); var basicCss = { width: "20px", height: "20px", position: "absolute", border: "solid 1px black" - } - $("#drag").css(basicCss).css({top: "0px", left: "0px", zIndex: 1000, backgroundColor: "red"}) - $("#midpoint").css(basicCss).css({top: "0px", left: "30px"}) + }; + $("#drag").css(basicCss).css({top: "0px", left: "0px", zIndex: 1000, backgroundColor: "red"}); + $("#midpoint").css(basicCss).css({top: "0px", left: "30px"}); $("#drop").css(basicCss).css({top: "30px", left: "30px"}); } -}) +}); test("dragging an element", function(){ var div = $("
                                        "+ "
                                        "+ "
                                        "+ "
                                        "+ "
                                        "); - $("#qunit-test-area").html(div); + $("#qunit-fixture").html(div); var basicCss = { width: "20px", height: "20px", position: "absolute", border: "solid 1px black" - } + }; $("#drag").css(basicCss).css({top: "0px", left: "0px", zIndex: 1000, backgroundColor: "red"}) $("#midpoint").css(basicCss).css({top: "0px", left: "30px"}) $("#drop").css(basicCss).css({top: "30px", left: "30px"}); @@ -43,52 +41,52 @@ test("dragging an element", function(){ var drags = {}, drops ={}; - $('#drag') - .live("dragdown", function(){ + $("#qunit-fixture") + .on("dragdown", '#drag',function(){ drags.dragdown = true; }) - .live("draginit", function(){ + .on("draginit", '#drag', function(){ drags.draginit = true; }) - .live("dragmove", function(){ + .on("dragmove", '#drag', function(){ drags.dragmove = true; }) - .live("dragend", function(){ + .on("dragend", '#drag', function(){ drags.dragend = true; }) - .live("dragover", function(){ + .on("dragover", '#drag', function(){ drags.dragover = true; }) - .live("dragout", function(){ + .on("dragout", '#drag', function(){ drags.dragout = true; }) - .live("dragcleanup", function() { + .on("dragcleanup", '#drag', function() { drags.dragcleanup = true; - }) + }); - $('#drop') - .live("dropinit", function(){ + $("#qunit-fixture") + .on("dropinit",'#drop', function(){ drops.dropinit = true; }) - .live("dropover", function(){ + .on("dropover",'#drop', function(){ drops.dropover = true; }) - .live("dropout", function(){ + .on("dropout",'#drop', function(){ drops.dropout = true; }) - .live("dropmove", function(){ + .on("dropmove",'#drop', function(){ drops.dropmove = true; }) - .live("dropon", function(){ + .on("dropon",'#drop', function(){ drops.dropon = true; }) - .live("dropend", function(){ + .on("dropend",'#drop', function(){ drops.dropend = true; - }) + }); stop(); - Syn.drag({to: "#midpoint"},"drag", function(){ + syn.drag("drag", {to: "#midpoint"},function(){ ok(drags.dragdown, "dragdown fired correctly") ok(drags.draginit, "draginit fired correctly") ok(drags.dragmove, "dragmove fired correctly") @@ -115,8 +113,9 @@ test("dragging an element", function(){ ok(drops.dropout, "dropout fired correctly") //div.remove(); start(); - }) -}) + $("#qunit-fixture").off() + }); +}); test("move event", function(){ var div = $("
                                        "+ @@ -125,13 +124,13 @@ test("move event", function(){ "
                                        "), moved = false, draginit = false; - $("#qunit-test-area").html(div); + $("#qunit-fixture").html(div); var basicCss = { width: "20px", height: "20px", position: "absolute", border: "solid 1px black" - } + }; $("#drag-move").css(basicCss).css({top: "0px", left: "0px", zIndex: 1000, backgroundColor: "red"}) $("#move-to").css(basicCss).css({top: "0px", left: "100px"}) @@ -145,11 +144,11 @@ test("move event", function(){ } }); - Syn.drag({to: "#move-to"},"drag-move", function(){ + syn.drag("drag-move",{to: "#move-to"}, function(){ ok(moved, 'Move event fired'); start(); }); -}) +}); test("drag position", function(){ this.makePoints(); @@ -157,19 +156,20 @@ test("drag position", function(){ var drags = {}, drops ={}; - $('#drag').live("draginit", function(){ + $("#qunit-fixture").on("draginit",'#drag', function(){ drags.draginit = true; }) var offset = $('#drag').offset(); stop(); - Syn.drag("+20 +20","drag", function(){ + syn.drag("drag","+20 +20", function(){ var offset2 = $('#drag').offset(); - equals(offset.top+20, Math.ceil(offset2.top), "top") - equals(offset.left+20, Math.ceil(offset2.left), "left") + equal(offset.top+20, Math.ceil(offset2.top), "top") + equal(offset.left+20, Math.ceil(offset2.left), "left") start(); - }) + $("#qunit-fixture").off() + }); }); test("dragdown" , function(){ @@ -181,7 +181,7 @@ test("dragdown" , function(){ "
                                        "+ "
                                        "); - $("#qunit-test-area").html(div); + $("#qunit-fixture").html(div); $("#dragger").css({ position: "absolute", backgroundColor : "blue", @@ -196,10 +196,10 @@ test("dragdown" , function(){ $('#draginp').focus(function(){ draginpfocused = true; - }) + }); $('#dragnoprevent').focus(function(){ dragnopreventfocused = true; - }) + }); $('#dragger').bind("dragdown", function(ev, drag){ if(ev.target.id == 'draginp'){ @@ -207,27 +207,29 @@ test("dragdown" , function(){ }else{ ev.preventDefault(); } - }) + }); var offset = $('#dragger').offset(); stop(); - Syn.drag("+20 +20","draginp", function(){ + syn.drag("draginp", "+20 +20",function(){ var offset2 = $('#dragger').offset(); - equals(offset.top, Math.ceil(offset2.top), "top") - equals(offset.left, Math.ceil(offset2.left), "left") + equal(offset.top, Math.ceil(offset2.top), "top") + equal(offset.left, Math.ceil(offset2.left), "left") - }).drag("+20 +20","dragnoprevent", function(){ + }).drag("dragnoprevent","+20 +20", function(){ var offset2 = $('#dragger').offset(); - equals(offset.top+20, Math.ceil(offset2.top), "top") - equals(offset.left+20, Math.ceil(offset2.left), "left") + equal(offset.top+20, Math.ceil(offset2.top), "top") + equal(offset.left+20, Math.ceil(offset2.left), "left") // IE doesn't respect preventDefault on text inputs (http://www.quirksmode.org/dom/events/click.html) - if(!$.browser.msie) - ok(draginpfocused, "First input was allowed to be focused correctly"); + //if(!document.body.attachEvent) { + // ok(draginpfocused, "First input was allowed to be focused correctly"); + //} + //ok(!dragnopreventfocused, "Second input was not allowed to focus"); start(); - }) + }); -}) +}); test("dragging child element (a handle)" , function(){ var div = $("
                                        "+ @@ -236,7 +238,7 @@ test("dragging child element (a handle)" , function(){ "
                                        "+ "
                                        "); - $("#qunit-test-area").html(div); + $("#qunit-fixture").html(div); $("#dragger").css({ position: "absolute", backgroundColor : "blue", @@ -252,16 +254,16 @@ test("dragging child element (a handle)" , function(){ $('#dragger').bind("draginit", function(ev, drag){ drag.only(); drag.representative(dragged); - }) + }); stop(); var offset = $('#dragger').offset(); - Syn.drag("+20 +20","dragged", function() { + syn.drag("dragged", "+20 +20",function() { var offset2 = $('#dragger').offset(); - equals(offset.top, offset2.top, "top") - equals(offset.left, offset2.left, "left") + equal(offset.top, offset2.top, "top") + equal(offset.left, offset2.left, "left") ok(dragged.is(':visible'), "Handle should be visible"); diff --git a/event/drag/limit/limit.html b/event/drag/limit/limit.html index 134ebaa5..e4b46b3e 100644 --- a/event/drag/limit/limit.html +++ b/event/drag/limit/limit.html @@ -39,7 +39,7 @@
                                        handle
                                        - - \ No newline at end of file diff --git a/event/drag/scroll/scroll.js b/event/drag/scroll/scroll.js index 07250898..09f06df3 100644 --- a/event/drag/scroll/scroll.js +++ b/event/drag/scroll/scroll.js @@ -1,13 +1,17 @@ -steal("jquery", "jquery/event/drop", function($) { //needs drop to determine if respondable +steal("jquery", "jquerypp/event/drop", function($) { //needs drop to determine if respondable /** * @add jQuery.Drag.prototype */ $.Drag.prototype. /** - * @plugin jquery/event/drag/scroll - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/drag/scroll/scroll.js + * @plugin jquerypp/event/drag/scroll + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquerypp/event/drag/scroll/scroll.js * + * @function jQuery.Drag.prototype.scrolls + * @parent jQuery.Drag.prototype + * + * @body * `drag.scrolls(elements, [options])` scroll elements with * a scroll bar as the drag moves to borders. * @@ -47,7 +51,8 @@ $.Scrollable = function(element, options){ delta : function(diff, distance){ return (distance - diff) / 2; }, - direction: "xy" + direction: "xy", + delay: 15 }, options); this.x = this.options.direction.indexOf("x") != -1; this.y = this.options.direction.indexOf("y") != -1; @@ -107,14 +112,17 @@ $.extend($.Scrollable.prototype,{ distance = this.options.distance; //check if we should scroll - if(bottom < distance && this.y) + if(bottom < distance && this.y) { dy = this.options.delta(bottom,distance); - else if(top < distance && this.y) - dy = -this.options.delta(top,distance) - if(right < distance && this.options && this.x) + } else if(top < distance && this.y) { + dy = -this.options.delta(top,distance); + } + + if(right < distance && this.options && this.x) { dx = this.options.delta(right,distance); - else if(left < distance && this.x) + } else if(left < distance && this.x) { dx = -this.options.delta(left,distance); + } //if we should scroll if(dx || dy){ @@ -122,7 +130,7 @@ $.extend($.Scrollable.prototype,{ var self = this; this.interval = setTimeout( function(){ self.move($(el), drag.movingElement, dx, dy, ev, ev.clientX, ev.clientY, ev.screenX, ev.screenY) - },15) + },this.options.delay) } }, /** diff --git a/event/drag/step/step.html b/event/drag/step/step.html index 80c20c46..a8888ec0 100644 --- a/event/drag/step/step.html +++ b/event/drag/step/step.html @@ -47,7 +47,7 @@ +
                                        diff --git a/event/drop/drop.html b/event/drop/drop.html index 5088f0c1..5859f39d 100644 --- a/event/drop/drop.html +++ b/event/drop/drop.html @@ -40,12 +40,11 @@

                                        Dropmove/Dropon

                                        Drop Count 0
                                        - + - - \ No newline at end of file diff --git a/event/drop/test.html b/event/drop/test.html new file mode 100644 index 00000000..2c547ae4 --- /dev/null +++ b/event/drop/test.html @@ -0,0 +1,3 @@ +jquerypp/event/drop + +
                                        diff --git a/event/event.js b/event/event.js index c4ed299b..114f98b5 100644 --- a/event/event.js +++ b/event/event.js @@ -1,33 +1,31 @@ /** - * @page specialevents Special Events - * @parent jquerymx * @description Special events like drag-drop. - * - * JavaScriptMVC provides a bunch of useful special events. Find out more info on the left. The following is a + * + * JavaScriptMVC provides a bunch of useful special events. Find out more info on the left. The following is a * brief summary: - * + * * ## [jQuery.event.special.default Default Events] - * - * Lets you supply default behavior for an event that is preventable + * + * Lets you supply default behavior for an event that is preventable * with event.preventDefault(). This is extremely useful for providing DOM-like api's for your widgets. - * + * * $("#tabs").delegate(".panel","default.open", function(){ * $(this).show() * }) - * + * * ## [jQuery.event.special.destroyed Destroyed Events] - * + * * Know if an element has been removed from the page. - * + * * $("#contextMenu").bind("destroyed", function(){ * // cleanup * $(document.body).unbind("click.contextMenu"); * }) - * + * * ## [jQuery.Drag Drag] and [jQuery.Drop Drop] Events - * + * * Listen to drag-drop events with event delegation. - * + * * $(".item").live("dragover", function(ev, drag){ * // let user know that the item can be dropped * $(this).addClass("canDrop"); @@ -35,8 +33,8 @@ * // let user know that the item can be dropped on * $(this).addClass('drop-able') * }) - * - * ## - * + * + * ## + * */ -steal('jquery'); \ No newline at end of file +steal('jquery'); diff --git a/event/fastfix/fastfix.js b/event/fastfix/fastfix.js deleted file mode 100644 index 3707b497..00000000 --- a/event/fastfix/fastfix.js +++ /dev/null @@ -1,112 +0,0 @@ -steal('jquery', function ($) { - // http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html - // https://gist.github.com/2377196 - - // IE 8 has Object.defineProperty but it only defines DOM Nodes. According to - // http://kangax.github.com/es5-compat-table/#define-property-ie-note - // All browser that have Object.defineProperties also support Object.defineProperty properly - if(Object.defineProperties) { - var - // Use defineProperty on an object to set the value and return it - set = function (obj, prop, val) { - if(val !== undefined) { - Object.defineProperty(obj, prop, { - value : val - }); - } - return val; - }, - // special converters - special = { - pageX : function (original) { - if(!original) { - return; - } - - var eventDoc = this.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - return original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - }, - pageY : function (original) { - if(!original) { - return; - } - - var eventDoc = this.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - return original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - }, - relatedTarget : function (original) { - if(!original) { - return; - } - - return original.fromElement === this.target ? original.toElement : original.fromElement; - }, - metaKey : function (originalEvent) { - if(!originalEvent) { - return; - } - return originalEvent.ctrlKey; - }, - which : function (original) { - if(!original) { - return; - } - - return original.charCode != null ? original.charCode : original.keyCode; - } - }; - - // Get all properties that should be mapped - jQuery.each(jQuery.event.keyHooks.props.concat(jQuery.event.mouseHooks.props).concat(jQuery.event.props), function (i, prop) { - if (prop !== "target") { - (function () { - Object.defineProperty(jQuery.Event.prototype, prop, { - get : function () { - // get the original value, undefined when there is no original event - var originalValue = this.originalEvent && this.originalEvent[prop]; - // overwrite getter lookup - return this['_' + prop] !== undefined ? this['_' + prop] : set(this, prop, - // if we have a special function and no value - special[prop] && originalValue === undefined ? - // call the special function - special[prop].call(this, this.originalEvent) : - // use the original value - originalValue) - }, - set : function (newValue) { - // Set the property with underscore prefix - this['_' + prop] = newValue; - } - }); - })(); - } - }); - - jQuery.event.fix = function (event) { - if (event[ jQuery.expando ]) { - return event; - } - // Create a jQuery event with at minimum a target and type set - var originalEvent = event, - event = jQuery.Event(originalEvent); - event.target = originalEvent.target; - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if (!event.target) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if (event.target.nodeType === 3) { - event.target = event.target.parentNode; - } - - return event; - } - } - - return $; -}); diff --git a/event/fastfix/fastfix.md b/event/fastfix/fastfix.md deleted file mode 100644 index 58dd79c4..00000000 --- a/event/fastfix/fastfix.md +++ /dev/null @@ -1,42 +0,0 @@ -@page jQuery.event.fastfix -@parent jquerypp - -`jQuery.event.fastfix` provides a faster `jQuery.event.fix` using ES 5 Getters first introduced in -[this blog post](http://bitovi.com/blog/2012/04/faster-jquery-event-fix.html). - -## How jQuery Normalizes Events - -When an event is received by jQuery, it __normalizes__ the event properties before it -dispatches the event to registered event handlers. __Normalizing__ means, that it makes sure -the event handler properties are the same across all browsers. For example, -IE does not support `event.relatedTarget`, instead IE provides `event.toElement` and `event.fromElement`. -jQuery uses those properties to set a `relatedTarget` property. - -Event handlers won't be receiving the original event. Instead they are getting a new -[jQuery.Event](http://api.jquery.com/category/events/event-object/) object with properties copied from -the raw HTML event. jQuery does this because it can't set properties on a raw HTML event. - -You can get the raw event with `originalEvent` like: - - $("#clickme").bind("click", function( ev ) { - ev.originalEvent - }) - -jQuery creates and normalizes the `jQuery.Event` from the raw event in `jQuery.event.fix`. - -## Using ES5 getters - -`jQuery.event.fastfix` uses ECMAScript 5 getters for browsers that [support Object.defineProperty](http://kangax.github.com/es5-compat-table/), -which allows `jQuery.event.fix` to avoid copying every property and normalizing it for every event. -Instead getters can do this on-demand. That is, they can lookup the `originalEvent`'s value and normalize it if needed. -`jQuery.event.fastfix` goes through the list of properties that `jQuery.event.fix` copies and creates getters for each one. - -In the getter, it checks if that property is special (needs normalizing) and uses that properties special -function to normalize the value. - -## Performance - -A [basic JSPerf](http://jsperf.com/jquery-event-fix/6) of `jQuery.event.fastfix` shows a -3 to 4 times performance improvement compared to the original `jQuery.event.fix`. Since event handling -and `jQuery.event.fix` are usually a major part of the runtime of a jQuery application including `jQuery.event.fastfix` -can bring you significant performance improvements in modern browsers. diff --git a/event/fastfix/fastfix_test.js b/event/fastfix/fastfix_test.js deleted file mode 100644 index 540ec581..00000000 --- a/event/fastfix/fastfix_test.js +++ /dev/null @@ -1,3207 +0,0 @@ -steal("jquery/event/fastfix", - 'funcunit/qunit').then(function () { - - module("jquery/event/fastfix"); - - test("null or undefined handler", function () { - expect(2); - // Supports Fixes bug #7229 - try { - jQuery("#firstp").click(null); - ok(true, "Passing a null handler will not throw an exception"); - } catch (e) { - } - - try { - jQuery("#firstp").click(undefined); - ok(true, "Passing an undefined handler will not throw an exception"); - } catch (e) { - } - }); - - test("bind(),live(),delegate() with non-null,defined data", function () { - - expect(3); - - var handler = function (event, data) { - equal(data, 0, "non-null, defined data (zero) is correctly passed"); - }; - - jQuery("#foo").bind("foo", handler); - jQuery("#foo").live("foo", handler); - jQuery("div").delegate("#foo", "foo", handler); - - jQuery("#foo").trigger("foo", 0); - - jQuery("#foo").unbind("foo", handler); - jQuery("#foo").die("foo", handler); - jQuery("div").undelegate("#foo", "foo"); - - }); - - test("Handler changes and .trigger() order", function () { - expect(1); - - var markup = jQuery( - "

                                        b

                                        " - ), - path = ""; - - markup - .find("*").andSelf().on("click", function (e) { - path += this.nodeName.toLowerCase() + " "; - }) - .filter("b").on("click", function (e) { - // Removing span should not stop propagation to original parents - if (e.target === this) { - jQuery(this).parent().remove(); - } - }); - - markup.find("b").trigger("click"); - - equal(path, "b p div div ", "Delivered all events"); - - markup.remove(); - }); - - test("bind(), with data", function () { - expect(4); - var handler = function (event) { - ok(event.data, "bind() with data, check passed data exists"); - equal(event.data["foo"], "bar", "bind() with data, Check value of passed data"); - }; - jQuery("#firstp").bind("click", {"foo" : "bar"}, handler).click().unbind("click", handler); - - ok(!jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data."); - - var test = function () { - }; - var handler2 = function (event) { - equal(event.data, test, "bind() with function data, Check value of passed data"); - }; - jQuery("#firstp").bind("click", test, handler2).click().unbind("click", handler2); - }); - - test("click(), with data", function () { - expect(3); - var handler = function (event) { - ok(event.data, "bind() with data, check passed data exists"); - equal(event.data["foo"], "bar", "bind() with data, Check value of passed data"); - }; - jQuery("#firstp").click({"foo" : "bar"}, handler).click().unbind("click", handler); - - ok(!jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using data."); - }); - - test("bind(), with data, trigger with data", function () { - expect(4); - var handler = function (event, data) { - ok(event.data, "check passed data exists"); - equal(event.data.foo, "bar", "Check value of passed data"); - ok(data, "Check trigger data"); - equal(data.bar, "foo", "Check value of trigger data"); - }; - jQuery("#firstp").bind("click", {foo : "bar"}, handler).trigger("click", [ - {bar : "foo"} - ]).unbind("click", handler); - }); - - test("bind(), multiple events at once", function () { - expect(2); - var clickCounter = 0, - mouseoverCounter = 0; - var handler = function (event) { - if (event.type == "click") { - clickCounter += 1; - } - else if (event.type == "mouseover") { - mouseoverCounter += 1; - } - - }; - jQuery("#firstp").bind("click mouseover", handler).trigger("click").trigger("mouseover"); - equal(clickCounter, 1, "bind() with multiple events at once"); - equal(mouseoverCounter, 1, "bind() with multiple events at once"); - }); - - test("bind(), five events at once", function () { - expect(1); - - var count = 0, - handler = function (event) { - count++; - }; - - jQuery("#firstp").bind("click mouseover foo bar baz", handler) - .trigger("click").trigger("mouseover") - .trigger("foo").trigger("bar") - .trigger("baz"); - - equal(count, 5, "bind() five events at once"); - }); - - test("bind(), multiple events at once and namespaces", function () { - expect(7); - - var cur, obj = {}; - - var div = jQuery("
                                        ").bind("focusin.a", function (e) { - equal(e.type, cur, "Verify right single event was fired."); - }); - - cur = "focusin"; - div.trigger("focusin.a"); - - // manually clean up detached elements - div.remove(); - - div = jQuery("
                                        ").bind("click mouseover", obj, function (e) { - equal(e.type, cur, "Verify right multi event was fired."); - equal(e.data, obj, "Make sure the data came in correctly."); - }); - - cur = "click"; - div.trigger("click"); - - cur = "mouseover"; - div.trigger("mouseover"); - - // manually clean up detached elements - div.remove(); - - div = jQuery("
                                        ").bind("focusin.a focusout.b", function (e) { - equal(e.type, cur, "Verify right multi event was fired."); - }); - - cur = "focusin"; - div.trigger("focusin.a"); - - cur = "focusout"; - div.trigger("focusout.b"); - - // manually clean up detached elements - div.remove(); - }); - - test("bind(), namespace with special add", function () { - expect(27); - - var div = jQuery("
                                        ").bind("test", function (e) { - ok(true, "Test event fired."); - }); - - var i = 0; - - jQuery.event.special["test"] = { - _default : function (e, data) { - equal(this, document, "Make sure we're at the top of the chain."); - equal(e.type, "test", "And that we're still dealing with a test event."); - equal(e.target, div[0], "And that the target is correct."); - ok(data !== undefined, "And that trigger data was passed."); - }, - setup : function () { - }, - teardown : function () { - ok(true, "Teardown called."); - }, - add : function (handleObj) { - var handler = handleObj.handler; - handleObj.handler = function (e) { - e.xyz = ++i; - handler.apply(this, arguments); - }; - }, - remove : function () { - ok(true, "Remove called."); - } - }; - - div.bind("test.a", {"x" : 1}, function (e) { - ok(!!e.xyz, "Make sure that the data is getting passed through."); - equal(e.data["x"], 1, "Make sure data is attached properly."); - }); - - div.bind("test.b", {"x" : 2}, function (e) { - ok(!!e.xyz, "Make sure that the data is getting passed through."); - equal(e.data["x"], 2, "Make sure data is attached properly."); - }); - - // Should trigger 5 - div.trigger("test", 33.33); - - // Should trigger 2 - div.trigger("test.a", "George Harrison"); - - // Should trigger 2 - div.trigger("test.b", { year : 1982 }); - - // Should trigger 4 - div.unbind("test"); - - div = jQuery("
                                        ").bind("test", function (e) { - ok(true, "Test event fired."); - }); - - // Should trigger 2 - div.appendTo("#qunit-fixture").remove(); - - delete jQuery.event.special["test"]; - }); - - test("bind(), no data", function () { - expect(1); - var handler = function (event) { - ok(!event.data, "Check that no data is added to the event object"); - }; - jQuery("#firstp").bind("click", handler).trigger("click"); - }); - - test("bind/one/unbind(Object)", function () { - expect(6); - - var clickCounter = 0, mouseoverCounter = 0; - - function handler(event) { - if (event.type == "click") { - - clickCounter++; - } - else if (event.type == "mouseover") { - mouseoverCounter++; - } - - } - - function handlerWithData(event) { - if (event.type == "click") { - clickCounter += event.data; - } - else if (event.type == "mouseover") { - mouseoverCounter += event.data; - } - } - - function trigger() { - $elem.trigger("click").trigger("mouseover"); - } - - var $elem = jQuery("#firstp") - // Regular bind - .bind({ - "click" : handler, - "mouseover" : handler - }) - // Bind with data - .one({ - "click" : handlerWithData, - "mouseover" : handlerWithData - }, 2); - - trigger(); - - equal(clickCounter, 3, "bind(Object)"); - equal(mouseoverCounter, 3, "bind(Object)"); - - trigger(); - equal(clickCounter, 4, "bind(Object)"); - equal(mouseoverCounter, 4, "bind(Object)"); - - jQuery("#firstp").unbind({ - "click" : handler, - "mouseover" : handler - }); - - trigger(); - equal(clickCounter, 4, "bind(Object)"); - equal(mouseoverCounter, 4, "bind(Object)"); - }); - - test("live/die(Object), delegate/undelegate(String, Object)", function () { - expect(6); - - var clickCounter = 0, mouseoverCounter = 0, - $p = jQuery("#firstp"), $a = $p.find("a:first"); - - var events = { - "click" : function (event) { - clickCounter += ( event.data || 1 ); - }, - "mouseover" : function (event) { - mouseoverCounter += ( event.data || 1 ); - } - }; - - function trigger() { - $a.trigger("click").trigger("mouseover"); - } - - $a.live(events); - $p.delegate("a", events, 2); - - trigger(); - equal(clickCounter, 3, "live/delegate"); - equal(mouseoverCounter, 3, "live/delegate"); - - $p.undelegate("a", events); - - trigger(); - equal(clickCounter, 4, "undelegate"); - equal(mouseoverCounter, 4, "undelegate"); - - $a.die(events); - - trigger(); - equal(clickCounter, 4, "die"); - equal(mouseoverCounter, 4, "die"); - }); - - test("live/delegate immediate propagation", function () { - expect(2); - - var $p = jQuery("#firstp"), $a = $p.find("a:first"), lastClick; - - lastClick = ""; - $a.live("click", function (e) { - lastClick = "click1"; - e.stopImmediatePropagation(); - }); - $a.live("click", function (e) { - lastClick = "click2"; - }); - $a.trigger("click"); - equal(lastClick, "click1", "live stopImmediatePropagation"); - $a.die("click"); - - lastClick = ""; - $p.delegate("a", "click", function (e) { - lastClick = "click1"; - e.stopImmediatePropagation(); - }); - $p.delegate("a", "click", function (e) { - lastClick = "click2"; - }); - $a.trigger("click"); - equal(lastClick, "click1", "delegate stopImmediatePropagation"); - $p.undelegate("click"); - }); - - test("bind/delegate bubbling, isDefaultPrevented", function () { - expect(2); - var $anchor2 = jQuery("#anchor2"), - $main = jQuery("#qunit-fixture"), - fakeClick = function ($jq) { - // Use a native click so we don't get jQuery simulated bubbling - if (document.createEvent) { - var e = document.createEvent("MouseEvents"); - e.initEvent("click", true, true); - $jq[0].dispatchEvent(e); - } - else if ($jq[0].click) { - $jq[0].click(); // IE - } - }; - $anchor2.click(function (e) { - e.preventDefault(); - }); - $main.delegate("#foo", "click", function (e) { - var orig = e.originalEvent; - - if (typeof(orig.defaultPrevented) === "boolean" || typeof(orig.returnValue) === "boolean" || orig["getPreventDefault"]) { - equal(e.isDefaultPrevented(), true, "isDefaultPrevented true passed to bubbled event"); - - } else { - // Opera < 11 doesn't implement any interface we can use, so give it a pass - ok(true, "isDefaultPrevented not supported by this browser, test skipped"); - } - }); - fakeClick($anchor2); - $anchor2.unbind("click"); - $main.undelegate("click"); - $anchor2.click(function (e) { - // Let the default action occur - }); - $main.delegate("#foo", "click", function (e) { - equal(e.isDefaultPrevented(), false, "isDefaultPrevented false passed to bubbled event"); - }); - fakeClick($anchor2); - $anchor2.unbind("click"); - $main.undelegate("click"); - }); - - test("bind(), iframes", function () { - // events don't work with iframes, see #939 - this test fails in IE because of contentDocument - var doc = jQuery("#loadediframe").contents(); - - jQuery("div", doc).bind("click",function () { - ok(true, "Binding to element inside iframe"); - }).click().unbind("click"); - }); - - test("bind(), trigger change on select", function () { - expect(5); - var counter = 0; - - function selectOnChange(event) { - equal(event.data, counter++, "Event.data is not a global event object"); - } - - jQuery("#form select").each(function (i) { - jQuery(this).bind("change", i, selectOnChange); - }).trigger("change"); - }); - - test("bind(), namespaced events, cloned events", 18, function () { - var firstp = jQuery("#firstp"); - - firstp.bind("custom.test", function (e) { - ok(false, "Custom event triggered"); - }); - - firstp.bind("click", function (e) { - ok(true, "Normal click triggered"); - equal(e.type + e.namespace, "click", "Check that only click events trigger this fn"); - }); - - firstp.bind("click.test", function (e) { - var check = "click"; - ok(true, "Namespaced click triggered"); - if (e.namespace) { - check += "test"; - } - equal(e.type + e.namespace, check, "Check that only click/click.test events trigger this fn"); - }); - - //clone(true) element to verify events are cloned correctly - firstp = firstp.add(firstp.clone(true).attr("id", "firstp2").insertBefore(firstp)); - - // Trigger both bound fn (8) - firstp.trigger("click"); - - // Trigger one bound fn (4) - firstp.trigger("click.test"); - - // Remove only the one fn - firstp.unbind("click.test"); - - // Trigger the remaining fn (4) - firstp.trigger("click"); - - // Remove the remaining namespaced fn - firstp.unbind(".test"); - - // Try triggering the custom event (0) - firstp.trigger("custom"); - - // using contents will get comments regular, text, and comment nodes - jQuery("#nonnodes").contents().bind("tester",function () { - equal(this.nodeType, 1, "Check node,textnode,comment bind just does real nodes"); - }).trigger("tester"); - - // Make sure events stick with appendTo'd elements (which are cloned) #2027 - jQuery("test").click(function () { - return false; - }).appendTo("#qunit-fixture"); - ok(jQuery("a.test:first").triggerHandler("click") === false, "Handler is bound to appendTo'd elements"); - }); - - test("bind(), multi-namespaced events", function () { - expect(6); - - var order = [ - "click.test.abc", - "click.test.abc", - "click.test", - "click.test.abc", - "click.test", - "custom.test2" - ]; - - function check(name, msg) { - deepEqual(name, order.shift(), msg); - } - - jQuery("#firstp").bind("custom.test", function (e) { - check("custom.test", "Custom event triggered"); - }); - - jQuery("#firstp").bind("custom.test2", function (e) { - check("custom.test2", "Custom event triggered"); - }); - - jQuery("#firstp").bind("click.test", function (e) { - check("click.test", "Normal click triggered"); - }); - - jQuery("#firstp").bind("click.test.abc", function (e) { - check("click.test.abc", "Namespaced click triggered"); - }); - - // Those would not trigger/unbind (#5303) - jQuery("#firstp").trigger("click.a.test"); - jQuery("#firstp").unbind("click.a.test"); - - // Trigger both bound fn (1) - jQuery("#firstp").trigger("click.test.abc"); - - // Trigger one bound fn (1) - jQuery("#firstp").trigger("click.abc"); - - // Trigger two bound fn (2) - jQuery("#firstp").trigger("click.test"); - - // Remove only the one fn - jQuery("#firstp").unbind("click.abc"); - - // Trigger the remaining fn (1) - jQuery("#firstp").trigger("click"); - - // Remove the remaining fn - jQuery("#firstp").unbind(".test"); - - // Trigger the remaining fn (1) - jQuery("#firstp").trigger("custom"); - }); - - test("bind(), with same function", function () { - expect(2); - - var count = 0, func = function () { - count++; - }; - - jQuery("#liveHandlerOrder").bind("foo.bar", func).bind("foo.zar", func); - jQuery("#liveHandlerOrder").trigger("foo.bar"); - - equal(count, 1, "Verify binding function with multiple namespaces."); - - jQuery("#liveHandlerOrder").unbind("foo.bar", func).unbind("foo.zar", func); - jQuery("#liveHandlerOrder").trigger("foo.bar"); - - equal(count, 1, "Verify that removing events still work."); - }); - - test("bind(), make sure order is maintained", function () { - expect(1); - - var elem = jQuery("#firstp"), log = [], check = []; - - jQuery.each(new Array(100), function (i) { - elem.bind("click", function () { - log.push(i); - }); - - check.push(i); - - }); - - elem.trigger("click"); - - equal(log.join(","), check.join(","), "Make sure order was maintained."); - - elem.unbind("click"); - }); - - test("bind(), with different this object", function () { - expect(4); - var thisObject = { myThis : true }, - data = { myData : true }, - handler1 = function (event) { - equal(this, thisObject, "bind() with different this object"); - }, - handler2 = function (event) { - equal(this, thisObject, "bind() with different this object and data"); - equal(event.data, data, "bind() with different this object and data"); - }; - - jQuery("#firstp") - .bind("click", jQuery.proxy(handler1, thisObject)).click().unbind("click", handler1) - .bind("click", data, jQuery.proxy(handler2, thisObject)).click().unbind("click", handler2); - - ok(!jQuery._data(jQuery("#firstp")[0], "events"), "Event handler unbound when using different this object and data."); - }); - - test("bind(name, false), unbind(name, false)", function () { - expect(3); - - var main = 0; - jQuery("#qunit-fixture").bind("click", function (e) { - main++; - }); - jQuery("#ap").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - - main = 0; - jQuery("#ap").bind("click", false); - jQuery("#ap").trigger("click"); - equal(main, 0, "Verify that no bubble happened."); - - main = 0; - jQuery("#ap").unbind("click", false); - jQuery("#ap").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - - // manually clean up events from elements outside the fixture - jQuery("#qunit-fixture").unbind("click"); - }); - - test("live(name, false), die(name, false)", function () { - expect(3); - - var main = 0; - jQuery("#qunit-fixture").live("click", function (e) { - main++; - }); - jQuery("#ap").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - - main = 0; - jQuery("#ap").live("click", false); - jQuery("#ap").trigger("click"); - equal(main, 0, "Verify that no bubble happened."); - - main = 0; - jQuery("#ap").die("click", false); - jQuery("#ap").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - jQuery("#qunit-fixture").die("click"); - }); - - test("delegate(selector, name, false), undelegate(selector, name, false)", function () { - expect(3); - - var main = 0; - - jQuery("#qunit-fixture").delegate("#ap", "click", function (e) { - main++; - }); - jQuery("#ap").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - - main = 0; - jQuery("#ap").delegate("#groups", "click", false); - jQuery("#groups").trigger("click"); - equal(main, 0, "Verify that no bubble happened."); - - main = 0; - jQuery("#ap").undelegate("#groups", "click", false); - jQuery("#groups").trigger("click"); - equal(main, 1, "Verify that the trigger happened correctly."); - jQuery("#qunit-fixture").undelegate("#ap", "click"); - }); - - test("bind()/trigger()/unbind() on plain object", function () { - expect(7); - - var obj = {}; - - // Make sure it doesn't complain when no events are found - jQuery(obj).trigger("test"); - - // Make sure it doesn't complain when no events are found - jQuery(obj).unbind("test"); - - jQuery(obj).bind({ - "test" : function () { - ok(true, "Custom event run."); - }, - "submit" : function () { - ok(true, "Custom submit event run."); - } - }); - - var events = jQuery._data(obj, "events"); - ok(events, "Object has events bound."); - equal(obj["events"], undefined, "Events object on plain objects is not events"); - equal(obj["test"], undefined, "Make sure that test event is not on the plain object."); - equal(obj["handle"], undefined, "Make sure that the event handler is not on the plain object."); - - // Should trigger 1 - jQuery(obj).trigger("test"); - jQuery(obj).trigger("submit"); - - jQuery(obj).unbind("test"); - jQuery(obj).unbind("submit"); - - // Should trigger 0 - jQuery(obj).trigger("test"); - - // Make sure it doesn't complain when no events are found - jQuery(obj).unbind("test"); - - equal(obj && obj[ jQuery.expando ] && - obj[ jQuery.expando ][ jQuery.expando ] && - obj[ jQuery.expando ][ jQuery.expando ]["events"], undefined, "Make sure events object is removed"); - }); - - test("unbind(type)", function () { - expect(1); - - var $elem = jQuery("#firstp"), - message; - - function error() { - ok(false, message); - } - - message = "unbind passing function"; - $elem.bind("error1", error).unbind("error1", error).triggerHandler("error1"); - - message = "unbind all from event"; - $elem.bind("error1", error).unbind("error1").triggerHandler("error1"); - - message = "unbind all"; - $elem.bind("error1", error).unbind().triggerHandler("error1"); - - message = "unbind many with function"; - $elem.bind("error1 error2", error) - .unbind("error1 error2", error) - .trigger("error1").triggerHandler("error2"); - - message = "unbind many"; // #3538 - $elem.bind("error1 error2", error) - .unbind("error1 error2") - .trigger("error1").triggerHandler("error2"); - - message = "unbind without a type or handler"; - $elem.bind("error1 error2.test", error) - .unbind() - .trigger("error1").triggerHandler("error2"); - - // Should only unbind the specified function - jQuery(document).bind("click", function () { - ok(true, "called handler after selective removal"); - }); - var func = function () { - }; - jQuery(document) - .bind("click", func) - .unbind("click", func) - .click() - .unbind("click"); - }); - - test("unbind(eventObject)", function () { - expect(4); - - var $elem = jQuery("#firstp"), - num; - - function assert(expected) { - num = 0; - $elem.trigger("foo").triggerHandler("bar"); - equal(num, expected, "Check the right handlers are triggered"); - } - - $elem - // This handler shouldn't be unbound - .bind("foo", function () { - num += 1; - }) - .bind("foo", function (e) { - $elem.unbind(e); - num += 2; - }) - // Neither this one - .bind("bar", function () { - num += 4; - }); - - assert(7); - assert(5); - - $elem.unbind("bar"); - assert(1); - - $elem.unbind(); - assert(0); - }); - - test("hover() and hover pseudo-event", function () { - expect(3); - - var times = 0, - handler1 = function (event) { - ++times; - }, - handler2 = function (event) { - ++times; - }; - - jQuery("#firstp") - .hover(handler1, handler2) - .mouseenter().mouseleave() - .unbind("mouseenter", handler1) - .unbind("mouseleave", handler2) - .hover(handler1) - .mouseenter().mouseleave() - .unbind("mouseenter mouseleave", handler1) - .mouseenter().mouseleave(); - - equal(times, 4, "hover handlers fired"); - - var balance = 0; - jQuery("#firstp") - .on("hovercraft", function () { - ok(false, "hovercraft is full of ills"); - }) - .on("click.hover.me.not", function (e) { - equal(e.handleObj.namespace, "hover.me.not", "hover hack doesn't mangle namespaces"); - }) - .bind("hover", function (e) { - if (e.type === "mouseenter") { - balance++; - } else if (e.type === "mouseleave") { - balance--; - } else { - ok(false, "hover pseudo: unknown event type " + e.type); - } - }) - .trigger("click") - .trigger("mouseenter") - .trigger("mouseleave") - .unbind("hover") - .trigger("mouseenter"); - - equal(balance, 0, "hover pseudo-event"); - }); - - test("mouseover triggers mouseenter", function () { - expect(1); - - var count = 0, - elem = jQuery(""); - elem.mouseenter(function () { - count++; - }); - elem.trigger("mouseover"); - equal(count, 1, "make sure mouseover triggers a mouseenter"); - - elem.remove(); - }); - - test("withinElement implemented with jQuery.contains()", function () { - - expect(1); - - jQuery("#qunit-fixture").append('
                                        '); - - jQuery("#jc-outer").bind("mouseenter mouseleave",function (event) { - - equal(this.id, "jc-outer", this.id + " " + event.type); - - }).trigger("mouseenter"); - - jQuery("#jc-inner").trigger("mousenter"); - - jQuery("#jc-outer").unbind("mouseenter mouseleave").remove(); - jQuery("#jc-inner").remove(); - - }); - - test("mouseenter, mouseleave don't catch exceptions", function () { - expect(2); - - var elem = jQuery("#firstp").hover(function () { - throw "an Exception"; - }); - - try { - elem.mouseenter(); - } catch (e) { - equal(e, "an Exception", "mouseenter doesn't catch exceptions"); - } - - try { - elem.mouseleave(); - } catch (e) { - equal(e, "an Exception", "mouseleave doesn't catch exceptions"); - } - }); - - test("trigger() shortcuts", function () { - expect(6); - - var elem = jQuery("
                                      1. Change location
                                      2. ").prependTo("#firstUL"); - elem.find("a").bind("click",function () { - var close = jQuery("spanx", this); // same with jQuery(this).find("span"); - equal(close.length, 0, "Context element does not exist, length must be zero"); - ok(!close[0], "Context element does not exist, direct access to element must return undefined"); - return false; - }).click(); - - // manually clean up detached elements - elem.remove(); - - jQuery("#check1").click(function () { - ok(true, "click event handler for checkbox gets fired twice, see #815"); - }).click(); - - var counter = 0; - jQuery("#firstp")[0].onclick = function (event) { - counter++; - }; - jQuery("#firstp").click(); - equal(counter, 1, "Check that click, triggers onclick event handler also"); - - var clickCounter = 0; - jQuery("#simon1")[0].onclick = function (event) { - clickCounter++; - }; - jQuery("#simon1").click(); - equal(clickCounter, 1, "Check that click, triggers onclick event handler on an a tag also"); - - elem = jQuery("").load(function () { - ok(true, "Trigger the load event, using the shortcut .load() (#2819)"); - }).load(); - - // manually clean up detached elements - elem.remove(); - - // test that special handlers do not blow up with VML elements (#7071) - jQuery('').appendTo('head'); - jQuery(' ').appendTo('#form'); - jQuery("#oval").click().keydown(); - }); - - test("trigger() bubbling", function () { - expect(18); - - var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0; - - jQuery(window).bind("click", function (e) { - win++; - }); - jQuery(document).bind("click", function (e) { - if (e.target !== document) { - doc++; - } - }); - jQuery("html").bind("click", function (e) { - html++; - }); - jQuery("body").bind("click", function (e) { - body++; - }); - jQuery("#qunit-fixture").bind("click", function (e) { - main++; - }); - jQuery("#ap").bind("click", function () { - ap++; - return false; - }); - - jQuery("html").trigger("click"); - equal(win, 1, "HTML bubble"); - equal(doc, 1, "HTML bubble"); - equal(html, 1, "HTML bubble"); - - jQuery("body").trigger("click"); - equal(win, 2, "Body bubble"); - equal(doc, 2, "Body bubble"); - equal(html, 2, "Body bubble"); - equal(body, 1, "Body bubble"); - - jQuery("#qunit-fixture").trigger("click"); - equal(win, 3, "Main bubble"); - equal(doc, 3, "Main bubble"); - equal(html, 3, "Main bubble"); - equal(body, 2, "Main bubble"); - equal(main, 1, "Main bubble"); - - jQuery("#ap").trigger("click"); - equal(doc, 3, "ap bubble"); - equal(html, 3, "ap bubble"); - equal(body, 2, "ap bubble"); - equal(main, 1, "ap bubble"); - equal(ap, 1, "ap bubble"); - - jQuery(document).trigger("click"); - equal(win, 4, "doc bubble"); - - // manually clean up events from elements outside the fixture - jQuery(document).unbind("click"); - jQuery("html, body, #qunit-fixture").unbind("click"); - }); - - test("trigger(type, [data], [fn])", function () { - expect(16); - - var handler = function (event, a, b, c) { - equal(event.type, "click", "check passed data"); - equal(a, 1, "check passed data"); - equal(b, "2", "check passed data"); - equal(c, "abc", "check passed data"); - return "test"; - }; - - var $elem = jQuery("#firstp"); - - // Simulate a "native" click - $elem[0].click = function () { - ok(true, "Native call was triggered"); - }; - - - $elem.live('mouseenter', function () { - ok(true, 'Trigger mouseenter bound by live'); - }); - - $elem.live('mouseleave', function () { - ok(true, 'Trigger mouseleave bound by live'); - }); - - $elem.trigger('mouseenter'); - - $elem.trigger('mouseleave'); - - $elem.die('mouseenter'); - - $elem.die('mouseleave'); - - // Triggers handlrs and native - // Trigger 5 - $elem.bind("click", handler).trigger("click", [1, "2", "abc"]); - - // Simulate a "native" click - $elem[0].click = function () { - ok(false, "Native call was triggered"); - }; - - // Trigger only the handlers (no native) - // Triggers 5 - equal($elem.triggerHandler("click", [1, "2", "abc"]), "test", "Verify handler response"); - - var pass = true, elem2; - try { - elem2 = jQuery("#form input:first"); - elem2.get(0).style.display = "none"; - elem2.trigger("focus"); - } catch (e) { - pass = false; - } - ok(pass, "Trigger focus on hidden element"); - - pass = true; - try { - jQuery("#qunit-fixture table:first").bind("test:test",function () { - }).trigger("test:test"); - } catch (e) { - pass = false; - } - ok(pass, "Trigger on a table with a colon in the even type, see #3533"); - - var form = jQuery("
                                        ").appendTo("body"); - - // Make sure it can be prevented locally - form.submit(function () { - ok(true, "Local bind still works."); - return false; - }); - - // Trigger 1 - form.trigger("submit"); - - form.unbind("submit"); - - jQuery(document).submit(function () { - ok(true, "Make sure bubble works up to document."); - return false; - }); - - // Trigger 1 - form.trigger("submit"); - - jQuery(document).unbind("submit"); - - form.remove(); - }); - - test("submit event bubbles on copied forms (#11649)", function () { - expect(3); - - var $formByClone, $formByHTML, - $testForm = jQuery("#testForm"), - $fixture = jQuery("#qunit-fixture"), - $wrapperDiv = jQuery("
                                        ").appendTo($fixture); - - function noSubmit(e) { - e.preventDefault(); - } - - function delegatedSubmit() { - ok(true, "Make sure submit event bubbles up."); - return false; - } - - // Attach a delegated submit handler to the parent element - $fixture.on("submit", "form", delegatedSubmit); - - // Trigger form submission to introduce the _submit_attached property - $testForm.on("submit", noSubmit).find("input[name=sub1]").click(); - - // Copy the form via .clone() and .html() - $formByClone = $testForm.clone(true, true).removeAttr("id"); - $formByHTML = jQuery($fixture.html()).filter("#testForm").removeAttr("id"); - $wrapperDiv.append($formByClone, $formByHTML); - - // Check submit bubbling on the copied forms - $wrapperDiv.find("form").on("submit", noSubmit).find("input[name=sub1]").click(); - - // Clean up - $wrapperDiv.remove(); - $fixture.off("submit", "form", delegatedSubmit); - $testForm.off("submit", noSubmit); - }); - - test("change event bubbles on copied forms (#11796)", function () { - expect(3); - - var $formByClone, $formByHTML, - $form = jQuery("#form"), - $fixture = jQuery("#qunit-fixture"), - $wrapperDiv = jQuery("
                                        ").appendTo($fixture); - - function delegatedChange() { - ok(true, "Make sure change event bubbles up."); - return false; - } - - // Attach a delegated change handler to the form - $fixture.on("change", "form", delegatedChange); - - // Trigger change event to introduce the _change_attached property - $form.find("select[name=select1]").val("1").change(); - - // Copy the form via .clone() and .html() - $formByClone = $form.clone(true, true).removeAttr("id"); - $formByHTML = jQuery($fixture.html()).filter("#form").removeAttr("id"); - $wrapperDiv.append($formByClone, $formByHTML); - - // Check change bubbling on the copied forms - $wrapperDiv.find("form select[name=select1]").val("2").change(); - - // Clean up - $wrapperDiv.remove(); - $fixture.off("change", "form", delegatedChange); - }); - - test("trigger(eventObject, [data], [fn])", function () { - expect(28); - - var $parent = jQuery("
                                        ").appendTo("body"), - $child = jQuery("

                                        foo

                                        ").appendTo($parent); - - $parent.get(0).style.display = "none"; - - var event = jQuery.Event("noNew"); - ok(event != window, "Instantiate jQuery.Event without the 'new' keyword"); - equal(event.type, "noNew", "Verify its type"); - - equal(event.isDefaultPrevented(), false, "Verify isDefaultPrevented"); - equal(event.isPropagationStopped(), false, "Verify isPropagationStopped"); - equal(event.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped"); - - event.preventDefault(); - equal(event.isDefaultPrevented(), true, "Verify isDefaultPrevented"); - event.stopPropagation(); - equal(event.isPropagationStopped(), true, "Verify isPropagationStopped"); - - event.isPropagationStopped = function () { - return false; - }; - event.stopImmediatePropagation(); - equal(event.isPropagationStopped(), true, "Verify isPropagationStopped"); - equal(event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped"); - - $parent.bind("foo", function (e) { - // Tries bubbling - equal(e.type, "foo", "Verify event type when passed passing an event object"); - equal(e.target.id, "child", "Verify event.target when passed passing an event object"); - equal(e.currentTarget.id, "par", "Verify event.currentTarget when passed passing an event object"); - equal(e.secret, "boo!", "Verify event object's custom attribute when passed passing an event object"); - }); - - // test with an event object - event = new jQuery.Event("foo"); - event.secret = "boo!"; - $child.trigger(event); - - // test with a literal object - $child.trigger({"type" : "foo", "secret" : "boo!"}); - - $parent.unbind(); - - function error() { - ok(false, "This assertion shouldn't be reached"); - } - - $parent.bind("foo", error); - - $child.bind("foo", function (e, a, b, c) { - equal(arguments.length, 4, "Check arguments length"); - equal(a, 1, "Check first custom argument"); - equal(b, 2, "Check second custom argument"); - equal(c, 3, "Check third custom argument"); - - equal(e.isDefaultPrevented(), false, "Verify isDefaultPrevented"); - equal(e.isPropagationStopped(), false, "Verify isPropagationStopped"); - equal(e.isImmediatePropagationStopped(), false, "Verify isImmediatePropagationStopped"); - - // Skips both errors - e.stopImmediatePropagation(); - - return "result"; - }); - - // We should add this back in when we want to test the order - // in which event handlers are iterated. - //$child.bind("foo", error ); - - event = new jQuery.Event("foo"); - $child.trigger(event, [1, 2, 3]).unbind(); - equal(event.result, "result", "Check event.result attribute"); - - // Will error if it bubbles - $child.triggerHandler("foo"); - - $child.unbind(); - $parent.unbind().remove(); - - // Ensure triggerHandler doesn't molest its event object (#xxx) - event = jQuery.Event("zowie"); - jQuery(document).triggerHandler(event); - equal(event.type, "zowie", "Verify its type"); - equal(event.isPropagationStopped(), false, "propagation not stopped"); - equal(event.isDefaultPrevented(), false, "default not prevented"); - }); - - test(".trigger() bubbling on disconnected elements (#10489)", function () { - expect(2); - - jQuery(window).on("click", function () { - ok(false, "click fired on window"); - }); - - jQuery("

                                        hi

                                        ") - .on("click", function () { - ok(true, "click fired on div"); - }) - .find("p") - .on("click", function () { - ok(true, "click fired on p"); - }) - .click() - .off("click") - .end() - .off("click") - .remove(); - - jQuery(window).off("click"); - }); - - test(".trigger() doesn't bubble load event (#10717)", function () { - expect(1); - - jQuery(window).on("load", function () { - ok(false, "load fired on window"); - }); - - // It's not an image, but as long as it fires load... - jQuery('') - .appendTo("body") - .on("load", function () { - ok(true, "load fired on img"); - }) - .trigger("load") - .remove(); - - jQuery(window).off("load"); - }); - - test("Delegated events in SVG (#10791)", function () { - expect(2); - - var svg = jQuery( - '' + - '' + - '' + - '' - ).appendTo("body"); - - jQuery("body") - .on("click", "#svg-by-id", function () { - ok(true, "delegated id selector"); - }) - .on("click", "[class~='svg-by-class']", function () { - ok(true, "delegated class selector"); - }) - .find("#svg-by-id, [class~='svg-by-class']") - .trigger("click") - .end() - .off("click"); - - svg.remove(); - }); - - test("Delegated events in forms (#10844; #11145; #8165; #11382, #11764)", function () { - expect(5); - - // Alias names like "id" cause havoc - var form = jQuery( - '
                                        ' + - '' + - '
                                        ' - ) - .on("submit", function (event) { - event.preventDefault(); - }) - .appendTo("body"); - - jQuery("body") - .on("submit", "#myform", function () { - ok(true, "delegated id selector with aliased id"); - }) - .find("#myform") - .trigger("submit") - .end() - .off("submit"); - - form.append(''); - jQuery("body") - .on("submit", "#myform", function () { - ok(true, "delegated id selector with aliased disabled"); - }) - .find("#myform") - .trigger("submit") - .end() - .off("submit"); - - form - .append('') - .on("click", "#nestyDisabledBtn", function () { - ok(true, "click on enabled/disabled button with nesty elements"); - }) - .on("mouseover", "#nestyDisabledBtn", function () { - ok(true, "mouse on enabled/disabled button with nesty elements"); - }) - .find("span") - .trigger("click")// yep - .trigger("mouseover")// yep - .end() - .find("#nestyDisabledBtn").prop("disabled", true).end() - .find("span") - .trigger("click")// nope - .trigger("mouseover")// yep - .end() - .off("click"); - - form.remove(); - }); - - test("Submit event can be stopped (#11049)", function () { - expect(1); - - // Since we manually bubble in IE, make sure inner handlers get a chance to cancel - var form = jQuery( - '
                                        ' + - '' + - '' + - '
                                        ' - ) - .appendTo("body"); - - jQuery("body") - .on("submit", function () { - ok(true, "submit bubbled on first handler"); - return false; - }) - .find("#myform input[type=submit]") - .each(function () { - this.click(); - }) - .end() - .on("submit", function () { - ok(false, "submit bubbled on second handler"); - return false; - }) - .find("#myform input[type=submit]") - .each(function () { - jQuery(this.form).on("submit", function (e) { - e.preventDefault(); - e.stopPropagation(); - }); - this.click(); - }) - .end() - .off("submit"); - - form.remove(); - }); - - test("on(beforeunload) creates/deletes window property instead of adding/removing event listener", function () { - expect(3); - - equal(window.onbeforeunload, null, "window property is null/undefined up until now"); - - var handle = function () { - }; - jQuery(window).on("beforeunload", handle); - - equal(typeof window.onbeforeunload, "function", "window property is set to a function"); - - jQuery(window).off("beforeunload", handle); - - equal(window.onbeforeunload, null, "window property has been unset to null/undefined"); - }); - - test("jQuery.Event( type, props )", function () { - - expect(5); - - var event = jQuery.Event("keydown", { keyCode : 64 }), - handler = function (event) { - ok("keyCode" in event, "Special property 'keyCode' exists"); - equal(event.keyCode, 64, "event.keyCode has explicit value '64'"); - }; - - // Supports jQuery.Event implementation - equal(event.type, "keydown", "Verify type"); - - // ensure "type" in props won't clobber the one set by constructor - equal(jQuery.inArray("type", jQuery.event.props), -1, "'type' property not in props (#10375)"); - - ok("keyCode" in event, "Special 'keyCode' property exists"); - - jQuery("body").bind("keydown", handler).trigger(event); - - jQuery("body").unbind("keydown"); - - }); - - test("jQuery.Event.currentTarget", function () { - expect(2); - - jQuery("

                                        ") - .on("click", "p", function (e) { - equal(e.currentTarget, this, "Check delegated currentTarget on event"); - }) - .find("button") - .on("click", function (e) { - equal(e.currentTarget, this, "Check currentTarget on event"); - }) - .click() - .off("click") - .end() - .off("click"); - }); - - test("toggle(Function, Function, ...)", function () { - expect(16); - - var count = 0, - fn1 = function (e) { - count++; - }, - fn2 = function (e) { - count--; - }, - preventDefault = function (e) { - e.preventDefault(); - }, - link = jQuery("#mark"); - link.click(preventDefault).click().toggle(fn1, fn2).click().click().click().click().click(); - equal(count, 1, "Check for toggle(fn, fn)"); - - jQuery("#firstp").toggle(function () { - equal(arguments.length, 4, "toggle correctly passes through additional triggered arguments, see #1701"); - },function () { - }).trigger("click", [ 1, 2, 3 ]); - - var first = 0; - jQuery("#simon1").one("click",function () { - ok(true, "Execute event only once"); - jQuery(this).toggle(function () { - equal(first++, 0, "toggle(Function,Function) assigned from within one('xxx'), see #1054"); - }, function () { - equal(first, 1, "toggle(Function,Function) assigned from within one('xxx'), see #1054"); - }); - return false; - }).click().click().click(); - - var turn = 0; - var fns = [ - function () { - turn = 1; - }, - function () { - turn = 2; - }, - function () { - turn = 3; - } - ]; - - var $div = jQuery("
                                         
                                        ").toggle(fns[0], fns[1], fns[2]); - $div.click(); - equal(turn, 1, "Trying toggle with 3 functions, attempt 1 yields 1"); - $div.click(); - equal(turn, 2, "Trying toggle with 3 functions, attempt 2 yields 2"); - $div.click(); - equal(turn, 3, "Trying toggle with 3 functions, attempt 3 yields 3"); - $div.click(); - equal(turn, 1, "Trying toggle with 3 functions, attempt 4 yields 1"); - $div.click(); - equal(turn, 2, "Trying toggle with 3 functions, attempt 5 yields 2"); - - $div.unbind("click", fns[0]); - var data = jQuery._data($div[0], "events"); - ok(!data, "Unbinding one function from toggle unbinds them all"); - - // manually clean up detached elements - $div.remove(); - - // Test Multi-Toggles - var a = [], b = []; - $div = jQuery("
                                        "); - $div.toggle(function () { - a.push(1); - }, function () { - a.push(2); - }); - $div.click(); - deepEqual(a, [1], "Check that a click worked."); - - $div.toggle(function () { - b.push(1); - }, function () { - b.push(2); - }); - $div.click(); - deepEqual(a, [1, 2], "Check that a click worked with a second toggle."); - deepEqual(b, [1], "Check that a click worked with a second toggle."); - - $div.click(); - deepEqual(a, [1, 2, 1], "Check that a click worked with a second toggle, second click."); - deepEqual(b, [1, 2], "Check that a click worked with a second toggle, second click."); - - // manually clean up detached elements - $div.remove(); - }); - - test(".live()/.die()", function () { - expect(66); - - var submit = 0, div = 0, livea = 0, liveb = 0; - - jQuery("div").live("submit", function () { - submit++; - return false; - }); - jQuery("div").live("click", function () { - div++; - }); - jQuery("div#nothiddendiv").live("click", function () { - livea++; - }); - jQuery("div#nothiddendivchild").live("click", function () { - liveb++; - }); - - // Nothing should trigger on the body - jQuery("body").trigger("click"); - equal(submit, 0, "Click on body"); - equal(div, 0, "Click on body"); - equal(livea, 0, "Click on body"); - equal(liveb, 0, "Click on body"); - - // This should trigger two events - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendiv").trigger("click"); - equal(submit, 0, "Click on div"); - equal(div, 1, "Click on div"); - equal(livea, 1, "Click on div"); - equal(liveb, 0, "Click on div"); - - // This should trigger three events (w/ bubbling) - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "Click on inner div"); - equal(div, 2, "Click on inner div"); - equal(livea, 1, "Click on inner div"); - equal(liveb, 1, "Click on inner div"); - - // This should trigger one submit - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("submit"); - equal(submit, 1, "Submit on div"); - equal(div, 0, "Submit on div"); - equal(livea, 0, "Submit on div"); - equal(liveb, 0, "Submit on div"); - - // Make sure no other events were removed in the process - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "die Click on inner div"); - equal(div, 2, "die Click on inner div"); - equal(livea, 1, "die Click on inner div"); - equal(liveb, 1, "die Click on inner div"); - - // Now make sure that the removal works - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").die("click"); - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "die Click on inner div"); - equal(div, 2, "die Click on inner div"); - equal(livea, 1, "die Click on inner div"); - equal(liveb, 0, "die Click on inner div"); - - // Make sure that the click wasn't removed too early - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendiv").trigger("click"); - equal(submit, 0, "die Click on inner div"); - equal(div, 1, "die Click on inner div"); - equal(livea, 1, "die Click on inner div"); - equal(liveb, 0, "die Click on inner div"); - - // Make sure that stopPropgation doesn't stop live events - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").live("click", function (e) { - liveb++; - e.stopPropagation(); - }); - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "stopPropagation Click on inner div"); - equal(div, 1, "stopPropagation Click on inner div"); - equal(livea, 0, "stopPropagation Click on inner div"); - equal(liveb, 1, "stopPropagation Click on inner div"); - - // Make sure click events only fire with primary click - submit = 0; - div = 0; - livea = 0; - liveb = 0; - var event = jQuery.Event("click"); - event.button = 1; - jQuery("div#nothiddendiv").trigger(event); - - equal(livea, 0, "live secondary click"); - - jQuery("div#nothiddendivchild").die("click"); - jQuery("div#nothiddendiv").die("click"); - jQuery("div").die("click"); - jQuery("div").die("submit"); - - // Test binding with a different context - var clicked = 0, container = jQuery("#qunit-fixture")[0]; - jQuery("#foo", container).live("click", function (e) { - clicked++; - }); - jQuery("div").trigger("click"); - jQuery("#foo").trigger("click"); - jQuery("#qunit-fixture").trigger("click"); - jQuery("body").trigger("click"); - equal(clicked, 2, "live with a context"); - - // Test unbinding with a different context - jQuery("#foo", container).die("click"); - jQuery("#foo").trigger("click"); - equal(clicked, 2, "die with a context"); - - // Test binding with event data - jQuery("#foo").live("click", true, function (e) { - equal(e.data, true, "live with event data"); - }); - jQuery("#foo").trigger("click").die("click"); - - // Test binding with trigger data - jQuery("#foo").live("click", function (e, data) { - equal(data, true, "live with trigger data"); - }); - jQuery("#foo").trigger("click", true).die("click"); - - // Test binding with different this object - jQuery("#foo").live("click", jQuery.proxy(function (e) { - equal(this.foo, "bar", "live with event scope"); - }, { foo : "bar" })); - jQuery("#foo").trigger("click").die("click"); - - // Test binding with different this object, event data, and trigger data - jQuery("#foo").live("click", true, jQuery.proxy(function (e, data) { - equal(e.data, true, "live with with different this object, event data, and trigger data"); - equal(this["foo"], "bar", "live with with different this object, event data, and trigger data"); - equal(data, true, "live with with different this object, event data, and trigger data"); - }, { "foo" : "bar" })); - jQuery("#foo").trigger("click", true).die("click"); - - // Verify that return false prevents default action - jQuery("#anchor2").live("click", function () { - return false; - }); - var hash = window.location.hash; - jQuery("#anchor2").trigger("click"); - equal(window.location.hash, hash, "return false worked"); - jQuery("#anchor2").die("click"); - - // Verify that .preventDefault() prevents default action - jQuery("#anchor2").live("click", function (e) { - e.preventDefault(); - }); - hash = window.location.hash; - jQuery("#anchor2").trigger("click"); - equal(window.location.hash, hash, "e.preventDefault() worked"); - jQuery("#anchor2").die("click"); - - // Test binding the same handler to multiple points - var called = 0; - - function callback() { - called++; - return false; - } - - jQuery("#nothiddendiv").live("click", callback); - jQuery("#anchor2").live("click", callback); - - jQuery("#nothiddendiv").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - called = 0; - jQuery("#anchor2").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - // Make sure that only one callback is removed - jQuery("#anchor2").die("click", callback); - - called = 0; - jQuery("#nothiddendiv").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - called = 0; - jQuery("#anchor2").trigger("click"); - equal(called, 0, "Verify that no click occurred."); - - // Make sure that it still works if the selector is the same, - // but the event type is different - jQuery("#nothiddendiv").live("foo", callback); - - // Cleanup - jQuery("#nothiddendiv").die("click", callback); - - called = 0; - jQuery("#nothiddendiv").trigger("click"); - equal(called, 0, "Verify that no click occurred."); - - called = 0; - jQuery("#nothiddendiv").trigger("foo"); - equal(called, 1, "Verify that one foo occurred."); - - // Cleanup - jQuery("#nothiddendiv").die("foo", callback); - - // Make sure we don't loose the target by DOM modifications - // after the bubble already reached the liveHandler - var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("").get(0); - - jQuery("#nothiddendivchild").live("click", function (e) { - jQuery("#nothiddendivchild").html(""); - }); - jQuery("#nothiddendivchild").live("click", function (e) { - if (e.target) { - livec++; - } - }); - - jQuery("#nothiddendiv span").click(); - equal(jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM."); - equal(livec, 1, "Verify that second handler occurred even with nuked target."); - - // Cleanup - jQuery("#nothiddendivchild").die("click"); - - // Verify that .live() ocurs and cancel buble in the same order as - // we would expect .bind() and .click() without delegation - var lived = 0, livee = 0; - - // bind one pair in one order - jQuery("span#liveSpan1 a").live("click", function () { - lived++; - return false; - }); - jQuery("span#liveSpan1").live("click", function () { - livee++; - }); - - jQuery("span#liveSpan1 a").click(); - equal(lived, 1, "Verify that only one first handler occurred."); - equal(livee, 0, "Verify that second handler doesn't."); - - // and one pair in inverse - jQuery("span#liveSpan2").live("click", function () { - livee++; - }); - jQuery("span#liveSpan2 a").live("click", function () { - lived++; - return false; - }); - - lived = 0; - livee = 0; - jQuery("span#liveSpan2 a").click(); - equal(lived, 1, "Verify that only one first handler occurred."); - equal(livee, 0, "Verify that second handler doesn't."); - - // Cleanup - jQuery("span#liveSpan1 a").die("click"); - jQuery("span#liveSpan1").die("click"); - jQuery("span#liveSpan2 a").die("click"); - jQuery("span#liveSpan2").die("click"); - - // Test this, target and currentTarget are correct - jQuery("span#liveSpan1").live("click", function (e) { - equal(this.id, "liveSpan1", "Check the this within a live handler"); - equal(e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a live handler"); - equal(e.delegateTarget, document, "Check the event.delegateTarget within a live handler"); - equal(e.target.nodeName.toUpperCase(), "A", "Check the event.target within a live handler"); - }); - - jQuery("span#liveSpan1 a").click(); - - jQuery("span#liveSpan1").die("click"); - - // Work with deep selectors - livee = 0; - - function clickB() { - livee++; - } - - jQuery("#nothiddendiv div").live("click", function () { - livee++; - }); - jQuery("#nothiddendiv div").live("click", clickB); - jQuery("#nothiddendiv div").live("mouseover", function () { - livee++; - }); - - equal(livee, 0, "No clicks, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 2, "Click, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("mouseover"); - equal(livee, 1, "Mouseover, deep selector."); - - jQuery("#nothiddendiv div").die("mouseover"); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 2, "Click, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("mouseover"); - equal(livee, 0, "Mouseover, deep selector."); - - jQuery("#nothiddendiv div").die("click", clickB); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 1, "Click, deep selector."); - - jQuery("#nothiddendiv div").die("click"); - - // blur a non-input element, we should force-fire its handlers - // regardless of whether it's burring or not (unlike browsers) - jQuery("#nothiddendiv div") - .live("blur", function () { - ok(true, "Live div trigger blur."); - }) - .trigger("blur") - .die("blur"); - }); - - test("die all bound events", function () { - expect(1); - - var count = 0; - var div = jQuery("div#nothiddendivchild"); - - div.live("click submit", function () { - count++; - }); - div.die(); - - div.trigger("click"); - div.trigger("submit"); - - equal(count, 0, "Make sure no events were triggered."); - }); - - test("live with multiple events", function () { - expect(1); - - var count = 0; - var div = jQuery("div#nothiddendivchild"); - - div.live("click submit", function () { - count++; - }); - - div.trigger("click"); - div.trigger("submit"); - - equal(count, 2, "Make sure both the click and submit were triggered."); - - // manually clean up events from elements outside the fixture - div.die(); - }); - - test("live with namespaces", function () { - expect(15); - - var count1 = 0, count2 = 0; - - jQuery("#liveSpan1").live("foo.bar", function (e) { - equal(e.namespace, "bar", "namespace is bar"); - count1++; - }); - - jQuery("#liveSpan1").live("foo.zed", function (e) { - equal(e.namespace, "zed", "namespace is zed"); - count2++; - }); - - jQuery("#liveSpan1").trigger("foo.bar"); - equal(count1, 1, "Got live foo.bar"); - equal(count2, 0, "Got live foo.bar"); - - count1 = 0; - count2 = 0; - - jQuery("#liveSpan1").trigger("foo.zed"); - equal(count1, 0, "Got live foo.zed"); - equal(count2, 1, "Got live foo.zed"); - - //remove one - count1 = 0; - count2 = 0; - - jQuery("#liveSpan1").die("foo.zed"); - jQuery("#liveSpan1").trigger("foo.bar"); - - equal(count1, 1, "Got live foo.bar after dieing foo.zed"); - equal(count2, 0, "Got live foo.bar after dieing foo.zed"); - - count1 = 0; - count2 = 0; - - jQuery("#liveSpan1").trigger("foo.zed"); - equal(count1, 0, "Got live foo.zed"); - equal(count2, 0, "Got live foo.zed"); - - //remove the other - jQuery("#liveSpan1").die("foo.bar"); - - count1 = 0; - count2 = 0; - - jQuery("#liveSpan1").trigger("foo.bar"); - equal(count1, 0, "Did not respond to foo.bar after dieing it"); - equal(count2, 0, "Did not respond to foo.bar after dieing it"); - - jQuery("#liveSpan1").trigger("foo.zed"); - equal(count1, 0, "Did not trigger foo.zed again"); - equal(count2, 0, "Did not trigger foo.zed again"); - }); - - test("live with change", function () { - expect(8); - - var selectChange = 0, checkboxChange = 0; - - var select = jQuery("select[name='S1']"); - select.live("change", function () { - selectChange++; - }); - - var checkbox = jQuery("#check2"), - checkboxFunction = function () { - checkboxChange++; - }; - checkbox.live("change", checkboxFunction); - - // test click on select - - // second click that changed it - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 1, "Change on click."); - - // test keys on select - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 1, "Change on keyup."); - - // test click on checkbox - checkbox.trigger("change"); - equal(checkboxChange, 1, "Change on checkbox."); - - // test blur/focus on text - var text = jQuery("#name"), textChange = 0, oldTextVal = text.val(); - text.live("change", function () { - textChange++; - }); - - text.val(oldTextVal + "foo"); - text.trigger("change"); - equal(textChange, 1, "Change on text input."); - - text.val(oldTextVal); - text.die("change"); - - // test blur/focus on password - var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val(); - password.live("change", function () { - passwordChange++; - }); - - password.val(oldPasswordVal + "foo"); - password.trigger("change"); - equal(passwordChange, 1, "Change on password input."); - - password.val(oldPasswordVal); - password.die("change"); - - // make sure die works - - // die all changes - selectChange = 0; - select.die("change"); - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 0, "Die on click works."); - - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 0, "Die on keyup works."); - - // die specific checkbox - checkbox.die("change", checkboxFunction); - checkbox.trigger("change"); - equal(checkboxChange, 1, "Die on checkbox."); - }); - - test("live with submit", function () { - expect(7); - - var count1 = 0, count2 = 0; - - jQuery("#testForm").live("submit", function (ev) { - count1++; - ev.preventDefault(); - }); - - jQuery("body").live("submit", function (ev) { - count2++; - ev.preventDefault(); - }); - - jQuery("#testForm input[name=sub1]").submit(); - equal(count1, 1, "Verify form submit."); - equal(count2, 1, "Verify body submit."); - - jQuery("#testForm input[name=sub1]").live("click", function (ev) { - ok(true, "cancelling submit still calls click handler"); - }); - - jQuery("#testForm input[name=sub1]")[0].click(); - equal(count1, 2, "Verify form submit."); - equal(count2, 2, "Verify body submit."); - - jQuery("#testForm button[name=sub4]")[0].click(); - equal(count1, 3, "Verify form submit."); - equal(count2, 3, "Verify body submit."); - - jQuery("#testForm").die("submit"); - jQuery("#testForm input[name=sub1]").die("click"); - jQuery("body").die("submit"); - }); - - test("live with special events", function () { - expect(13); - - jQuery.event.special["foo"] = { - setup : function (data, namespaces, handler) { - ok(true, "Setup run."); - }, - teardown : function (namespaces) { - ok(true, "Teardown run."); - }, - add : function (handleObj) { - ok(true, "Add run."); - }, - remove : function (handleObj) { - ok(true, "Remove run."); - }, - _default : function (event, arg) { - ok(event.type === "foo" && arg == 42, "Default run with correct args."); - } - }; - - // Run: setup, add - jQuery("#liveSpan1").live("foo.a", function (e) { - ok(true, "Handler 1 run."); - }); - - // Run: add - jQuery("#liveSpan1").live("foo.b", function (e) { - ok(true, "Handler 2 run."); - }); - - // Run: Handler 1, Handler 2, Default - jQuery("#liveSpan1").trigger("foo", 42); - - // Run: Handler 1, Default - jQuery("#liveSpan1").trigger("foo.a", 42); - - // Run: remove - jQuery("#liveSpan1").die("foo.a"); - - // Run: Handler 2, Default - jQuery("#liveSpan1").trigger("foo", 42); - - // Run: remove, teardown - jQuery("#liveSpan1").die("foo"); - - delete jQuery.event.special["foo"]; - }); - - test(".delegate()/.undelegate()", function () { - expect(65); - - var submit = 0, div = 0, livea = 0, liveb = 0; - - jQuery("#body").delegate("div", "submit", function () { - submit++; - return false; - }); - jQuery("#body").delegate("div", "click", function () { - div++; - }); - jQuery("#body").delegate("div#nothiddendiv", "click", function () { - livea++; - }); - jQuery("#body").delegate("div#nothiddendivchild", "click", function () { - liveb++; - }); - - // Nothing should trigger on the body - jQuery("body").trigger("click"); - equal(submit, 0, "Click on body"); - equal(div, 0, "Click on body"); - equal(livea, 0, "Click on body"); - equal(liveb, 0, "Click on body"); - - // This should trigger two events - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendiv").trigger("click"); - equal(submit, 0, "Click on div"); - equal(div, 1, "Click on div"); - equal(livea, 1, "Click on div"); - equal(liveb, 0, "Click on div"); - - // This should trigger three events (w/ bubbling) - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "Click on inner div"); - equal(div, 2, "Click on inner div"); - equal(livea, 1, "Click on inner div"); - equal(liveb, 1, "Click on inner div"); - - // This should trigger one submit - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("submit"); - equal(submit, 1, "Submit on div"); - equal(div, 0, "Submit on div"); - equal(livea, 0, "Submit on div"); - equal(liveb, 0, "Submit on div"); - - // Make sure no other events were removed in the process - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "undelegate Click on inner div"); - equal(div, 2, "undelegate Click on inner div"); - equal(livea, 1, "undelegate Click on inner div"); - equal(liveb, 1, "undelegate Click on inner div"); - - // Now make sure that the removal works - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("#body").undelegate("div#nothiddendivchild", "click"); - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "undelegate Click on inner div"); - equal(div, 2, "undelegate Click on inner div"); - equal(livea, 1, "undelegate Click on inner div"); - equal(liveb, 0, "undelegate Click on inner div"); - - // Make sure that the click wasn't removed too early - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("div#nothiddendiv").trigger("click"); - equal(submit, 0, "undelegate Click on inner div"); - equal(div, 1, "undelegate Click on inner div"); - equal(livea, 1, "undelegate Click on inner div"); - equal(liveb, 0, "undelegate Click on inner div"); - - // Make sure that stopPropgation doesn't stop live events - submit = 0; - div = 0; - livea = 0; - liveb = 0; - jQuery("#body").delegate("div#nothiddendivchild", "click", function (e) { - liveb++; - e.stopPropagation(); - }); - jQuery("div#nothiddendivchild").trigger("click"); - equal(submit, 0, "stopPropagation Click on inner div"); - equal(div, 1, "stopPropagation Click on inner div"); - equal(livea, 0, "stopPropagation Click on inner div"); - equal(liveb, 1, "stopPropagation Click on inner div"); - - // Make sure click events only fire with primary click - submit = 0; - div = 0; - livea = 0; - liveb = 0; - var event = jQuery.Event("click"); - event.button = 1; - jQuery("div#nothiddendiv").trigger(event); - - equal(livea, 0, "delegate secondary click"); - - jQuery("#body").undelegate("div#nothiddendivchild", "click"); - jQuery("#body").undelegate("div#nothiddendiv", "click"); - jQuery("#body").undelegate("div", "click"); - jQuery("#body").undelegate("div", "submit"); - - // Test binding with a different context - var clicked = 0, container = jQuery("#qunit-fixture")[0]; - jQuery("#qunit-fixture").delegate("#foo", "click", function (e) { - clicked++; - }); - jQuery("div").trigger("click"); - jQuery("#foo").trigger("click"); - jQuery("#qunit-fixture").trigger("click"); - jQuery("body").trigger("click"); - equal(clicked, 2, "delegate with a context"); - - // Test unbinding with a different context - jQuery("#qunit-fixture").undelegate("#foo", "click"); - jQuery("#foo").trigger("click"); - equal(clicked, 2, "undelegate with a context"); - - // Test binding with event data - jQuery("#body").delegate("#foo", "click", true, function (e) { - equal(e.data, true, "delegate with event data"); - }); - jQuery("#foo").trigger("click"); - jQuery("#body").undelegate("#foo", "click"); - - // Test binding with trigger data - jQuery("#body").delegate("#foo", "click", function (e, data) { - equal(data, true, "delegate with trigger data"); - }); - jQuery("#foo").trigger("click", true); - jQuery("#body").undelegate("#foo", "click"); - - // Test binding with different this object - jQuery("#body").delegate("#foo", "click", jQuery.proxy(function (e) { - equal(this["foo"], "bar", "delegate with event scope"); - }, { "foo" : "bar" })); - jQuery("#foo").trigger("click"); - jQuery("#body").undelegate("#foo", "click"); - - // Test binding with different this object, event data, and trigger data - jQuery("#body").delegate("#foo", "click", true, jQuery.proxy(function (e, data) { - equal(e.data, true, "delegate with with different this object, event data, and trigger data"); - equal(this.foo, "bar", "delegate with with different this object, event data, and trigger data"); - equal(data, true, "delegate with with different this object, event data, and trigger data"); - }, { "foo" : "bar" })); - jQuery("#foo").trigger("click", true); - jQuery("#body").undelegate("#foo", "click"); - - // Verify that return false prevents default action - jQuery("#body").delegate("#anchor2", "click", function () { - return false; - }); - var hash = window.location.hash; - jQuery("#anchor2").trigger("click"); - equal(window.location.hash, hash, "return false worked"); - jQuery("#body").undelegate("#anchor2", "click"); - - // Verify that .preventDefault() prevents default action - jQuery("#body").delegate("#anchor2", "click", function (e) { - e.preventDefault(); - }); - hash = window.location.hash; - jQuery("#anchor2").trigger("click"); - equal(window.location.hash, hash, "e.preventDefault() worked"); - jQuery("#body").undelegate("#anchor2", "click"); - - // Test binding the same handler to multiple points - var called = 0; - - function callback() { - called++; - return false; - } - - jQuery("#body").delegate("#nothiddendiv", "click", callback); - jQuery("#body").delegate("#anchor2", "click", callback); - - jQuery("#nothiddendiv").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - called = 0; - jQuery("#anchor2").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - // Make sure that only one callback is removed - jQuery("#body").undelegate("#anchor2", "click", callback); - - called = 0; - jQuery("#nothiddendiv").trigger("click"); - equal(called, 1, "Verify that only one click occurred."); - - called = 0; - jQuery("#anchor2").trigger("click"); - equal(called, 0, "Verify that no click occurred."); - - // Make sure that it still works if the selector is the same, - // but the event type is different - jQuery("#body").delegate("#nothiddendiv", "foo", callback); - - // Cleanup - jQuery("#body").undelegate("#nothiddendiv", "click", callback); - - called = 0; - jQuery("#nothiddendiv").trigger("click"); - equal(called, 0, "Verify that no click occurred."); - - called = 0; - jQuery("#nothiddendiv").trigger("foo"); - equal(called, 1, "Verify that one foo occurred."); - - // Cleanup - jQuery("#body").undelegate("#nothiddendiv", "foo", callback); - - // Make sure we don't loose the target by DOM modifications - // after the bubble already reached the liveHandler - var livec = 0, elemDiv = jQuery("#nothiddendivchild").html("").get(0); - - jQuery("#body").delegate("#nothiddendivchild", "click", function (e) { - jQuery("#nothiddendivchild").html(""); - }); - jQuery("#body").delegate("#nothiddendivchild", "click", function (e) { - if (e.target) { - livec++; - } - }); - - jQuery("#nothiddendiv span").click(); - equal(jQuery("#nothiddendiv span").length, 0, "Verify that first handler occurred and modified the DOM."); - equal(livec, 1, "Verify that second handler occurred even with nuked target."); - - // Cleanup - jQuery("#body").undelegate("#nothiddendivchild", "click"); - - // Verify that .live() ocurs and cancel buble in the same order as - // we would expect .bind() and .click() without delegation - var lived = 0, livee = 0; - - // bind one pair in one order - jQuery("#body").delegate("span#liveSpan1 a", "click", function () { - lived++; - return false; - }); - jQuery("#body").delegate("span#liveSpan1", "click", function () { - livee++; - }); - - jQuery("span#liveSpan1 a").click(); - equal(lived, 1, "Verify that only one first handler occurred."); - equal(livee, 0, "Verify that second handler doesn't."); - - // and one pair in inverse - jQuery("#body").delegate("span#liveSpan2", "click", function () { - livee++; - }); - jQuery("#body").delegate("span#liveSpan2 a", "click", function () { - lived++; - return false; - }); - - lived = 0; - livee = 0; - jQuery("span#liveSpan2 a").click(); - equal(lived, 1, "Verify that only one first handler occurred."); - equal(livee, 0, "Verify that second handler doesn't."); - - // Cleanup - jQuery("#body").undelegate("click"); - - // Test this, target and currentTarget are correct - jQuery("#body").delegate("span#liveSpan1", "click", function (e) { - equal(this.id, "liveSpan1", "Check the this within a delegate handler"); - equal(e.currentTarget.id, "liveSpan1", "Check the event.currentTarget within a delegate handler"); - equal(e.delegateTarget, document.body, "Check the event.delegateTarget within a delegate handler"); - equal(e.target.nodeName.toUpperCase(), "A", "Check the event.target within a delegate handler"); - }); - - jQuery("span#liveSpan1 a").click(); - - jQuery("#body").undelegate("span#liveSpan1", "click"); - - // Work with deep selectors - livee = 0; - - function clickB() { - livee++; - } - - jQuery("#body").delegate("#nothiddendiv div", "click", function () { - livee++; - }); - jQuery("#body").delegate("#nothiddendiv div", "click", clickB); - jQuery("#body").delegate("#nothiddendiv div", "mouseover", function () { - livee++; - }); - - equal(livee, 0, "No clicks, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 2, "Click, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("mouseover"); - equal(livee, 1, "Mouseover, deep selector."); - - jQuery("#body").undelegate("#nothiddendiv div", "mouseover"); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 2, "Click, deep selector."); - - livee = 0; - jQuery("#nothiddendivchild").trigger("mouseover"); - equal(livee, 0, "Mouseover, deep selector."); - - jQuery("#body").undelegate("#nothiddendiv div", "click", clickB); - - livee = 0; - jQuery("#nothiddendivchild").trigger("click"); - equal(livee, 1, "Click, deep selector."); - - jQuery("#body").undelegate("#nothiddendiv div", "click"); - }); - - test("jQuery.off using dispatched jQuery.Event", function () { - expect(1); - - var markup = jQuery('

                                        target

                                        '), - count = 0; - markup - .on("click.name", "a", function (event) { - equal(++count, 1, "event called once before removal"); - jQuery().off(event); - }) - .find("a").click().click().end() - .remove(); - }); - - test("delegated event with delegateTarget-relative selector", function () { - expect(3); - var markup = jQuery("
                                        ").appendTo("#qunit-fixture"); - - // Positional selector (#11315) - markup - .on("click", ">li>a", function () { - ok(this.id === "a0", "child li was clicked"); - }) - .find("#ul0") - .on("click", "li:first>a", function () { - ok(this.id === "a0_0", "first li under #u10 was clicked"); - }) - .end() - .find("a").click().end() - .find("#ul0").off(); - - // Non-positional selector (#12383) - markup = markup.wrap("
                                        ").parent(); - markup - .find("#ul0") - .on("click", "div li a", function () { - ok(false, "div is ABOVE the delegation point!"); - }) - .on("click", "ul a", function () { - ok(false, "ul is the delegation point!"); - }) - .on("click", "li.test a", function () { - ok(true, "li.test is below the delegation point."); - }) - .find("#a0_0").click(); - - markup.remove(); - }); - - test("stopPropagation() stops directly-bound events on delegated target", function () { - expect(1); - - var markup = jQuery(""); - markup - .on("click", function () { - ok(false, "directly-bound event on delegate target was called"); - }) - .on("click", "a", function (e) { - e.stopPropagation(); - ok(true, "delegated handler was called"); - }) - .find("a").click().end() - .remove(); - }); - - test("undelegate all bound events", function () { - expect(2); - - var count = 0, - clicks = 0, - div = jQuery("#body"); - - div.delegate("div#nothiddendivchild", "click submit", function () { - count++; - }); - div.bind("click", function () { - clicks++; - }); - div.undelegate(); - - jQuery("div#nothiddendivchild").trigger("click"); - jQuery("div#nothiddendivchild").trigger("submit"); - - equal(count, 0, "Make sure no events were triggered."); - - div.trigger("click"); - equal(clicks, 2, "Make sure delegated and directly bound event occurred."); - div.unbind("click"); - }); - - test("delegate with multiple events", function () { - expect(1); - - var count = 0; - var div = jQuery("#body"); - - div.delegate("div#nothiddendivchild", "click submit", function () { - count++; - }); - - jQuery("div#nothiddendivchild").trigger("click"); - jQuery("div#nothiddendivchild").trigger("submit"); - - equal(count, 2, "Make sure both the click and submit were triggered."); - - jQuery("#body").undelegate(); - }); - - test("delegate with change", function () { - expect(8); - - var selectChange = 0, checkboxChange = 0; - - var select = jQuery("select[name='S1']"); - jQuery("#body").delegate("select[name='S1']", "change", function () { - selectChange++; - }); - - var checkbox = jQuery("#check2"), - checkboxFunction = function () { - checkboxChange++; - }; - jQuery("#body").delegate("#check2", "change", checkboxFunction); - - // test click on select - - // second click that changed it - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 1, "Change on click."); - - // test keys on select - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 1, "Change on keyup."); - - // test click on checkbox - checkbox.trigger("change"); - equal(checkboxChange, 1, "Change on checkbox."); - - // test blur/focus on text - var text = jQuery("#name"), textChange = 0, oldTextVal = text.val(); - jQuery("#body").delegate("#name", "change", function () { - textChange++; - }); - - text.val(oldTextVal + "foo"); - text.trigger("change"); - equal(textChange, 1, "Change on text input."); - - text.val(oldTextVal); - jQuery("#body").die("change"); - - // test blur/focus on password - var password = jQuery("#name"), passwordChange = 0, oldPasswordVal = password.val(); - jQuery("#body").delegate("#name", "change", function () { - passwordChange++; - }); - - password.val(oldPasswordVal + "foo"); - password.trigger("change"); - equal(passwordChange, 1, "Change on password input."); - - password.val(oldPasswordVal); - jQuery("#body").undelegate("#name", "change"); - - // make sure die works - - // die all changes - selectChange = 0; - jQuery("#body").undelegate("select[name='S1']", "change"); - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 0, "Die on click works."); - - selectChange = 0; - select[0].selectedIndex = select[0].selectedIndex ? 0 : 1; - select.trigger("change"); - equal(selectChange, 0, "Die on keyup works."); - - // die specific checkbox - jQuery("#body").undelegate("#check2", "change", checkboxFunction); - checkbox.trigger("change"); - equal(checkboxChange, 1, "Die on checkbox."); - }); - - test("delegate with submit", function () { - var count1 = 0, count2 = 0; - - jQuery("#body").delegate("#testForm", "submit", function (ev) { - count1++; - ev.preventDefault(); - }); - - jQuery(document).delegate("body", "submit", function (ev) { - count2++; - ev.preventDefault(); - }); - - jQuery("#testForm input[name=sub1]").submit(); - equal(count1, 1, "Verify form submit."); - equal(count2, 1, "Verify body submit."); - - jQuery("#body").undelegate(); - jQuery(document).undelegate(); - }); - - test("undelegate() with only namespaces", function () { - expect(2); - - var $delegate = jQuery("#liveHandlerOrder"), - count = 0; - - $delegate.delegate("a", "click.ns", function (e) { - count++; - }); - - jQuery("a", $delegate).eq(0).trigger("click.ns"); - - equal(count, 1, "delegated click.ns"); - - $delegate.undelegate(".ns"); - - jQuery("a", $delegate).eq(1).trigger("click.ns"); - - equal(count, 1, "no more .ns after undelegate"); - }); - - test("Non DOM element events", function () { - expect(1); - - var o = {}; - - jQuery(o).bind("nonelementobj", function (e) { - ok(true, "Event on non-DOM object triggered"); - }); - - jQuery(o).trigger("nonelementobj"); - }); - - test("inline handler returning false stops default", function () { - expect(1); - - var markup = jQuery(""); - markup.click(function (e) { - ok(e.isDefaultPrevented(), "inline handler prevented default"); - return false; - }); - markup.find("a").click(); - markup.off("click"); - }); - - test("window resize", function () { - expect(2); - - jQuery(window).unbind(); - - jQuery(window).bind("resize",function () { - ok(true, "Resize event fired."); - }).resize().unbind("resize"); - - ok(!jQuery._data(window, "__events__"), "Make sure all the events are gone."); - }); - - test("focusin bubbles", function () { - expect(2); - - var input = jQuery("").prependTo("body"), - order = 0; - - // focus the element so DOM focus won't fire - input[0].focus(); - - jQuery("body").bind("focusin.focusinBubblesTest", function () { - equal(1, order++, "focusin on the body second"); - }); - - input.bind("focusin.focusinBubblesTest", function () { - equal(0, order++, "focusin on the element first"); - }); - -// Removed since DOM focus is unreliable on test swarm - // DOM focus method -// input[0].focus(); - - // To make the next focus test work, we need to take focus off the input. - // This will fire another focusin event, so set order to reflect that. -// order = 1; -// jQuery("#text1")[0].focus(); - - // jQuery trigger, which calls DOM focus - order = 0; - input.trigger("focus"); - - input.remove(); - jQuery("body").unbind("focusin.focusinBubblesTest"); - }); - - test("custom events with colons (#3533, #8272)", function () { - expect(1); - - var tab = jQuery("
                                        trigger
                                        ").appendTo("body"); - try { - tab.trigger("back:forth"); - ok(true, "colon events don't throw"); - } catch (e) { - ok(false, "colon events die"); - } - tab.remove(); - - }); - - test(".on and .off", function () { - expect(9); - var counter, mixfn; - - var $onandoff = jQuery("

                                        onandoff

                                        workedorborked?
                                        ").appendTo("body"); - - // Simple case - jQuery("#onandoff") - .on("whip", function () { - ok(true, "whipped it good"); - }) - .trigger("whip") - .off(); - - // Direct events only - counter = 0; - jQuery("#onandoff b") - .on("click", 5, function (e, trig) { - counter += e.data + (trig || 9); // twice, 5+9+5+17=36 - }) - .one("click", 7, function (e, trig) { - counter += e.data + (trig || 11); // once, 7+11=18 - }) - .click() - .trigger("click", 17) - .off("click"); - equal(counter, 54, "direct event bindings with data"); - - // Delegated events only - counter = 0; - jQuery("#onandoff") - .on("click", "em", 5, function (e, trig) { - counter += e.data + (trig || 9); // twice, 5+9+5+17=36 - }) - .one("click", "em", 7, function (e, trig) { - counter += e.data + (trig || 11); // once, 7+11=18 - }) - .find("em") - .click() - .trigger("click", 17) - .end() - .off("click", "em"); - equal(counter, 54, "delegated event bindings with data"); - - - // Mixed event bindings and types - counter = 0; - mixfn = function (e, trig) { - counter += (e.data || 0) + (trig || 1); - }; - jQuery("#onandoff") - .on("click clack cluck", "em", 2, mixfn) - .on("cluck", "b", 7, mixfn) - .on("cluck", mixfn) - .trigger("what!") - .each(function () { - equal(counter, 0, "nothing triggered yet"); - }) - .find("em") - .one("cluck", 3, mixfn) - .trigger("cluck", 8)// 3+8 2+8 + 0+8 = 29 - .off() - .trigger("cluck", 9)// 2+9 + 0+9 = 20 - .end() - .each(function () { - equal(counter, 49, "after triggering em element"); - }) - .off("cluck", function () { - })// shouldn't remove anything - .trigger("cluck", 2)// 0+2 = 2 - .each(function () { - equal(counter, 51, "after triggering #onandoff cluck"); - }) - .find("b") - .on("click", 95, mixfn) - .on("clack", "p", 97, mixfn) - .one("cluck", 3, mixfn) - .trigger("quack", 19)// 0 - .off("click clack cluck") - .end() - .each(function () { - equal(counter, 51, "after triggering b"); - }) - .trigger("cluck", 3)// 0+3 = 3 - .off("clack", "em", mixfn) - .find("em") - .trigger("clack")// 0 - .end() - .each(function () { - equal(counter, 54, "final triggers"); - }) - .off("click cluck"); - - // We should have removed all the event handlers ... kinda hacky way to check this - var data = jQuery.data[ jQuery("#onandoff")[0].expando ] || {}; - equal(data["events"], undefined, "no events left"); - - $onandoff.remove(); - }); - - test("special bind/delegate name mapping", function () { - expect(7); - - jQuery.event.special["slap"] = { - bindType : "click", - delegateType : "swing", - handle : function (event) { - equal(event.handleObj.origType, "slap", "slapped your mammy, " + event.type); - } - }; - - var comeback = function (event) { - ok(true, "event " + event.type + " triggered"); - }; - - jQuery("
                                        ") - .on("slap", "button", jQuery.noop) - .on("swing", "button", comeback) - .find("button") - .on("slap", jQuery.noop) - .on("click", comeback) - .trigger("click")// bindType-slap and click - .off("slap") - .trigger("click")// click - .off("click") - .trigger("swing")// delegateType-slap and swing - .end() - .off("slap swing", "button") - .find("button")// everything should be gone - .trigger("slap") - .trigger("click") - .trigger("swing") - .end() - .remove(); - delete jQuery.event.special["slap"]; - - jQuery.event.special["gutfeeling"] = { - bindType : "click", - delegateType : "click", - handle : function (event) { - equal(event.handleObj.origType, "gutfeeling", "got a gutfeeling"); - // Need to call the handler since .one() uses it to unbind - return event.handleObj.handler.call(this, event); - } - }; - - // Ensure a special event isn't removed by its mapped type - jQuery('

                                        Gut Feeling

                                        ') - .on("click", jQuery.noop) - .on("gutfeeling", jQuery.noop) - .off("click") - .trigger("gutfeeling") - .remove(); - - // Ensure special events are removed when only a namespace is provided - jQuery('

                                        Gut Feeling

                                        ') - .on("gutfeeling.Devo", jQuery.noop) - .off(".Devo") - .trigger("gutfeeling") - .remove(); - - // Ensure .one() events are removed after their maiden voyage - jQuery('

                                        Gut Feeling

                                        ') - .one("gutfeeling", jQuery.noop) - .trigger("gutfeeling")// This one should - .trigger("gutfeeling")// This one should not - .remove(); - - delete jQuery.event.special["gutfeeling"]; - }); - - test(".on and .off, selective mixed removal (#10705)", function () { - expect(7); - - var clockout = 0, - timingx = function (e) { - ok(true, "triggered " + e.type); - }; - - jQuery("

                                        Strange Pursuit

                                        ") - .on("click", timingx) - .on("click.duty", timingx) - .on("click.now", timingx) - .on("devo", timingx) - .on("future", timingx) - .trigger("click")// 3 - .trigger("devo")// 1 - .off(".duty devo ")// trailing space - .trigger("future")// 1 - .trigger("click")// 2 - .off("future click") - .trigger("click"); // 0 - }); - - test(".on( event-map, null-selector, data ) #11130", function () { - - expect(1); - - var $p = jQuery("

                                        Strange Pursuit

                                        "), - data = "bar", - map = { - "foo" : function (event) { - equal(event.data, "bar", "event.data correctly relayed with null selector"); - $p.remove(); - } - }; - - $p.on(map, null, data).trigger("foo"); - }); - - test("clone() delegated events (#11076)", function () { - expect(3); - - var counter = { "center" : 0, "fold" : 0, "centerfold" : 0 }, - clicked = function (event) { - counter[ jQuery(this).text().replace(/\s+/, "") ]++; - }, - table = - jQuery("
                                        centerfold
                                        ") - .on("click", "tr", clicked) - .on("click", "td:first-child", clicked) - .on("click", "td:last-child", clicked), - clone = table.clone(true); - - clone.find("td").click(); - equal(counter["center"], 1, "first child"); - equal(counter["fold"], 1, "last child"); - equal(counter["centerfold"], 2, "all children"); - - table.remove(); - clone.remove(); - }); - - (function () { - // This code must be run before DOM ready! - var notYetReady, noEarlyExecution, - order = [], - args = {}; - - notYetReady = !jQuery.isReady; - - test("jQuery.isReady", function () { - expect(2); - - equal(notYetReady, true, "jQuery.isReady should not be true before DOM ready"); - equal(jQuery.isReady, true, "jQuery.isReady should be true once DOM is ready"); - }); - - // Create an event handler. - function makeHandler(testId) { - // When returned function is executed, push testId onto `order` array - // to ensure execution order. Also, store event handler arg to ensure - // the correct arg is being passed into the event handler. - return function (arg) { - order.push(testId); - args[testId] = arg; - }; - } - - // Bind to the ready event in every possible way. - jQuery(makeHandler("a")); - jQuery(document).ready(makeHandler("b")); - jQuery(document).bind("ready.readytest", makeHandler("c")); - - // Do it twice, just to be sure. - jQuery(makeHandler("d")); - jQuery(document).ready(makeHandler("e")); - jQuery(document).bind("ready.readytest", makeHandler("f")); - - noEarlyExecution = order.length === 0; - - // This assumes that QUnit tests are run on DOM ready! - test("jQuery ready", function () { - expect(10); - - ok(noEarlyExecution, "Handlers bound to DOM ready should not execute before DOM ready"); - - // Ensure execution order. - deepEqual(order, ["a", "b", "d", "e", "c", "f"], "Bound DOM ready handlers should execute in bind-order, but those bound with jQuery(document).bind( 'ready', fn ) will always execute last"); - - // Ensure handler argument is correct. - equal(args["a"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery"); - equal(args["b"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery"); - ok(args["c"] instanceof jQuery.Event, "Argument passed to fn in jQuery(document).bind( 'ready', fn ) should be an event object"); - - order = []; - - // Now that the ready event has fired, again bind to the ready event - // in every possible way. These event handlers should execute immediately. - jQuery(makeHandler("g")); - equal(order.pop(), "g", "Event handler should execute immediately"); - equal(args["g"], jQuery, "Argument passed to fn in jQuery( fn ) should be jQuery"); - - jQuery(document).ready(makeHandler("h")); - equal(order.pop(), "h", "Event handler should execute immediately"); - equal(args["h"], jQuery, "Argument passed to fn in jQuery(document).ready( fn ) should be jQuery"); - - jQuery(document).bind("ready.readytest", makeHandler("never")); - equal(order.length, 0, "Event handler should never execute since DOM ready has already passed"); - - // Cleanup. - jQuery(document).unbind("ready.readytest"); - }); - - })(); - - test("change handler should be detached from element", function () { - expect(2); - - var $fixture = jQuery("").appendTo("body"); - - var originRemoveEvent = jQuery.removeEvent; - - var wrapperRemoveEvent = function (elem, type, handle) { - equal("change", type, "Event handler for 'change' event should be removed"); - equal("change-ie-leak", jQuery(elem).attr("id"), "Event handler for 'change' event should be removed from appropriate element"); - originRemoveEvent(elem, type, handle); - }; - - jQuery.removeEvent = wrapperRemoveEvent; - - $fixture.bind("change", function (event) { - }); - $fixture.unbind("change"); - - $fixture.remove(); - - jQuery.removeEvent = originRemoveEvent; - }); - - asyncTest("trigger click on checkbox, fires change event", function () { - expect(1); - - var check = jQuery("#check2"); - - check.on("change",function () { - // get it? - check.off("change"); - ok(true, "Change event fired as a result of triggered click"); - start(); - }).trigger("click"); - }); - }); \ No newline at end of file diff --git a/event/fastfix/qunit.html b/event/fastfix/qunit.html deleted file mode 100644 index c264afe9..00000000 --- a/event/fastfix/qunit.html +++ /dev/null @@ -1,229 +0,0 @@ - - - FastFix Test Suite - - - - - - -

                                        FastFix Event Test Suite

                                        - -

                                        - -
                                        -

                                        - -
                                        -
                                          -
                                          - - -
                                          -
                                          -
                                          - - -
                                          -
                                          -

                                          See this blog entry for more information.

                                          -

                                          - Here are some links in a normal paragraph: Google, - Google Groups (Link). - This link has class="blog": - diveintomark - -

                                          -
                                          -

                                          Everything inside the red border is inside a div with id="foo".

                                          -

                                          This is a normal link: Yahoo

                                          -

                                          This link has class="blog": Simon Willison's Weblog

                                          - -
                                          - -

                                          Try them out:

                                          -
                                            -
                                              -
                                              - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - test element -
                                              - Float test. - -
                                              - - -
                                              -
                                              - -
                                              - - - - -
                                              - -
                                              - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
                                              -
                                              -
                                              - -
                                              -
                                              hi there
                                              -
                                              -
                                              -
                                              -
                                              -
                                              -
                                              -
                                              -
                                              - -
                                              -
                                                -
                                              1. Rice
                                              2. -
                                              3. Beans
                                              4. -
                                              5. Blinis
                                              6. -
                                              7. Tofu
                                              8. -
                                              - -
                                              I'm hungry. I should...
                                              - ...Eat lots of food... | - ...Eat a little food... | - ...Eat no food... - ...Eat a burger... - ...Eat some funyuns... - ...Eat some funyuns... -
                                              - -
                                              - - -
                                              - -
                                              - 1 - 2 -
                                              -
                                              -
                                              - - - \ No newline at end of file diff --git a/event/handle/handle.js b/event/handle/handle.js index 42961301..4fb8fdc7 100644 --- a/event/handle/handle.js +++ b/event/handle/handle.js @@ -27,19 +27,19 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ namespaces.sort(); } - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { + if ( (!elem || $.event.customEvent[ type ]) && !$.event.global[ type ] ) { // No jQuery handlers for this event type, and it can't have inline handlers return; } // Caller can pass in an Event, Object, or just an event type string event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : + // $.Event object + event[ $.expando ] ? event : // Object literal - new jQuery.Event( type, event ) : + new $.Event( type, event ) : // Just the event type (string) - new jQuery.Event( type ); + new $.Event( type ); event.type = type; event.exclusive = exclusive; @@ -55,14 +55,14 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ // Handle a global trigger if ( !elem ) { // TODO: Stop taunting the data cache; remove global events and always attach to document - jQuery.each( jQuery.cache, function() { + $.each( $.cache, function() { // internalKey variable is just used to make it easier to find // and potentially change this stuff later; currently it just - // points to jQuery.expando - var internalKey = jQuery.expando, + // points to $.expando + var internalKey = $.expando, internalCache = this[ internalKey ]; if ( internalCache && internalCache.events && internalCache.events[ type ] ) { - jQuery.event.trigger( event, data, internalCache.handle.elem ); + $.event.trigger( event, data, internalCache.handle.elem ); } }); return; @@ -78,7 +78,7 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ event.target = elem; // Clone any incoming data and prepend the event, creating the handler arg list - data = data ? jQuery.makeArray( data ) : []; + data = data ? $.makeArray( data ) : []; data.unshift( event ); var cur = elem, @@ -87,7 +87,7 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ // Fire event on the current element, then bubble up the DOM tree do { - var handle = jQuery._data( cur, "handle" ); + var handle = $._data( cur, "handle" ); event.currentTarget = cur; if ( handle ) { @@ -95,7 +95,7 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ } // Trigger an inline bound script - if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { + if ( ontype && $.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) { event.result = false; event.preventDefault(); } @@ -107,10 +107,10 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ // If nobody prevented the default action, do it now if ( !event.isDefaultPrevented() ) { var old, - special = jQuery.event.special[ type ] || {}; + special = $.event.special[ type ] || {}; if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + !(type === "click" && $.nodeName( elem, "a" )) && $.acceptData( elem ) ) { // Call a native DOM method on the target with the same name name as the event. // Can't use an .isFunction)() check here because IE6/7 fails that test. @@ -124,7 +124,7 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ elem[ ontype ] = null; } - jQuery.event.triggered = type; + $.event.triggered = type; elem[ type ](); } } catch ( ieError ) {} @@ -133,7 +133,7 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ elem[ ontype ] = old; } - jQuery.event.triggered = undefined; + $.event.triggered = undefined; } } @@ -142,9 +142,9 @@ $.event.trigger = function(event, data, elem, onlyHandlers){ // a copy of $'s handle function that goes until it finds $.event.handle = function( event ) { - event = jQuery.event.fix( event || window.event ); + event = $.event.fix( event || window.event ); // Snapshot the handlers list since a called handler may add/remove events. - var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0), + var handlers = (($._data( this, "events" ) || {})[ event.type ] || []).slice(0), run_all = !event.exclusive && !event.namespace, args = Array.prototype.slice.call( arguments, 0 ); diff --git a/event/hashchange/hashchange.js b/event/hashchange/hashchange.js deleted file mode 100644 index 25bf7a86..00000000 --- a/event/hashchange/hashchange.js +++ /dev/null @@ -1,270 +0,0 @@ -/*! - * jQuery hashchange event - v1.2 - 2/11/2010 - * http://benalman.com/projects/jquery-hashchange-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ - -// Script: jQuery hashchange event -// -// *Version: 1.2, Last updated: 2/11/2010* -// -// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ -// GitHub - http://github.com/cowboy/jquery-hashchange/ -// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js -// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (1.1kb) -// -// About: License -// -// Copyright (c) 2010 "Cowboy" Ben Alman, -// Dual licensed under the MIT and GPL licenses. -// http://benalman.com/about/license/ -// -// About: Examples -// -// This working example, complete with fully commented code, illustrate one way -// in which this plugin can be used. -// -// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ -// -// About: Support and Testing -// -// Information about what version or versions of jQuery this plugin has been -// tested with, what browsers it has been tested in, and where the unit tests -// reside (so you can test it yourself). -// -// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 -// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.7, Safari 3-4, Chrome, Opera 9.6-10.1. -// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ -// -// About: Known issues -// -// While this jQuery hashchange event implementation is quite stable and robust, -// there are a few unfortunate browser bugs surrounding expected hashchange -// event-based behaviors, independent of any JavaScript window.onhashchange -// abstraction. See the following examples for more information: -// -// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ -// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ -// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ -// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ -// -// About: Release History -// -// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin -// from a page on another domain would cause an error in Safari 4. Also, -// IE6/7 Iframe is now inserted after the body (this actually works), -// which prevents the page from scrolling when the event is first bound. -// Event can also now be bound before DOM ready, but it won't be usable -// before then in IE6/7. -// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug -// where browser version is incorrectly reported as 8.0, despite -// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. -// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special -// window.onhashchange functionality into a separate plugin for users -// who want just the basic event & back button support, without all the -// extra awesomeness that BBQ provides. This plugin will be included as -// part of jQuery BBQ, but also be available separately. -/** - * @add jQuery.event.special - */ -// -/** - * @attribute hashchange - * - * Documentation on JMVC's hashchange event can - * be found at [http://benalman.com/projects/jquery-hashchange-plugin/]. - * - * ### Examples - * - * // with jQuery - * $(window).bind('hashchange', function(){ - * // do something - * }) - * - * // with $.Controller - * $.Controller('Nav',{ - * "{window} hashchange" : function(){ - * // do something - * } - * }) - * - */ -steal('jquery', function($){ - '$:nomunge'; // Used by YUI compressor. - - // Method / object references. - var fake_onhashchange, - jq_event_special = $.event.special, - - // Reused strings. - str_location = 'location', - str_hashchange = 'hashchange', - str_href = 'href', - - // IE6/7 specifically need some special love when it comes to back-button - // support, so let's do a little browser sniffing.. - browser = $.browser, - mode = document.documentMode, - is_old_ie = browser.msie && ( mode === undefined || mode < 8 ), - - // Does the browser support window.onhashchange? Test for IE version, since - // IE8 incorrectly reports this when in "IE7" or "IE8 Compatibility View"! - supports_onhashchange = 'on' + str_hashchange in window && !is_old_ie; - - // Get location.hash (or what you'd expect location.hash to be) sans any - // leading #. Thanks for making this necessary, Firefox! - function get_fragment( url ) { - url = url || window[ str_location ][ str_href ]; - return url.replace( /^[^#]*#?(.*)$/, '$1' ); - }; - - // Property: jQuery.hashchangeDelay - // - // The numeric interval (in milliseconds) at which the - // polling loop executes. Defaults to 100. - - $[ str_hashchange + 'Delay' ] = 100; - - // Event: hashchange event - // - // Fired when location.hash changes. In browsers that support it, the native - // window.onhashchange event is used (IE8, FF3.6), otherwise a polling loop is - // initialized, running every milliseconds to see if - // the hash has changed. In IE 6 and 7, a hidden Iframe is created to allow - // the back button and hash-based history to work. - // - // Usage: - // - // > $(window).bind( 'hashchange', function(e) { - // > var hash = location.hash; - // > ... - // > }); - // - // Additional Notes: - // - // * The polling loop and Iframe are not created until at least one callback - // is actually bound to 'hashchange'. - // * If you need the bound callback(s) to execute immediately, in cases where - // the page 'state' exists on page load (via bookmark or page refresh, for - // example) use $(window).trigger( 'hashchange' ); - // * The event can be bound before DOM ready, but since it won't be usable - // before then in IE6/7 (due to the necessary Iframe), recommended usage is - // to bind it inside a $(document).ready() callback. - - jq_event_special[ str_hashchange ] = $.extend( jq_event_special[ str_hashchange ], { - - // Called only when the first 'hashchange' event is bound to window. - setup: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to create our own. And we don't want to call this - // until the user binds to the event, just in case they never do, since it - // will create a polling loop and possibly even a hidden Iframe. - $( fake_onhashchange.start ); - }, - - // Called only when the last 'hashchange' event is unbound from window. - teardown: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to stop ours (if possible). - $( fake_onhashchange.stop ); - } - - }); - - // fake_onhashchange does all the work of triggering the window.onhashchange - // event for browsers that don't natively support it, including creating a - // polling loop to watch for hash changes and in IE 6/7 creating a hidden - // Iframe to enable back and forward. - fake_onhashchange = (function(){ - var self = {}, - timeout_id, - iframe, - set_history, - get_history; - - // Initialize. In IE 6/7, creates a hidden Iframe for history handling. - function init(){ - // Most browsers don't need special methods here.. - set_history = get_history = function(val){ return val; }; - - // But IE6/7 do! - if ( is_old_ie ) { - - // Create hidden Iframe after the end of the body to prevent initial - // page load from scrolling unnecessarily. - iframe = $(' Generally it is recommended to use `keypress` to retrieve the actual character being pressed. -> Note: In Mac OS Firefox (currently version 12 and 13) won't return any values at all for international +> Note: In Mac OS Firefox won't return any values at all for international characters on *keydown* and *keyup*. ## Demo -@demo jquery/event/key/key.html +@demo jquerypp/event/key/key.html 200 \ No newline at end of file diff --git a/event/key/key_test.js b/event/key/key_test.js index 60bed3ca..62535dfd 100644 --- a/event/key/key_test.js +++ b/event/key/key_test.js @@ -1,9 +1,9 @@ -steal('funcunit/qunit','funcunit/syn','jquery/event/key').then(function(){ +steal('steal-qunit', 'syn', 'jquerypp/event/key', function(QUnit, Syn) { -module('jquery/event/key'); +module('jquerypp/event/key'); test("type some things", function(){ - $("#qunit-test-area").append("") + $("#qunit-fixture").append("") var keydown, keypress, keyup; $('#key').keydown(function(ev){ keydown = ev.keyName(); @@ -15,10 +15,10 @@ test("type some things", function(){ stop(); - Syn.key("a","key", function(){ - equals(keydown, "a","keydown"); - equals(keypress,"a","keypress"); - equals(keyup, "a","keyup"); + Syn.key("key","a", function(){ + equal(keydown, "a","keydown"); + equal(keypress,"a","keypress"); + equal(keyup, "a","keyup"); start(); }); }) diff --git a/event/key/qunit.html b/event/key/qunit.html deleted file mode 100644 index 608329d0..00000000 --- a/event/key/qunit.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - -

                                              Key Test Suite

                                              -

                                              -
                                              -

                                              -
                                              -
                                                -
                                                - - \ No newline at end of file diff --git a/event/key/test.html b/event/key/test.html new file mode 100644 index 00000000..3380a070 --- /dev/null +++ b/event/key/test.html @@ -0,0 +1,3 @@ +jquerypp/event/key + +
                                                diff --git a/event/livehack/livehack.js b/event/livehack/livehack.js index d1397adc..9038c6de 100644 --- a/event/livehack/livehack.js +++ b/event/livehack/livehack.js @@ -1,6 +1,6 @@ steal('jquery', function($) { - var event = jQuery.event, + var event = $.event, //helper that finds handlers by type and calls back a function, this is basically handle // events - the events object diff --git a/event/mousehold/mousehold.js b/event/mousehold/mousehold.js index d5df9de6..bc31a9a8 100644 --- a/event/mousehold/mousehold.js +++ b/event/mousehold/mousehold.js @@ -1,9 +1,9 @@ -steal('jquery', 'jquery/event/livehack', function($) { +steal('jquery', 'jquerypp/event/livehack', function($) { /** * @class jQuery.Mousehold - * @plugin jquery/event/mousehold - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/event/mousehold/mousehold.js + * @plugin jquerypp/event/mousehold + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquerypp/event/mousehold/mousehold.js * @parent jQuery.event.mousehold * * Creates a new mousehold. The constructor should not be called directly. @@ -134,5 +134,5 @@ event.setupHelper([ * */ "mousehold" ], "mousedown", onmousehold ); - +return $; }); \ No newline at end of file diff --git a/event/move/move.js b/event/move/move.js index f85e7136..e41ffdcd 100644 --- a/event/move/move.js +++ b/event/move/move.js @@ -1,4 +1,4 @@ -steal('jquery', 'jquery/event/reverse', function() { +steal('jquery', 'jquerypp/event/reverse', function($) { $.event.reverse('move'); return $; }); \ No newline at end of file diff --git a/event/pause/pause.html b/event/pause/pause.html index ee926d46..d1648830 100644 --- a/event/pause/pause.html +++ b/event/pause/pause.html @@ -137,115 +137,116 @@
                                                - + - - - - -

                                                swipe Test Suite

                                                -

                                                -
                                                -

                                                -
                                                -
                                                  -
                                                  - - \ No newline at end of file diff --git a/event/pause/test.html b/event/pause/test.html new file mode 100644 index 00000000..f72d925a --- /dev/null +++ b/event/pause/test.html @@ -0,0 +1,3 @@ +jquerypp/event/pause + +
                                                  diff --git a/event/destroyed/destroyed.html b/event/removed/removed.html similarity index 50% rename from event/destroyed/destroyed.html rename to event/removed/removed.html index 00a56749..5b03c176 100644 --- a/event/destroyed/destroyed.html +++ b/event/removed/removed.html @@ -1,27 +1,26 @@ - destroyed demo + remove demo
                                                  -
                                                  Click Below to destroy me
                                                  +
                                                  Click Below to remove me
                                                  Click here!
                                                  - + diff --git a/event/destroyed/destroyed.js b/event/removed/removed.js similarity index 75% rename from event/destroyed/destroyed.js rename to event/removed/removed.js index cb00616d..c0ce1b46 100644 --- a/event/destroyed/destroyed.js +++ b/event/removed/removed.js @@ -1,19 +1,19 @@ steal('jquery', function( $ ) { /** * @attribute destroyed - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/dom/destroyed/destroyed.js - * @test jquery/event/destroyed/qunit.html + * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquerypp/dom/removed/removed + * @test jquerypp/event/destroyed/qunit.html */ // Store the old jQuery.cleanData - var oldClean = jQuery.cleanData; + var oldClean = $.cleanData; // Overwrites cleanData which is called by jQuery on manipulation methods $.cleanData = function( elems ) { for ( var i = 0, elem; (elem = elems[i]) !== undefined; i++ ) { // Trigger the destroyed event - $(elem).triggerHandler("destroyed"); + $(elem).triggerHandler("removed"); } // Call the old jQuery.cleanData oldClean(elems); diff --git a/event/removed/removed.md b/event/removed/removed.md new file mode 100644 index 00000000..34f906f1 --- /dev/null +++ b/event/removed/removed.md @@ -0,0 +1,28 @@ +@constructor jQuery.event.removed +@parent jquerypp + +@body + +`jQuery.event.removed` adds a `removed` event that is triggered when an element has been removed. + +The removed event is called when the element is removed as a result of a jQuery DOM +[manipulation method](http://api.jquery.com/category/manipulation/) like *remove*, *html*, *replaceWith*, etc. +Destroyed events do not bubble, so make sure you don't use live or delegate with removed events. + +The removed event is very useful when you want to remove certain event handlers or clean up references +when the element has been removed. This is very important in order to create long lived applications +that do not leak. + +## Quick Example + + $(".foo").on("removed", function(){ + //clean up code + }); + +## Quick Demo + +@demo jquerypp/event/removed/removed.html 200 + +## More Involved Demo + +@demo jquerypp/event/removed/removed_menu.html \ No newline at end of file diff --git a/event/destroyed/destroyed_menu.html b/event/removed/removed_menu.html similarity index 98% rename from event/destroyed/destroyed_menu.html rename to event/removed/removed_menu.html index 739a9f48..4344a07a 100644 --- a/event/destroyed/destroyed_menu.html +++ b/event/removed/removed_menu.html @@ -37,7 +37,7 @@ Remove a "Show Menu"
                                                  - + +
                                                  diff --git a/event/resize/demo.html b/event/resize/demo.html index e62f8d2b..4f3ee228 100644 --- a/event/resize/demo.html +++ b/event/resize/demo.html @@ -72,11 +72,7 @@

                                                  Folders:

                                                  A footer
                                                  - - - - -

                                                  selection Test Suite

                                                  -

                                                  -
                                                  -

                                                  -
                                                  -
                                                    -
                                                    - - \ No newline at end of file diff --git a/event/resize/resize.html b/event/resize/resize.html index 6848c248..8a2e917c 100644 --- a/event/resize/resize.html +++ b/event/resize/resize.html @@ -25,23 +25,21 @@

                                                    Click an element to see who gets resized as a result. Elements with red bor
                                                  1. JavaScriptMVC is just WAY smart
                                                  2. - + + \ No newline at end of file diff --git a/event/resize/resize.js b/event/resize/resize.js index 2e486ed3..74c09ff5 100644 --- a/event/resize/resize.js +++ b/event/resize/resize.js @@ -1,4 +1,4 @@ -steal('jquery/event/reverse', function() { +steal('jquerypp/event/reverse', function($) { var // bind on the window window resizes to happen win = $(window), diff --git a/event/resize/resize.md b/event/resize/resize.md index 8faa99d0..b357e230 100644 --- a/event/resize/resize.md +++ b/event/resize/resize.md @@ -1,4 +1,4 @@ -@page jQuery.event.resize +@constructor jQuery.event.resize @parent jquerypp `jQuery.event.resize` allows you to listen to `resize` events on arbitrary elements. diff --git a/event/resize/resize_test.js b/event/resize/resize_test.js index 8d329237..18a5c07f 100644 --- a/event/resize/resize_test.js +++ b/event/resize/resize_test.js @@ -1,7 +1,7 @@ -steal('funcunit/qunit', 'jquery/event/resize').then(function() { +steal('steal-qunit', 'jquerypp/event/resize',function() { - module("jquery/event/resize") + module("jquerypp/event/resize") test("resize hits only children in order", function() { @@ -13,21 +13,21 @@ steal('funcunit/qunit', 'jquery/event/resize').then(function() { ids.push(this.id ? this.id : this) } }, - divs = $("#qunit-test-area").html("
                                                    ").find('div').bind('resize', record); + divs = $("#qunit-fixture").html("
                                                    ").find('div').bind('resize', record); $(document.body).bind('resize', record); - $("#qunit-test-area").children().eq(0).trigger("resize"); + $("#qunit-fixture").children().eq(0).trigger("resize"); - same(ids, ['1', '1.1', '1.2']) + deepEqual(ids, ['1', '1.1', '1.2']) ids = []; - $("#qunit-test-area").trigger("resize"); - same(ids, [document.body.tagName.toLowerCase(), '1', '1.1', '1.2', '2']); + $("#qunit-fixture").trigger("resize"); + deepEqual(ids, [document.body.tagName.toLowerCase(), '1', '1.1', '1.2', '2']); ids = []; $(window).trigger("resize"); - same(ids, [document.body.tagName.toLowerCase(), '1', '1.1', '1.2', '2']); + deepEqual(ids, [document.body.tagName.toLowerCase(), '1', '1.1', '1.2', '2']); $(document.body).unbind('resize', record); }); @@ -41,12 +41,12 @@ steal('funcunit/qunit', 'jquery/event/resize').then(function() { ev.stopPropagation(); } }, - divs = $("#qunit-test-area").html("
                                                    ").find('div').bind('resize', record); + divs = $("#qunit-fixture").html("
                                                    ").find('div').bind('resize', record); $(document.body).bind('resize', record); $(window).trigger("resize"); - same(ids, [document.body.tagName.toLowerCase(), '1']); + deepEqual(ids, [document.body.tagName.toLowerCase(), '1']); $(document.body).unbind('resize', record); }); @@ -58,15 +58,15 @@ steal('funcunit/qunit', 'jquery/event/resize').then(function() { ids.push(this.id ? this.id : this); }, - divs = $("#qunit-test-area").html("
                                                    "); + divs = $("#qunit-fixture").html("
                                                    "); divs.find("#1\\.1\\.1").bind("resize", record); divs.find("#1").bind("resize", record); $("#1\\.1").trigger("resize", [false]); - same(ids, ['1.1.1']); + deepEqual(ids, ['1.1.1']); - $("#qunit-test-area").empty(); + $("#qunit-fixture").empty(); }); diff --git a/event/resize/test.html b/event/resize/test.html new file mode 100644 index 00000000..1f9ae013 --- /dev/null +++ b/event/resize/test.html @@ -0,0 +1,3 @@ +jquerypp/event/resize + +
                                                    diff --git a/event/reverse/qunit.html b/event/reverse/qunit.html deleted file mode 100644 index 72e59180..00000000 --- a/event/reverse/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - jQuery.event.reverse QUnit Test - - - - -

                                                    jQuery.event.reverse Test Suite

                                                    - -

                                                    - -
                                                    -

                                                    - -
                                                    -
                                                      -
                                                      - - - \ No newline at end of file diff --git a/event/reverse/reverse.html b/event/reverse/reverse.html deleted file mode 100644 index 60bbdbb4..00000000 --- a/event/reverse/reverse.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - Move Demo Page - - - - -
                                                      - Drag me -
                                                      -
                                                      Innermost div
                                                      -
                                                      -
                                                      - - - - - - \ No newline at end of file diff --git a/event/reverse/reverse.js b/event/reverse/reverse.js index 3cc800fd..70caf666 100644 --- a/event/reverse/reverse.js +++ b/event/reverse/reverse.js @@ -1,7 +1,8 @@ -steal('jquery', function() { +steal('jquery', function($) { $.event.reverse = function(name, attributes) { var bound = $(), - count = 0; + count = 0, + dispatch = $.event.handle || $.event.dispatch; $.event.special[name] = { setup: function() { @@ -40,7 +41,7 @@ steal('jquery', function() { var where = data === false ? ev.target : this // trigger all this element's handlers - $.event.handle.call(where, ev, data); + dispatch.call(where, ev, data); if ( ev.isPropagationStopped() ) { count--; return; @@ -56,7 +57,7 @@ steal('jquery', function() { while (++index < length && (child = bound[index]) && (isWindow || $.contains(where, child)) ) { // call the event - $.event.handle.call(child, ev, data); + dispatch.call(child, ev, data); if ( ev.isPropagationStopped() ) { // move index until the item is not in the current child diff --git a/event/reverse/reverse_test.js b/event/reverse/reverse_test.js index df976dbd..8c3e3272 100644 --- a/event/reverse/reverse_test.js +++ b/event/reverse/reverse_test.js @@ -1,8 +1,11 @@ -steal('funcunit/qunit', 'jquery/event/move').then(function() { +steal('steal-qunit', 'jquerypp/event/move',function() { + + module('jquerypp/event/reverse') + $.event.reverse('test'); test('Event bubbling', 3, function() { - $('#qunit-test-area').html('
                                                      ' + + $('#qunit-fixture').html('
                                                      ' + '
                                                      ' + '
                                                      Innermost div
                                                      ' + '
                                                      ' + @@ -18,7 +21,7 @@ steal('funcunit/qunit', 'jquery/event/move').then(function() { }); test('stopPropagation', 2, function() { - $('#qunit-test-area').html('
                                                      ' + + $('#qunit-fixture').html('
                                                      ' + '
                                                      ' + '
                                                      Innermost div
                                                      ' + '
                                                      ' + @@ -38,14 +41,14 @@ steal('funcunit/qunit', 'jquery/event/move').then(function() { }); test('passing data', 1, function() { - $('#qunit-test-area').html('
                                                      ' + + $('#qunit-fixture').html('
                                                      ' + '
                                                      ' + '
                                                      Innermost div
                                                      ' + '
                                                      ' + '
                                                      '); $('#inner').on('test', function(ev, data) { - equals(data.data, true, 'data passed!'); + equal(data.data, true, 'data passed!'); }); $('#outer').trigger('test', { data: true }); diff --git a/event/reverse/test.html b/event/reverse/test.html new file mode 100644 index 00000000..f1f2fd2b --- /dev/null +++ b/event/reverse/test.html @@ -0,0 +1,3 @@ +jquerypp/event/reverse + +
                                                      diff --git a/event/selection/qunit.html b/event/selection/qunit.html deleted file mode 100644 index 8a555e7b..00000000 --- a/event/selection/qunit.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - selection QUnit Test - - - - - -

                                                      selection Test Suite

                                                      -

                                                      -
                                                      -

                                                      -
                                                      -
                                                        -
                                                        - - \ No newline at end of file diff --git a/event/selection/selection.html b/event/selection/selection.html deleted file mode 100644 index f71dfd2c..00000000 --- a/event/selection/selection.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - selection - - - - - - - - - - - - - - - - - - - - -
                                                        Select Textarea
                                                        Select Input
                                                        Select Within One Element

                                                        0123456789

                                                        Select Across Multiple Elements
                                                        012
                                                        345
                                                        - - -

                                                        Hello World! how are you today?

                                                        -

                                                        I am good, thank you.

                                                        -
                                                        - - - - - - \ No newline at end of file diff --git a/event/selection/selection.js b/event/selection/selection.js deleted file mode 100644 index b3cb8593..00000000 --- a/event/selection/selection.js +++ /dev/null @@ -1,97 +0,0 @@ -// a text selection event that is useful in mobile safari - -steal('jquery', 'jquery/dom/range', 'jquery/event/livehack', function($){ - - - var event = $.event; - - event.selection = { - delay : 300, - preventDefault : event.supportTouch - }; - - event.setupHelper( ["selectionStart","selectionEnd","selectionEnding","selectionMoving","selectionMove"], "mousedown", function(ev){ - //now start checking mousemoves to update location - var delegate = ev.delegateTarget || ev.currentTarget, - selector = ev.handleObj.selector, - ready = false, - el = this, - startRange = $.Range(ev), - getRange = function(ev){ - var range = $.Range(ev), - pos = startRange.compare("START_TO_START", range), - entire; - if(pos == -1 || pos == 0){ - return startRange.clone().move("END_TO_END", range) - } else { - return range.clone().move("END_TO_END", startRange) - } - }, - cleanUp = function(){ - $(delegate).unbind('mousemove', mousemove) - .unbind('mouseup',mouseup); - clearTimeout(moveTimer); - startRange = null; - }, - mouseup = function(moveev){ - - if(!ready){ - cleanUp(); - return - } - $.each(event.find(delegate, ["selectionMoving"], selector), function(){ - this.call(el, moveev, range) - }); - var range = getRange(moveev); - cleanUp(); - $.each(event.find(delegate, ["selectionEnd"], selector), function(){ - this.call(el, ev, range); - }); - - }, - mousemove = function(moveev){ - // safari keeps triggering moves even if we haven't moved - if(moveev.clientX == ev.clientX && moveev.clientY == ev.clientY){ - return; - } - - if(!ready){ - return cleanUp(); - } - $.each(event.find(delegate, ["selectionMoving"], selector), function(){ - this.call(el, moveev, range) - }); - var range = getRange(moveev); - $.each(event.find(delegate, ["selectionMove"], selector), function(){ - this.call(el, moveev, range) - }); - }, - start = function(){ - ready = true; - var startEv = event.selection.preventDefault ? $.Event('selectionStart') : ev; - var startEv = $.extend(ev, startEv) - $.each(event.find(delegate, ["selectionStart"], selector), function(){ - this.call(el, startEv, startRange) - }); - - if(event.selection.preventDefault && startEv.isDefaultPrevented()){ - ready = false; - cleanUp(); - } - }, - moveTimer; - - if(event.selection.preventDefault){ - ev.preventDefault(); - moveTimer = setTimeout(start, event.selection.delay); - } else { - start(); - } - - - $(delegate).bind('mousemove', mousemove) - .bind('mouseup',mouseup) - }); - - return $; -}); \ No newline at end of file diff --git a/event/selection/selection.md b/event/selection/selection.md deleted file mode 100644 index 6c3f076b..00000000 --- a/event/selection/selection.md +++ /dev/null @@ -1,3 +0,0 @@ -@page jQuery.event.selection -@parent jquerypp -@hide diff --git a/event/selection/selection_test.js b/event/selection/selection_test.js deleted file mode 100644 index 2a7e5131..00000000 --- a/event/selection/selection_test.js +++ /dev/null @@ -1,39 +0,0 @@ -steal("funcunit/qunit", "jquery/dom/selection").then(function(){ - -module("jquery/dom/selection"); - -test("getCharElement", function(){ - $("#qunit-test-area") - .html(""+ - ""+ - "

                                                        0123456789

                                                        "+ - "
                                                        012
                                                        345
                                                        "); - stop(); - setTimeout(function(){ - var types = ['textarea','#inp','#1','#2']; - for(var i =0; i< types.length; i++){ - console.log(types[i]) - $(types[i]).selection(1,5); - } - /* - $('textarea').selection(1,5); - $('input').selection(1,5); - $('#1').selection(1,5); - $('#2').selection(1,5); - */ - var res = []; - for(var i =0; i< types.length; i++){ - res.push( $(types[i]).selection() ); - } - - - - for(var i =0; i< res.length; i++){ - same(res[i],{start: 1, end: 5},types[i]) - } - - start(); - },1000) -}); - -}); \ No newline at end of file diff --git a/event/swipe/qunit.html b/event/swipe/qunit.html deleted file mode 100644 index e65f52bd..00000000 --- a/event/swipe/qunit.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - swipe QUnit Test - - - - - -

                                                        swipe Test Suite

                                                        -

                                                        -
                                                        -

                                                        -
                                                        -
                                                          -
                                                          - - \ No newline at end of file diff --git a/event/swipe/swipe.html b/event/swipe/swipe.html index 16aa793f..1cb0e229 100644 --- a/event/swipe/swipe.html +++ b/event/swipe/swipe.html @@ -29,22 +29,27 @@
                                                        1. Swipe Me
                                                        2. - + + \ No newline at end of file diff --git a/event/swipe/swipe.js b/event/swipe/swipe.js index b0769880..189d7db5 100644 --- a/event/swipe/swipe.js +++ b/event/swipe/swipe.js @@ -1,4 +1,4 @@ -steal('jquery', 'jquery/event/livehack', function($) { +steal('jquery', 'jquerypp/event/livehack', function($) { var isPhantom = /Phantom/.test(navigator.userAgent), supportTouch = !isPhantom && "ontouchend" in document, scrollEvent = "touchmove scroll", @@ -12,7 +12,7 @@ var isPhantom = /Phantom/.test(navigator.userAgent), event; return { time: (new Date).getTime(), - coords: [ d.pageX, d.pageY ], + coords: [ d.clientX, d.clientY ], origin: $( event.target ) }; }; @@ -22,19 +22,31 @@ var isPhantom = /Phantom/.test(navigator.userAgent), */ var swipe = $.event.swipe = { /** - * @attribute delay - * Delay is the upper limit of time the swipe motion can take in milliseconds. This defaults to 500. + * @property {Number} jQuery.event.swipe.delay delay + * @parent jQuery.event.swipe + * + * @body * + * Delay is the upper limit of time the swipe motion can take in milliseconds. This defaults to 500. + * * A user must perform the swipe motion in this much time. */ delay : 500, /** - * @attribute max + * @property {Number} jQuery.event.swipe.max max + * @parent jQuery.event.swipe + * + * @body + * * The maximum distance the pointer must travel in pixels. The default is 75 pixels. */ max : 320, /** - * @attribute min + * @property {Number} jQuery.event.swipe.min min + * @parent jQuery.event.swipe + * + * @body + * * The minimum distance the pointer must travel in pixels. The default is 30 pixels. */ min : 30 @@ -74,7 +86,7 @@ $.event.setupHelper( [ delegate = ev.delegateTarget || ev.currentTarget, selector = ev.handleObj.selector, entered = this; - + function moveHandler(event){ if ( !start ) { return; @@ -117,7 +129,7 @@ $.event.setupHelper( [ $.each($.event.find(delegate, events, selector), function(){ this.call(entered, ev, {start : start, end: stop}) }) - + } } // reset start and stop diff --git a/event/swipe/swipe.md b/event/swipe/swipe.md index 09bc5746..9a059653 100644 --- a/event/swipe/swipe.md +++ b/event/swipe/swipe.md @@ -1,4 +1,4 @@ -@page jQuery.event.swipe +@page jQuery.event.swipe jQuery.event.swipe @parent jquerypp `jQuery.event.swipe` provides cross browser `swipeleft`, `swiperight`, `swipeup`, `swipedown` and a general `swipe` event. diff --git a/event/swipe/swipe_test.js b/event/swipe/swipe_test.js index c21c64d6..47caacfc 100644 --- a/event/swipe/swipe_test.js +++ b/event/swipe/swipe_test.js @@ -1,121 +1,143 @@ -steal('funcunit/qunit','funcunit/syn','jquery/event/swipe').then(function(){ - -module("jquery/swipe", {setup : function(){ - $("#qunit-test-area").html("") - var div = $("
                                                          "+ - "
                                                          one
                                                          "+ - "
                                                          two
                                                          three
                                                          "+ - "
                                                          "); - - div.appendTo($("#qunit-test-area")); - var basicCss = { - position: "absolute", - border: "solid 1px black" - } - $("#outer").css(basicCss).css({top: "10px", left: "10px", - zIndex: 1000, backgroundColor: "green", width: "200px", height: "200px"}) -}}); - -test("swipe right event",2, function(){ - - $("#outer").bind("swipe",function(){ - ok(true,"swipe called"); - }).bind("swipeleft", function(){ - ok(false, "swipe left") - }).bind("swiperight", function(){ - ok(true, "swiperight") +steal('steal-qunit', 'syn', 'jquerypp/event/swipe', function (QUnit, syn) { + var swipe; + + module("jquerypp/swipe", { + setup : function () { + $("#qunit-fixture").html(""); + + var div = $("
                                                          " + + "
                                                          one
                                                          " + + "
                                                          two
                                                          three
                                                          " + + "
                                                          "); + + div.appendTo($("#qunit-fixture")); + var basicCss = { + position : "absolute", + border : "solid 1px black" + }; + + $("#outer").css(basicCss).css({top : "10px", left : "10px", + zIndex : 1000, backgroundColor : "green", width : "200px", height : "200px"}); + + $("#qunit-fixture").css({top: "0px", left: "0px"}); + + swipe = {}; + + $("#outer").bind("swipe",function () { + swipe.general = true; + }) + .bind("swipeleft",function () { + swipe.left = true; + }) + .bind("swiperight", function () { + swipe.right = true; + }) + .bind("swipeup", function () { + swipe.up = true; + }) + .bind("swipedown", function () { + swipe.down = true; + }); + }, + teardown: function(){ + $("#qunit-fixture").css({top: "", left: ""}); + } }); - stop(); - Syn.drag({ - from: "20x20", - to: "50x20", - duration: 100 - },"outer", function(){ - start(); - }) - -}); + test("swipe right event", 5, function () { + stop(); + syn.drag("outer", { + from : "20x20", + to : "50x20", + duration : 100 + }, function () { + start(); + + ok(swipe.general, 'swipe'); + ok(swipe.right, 'swipe right'); + + ok(!swipe.left, 'swipe left'); + ok(!swipe.up, 'swipe up'); + ok(!swipe.down, 'swipe down'); + }); -test("swipe left event",2, function(){ - - $("#outer").bind("swipe",function(){ - ok(true,"swipe called"); - }).bind("swipeleft", function(){ - ok(true, "swipe left") - }).bind("swiperight", function(){ - ok(false, "swiperight") }); - stop(); - Syn.drag({ - from: "50x20", - to: "20x20", - duration: 100 - },"outer", function(){ - start(); - }) - -}); -test("swipe up event",2, function(){ - - $("#outer").bind("swipe",function(){ - ok(true,"swipe called"); - }).bind("swipeup", function(){ - ok(true, "swipe left") - }).bind("swiperight", function(){ - ok(false, "swiperight") - }).bind("swipedown", function(){ - ok(false, "swipedown") + + test("swipe left event", 5, function () { + stop(); + + syn.drag("outer", { + from : "50x20", + to : "20x20", + duration : 100 + }, function () { + start(); + + ok(swipe.general, 'swipe'); + ok(swipe.left, 'swipe left'); + + ok(!swipe.right, 'swipe right'); + ok(!swipe.up, 'swipe up'); + ok(!swipe.down, 'swipe down'); + }); }); - stop(); - Syn.drag({ - from: "20x50", - to: "20x20", - duration: 100 - },"outer", function(){ - start(); - }) - -}); -test("swipe down event",2, function(){ - - $("#outer").bind("swipe",function(){ - ok(true,"swipe called"); - }).bind("swipeup", function(){ - ok(false, "swipe left") - }).bind("swiperight", function(){ - ok(false, "swiperight") - }).bind("swipedown", function(){ - ok(true, "swipedown") + + test("swipe up event", 5, function () { + stop(); + syn.drag("outer", { + from : "20x50", + to : "20x20", + duration : 100 + }, function () { + start(); + + ok(swipe.general, 'swipe'); + ok(swipe.up, 'swipe up'); + + ok(!swipe.left, 'swipe left'); + ok(!swipe.right, 'swipe right'); + ok(!swipe.down, 'swipe down'); + }) + }); - stop(); - Syn.drag({ - from: "20x20", - to: "20x50", - duration: 100 - },"outer", function(){ - start(); - }) - -}); -test("#33: using swipe.max", function() { + test("swipe down event", 5, function () { + stop(); + syn.drag("outer",{ + from : "20x20", + to : "20x50", + duration : 100 + }, function () { + start(); + ok(swipe.general, 'swipe'); + ok(swipe.down, 'swipe down'); + + ok(!swipe.left, 'swipe left'); + ok(!swipe.right, 'swipe right'); + ok(!swipe.up, 'swipe up'); + }); - $("#outer").bind("swipe",function(){ - ok(false,"Swipe shouldn't be called when dragged more than swipe.max"); }); - stop(); - Syn.drag({ - from: "20x20", - to: "20x96", - duration: 100 - },"outer", function(){ - start(); - }) -}) + test("#33: using swipe.max", function () { + + $.event.swipe.max = 75; + $("#outer").bind("swipe", function () { + ok(false, "Swipe shouldn't be called when dragged more than swipe.max"); + }); + stop(); + syn.drag("outer",{ + from : "20x20", + to : "20x96", + duration : 100 + }, function () { + ok(true, 'Done dragging'); + start(); + }) -}) \ No newline at end of file + }) + +}); diff --git a/event/swipe/test.html b/event/swipe/test.html new file mode 100644 index 00000000..4a72b503 --- /dev/null +++ b/event/swipe/test.html @@ -0,0 +1,3 @@ +jquerypp/event/swipe + +
                                                          diff --git a/event/tap/tap.html b/event/tap/tap.html index 6979f127..fb1c54e8 100644 --- a/event/tap/tap.html +++ b/event/tap/tap.html @@ -21,13 +21,13 @@
                                                          I'd Tap That - + \ No newline at end of file diff --git a/event/tap/tap.js b/event/tap/tap.js index 3b1d75f9..9c05b8e2 100644 --- a/event/tap/tap.js +++ b/event/tap/tap.js @@ -1,52 +1,73 @@ -steal('jquery', 'jquery/event/livehack', function($){ -var supportTouch = "ontouchend" in document, - scrollEvent = "touchmove scroll", - touchStartEvent = supportTouch ? "touchstart" : "mousedown", - touchStopEvent = supportTouch ? "touchend" : "mouseup", - touchMoveEvent = supportTouch ? "touchmove" : "mousemove", - data = function(event){ - var d = event.originalEvent.touches ? - event.originalEvent.touches[ 0 ] || event.originalEvent.changedTouches[ 0 ] : - event; - return { - time: (new Date).getTime(), - coords: [ d.pageX, d.pageY ], - origin: $( event.target ) - }; - }; - -/** - * @add jQuery.event.special - */ -$.event.setupHelper( ["tap"], touchStartEvent, function(ev){ - //listen to mouseup - var start = data(ev), - stop, - delegate = ev.delegateTarget || ev.currentTarget, - selector = ev.handleObj.selector, - entered = this, - moved = false, - touching = true, - timer; - - - function upHandler(event){ - stop = data(event); - if ((Math.abs( start.coords[0] - stop.coords[0] ) < 10) || - ( Math.abs( start.coords[1] - stop.coords[1] ) < 10) ){ - $.each($.event.find(delegate, ["tap"], selector), function(){ - this.call(entered, ev, {start : start, end: stop}) - }) +steal('jquery', 'jquerypp/event/livehack', function( $ ) { + + var supportTouch = "ontouchend" in document, + scrollEvent = "touchmove scroll", + touchStartEvent = supportTouch ? "touchstart" : "mousedown", + touchStopEvent = supportTouch ? "touchend" : "mouseup", + touchMoveEvent = supportTouch ? "touchmove" : "mousemove", + data = function(event){ + var d = event.originalEvent.touches ? + event.originalEvent.touches[ 0 ] || event.originalEvent.changedTouches[ 0 ] : + event; + return { + time: (new Date()).getTime(), + coords: [ d.pageX, d.pageY ], + origin: $( event.target ) + }; + }, + touchStartTime = Date.now(), + touchStart = {}; + + // Listen and record information on touch start + $(document.body).on(touchStartEvent, function(ev) { + touchStart = data(ev); + touchStartTime = Date.now(); + }); + + /** + * @add jQuery.event.special + */ + $.event.setupHelper( ["tap"], touchStopEvent, function( ev ) { + //listen to mouseup + var stop = data(ev), + start = touchStart, + delegate = ev.delegateTarget || ev.currentTarget, + $delegate = $(delegate), + originalEvent = ev, + selector = ev.handleObj.selector, + entered = this, + moved = false, + touching = true, + timer, + now = new Date(); + + + // If the time between touch up and down was small and user's finger + // didn't move far, find all the tap events and trigger. + if(now - touchStartTime < 500 && ( Math.abs( start.coords[0] - stop.coords[0] ) < 10) && + ( Math.abs( start.coords[1] - stop.coords[1] ) < 10 )) { + $.each($.event.find( delegate, ["tap"], selector ), function() { + + var tap = new $.Event('tap'); + + var result = this.call( entered, tap, { + start : start, + end: stop + }); + + if(result == false || tap.isDefaultPrevented()) { + originalEvent.preventDefault(); + } + if(result == false || tap.isPropagationStopped()) { + originalEvent.stopPropagation(); + } + if(tap.isImmediatePropagationStopped()) { + originalEvent.stopImmediatePropagation(); + } + }); } - }; - - timer = setTimeout(function() { - $(delegate).unbind(touchStopEvent, upHandler); - }, 500 ); - - $(delegate).one(touchStopEvent, upHandler); - -}); + + }); -return $; -}); \ No newline at end of file + return $; +}); diff --git a/iframe.html b/iframe.html new file mode 100644 index 00000000..46edda98 --- /dev/null +++ b/iframe.html @@ -0,0 +1,8 @@ + + + iframe + + +
                                                          span text
                                                          + + \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 00000000..ba35731c --- /dev/null +++ b/index.js @@ -0,0 +1,20 @@ +steal('jquery', + 'jquerypp/dom/animate', + 'jquerypp/dom/compare', + 'jquerypp/dom/cookie', + 'jquerypp/dom/form_params', + 'jquerypp/dom/range', + 'jquerypp/dom/selection', + 'jquerypp/dom/within', + 'jquerypp/event/drag', + 'jquerypp/event/drop', + 'jquerypp/event/hover', + 'jquerypp/event/key', + 'jquerypp/event/pause', + 'jquerypp/event/removed', + 'jquerypp/event/resize', + 'jquerypp/event/swipe', + 'jquerypp/lang/vector', + function($) { + return $; + }); \ No newline at end of file diff --git a/jquerypp.md b/jquerypp.md index d137a2e0..2604537c 100644 --- a/jquerypp.md +++ b/jquerypp.md @@ -1,5 +1,5 @@ @page jquerypp jQuery++ -@parent index 1 +@parent javascriptmvc 1 @description jQuery's missing utils and special events jQuery++ is a collection of useful jQuery libraries that provide @@ -9,11 +9,11 @@ implement and organize large-scale jQuery applications. ## DOM Helpers DOM helpers extend jQuery with extra functionality for -manipulating the DOM. For example, [dimensions] lets you set the +manipulating the DOM. For example, [dimensions] lets you set the outer width and height of elements like: $('#foo').outerWidth(500); - + jQuery++ comes with the following DOM helper plugins: - [jQuery.animate Animate] - Let jQuery use CSS animations. @@ -31,7 +31,7 @@ jQuery++ comes with the following DOM helper plugins: jQuery++ also adds a number of new events to jQuery that make creating responsive applications a lot easier: - [jQuery.event.default Default] - Provide default behaviors for events. -- [jQuery.event.destroyed Destroyed] - Know when an element is removed from the page. +- [jQuery.event.removed Removed] - Know when an element is removed from the page. - [jQuery.event.drag Drag] - Delegatable drag events. - [jQuery.event.drop Drop] - Delegatable drop events. - [jQuery.event.fastfix Fastfix] - Speed up jQuery event handling. diff --git a/lang/json/json.js b/lang/json/json.js deleted file mode 100644 index 8d74b29c..00000000 --- a/lang/json/json.js +++ /dev/null @@ -1,212 +0,0 @@ -/* - * jQuery JSON Plugin - * version: 2.1 (2009-08-14) - * - * This document is licensed as free software under the terms of the - * MIT License: http://www.opensource.org/licenses/mit-license.php - * - * Brantley Harris wrote this plugin. It is based somewhat on the JSON.org - * website's http://www.json.org/json2.js, which proclaims: - * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that - * I uphold. - * - * It is also influenced heavily by MochiKit's serializeJSON, which is - * copyrighted 2005 by Bob Ippolito. - */ -// - - steal('jquery', function($) { - /** - * @page jQuery.toJSON jQuery.toJSON - * @parent jquerymx.lang - * - * jQuery.toJSON( json-serializble ) - * - * Converts the given argument into a JSON respresentation. - * - * If an object has a "toJSON" function, that will - * be used to get the representation. - * Non-integer/string keys are skipped in the - * object, as are keys that point to a function. - * - * json-serializble: - * The *thing* to be converted. - */ - $.toJSON = function(o, replacer, space, recurse) - { - if (typeof(JSON) == 'object' && JSON.stringify) - return JSON.stringify(o, replacer, space); - - if (!recurse && $.isFunction(replacer)) - o = replacer("", o); - - if (typeof space == "number") - space = " ".substring(0, space); - space = (typeof space == "string") ? space.substring(0, 10) : ""; - - var type = typeof(o); - - if (o === null) - return "null"; - - if (type == "undefined" || type == "function") - return undefined; - - if (type == "number" || type == "boolean") - return o + ""; - - if (type == "string") - return $.quoteString(o); - - if (type == 'object') - { - if (typeof o.toJSON == "function") - return $.toJSON( o.toJSON(), replacer, space, true ); - - if (o.constructor === Date) - { - var month = o.getUTCMonth() + 1; - if (month < 10) month = '0' + month; - - var day = o.getUTCDate(); - if (day < 10) day = '0' + day; - - var year = o.getUTCFullYear(); - - var hours = o.getUTCHours(); - if (hours < 10) hours = '0' + hours; - - var minutes = o.getUTCMinutes(); - if (minutes < 10) minutes = '0' + minutes; - - var seconds = o.getUTCSeconds(); - if (seconds < 10) seconds = '0' + seconds; - - var milli = o.getUTCMilliseconds(); - if (milli < 100) milli = '0' + milli; - if (milli < 10) milli = '0' + milli; - - return '"' + year + '-' + month + '-' + day + 'T' + - hours + ':' + minutes + ':' + seconds + - '.' + milli + 'Z"'; - } - - var process = ($.isFunction(replacer)) ? - function (k, v) { return replacer(k, v); } : - function (k, v) { return v; }, - nl = (space) ? "\n" : "", - sp = (space) ? " " : ""; - - if (o.constructor === Array) - { - var ret = []; - for (var i = 0; i < o.length; i++) - ret.push(( $.toJSON( process(i, o[i]), replacer, space, true ) || "null" ).replace(/^/gm, space)); - - return "[" + nl + ret.join("," + nl) + nl + "]"; - } - - var pairs = [], proplist; - if ($.isArray(replacer)) { - proplist = $.map(replacer, function (v) { - return (typeof v == "string" || typeof v == "number") ? - v + "" : - null; - }); - } - for (var k in o) { - var name, val, type = typeof k; - - if (proplist && $.inArray(k + "", proplist) == -1) - continue; - - if (type == "number") - name = '"' + k + '"'; - else if (type == "string") - name = $.quoteString(k); - else - continue; //skip non-string or number keys - - val = $.toJSON( process(k, o[k]), replacer, space, true ); - - if (typeof val == "undefined") - continue; //skip pairs where the value is a function. - - pairs.push((name + ":" + sp + val).replace(/^/gm, space)); - } - - return "{" + nl + pairs.join("," + nl) + nl + "}"; - } - }; - - /** - * @function jQuery.evalJSON - * Evaluates a given piece of json source. - **/ - $.evalJSON = function(src) - { - if (typeof(JSON) == 'object' && JSON.parse) - return JSON.parse(src); - return eval("(" + src + ")"); - }; - - /** - * @function jQuery.secureEvalJSON - * Evals JSON in a way that is *more* secure. - **/ - $.secureEvalJSON = function(src) - { - if (typeof(JSON) == 'object' && JSON.parse) - return JSON.parse(src); - - var filtered = src; - filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@'); - filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']'); - filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, ''); - - if (/^[\],:{}\s]*$/.test(filtered)) - return eval("(" + src + ")"); - else - throw new SyntaxError("Error parsing JSON, source is not valid."); - }; - - /** - * @function jQuery.quoteString - * - * Returns a string-repr of a string, escaping quotes intelligently. - * Mostly a support function for toJSON. - * - * Examples: - * - * jQuery.quoteString("apple") //-> "apple" - * - * jQuery.quoteString('"Where are we going?", she asked.') - * // -> "\"Where are we going?\", she asked." - **/ - $.quoteString = function(string) - { - if (string.match(_escapeable)) - { - return '"' + string.replace(_escapeable, function (a) - { - var c = _meta[a]; - if (typeof c === 'string') return c; - c = a.charCodeAt(); - return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); - }) + '"'; - } - return '"' + string + '"'; - }; - - var _escapeable = /["\\\x00-\x1f\x7f-\x9f]/g; - - var _meta = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '\\': '\\\\' - }; -}) \ No newline at end of file diff --git a/lang/lang_test.js b/lang/lang_test.js index 4cf8a3f5..e7fe3198 100644 --- a/lang/lang_test.js +++ b/lang/lang_test.js @@ -1 +1 @@ -steal('./object/object_test','./observe/observe_test','./string/string_test', './vector/vector_test.js') +steal('./vector/vector_test.js') diff --git a/lang/object/object.html b/lang/object/object.html deleted file mode 100644 index 7d4be073..00000000 --- a/lang/object/object.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - object - - - -

                                                          object Demo

                                                          -

                                                          This is a dummy page to show off your plugin

                                                          - - - - \ No newline at end of file diff --git a/lang/object/object.js b/lang/object/object.js deleted file mode 100644 index d81f23c7..00000000 --- a/lang/object/object.js +++ /dev/null @@ -1,225 +0,0 @@ -steal('jquery',function($){ - -var isArray = $.isArray, - // essentially returns an object that has all the must have comparisons ... - // must haves, do not return true when provided undefined - cleanSet = function(obj, compares){ - var copy = $.extend({}, obj); - for(var prop in copy) { - var compare = compares[prop] === undefined ? compares["*"] : compares[prop]; - if( same(copy[prop], undefined, compare ) ) { - delete copy[prop] - } - } - return copy; - }, - propCount = function(obj){ - var count = 0; - for(var prop in obj) count++; - return count; - }; - -/** - * @class jQuery.Object - * @parent jquerymx.lang - * - * Object contains several helper methods that - * help compare objects. - * - * ## same - * - * Returns true if two objects are similar. - * - * $.Object.same({foo: "bar"} , {bar: "foo"}) //-> false - * - * ## subset - * - * Returns true if an object is a set of another set. - * - * $.Object.subset({}, {foo: "bar"} ) //-> true - * - * ## subsets - * - * Returns the subsets of an object - * - * $.Object.subsets({userId: 20}, - * [ - * {userId: 20, limit: 30}, - * {userId: 5}, - * {} - * ]) - * //-> [{userId: 20, limit: 30}] - */ -$.Object = {}; - -/** - * @function same - * Returns if two objects are the same. It takes an optional compares object that - * can be used to make comparisons. - * - * This function does not work with objects that create circular references. - * - * ## Examples - * - * $.Object.same({name: "Justin"}, - * {name: "JUSTIN"}) //-> false - * - * // ignore the name property - * $.Object.same({name: "Brian"}, - * {name: "JUSTIN"}, - * {name: null}) //-> true - * - * // ignore case - * $.Object.same({name: "Justin"}, - * {name: "JUSTIN"}, - * {name: "i"}) //-> true - * - * // deep rule - * $.Object.same({ person : { name: "Justin" } }, - * { person : { name: "JUSTIN" } }, - * { person : { name: "i" } }) //-> true - * - * // supplied compare function - * $.Object.same({age: "Thirty"}, - * {age: 30}, - * {age: function( a, b ){ - * if( a == "Thirty" ) { - * a = 30 - * } - * if( b == "Thirty" ) { - * b = 30 - * } - * return a === b; - * }}) //-> true - * - * @param {Object} a an object to compare - * @param {Object} b an object to compare - * @param {Object} [compares] an object that indicates how to - * compare specific properties. - * Typically this is a name / value pair - * - * $.Object.same({name: "Justin"},{name: "JUSTIN"},{name: "i"}) - * - * There are two compare functions that you can specify with a string: - * - * - 'i' - ignores case - * - null - ignores this property - * - * @param {Object} [deep] used internally - */ -var same = $.Object.same = function(a, b, compares, aParent, bParent, deep){ - var aType = typeof a, - aArray = isArray(a), - comparesType = typeof compares, - compare; - - if(comparesType == 'string' || compares === null ){ - compares = compareMethods[compares]; - comparesType = 'function' - } - if(comparesType == 'function'){ - return compares(a, b, aParent, bParent) - } - compares = compares || {}; - - if(deep === -1){ - return aType === 'object' || a === b; - } - if(aType !== typeof b || aArray !== isArray(b)){ - return false; - } - if(a === b){ - return true; - } - if(aArray){ - if(a.length !== b.length){ - return false; - } - for(var i =0; i < a.length; i ++){ - compare = compares[i] === undefined ? compares["*"] : compares[i] - if(!same(a[i],b[i], a, b, compare )){ - return false; - } - }; - return true; - } else if(aType === "object" || aType === 'function'){ - var bCopy = $.extend({}, b); - for(var prop in a){ - compare = compares[prop] === undefined ? compares["*"] : compares[prop]; - if(! same( a[prop], b[prop], compare , a, b, deep === false ? -1 : undefined )){ - return false; - } - delete bCopy[prop]; - } - // go through bCopy props ... if there is no compare .. return false - for(prop in bCopy){ - if( compares[prop] === undefined || - ! same( undefined, b[prop], compares[prop] , a, b, deep === false ? -1 : undefined )){ - return false; - } - } - return true; - } - return false; -}; - -/** - * @function subsets - * Returns the sets in 'sets' that are a subset of checkSet - * @param {Object} checkSet - * @param {Object} sets - */ -$.Object.subsets = function(checkSet, sets, compares){ - var len = sets.length, - subsets = [], - checkPropCount = propCount(checkSet), - setLength; - - for(var i =0; i < len; i++){ - //check this subset - var set = sets[i]; - if( $.Object.subset(checkSet, set, compares) ){ - subsets.push(set) - } - } - return subsets; -}; -/** - * @function subset - * Compares if checkSet is a subset of set - * @param {Object} checkSet - * @param {Object} set - * @param {Object} [compares] - * @param {Object} [checkPropCount] - */ -$.Object.subset = function(subset, set, compares){ - // go through set {type: 'folder'} and make sure every property - // is in subset {type: 'folder', parentId :5} - // then make sure that set has fewer properties - // make sure we are only checking 'important' properties - // in subset (ones that have to have a value) - - var setPropCount =0, - compares = compares || {}; - - for(var prop in set){ - - if(! same(subset[prop], set[prop], compares[prop], subset, set ) ){ - return false; - } - } - return true; -} - - -var compareMethods = { - "null" : function(){ - return true; - }, - i : function(a, b){ - return (""+a).toLowerCase() == (""+b).toLowerCase() - } -} - - -}); \ No newline at end of file diff --git a/lang/object/object_test.js b/lang/object/object_test.js deleted file mode 100644 index c1952713..00000000 --- a/lang/object/object_test.js +++ /dev/null @@ -1,105 +0,0 @@ -steal('funcunit/qunit','./object',function(){ - -module("object"); - -test("same", function(){ - - - ok( $.Object.same({type: "FOLDER"},{type: "FOLDER", count: 5}, { - count: null - }), "count ignored" ); - - ok( $.Object.same({type: "folder"},{type: "FOLDER"}, { - type: "i" - }), "folder case ignored" ); -}) - -test("subsets", function(){ - - var res1 = $.Object.subsets({parentId: 5, type: "files"}, - [{parentId: 6}, {type: "folders"}, {type: "files"}]); - - same(res1,[{type: "files"}]) - - var res2 = $.Object.subsets({parentId: 5, type: "files"}, - [{}, {type: "folders"}, {type: "files"}]); - - same(res2,[{},{type: "files"}]); - - var res3 = $.Object.subsets({parentId: 5, type: "folders"}, - [{parentId: 5},{type: "files"}]); - - same(res3,[{parentId: 5}]) -}); - -test("subset compare", function(){ - - ok( $.Object.subset( - {type: "FOLDER"}, - {type: "FOLDER"}), - - "equal sets" ); - - ok( $.Object.subset( - {type: "FOLDER", parentId: 5}, - {type: "FOLDER"}), - - "sub set" ); - - ok(! $.Object.subset( - {type: "FOLDER"}, - {type: "FOLDER", parentId: 5}), - - "wrong way" ); - - - ok(! $.Object.subset( - {type: "FOLDER", parentId: 7}, - {type: "FOLDER", parentId: 5}), - - "different values" ); - - ok( $.Object.subset( - {type: "FOLDER", count: 5}, // subset - {type: "FOLDER"}, - {count: null} ), - - "count ignored" ); - - - ok( $.Object.subset( - {type: "FOLDER", kind: "tree"}, // subset - {type: "FOLDER", foo: true, bar: true }, - {foo: null, bar: null} ), - - "understands a subset" ); - ok( $.Object.subset( - {type: "FOLDER", foo: true, bar: true }, - {type: "FOLDER", kind: "tree"}, // subset - - {foo: null, bar: null, kind : null} ), - - "ignores nulls" ); -}); - -test("searchText", function(){ - var item = { - id: 1, - name: "thinger" - }, - searchText = { - searchText : "foo" - }, - compare = { - searchText : function(items, paramsText, itemr, params){ - equals(item,itemr); - equals(searchText, params) - return true; - } - }; - - ok( $.Object.subset( item, searchText, compare ), "searchText" ); -}); - - -}); \ No newline at end of file diff --git a/lang/object/qunit.html b/lang/object/qunit.html deleted file mode 100644 index d661e08c..00000000 --- a/lang/object/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - object QUnit Test - - - - -

                                                          object Test Suite

                                                          -

                                                          -
                                                          -

                                                          -
                                                          -
                                                            -
                                                            - - \ No newline at end of file diff --git a/lang/observe/delegate/delegate.js b/lang/observe/delegate/delegate.js deleted file mode 100644 index 0d1b744e..00000000 --- a/lang/observe/delegate/delegate.js +++ /dev/null @@ -1,4 +0,0 @@ -steal('jquery/lang/observe','can/observe/delegate',function(){ - - -}) diff --git a/lang/observe/delegate/delegate_test.js b/lang/observe/delegate/delegate_test.js deleted file mode 100644 index 028e44c9..00000000 --- a/lang/observe/delegate/delegate_test.js +++ /dev/null @@ -1,253 +0,0 @@ -steal('funcunit/qunit','jquery/lang/observe',function(){ - - -module('jquery/lang/observe/delegate') - -var matches = $.Observe.prototype.delegate.matches; - -test("matches", function(){ - - equals( matches(['**'], ['foo','bar','0']) , - 'foo.bar.0' , "everything" ); - - equals( matches(['*.**'], ['foo']) , - null , "everything at least one level deep" ) - - equals( matches(['foo','*'], ['foo','bar','0']) , - 'foo.bar' ) - - equals(matches(['*'], - ['foo','bar','0']) , - 'foo' ); - - equals( matches([ '*', 'bar' ], - ['foo','bar','0']) , - 'foo.bar' ) - // - props - - // - returns - 'foo.bar' -}) - -test("list events", function(){ - return; - var list = new $.Observe.List([ - {name: 'Justin'}, - {name: 'Brian'}, - {name: 'Austin'}, - {name: 'Mihael'}]) - list.comparator = 'name'; - list.sort(); - // events on a list - // - move - item from one position to another - // due to changes in elements that change the sort order - // - add (items added to a list) - // - remove (items removed from a list) - // - reset (all items removed from the list) - // - change something happened - - // a move directly on this list - list.bind('move', function(ev, item, newPos, oldPos){ - ok(true,"move called"); - equals(item.name, "Zed"); - equals(newPos, 3); - equals(oldPos, 0); - }); - - // a remove directly on this list - list.bind('remove', function(ev, items, oldPos){ - ok(true,"remove called"); - equals(items.length,1); - equals(items[0].name, 'Alexis'); - equals(oldPos, 0, "put in right spot") - }) - list.bind('add', function(ev, items, newPos){ - ok(true,"add called"); - equals(items.length,1); - equals(items[0].name, 'Alexis'); - equals(newPos, 0, "put in right spot") - }); - - list.push({name: 'Alexis'}); - - // now lets remove alexis ... - list.splice(0,1); - list[0].attr('name',"Zed") -}) - - -test("delegate", 4,function(){ - - var state = new $.Observe({ - properties : { - prices : [] - } - }); - var prices = state.attr('properties.prices'); - - state.delegate("properties.prices","change", function(ev, attr, how, val, old){ - equals(attr, "0", "correct change name") - equals(how, "add") - equals(val[0].attr("foo"),"bar", "correct") - ok(this === prices, "rooted element") - }); - - prices.push({foo: "bar"}); - - state.undelegate(); - -}) -test("delegate on add", 2, function(){ - - var state = new $.Observe({}); - - state.delegate("foo","add", function(ev, newVal){ - ok(true, "called"); - equals(newVal, "bar","got newVal") - }).delegate("foo","remove", function(){ - ok(false,"remove should not be called") - }); - - state.attr("foo","bar") - -}) - -test("delegate set is called on add", 2, function(){ - var state = new $.Observe({}); - - state.delegate("foo","set", function(ev, newVal){ - ok(true, "called"); - equals(newVal, "bar","got newVal") - }); - state.attr("foo","bar") -}); - -test("delegate's this", 5, function(){ - var state = new $.Observe({ - person : { - name : { - first : "justin", - last : "meyer" - } - }, - prop : "foo" - }); - var n = state.attr('person.name'), - check - - // listen to person name changes - state.delegate("person.name","set", check = function(ev, newValue, oldVal, from){ - // make sure we are getting back the person.name - equals(this, n) - equals(newValue, "Brian"); - equals(oldVal, "justin"); - // and how to get there - equals(from,"first") - }); - n.attr('first',"Brian"); - state.undelegate("person.name",'set',check) - // stop listening - - // now listen to changes in prop - state.delegate("prop","set", function(){ - equals(this, 'food'); - }); // this is weird, probably need to support direct bind ... - - // update the prop - state.attr('prop','food') -}) - - -test("delegate on deep properties with *", function(){ - var state = new $.Observe({ - person : { - name : { - first : "justin", - last : "meyer" - } - } - }); - - state.delegate("person","set", function(ev, newVal, oldVal, attr){ - equals(this, state.attr('person'), "this is set right") - equals(attr, "name.first") - }); - state.attr("person.name.first","brian") -}); - -test("compound sets", function(){ - - var state = new $.Observe({ - type : "person", - id: "5" - }); - var count = 0; - state.delegate("type=person id","set", function(){ - equals(state.type, "person","type is person") - ok(state.id !== undefined, "id has value"); - count++; - }) - - // should trigger a change - state.attr("id",0); - equals(count, 1, "changing the id to 0 caused a change"); - - // should not fire a set - state.removeAttr("id") - equals(count, 1, "removing the id changed nothing"); - - state.attr("id",3) - equals(count, 2, "adding an id calls callback"); - - state.attr("type","peter") - equals(count, 2, "changing the type does not fire callback"); - - state.removeAttr("type"); - state.removeAttr("id"); - - equals(count, 2, ""); - - state.attr({ - type : "person", - id: "5" - }); - - equals(count, 3, "setting person and id only fires 1 event"); - - state.removeAttr("type"); - state.removeAttr("id"); - - state.attr({ - type : "person" - }); - equals(count, 3, "setting person does not fire anything"); -}) - -test("undelegate within event loop",1, function(){ - - var state = new $.Observe({ - type : "person", - id: "5" - }); - var f1 = function(){ - state.undelegate("type","add",f2); - }, - f2 = function(){ - ok(false,"I am removed, how am I called") - }, - f3 = function(){ - state.undelegate("type","add",f1); - }, - f4 = function(){ - ok(true,"f4 called") - }; - state.delegate("type", "set", f1); - state.delegate("type","set",f2); - state.delegate("type","set",f3); - state.delegate("type","set",f4); - state.attr("type","other"); - -}) - - - - -}); \ No newline at end of file diff --git a/lang/observe/demo.html b/lang/observe/demo.html deleted file mode 100644 index 301be853..00000000 --- a/lang/observe/demo.html +++ /dev/null @@ -1,140 +0,0 @@ - - - - object - - - -

                                                            My Unsorted Todo List

                                                            -
                                                              - -
                                                            -

                                                            My Sorted Todo List

                                                            -
                                                              - -
                                                            - -
                                                            - - - - - \ No newline at end of file diff --git a/lang/observe/observe.html b/lang/observe/observe.html deleted file mode 100644 index 4a9d0a8f..00000000 --- a/lang/observe/observe.html +++ /dev/null @@ -1,83 +0,0 @@ - - - - object - - - -

                                                            $.Observe Demo

                                                            -

                                                            Make changes to the JSON in the following textarea. - Click Update Attrs to merge the JSON and see the events produced.

                                                            -
                                                            o = new $.Observe({})
                                                            -
                                                            o.attrs(
                                                            -, true) -
                                                            
                                                            -	
                                                            o.bind('change', function( ev, attr, how, newValue, prevValue, where ) { 
                                                            - - - - - - - - - -
                                                            attrhownewValueprevValuewhere
                                                            - - - - - - \ No newline at end of file diff --git a/lang/observe/observe.js b/lang/observe/observe.js deleted file mode 100644 index 36b79355..00000000 --- a/lang/observe/observe.js +++ /dev/null @@ -1,3 +0,0 @@ -steal('can/util', 'jquery', 'can/observe', function(can) { - $.Observe = can.Observe; -}); diff --git a/lang/observe/observe.md b/lang/observe/observe.md deleted file mode 100644 index 12d9302d..00000000 --- a/lang/observe/observe.md +++ /dev/null @@ -1,86 +0,0 @@ -## 3.1 Backlog - Deferreds - -jQuery 1.6 brought Deferred support. They are a great feature -that promise to make a lot of asynchronous functionality -easier to write and manage. But, many people struggle -with uses other than 'waiting for a bunch of Ajax requests to complete'. For 3.1, we -identified an extremely common, but annoying, practice that becomes -a one-liner with deferreds: loading data and a template and rendering the -result into an element. - -## Templates Consume Deferreds - -Here's what that looks like in 3.1: - - $('#todos').html('temps/todos.ejs', $.get('/todos',{},'json') ); - -This will make two parallel ajax requests. One request -is made for the template at `temps/todos.ejs` which might look like: - -
                                                            <% for(var i =0; i< this.length; i++) { %>
                                                            -  <li><%= this[i].name %></li>
                                                            -<% } %>
                                                            -
                                                            - -The second request loads `/todos` which might look like: - - [ - {"id" : 1, "name": "Take out the Trash"}, - {"id" : 2, "name": "Do the Laundry"} - ] - -When both have been loaded, the template is rendered with the todos data and -the result set as the `#todos` element's innerHTML. - -This is fab fast! The AJAX and template request are made in parallel and rendered -when both are complete. I am too lazy to write -out what this would look like before deferreds. Actually, I'm not too lazy: - - var template, - data, - done = function(){ - if( template && data ) { - var html = new EJS({text: template}) - .render(data); - $('#todos').html( html ) - } - } - $.get('temps/todos.ejs', function(text){ - template = text; - done(); - },'text') - $.get('/todos',{}, function(json){ - data = json - done(); - },'json') - -## Models Return Deferreds - -Model AJAX functions now return deferreds. Creating models like: - - $.Model('User',{ - findAll: '/users' - },{}); - - $.Model('Todo',{ - findAll: '/todos' - },{}) - -Lets you request todos and users and get back a deferred that can be -used in functions that accept deferreds like $.when: - - $.when( User.findAll(), - Todo.findAll() ) - -Or $.View: - - $('#content').html('temps/content.ejs',{ - users : User.findAll(), - todos: Todo.findAll() - }) - -## Conclusion - -Despite using templates, this is -still 'waiting for a bunch of Ajax requests to complete'. Does -anyone have other good uses for deferreds? diff --git a/lang/observe/observe_test.js b/lang/observe/observe_test.js deleted file mode 100644 index c33b9514..00000000 --- a/lang/observe/observe_test.js +++ /dev/null @@ -1,312 +0,0 @@ -steal('funcunit/qunit','jquery/lang/observe/delegate',function(){ - -module('jquery/lang/observe') - -test("Basic Observe",9,function(){ - - var state = new $.Observe({ - category : 5, - productType : 4, - properties : { - brand: [], - model : [], - price : [] - } - }); - - var added; - - state.bind("change", function(ev, attr, how, val, old){ - equals(attr, "properties.brand.0", "correct change name") - equals(how, "add") - equals(val[0].attr("foo"),"bar", "correct") - - added = val[0]; - }); - - - - state.attr("properties.brand").push({foo: "bar"}); - state.unbind("change"); - - added.bind("change", function(ev, attr, how, val, old){ - equals(attr, "foo") - equals(how, "set") - equals(val, "zoo") - }) - state.bind("change", function(ev, attr, how, val, old){ - equals(attr, "properties.brand.0.foo") - equals(how, "set") - equals(val,"zoo") - }); - added.attr("foo", "zoo"); - -}); - -test("list splice", function(){ - var l = new $.Observe.List([0,1,2,3]), - first = true; - - l.bind('change', function( ev, attr, how, newVals, oldVals ) { - equals (attr, "1") - // where comes from the attr ... - //equals(where, 1) - if(first){ - equals( how, "remove", "removing items" ) - equals( newVals, undefined, "no new Vals" ) - } else { - same( newVals, ["a","b"] , "got the right newVals") - equals( how, "add", "adding items" ) - } - - first = false; - }) - - l.splice(1,2, "a", "b"); - same(l.serialize(), [0,"a","b", 3], "serialized") -}); - -test("list pop", function(){ - var l = new $.Observe.List([0,1,2,3]); - - l.bind('change', function( ev, attr, how, newVals, oldVals ) { - equals (attr, "3") - - equals( how, "remove" ) - equals( newVals, undefined ) - same( oldVals, [3] ) - }) - - l.pop(); - same(l.serialize(), [0,1,2]) -}) - -test("changing an object unbinds", function(){ - var state = new $.Observe({ - category : 5, - productType : 4, - properties : { - brand: [], - model : [], - price : [] - } - }), - count = 0; - - var brand = state.attr("properties.brand"); - - state.bind("change", function(ev, attr, how, val, old){ - equals(attr,"properties.brand"); - - equals(count, 0, "count called once"); - count++; - equals(how, "set") - equals(val[0], "hi") - }); - if (typeof console != "undefined") console.log("before") - state.attr("properties.brand",["hi"]); - if (typeof console != "undefined") console.log("after") - - brand.push(1,2,3); - -}); - -test("replacing with an object that object becomes observable",function(){ - var state = new $.Observe({ - properties : { - brand: [], - model : [], - price : [] - } - }); - - ok(state.attr("properties").bind, "has bind function"); - - state.attr("properties",{}); - - ok(state.attr("properties").bind, "has bind function"); -}); - -test("remove attr", function(){ - var state = new $.Observe({ - properties : { - brand: [], - model : [], - price : [] - } - }); - - state.bind("change", function(ev, attr, how, newVal, old){ - equals(attr, "properties"); - equals(how, "remove") - same(old.serialize() ,{ - brand: [], - model : [], - price : [] - } ); - }) - - state.removeAttr("properties"); - equals(undefined, state.attr("properties") ); -}); - -test("attr", function(){ - var state = new $.Observe({ - properties : { - foo: "bar", - brand: [] - } - }); - - state.bind("change", function(ev, attr, how, newVal){ - equals(attr, "properties.foo") - equals(newVal, "bad") - }) - - state.attr({ - properties : { - foo: "bar", - brand: [] - } - }) - - state.attr({ - properties : { - foo: "bad", - brand: [] - } - }); - - state.unbind("change"); - - state.bind("change", function(ev, attr, how, newVal){ - equals(attr, "properties.brand.0") - equals(how,"add") - same(newVal, ["bad"]) - }); - - state.attr({ - properties : { - foo: "bad", - brand: ["bad"] - } - }); - -}); - -test("empty get", function(){ - var state = new $.Observe({}); - - equals(state.attr('foo.bar'), undefined) -}); - -test("attr deep array ", function(){ - var state = new $.Observe({}); - var arr = [{ - foo: "bar" - }], - thing = { - arr: arr - }; - - state.attr({ - thing: thing - }, true); - - ok(thing.arr === arr, "thing unmolested"); -}); - -test('attrs semi-serialize', function(){ - var first = { - foo : {bar: 'car'}, - arr: [1,2,3, {four: '5'} - ] - }, - compare = $.extend(true, {}, first); - var res = new $.Observe(first).attr(); - same(res,compare, "test") -}) - -test("attrs sends events after it is done", function(){ - var state = new $.Observe({foo: 1, bar: 2}) - state.bind('change', function(){ - equals(state.attr('foo'), -1, "foo set"); - equals(state.attr('bar'), -2, "bar set") - }) - state.attr({foo: -1, bar: -2}); -}) - -test("direct property access", function(){ - var state = new $.Observe({foo: 1, attr: 2}); - equals(state.foo,1); - equals(typeof state.attr, 'function') -}) - -test("pop unbinds", function(){ - var l = new $.Observe.List([{foo: 'bar'}]); - var o = l.attr(0), - count = 0; - l.bind('change', function(ev, attr, how, newVal, oldVal){ - count++; - if(count == 1){ - // the prop change - equals(attr, '0.foo', "count is set"); - } else if(count === 2 ){ - equals(how, "remove"); - equals(attr, "0") - } else { - ok(false, "called too many times") - } - - }) - - equals( o.attr('foo') , 'bar'); - - o.attr('foo','car') - l.pop(); - o.attr('foo','bad') -}) - -test("splice unbinds", function(){ - var l = new $.Observe.List([{foo: 'bar'}]); - var o = l.attr(0), - count = 0; - l.bind('change', function(ev, attr, how, newVal, oldVal){ - count++; - if(count == 1){ - // the prop change - equals(attr, '0.foo', "count is set"); - } else if(count === 2 ){ - equals(how, "remove"); - equals(attr, "0") - } else { - ok(false, "called too many times") - } - - }) - - equals( o.attr('foo') , 'bar'); - - o.attr('foo','car') - l.splice(0,1); - o.attr('foo','bad') -}); - - -test("always gets right attr even after moving array items", function(){ - var l = new $.Observe.List([{foo: 'bar'}]); - var o = l.attr(0); - l.unshift("A new Value") - - - l.bind('change', function(ev, attr, how){ - equals(attr, "1.foo") - }) - - - o.attr('foo','led you') -}) - - - -}).then('./delegate/delegate_test.js'); diff --git a/lang/observe/qunit.html b/lang/observe/qunit.html deleted file mode 100644 index dfd2ef53..00000000 --- a/lang/observe/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

                                                            Observe Test Suite

                                                            -

                                                            -
                                                            -

                                                            -
                                                              -
                                                              - associations - list - - - \ No newline at end of file diff --git a/lang/openajax/openajax.html b/lang/openajax/openajax.html deleted file mode 100644 index b2c08e0c..00000000 --- a/lang/openajax/openajax.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Lang Performance Test - - - -
                                                              -
                                                              - - - - - \ No newline at end of file diff --git a/lang/openajax/openajax.js b/lang/openajax/openajax.js deleted file mode 100644 index cc48f88f..00000000 --- a/lang/openajax/openajax.js +++ /dev/null @@ -1,198 +0,0 @@ -//!steal-clean -/******************************************************************************* - * OpenAjax.js - * - * Reference implementation of the OpenAjax Hub, as specified by OpenAjax Alliance. - * Specification is under development at: - * - * http://www.openajax.org/member/wiki/OpenAjax_Hub_Specification - * - * Copyright 2006-2009 OpenAjax Alliance - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 . Unless - * required by applicable law or agreed to in writing, software distributed - * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - * - ******************************************************************************/ -steal.then(function(){ -// prevent re-definition of the OpenAjax object -if(!window["OpenAjax"]){ - /** - * @class OpenAjax - * Use OpenAjax.hub to publish and subscribe to messages. - */ - OpenAjax = new function(){ - var t = true; - var f = false; - var g = window; - var ooh = "org.openajax.hub."; - - var h = {}; - this.hub = h; - h.implementer = "http://openajax.org"; - h.implVersion = "2.0"; - h.specVersion = "2.0"; - h.implExtraData = {}; - var libs = {}; - h.libraries = libs; - - h.registerLibrary = function(prefix, nsURL, version, extra){ - libs[prefix] = { - prefix: prefix, - namespaceURI: nsURL, - version: version, - extraData: extra - }; - this.publish(ooh+"registerLibrary", libs[prefix]); - } - h.unregisterLibrary = function(prefix){ - this.publish(ooh+"unregisterLibrary", libs[prefix]); - delete libs[prefix]; - } - - h._subscriptions = { c:{}, s:[] }; - h._cleanup = []; - h._subIndex = 0; - h._pubDepth = 0; - - h.subscribe = function(name, callback, scope, subscriberData, filter) - { - if(!scope){ - scope = window; - } - var handle = name + "." + this._subIndex; - var sub = { scope: scope, cb: callback, fcb: filter, data: subscriberData, sid: this._subIndex++, hdl: handle }; - var path = name.split("."); - this._subscribe(this._subscriptions, path, 0, sub); - return handle; - } - - h.publish = function(name, message) - { - var path = name.split("."); - this._pubDepth++; - this._publish(this._subscriptions, path, 0, name, message); - this._pubDepth--; - if((this._cleanup.length > 0) && (this._pubDepth == 0)) { - for(var i = 0; i < this._cleanup.length; i++) - this.unsubscribe(this._cleanup[i].hdl); - delete(this._cleanup); - this._cleanup = []; - } - } - - h.unsubscribe = function(sub) - { - var path = sub.split("."); - var sid = path.pop(); - this._unsubscribe(this._subscriptions, path, 0, sid); - } - - h._subscribe = function(tree, path, index, sub) - { - var token = path[index]; - if(index == path.length) - tree.s.push(sub); - else { - if(typeof tree.c == "undefined") - tree.c = {}; - if(typeof tree.c[token] == "undefined") { - tree.c[token] = { c: {}, s: [] }; - this._subscribe(tree.c[token], path, index + 1, sub); - } - else - this._subscribe( tree.c[token], path, index + 1, sub); - } - } - - h._publish = function(tree, path, index, name, msg, pid) { - if(typeof tree != "undefined") { - var node; - if(index == path.length) { - node = tree; - } else { - this._publish(tree.c[path[index]], path, index + 1, name, msg, pid); - this._publish(tree.c["*"], path, index + 1, name, msg, pid); - node = tree.c["**"]; - } - if(typeof node != "undefined") { - var callbacks = node.s; - var max = callbacks.length; - for(var i = 0; i < max; i++) { - if(callbacks[i].cb) { - var sc = callbacks[i].scope; - var cb = callbacks[i].cb; - var fcb = callbacks[i].fcb; - var d = callbacks[i].data; - if(typeof cb == "string"){ - // get a function object - cb = sc[cb]; - } - if(typeof fcb == "string"){ - // get a function object - fcb = sc[fcb]; - } - if((!fcb) || (fcb.call(sc, name, msg, d))) { - cb.call(sc, name, msg, d, pid); - } - } - } - } - } - } - - h._unsubscribe = function(tree, path, index, sid) { - if(typeof tree != "undefined") { - if(index < path.length) { - var childNode = tree.c[path[index]]; - this._unsubscribe(childNode, path, index + 1, sid); - if(childNode.s.length == 0) { - for(var x in childNode.c) - return; - delete tree.c[path[index]]; - } - return; - } - else { - var callbacks = tree.s; - var max = callbacks.length; - for(var i = 0; i < max; i++) - if(sid == callbacks[i].sid) { - if(this._pubDepth > 0) { - callbacks[i].cb = null; - this._cleanup.push(callbacks[i]); - } - else - callbacks.splice(i, 1); - return; - } - } - } - } - // The following function is provided for automatic testing purposes. - // It is not expected to be deployed in run-time OpenAjax Hub implementations. - h.reinit = function() - { - for (var lib in OpenAjax.hub.libraries) { - delete OpenAjax.hub.libraries[lib]; - } - OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "1.0", {}); - - delete OpenAjax._subscriptions; - OpenAjax._subscriptions = {c:{},s:[]}; - delete OpenAjax._cleanup; - OpenAjax._cleanup = []; - OpenAjax._subIndex = 0; - OpenAjax._pubDepth = 0; - } - }; - // Register the OpenAjax Hub itself as a library. - OpenAjax.hub.registerLibrary("OpenAjax", "http://openajax.org/hub", "1.0", {}); - -} -OpenAjax.hub.registerLibrary("JavaScriptMVC", "http://JavaScriptMVC.com", "3.1", {}); -}); diff --git a/lang/qunit.html b/lang/qunit.html deleted file mode 100644 index 0cec0f90..00000000 --- a/lang/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

                                                              Lang Test Suite

                                                              -

                                                              -
                                                              -

                                                              -
                                                                -
                                                                - associations - list - - - \ No newline at end of file diff --git a/lang/string/deparam/deparam.js b/lang/string/deparam/deparam.js deleted file mode 100644 index e490730c..00000000 --- a/lang/string/deparam/deparam.js +++ /dev/null @@ -1,71 +0,0 @@ -steal('jquery', function() { - - var digitTest = /^\d+$/, - keyBreaker = /([^\[\]]+)|(\[\])/g, - plus = /\+/g, - paramTest = /([^?#]*)(#.*)?$/; - - /** - * @add jQuery.String - */ - $.String = $.extend($.String || {}, { - - /** - * @function deparam - * - * Takes a string of name value pairs and returns a Object literal that represents those params. - * - * @param {String} params a string like "foo=bar&person[age]=3" - * @return {Object} A JavaScript Object that represents the params: - * - * { - * foo: "bar", - * person: { - * age: "3" - * } - * } - */ - deparam: function(params){ - - if(! params || ! paramTest.test(params) ) { - return {}; - } - - - var data = {}, - pairs = params.split('&'), - current; - - for(var i=0; i < pairs.length; i++){ - current = data; - var pair = pairs[i].split('='); - - // if we find foo=1+1=2 - if(pair.length != 2) { - pair = [pair[0], pair.slice(1).join("=")] - } - - var key = decodeURIComponent(pair[0].replace(plus, " ")), - value = decodeURIComponent(pair[1].replace(plus, " ")), - parts = key.match(keyBreaker); - - for ( var j = 0; j < parts.length - 1; j++ ) { - var part = parts[j]; - if (!current[part] ) { - // if what we are pointing to looks like an array - current[part] = digitTest.test(parts[j+1]) || parts[j+1] == "[]" ? [] : {} - } - current = current[part]; - } - lastPart = parts[parts.length - 1]; - if(lastPart == "[]"){ - current.push(value) - }else{ - current[lastPart] = value; - } - } - return data; - } - }); - -}) diff --git a/lang/string/deparam/deparam_test.js b/lang/string/deparam/deparam_test.js deleted file mode 100644 index 5a40a261..00000000 --- a/lang/string/deparam/deparam_test.js +++ /dev/null @@ -1,50 +0,0 @@ -steal('funcunit/qunit','./deparam').then(function(){ - -module('jquery/lang/deparam') - -test("Basic deparam",function(){ - - var data = $.String.deparam("a=b"); - equals(data.a,"b") - - var data = $.String.deparam("a=b&c=d"); - equals(data.a,"b") - equals(data.c,"d") -}) -test("Nested deparam",function(){ - - var data = $.String.deparam("a[b]=1&a[c]=2"); - equals(data.a.b,1) - equals(data.a.c,2) - - var data = $.String.deparam("a[]=1&a[]=2"); - equals(data.a[0],1) - equals(data.a[1],2) - - var data = $.String.deparam("a[b][]=1&a[b][]=2"); - equals(data.a.b[0],1) - equals(data.a.b[1],2) - - var data = $.String.deparam("a[0]=1&a[1]=2"); - equals(data.a[0],1) - equals(data.a[1],2) -}); - - -test("deparam an array", function(){ - var data = $.String.deparam("a[0]=1&a[1]=2"); - - ok($.isArray(data.a), "is array") - - equals(data.a[0],1) - equals(data.a[1],2) -}) - -test("deparam object with spaces", function(){ - var data = $.String.deparam("a+b=c+d&+e+f+=+j+h+"); - - equals(data["a b"], "c d") - equals(data[" e f "], " j h ") -}) - -}) diff --git a/lang/string/deparam/qunit.html b/lang/string/deparam/qunit.html deleted file mode 100644 index c44742f4..00000000 --- a/lang/string/deparam/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

                                                                Deparam Test Suite

                                                                -

                                                                -
                                                                -

                                                                -
                                                                  -
                                                                  - associations - list - - - \ No newline at end of file diff --git a/lang/string/qunit.html b/lang/string/qunit.html deleted file mode 100644 index 4388f99b..00000000 --- a/lang/string/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - string QUnit Test - - - - -

                                                                  string Test Suite

                                                                  -

                                                                  -
                                                                  -

                                                                  -
                                                                  -
                                                                    -
                                                                    - - \ No newline at end of file diff --git a/lang/string/rsplit/rsplit.js b/lang/string/rsplit/rsplit.js deleted file mode 100644 index 865a8b56..00000000 --- a/lang/string/rsplit/rsplit.js +++ /dev/null @@ -1,35 +0,0 @@ -steal('jquery/lang/string', function() { - /** - * @add jQuery.String - */ - $.String. - /** - * Splits a string with a regex correctly cross browser - * - * $.String.rsplit("a.b.c.d", /\./) //-> ['a','b','c','d'] - * - * @param {String} string The string to split - * @param {RegExp} regex A regular expression - * @return {Array} An array of strings - */ - rsplit = function( string, regex ) { - var result = regex.exec(string), - retArr = [], - first_idx, last_idx; - while ( result !== null ) { - first_idx = result.index; - last_idx = regex.lastIndex; - if ( first_idx !== 0 ) { - retArr.push(string.substring(0, first_idx)); - string = string.slice(first_idx); - } - retArr.push(result[0]); - string = string.slice(result[0].length); - result = regex.exec(string); - } - if ( string !== '' ) { - retArr.push(string); - } - return retArr; - }; -}); \ No newline at end of file diff --git a/lang/string/string.html b/lang/string/string.html deleted file mode 100644 index c84d332a..00000000 --- a/lang/string/string.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - string - - - -

                                                                    string Demo

                                                                    -

                                                                    This is a dummy page to show off your plugin

                                                                    - - - - \ No newline at end of file diff --git a/lang/string/string.js b/lang/string/string.js deleted file mode 100644 index 35dd2ab4..00000000 --- a/lang/string/string.js +++ /dev/null @@ -1,236 +0,0 @@ -/** - * @page jquerymx.lang Language Helpers - * @parent jquerymx - * @description A collection of language helpers for things like String, Objects, etc. - * - * JavaScriptMVC has several lightweight language helper plugins. - * - * ## [jQuery.Object Object] - * - * Methods useful for comparing Objects. For example, if two - * objects are the same: - * - * $.Object.same({foo: "bar"}, {foo: "bar"}); - * - * ## [jQuery.Observe Observe] - * - * Makes an Object's properties observable: - * - * var person = new $.Observe({ name: "Justin" }) - * person.bind('change', function(){ ... }) - * person.attr('name', "Brian"); - * - * ## [jQuery.String String] - * - * String helpers capitalize, underscore, and perform similar manipulations - * on strings. They can also lookup a value in an object: - * - * $.String.getObject("foo.bar",{foo: {bar: "car"}}) - * - * ## [jQuery.toJSON toJSON] - * - * Used to create or consume JSON strings. - * - * ## [jQuery.Vector Vector] - * - * Used for vector math. - */ -//string helpers -steal('jquery', function() { - // Several of the methods in this plugin use code adapated from Prototype - // Prototype JavaScript framework, version 1.6.0.1 - // (c) 2005-2007 Sam Stephenson - var regs = { - undHash: /_|-/, - colons: /::/, - words: /([A-Z]+)([A-Z][a-z])/g, - lowUp: /([a-z\d])([A-Z])/g, - dash: /([a-z\d])([A-Z])/g, - replacer: /\{([^\}]+)\}/g, - dot: /\./ - }, - // gets the nextPart property from current - // add - if true and nextPart doesnt exist, create it as an empty object - getNext = function(current, nextPart, add){ - return current[nextPart] !== undefined ? current[nextPart] : ( add && (current[nextPart] = {}) ); - }, - // returns true if the object can have properties (no nulls) - isContainer = function(current){ - var type = typeof current; - return current && ( type == 'function' || type == 'object' ); - }, - // a reference - getObject, - /** - * @class jQuery.String - * @parent jquerymx.lang - * - * A collection of useful string helpers. Available helpers are: - *
                                                                      - *
                                                                    • [jQuery.String.capitalize|capitalize]: Capitalizes a string (some_string » Some_string)
                                                                    • - *
                                                                    • [jQuery.String.camelize|camelize]: Capitalizes a string from something undercored - * (some_string » someString, some-string » someString)
                                                                    • - *
                                                                    • [jQuery.String.classize|classize]: Like [jQuery.String.camelize|camelize], - * but the first part is also capitalized (some_string » SomeString)
                                                                    • - *
                                                                    • [jQuery.String.niceName|niceName]: Like [jQuery.String.classize|classize], but a space separates each 'word' (some_string » Some String)
                                                                    • - *
                                                                    • [jQuery.String.underscore|underscore]: Underscores a string (SomeString » some_string)
                                                                    • - *
                                                                    • [jQuery.String.sub|sub]: Returns a string with {param} replaced values from data. - *
                                                                      -		 *       $.String.sub("foo {bar}",{bar: "far"})
                                                                      -		 *       //-> "foo far"
                                                                      - *
                                                                    • - *
                                                                    - * - */ - str = $.String = $.extend( $.String || {} , { - - - /** - * @function getObject - * Gets an object from a string. It can also modify objects on the - * 'object path' by removing or adding properties. - * - * Foo = {Bar: {Zar: {"Ted"}}} - * $.String.getObject("Foo.Bar.Zar") //-> "Ted" - * - * @param {String} name the name of the object to look for - * @param {Array} [roots] an array of root objects to look for the - * name. If roots is not provided, the window is used. - * @param {Boolean} [add] true to add missing objects to - * the path. false to remove found properties. undefined to - * not modify the root object - * @return {Object} The object. - */ - getObject : getObject = function( name, roots, add ) { - - // the parts of the name we are looking up - // ['App','Models','Recipe'] - var parts = name ? name.split(regs.dot) : [], - length = parts.length, - current, - ret, - i, - r = 0, - type; - - // make sure roots is an array - roots = $.isArray(roots) ? roots : [roots || window]; - - if(length == 0){ - return roots[0]; - } - // for each root, mark it as current - while( current = roots[r++] ) { - // walk current to the 2nd to last object - // or until there is not a container - for (i =0; i < length - 1 && isContainer(current); i++ ) { - current = getNext(current, parts[i], add); - } - // if we can get a property from the 2nd to last object - if( isContainer(current) ) { - - // get (and possibly set) the property - ret = getNext(current, parts[i], add); - - // if there is a value, we exit - if( ret !== undefined ) { - // if add is false, delete the property - if ( add === false ) { - delete current[parts[i]]; - } - return ret; - - } - } - } - }, - /** - * Capitalizes a string - * @param {String} s the string. - * @return {String} a string with the first character capitalized. - */ - capitalize: function( s, cache ) { - return s.charAt(0).toUpperCase() + s.substr(1); - }, - /** - * Capitalizes a string from something undercored. Examples: - * @codestart - * jQuery.String.camelize("one_two") //-> "oneTwo" - * "three-four".camelize() //-> threeFour - * @codeend - * @param {String} s - * @return {String} a the camelized string - */ - camelize: function( s ) { - s = str.classize(s); - return s.charAt(0).toLowerCase() + s.substr(1); - }, - /** - * Like [jQuery.String.camelize|camelize], but the first part is also capitalized - * @param {String} s - * @return {String} the classized string - */ - classize: function( s , join) { - var parts = s.split(regs.undHash), - i = 0; - for (; i < parts.length; i++ ) { - parts[i] = str.capitalize(parts[i]); - } - - return parts.join(join || ''); - }, - /** - * Like [jQuery.String.classize|classize], but a space separates each 'word' - * @codestart - * jQuery.String.niceName("one_two") //-> "One Two" - * @codeend - * @param {String} s - * @return {String} the niceName - */ - niceName: function( s ) { - return str.classize(s,' '); - }, - - /** - * Underscores a string. - * @codestart - * jQuery.String.underscore("OneTwo") //-> "one_two" - * @codeend - * @param {String} s - * @return {String} the underscored string - */ - underscore: function( s ) { - return s.replace(regs.colons, '/').replace(regs.words, '$1_$2').replace(regs.lowUp, '$1_$2').replace(regs.dash, '_').toLowerCase(); - }, - /** - * Returns a string with {param} replaced values from data. - * - * $.String.sub("foo {bar}",{bar: "far"}) - * //-> "foo far" - * - * @param {String} s The string to replace - * @param {Object} data The data to be used to look for properties. If it's an array, multiple - * objects can be used. - * @param {Boolean} [remove] if a match is found, remove the property from the object - */ - sub: function( s, data, remove ) { - var obs = [], - remove = typeof remove == 'boolean' ? !remove : remove; - obs.push(s.replace(regs.replacer, function( whole, inside ) { - //convert inside to type - var ob = getObject(inside, data, remove); - - // if a container, push into objs (which will return objects found) - if( isContainer(ob) ){ - obs.push(ob); - return ""; - }else{ - return ""+ob; - } - })); - - return obs.length <= 1 ? obs[0] : obs; - }, - _regs : regs - }); -}); \ No newline at end of file diff --git a/lang/string/string_test.js b/lang/string/string_test.js deleted file mode 100644 index 9d345984..00000000 --- a/lang/string/string_test.js +++ /dev/null @@ -1,46 +0,0 @@ -steal('funcunit/qunit','./string').then(function(){ - -module("jquery/lang/string") - -test("$.String.sub", function(){ - equals($.String.sub("a{b}",{b: "c"}),"ac") - - var foo = {b: "c"}; - - equals($.String.sub("a{b}",foo,true),"ac"); - - ok(!foo.b, "removed this b"); - - -}); - -test("$.String.sub double", function(){ - equals($.String.sub("{b} {d}",[{b: "c", d: "e"}]),"c e"); -}) - -test("String.underscore", function(){ - equals($.String.underscore("Foo.Bar.ZarDar"),"foo.bar.zar_dar") -}) - - -test("$.String.getObject", function(){ - var obj = $.String.getObject("foo", [{a: 1}, {foo: 'bar'}]); - - equals(obj,'bar', 'got bar') - - - // test null data - - var obj = $.String.getObject("foo", [{a: 1}, {foo: 0}]); - - equals(obj,0, 'got 0 (falsey stuff)') -}); - -test("$.String.niceName", function(){ - var str = "some_underscored_string"; - var niceStr = $.String.niceName(str); - equals(niceStr, 'Some Underscored String', 'got correct niceName'); -}) - - -}).then('./deparam/deparam_test'); diff --git a/lang/vector/vector.js b/lang/vector/vector.js index be423d15..f4679da0 100644 --- a/lang/vector/vector.js +++ b/lang/vector/vector.js @@ -3,7 +3,7 @@ steal('jquery', function($){ getSetOne = function(v){ return v !== undefined ? (this.array[1] = v) : this.array[1]}; /** - * @class jQuery.Vector + * @constructor jQuery.Vector * @parent jquerypp * * `jQuery.Vector` represents a multi dimensional vector with shorthand methods for @@ -11,8 +11,6 @@ steal('jquery', function($){ * * It is mainly used in [jQuery.event.drag drag] & [jQuery.event.drop drop] events. * - * @constructor creates a new vector instance from the arguments. Example: - * * new jQuery.Vector(1,2) */ $.Vector = function(arr) { @@ -23,7 +21,11 @@ steal('jquery', function($){ /* @Prototype*/ { /** - * Applys the function to every item in the vector and returns a new vector. + * @function jQuery.Vector.prototype.app app + * @signature `jQuery.vector.app([f])` + * + * @body + * Applies the function to every item in the vector and returns a new vector. * * @param {Function} f The function to apply * @return {jQuery.Vector} A new $.Vector instance @@ -37,6 +39,11 @@ steal('jquery', function($){ return new $.Vector(newArr); }, /** + * @function jQuery.Vector.prototype.plus plus + * @signature `jQuery.vector.plus()` + * + * @body + * * Adds two vectors together and returns a new instance. Example: * * new $.Vector(1,2).plus(2,3) //-> (3, 5) @@ -54,6 +61,10 @@ steal('jquery', function($){ return vec.update(arr); }, /** + * @function jQuery.Vector.prototype.minus minus + * @signature `jQuery.vector.minus()` + * + * @body * Subtract one vector from another and returns a new instance. Example: * * new $.Vector(4, 5).minus(2, 1) //-> (2, 4) @@ -70,11 +81,15 @@ steal('jquery', function($){ return vec.update(arr); }, /** - * Returns the current vector if it is equal to the vector passed in. + * @function jQuery.Vector.prototype.equals equals + * @signature `jQuery.vector.equal()` * - * `null` if otherwise. + * @body * * @return {jQuery.Vector} + * Returns the current vector if it is equal to the vector passed in. + * + * `null` if otherwise. */ equals: function() { var i, args = arguments[0] instanceof $.Vector ? arguments[0].array : $.makeArray(arguments), @@ -88,9 +103,13 @@ steal('jquery', function($){ return vec.update(arr); }, /** + * @function jQuery.Vector.prototype.x x + * @signature `jQuery.vector.x()` + * + * @body * Returns the first value of the vector. * You can also access the same value through the following aliases the - * [jQuery.Vector.prototype.left vector.left()] and [jQuery.Vector.prototype.left vector.width()] + * vector.left() and vector.width() * aliases. * * For example: @@ -118,6 +137,10 @@ steal('jquery', function($){ */ width: getSetZero, /** + * @function jQuery.Vector.prototype.y y + * @signature `jQuery.vector.y()` + * + * @body * Returns the second value of the vector. * You can also access the same value through the [jQuery.Vector.prototype.top vector.top()] * and [jQuery.Vector.prototype.height vector.height()] aliases. @@ -147,6 +170,11 @@ steal('jquery', function($){ */ height: getSetOne, /** + * @function jQuery.Vector.prototype.toString toString + * @signature `jQuery.vector.toString()` + * + * @body + * * Returns a string representation of the vector in the form of (x,y,...) * * var v = new $.Vector(4, 6, 1, 3); @@ -158,6 +186,11 @@ steal('jquery', function($){ return "(" + this.array.join(', ') + ")"; }, /** + * @function jQuery.Vector.prototype.update update + * @signature `jQuery.vector.update([array])` + * + * @body + * * Replaces the vectors contents * * var v = new $.Vector(2, 3); @@ -180,9 +213,9 @@ steal('jquery', function($){ }; $.Event.prototype.vector = function() { - var - // Get the first touch element for touch events - touches = "ontouchend" in document && this.originalEvent.touches.length ? this.originalEvent.changedTouches[0] : this; + // Get the first touch element for touch events + var touches = "ontouchend" in document && this.originalEvent.changedTouches && + this.originalEvent.changedTouches.length ? this.originalEvent.changedTouches[0] : this; if ( this.originalEvent.synthetic ) { var doc = document.documentElement, body = document.body; @@ -197,7 +230,7 @@ steal('jquery', function($){ if ( this[0] == window ) { return new $.Vector(window.pageXOffset ? window.pageXOffset : document.documentElement.scrollLeft, window.pageYOffset ? window.pageYOffset : document.documentElement.scrollTop); } else { - var offset = this.offset(); + var offset = this.offset() || {}; return new $.Vector(offset.left, offset.top); } }; @@ -210,4 +243,6 @@ steal('jquery', function($){ return new $.Vector(this[which + "Width"](), this[which + "Height"]()); } }; + + return $; }); diff --git a/lang/vector/vector_test.js b/lang/vector/vector_test.js index 1114eab2..20fa47d8 100644 --- a/lang/vector/vector_test.js +++ b/lang/vector/vector_test.js @@ -1,6 +1,6 @@ -steal('funcunit/qunit','./vector.js').then(function(){ +steal('steal-qunit','./vector.js',function(){ - module("jquery/lang/vector") + module("jquerypp/lang/vector") test("Init", function(){ var v = new $.Vector(1,4, 2, 3); diff --git a/model/backup/backup.html b/model/backup/backup.html deleted file mode 100644 index 89e67b03..00000000 --- a/model/backup/backup.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - Model Backup Demo - - - -
                                                                    -

                                                                    Model Backup Demo

                                                                    -

                                                                    This demo shows backing up and restoring model instances. - Click the names to change birthdays. After changing some birthdays, - click RESTORE. -

                                                                    -
                                                                    -
                                                                    -
                                                                    -
                                                                    -RESTORE -
                                                                    - - - - \ No newline at end of file diff --git a/model/backup/backup.js b/model/backup/backup.js deleted file mode 100644 index 3d78207c..00000000 --- a/model/backup/backup.js +++ /dev/null @@ -1,2 +0,0 @@ -//allows you to backup and restore a model instance -steal('can/observe/backup','can/model'); \ No newline at end of file diff --git a/model/backup/qunit.html b/model/backup/qunit.html deleted file mode 100644 index 954b041b..00000000 --- a/model/backup/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

                                                                    Model Backup Test Suite

                                                                    -

                                                                    -
                                                                    -

                                                                    -
                                                                    -
                                                                      -
                                                                      - - \ No newline at end of file diff --git a/model/backup/qunit/qunit.js b/model/backup/qunit/qunit.js deleted file mode 100644 index 3ea978a0..00000000 --- a/model/backup/qunit/qunit.js +++ /dev/null @@ -1,107 +0,0 @@ -steal('funcunit/qunit') - .then("jquery/model/backup").then(function(){ - - -module("jquery/model/backup",{ - setup : function(){ - $.Model.extend("Recipe") - } -}) - -test("backing up", function(){ - var recipe = new Recipe({name: "cheese"}); - ok(!recipe.isDirty(), "not backedup, but clean") - - recipe.backup(); - ok(!recipe.isDirty(), "backedup, but clean"); - - recipe.attr('name', 'blah') - - ok(recipe.isDirty(), "dirty"); - - recipe.restore(); - - ok(!recipe.isDirty(), "restored, clean"); - - equals(recipe.name, "cheese" ,"name back"); - -}); - -test("backup / restore with associations", function(){ - $.Model("Instruction"); - $.Model("Cookbook"); - - $.Model("Recipe",{ - attributes : { - instructions : "Instruction.models", - cookbook: "Cookbook.model" - } - },{}); - - - - - var recipe = new Recipe({ - name: "cheese burger", - instructions : [ - { - description: "heat meat" - }, - { - description: "add cheese" - } - ], - cookbook: { - title : "Justin's Grillin Times" - } - }); - - //test basic is dirty - - ok(!recipe.isDirty(), "not backedup, but clean") - - recipe.backup(); - ok(!recipe.isDirty(), "backedup, but clean"); - - recipe.attr('name','blah') - - ok(recipe.isDirty(), "dirty"); - - recipe.restore(); - - ok(!recipe.isDirty(), "restored, clean"); - - equals(recipe.name, "cheese burger" ,"name back"); - - // test belongs too - - ok(!recipe.cookbook.isDirty(), "cookbook not backedup, but clean"); - - recipe.cookbook.backup(); - - recipe.cookbook.attr("title","Brian's Burgers"); - - ok(!recipe.isDirty(), "recipe itself is clean"); - - ok(recipe.isDirty(true), "recipe is dirty if checking associations"); - - recipe.cookbook.restore() - - ok(!recipe.isDirty(true), "recipe is now clean with checking associations"); - - equals(recipe.cookbook.title, "Justin's Grillin Times" ,"cookbook title back"); - - //try belongs to recursive restore - - recipe.cookbook.attr("title","Brian's Burgers"); - recipe.restore(); - ok(recipe.isDirty(true), "recipe is dirty if checking associations, after a restore"); - - recipe.restore(true); - ok(!recipe.isDirty(true), "cleaned all of recipe and its associations"); - - -}) - -}) - \ No newline at end of file diff --git a/model/demo-convert.html b/model/demo-convert.html deleted file mode 100644 index 73dcf41e..00000000 --- a/model/demo-convert.html +++ /dev/null @@ -1,77 +0,0 @@ - - - - Model Convert Demo - - - -
                                                                      -

                                                                      Model Convert Demo

                                                                      -

                                                                      This demo shows converting date strings sent by the - server to JavaScript dates with attributes and convert.

                                                                      -
                                                                      -
                                                                      -
                                                                        -
                                                                        - - - - \ No newline at end of file diff --git a/model/demo-dom.html b/model/demo-dom.html deleted file mode 100644 index f0958e6d..00000000 --- a/model/demo-dom.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - Model Convert Demo - - - -
                                                                        -

                                                                        Model DOM Helpers Demo

                                                                        -

                                                                        This demo shows using models to set an instance on an element.

                                                                        -
                                                                        -
                                                                        -
                                                                          -
                                                                          - - - - \ No newline at end of file diff --git a/model/demo-encapsulate.html b/model/demo-encapsulate.html deleted file mode 100644 index 3bd632c4..00000000 --- a/model/demo-encapsulate.html +++ /dev/null @@ -1,148 +0,0 @@ - - - - Grid / Encapsulate Demo - - - -
                                                                          -

                                                                          Model Encapsulate Demo

                                                                          -

                                                                          This demonstrates how encapsulating Ajax functionality in - models makes your code more reusable. The same grid - widget uses two different models. -

                                                                          -
                                                                          -
                                                                          -

                                                                          Recipe Grid

                                                                          -
                                                                          -

                                                                          Work Item Grid

                                                                          -
                                                                          -
                                                                          - - - - - - - \ No newline at end of file diff --git a/model/demo-events.html b/model/demo-events.html deleted file mode 100644 index 9c12d940..00000000 --- a/model/demo-events.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - Model Events Demo - - - -
                                                                          -

                                                                          Model Events Demo

                                                                          -

                                                                          This demo shows listening to model update events. - Clicking on a person's name will show a form to update - their birthday. Change the birthday and 'blur' the - input to update their listed age.

                                                                          -
                                                                          -
                                                                          -
                                                                          - -

                                                                          Direct Binding

                                                                          -

                                                                          - The following list binds - directly to "birthday" events. -

                                                                          -
                                                                          - -

                                                                          Model Binding

                                                                          -

                                                                          - The following list binds - to "updated" events on Contact. -

                                                                          -
                                                                          -
                                                                          - - - - - \ No newline at end of file diff --git a/model/demo-setter.html b/model/demo-setter.html deleted file mode 100644 index 6d0d58e8..00000000 --- a/model/demo-setter.html +++ /dev/null @@ -1,78 +0,0 @@ - - - - Model Events Demo - - - -
                                                                          -

                                                                          Model Setter Demo

                                                                          -

                                                                          This demo shows converting date strings sent by the - server to JavaScript dates with Setters.

                                                                          -
                                                                          -
                                                                          -
                                                                            -
                                                                            - - - - - \ No newline at end of file diff --git a/model/fixtures/school.json b/model/fixtures/school.json deleted file mode 100644 index 734e4916..00000000 --- a/model/fixtures/school.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id": 4, - "name" : "Highland" -} \ No newline at end of file diff --git a/model/fixtures/schools.json b/model/fixtures/schools.json deleted file mode 100644 index 1b596fa0..00000000 --- a/model/fixtures/schools.json +++ /dev/null @@ -1,4 +0,0 @@ -[{ - "id": 1, - "name" : "adler" -}] diff --git a/model/list/cookie/cookie.html b/model/list/cookie/cookie.html deleted file mode 100644 index f94eae02..00000000 --- a/model/list/cookie/cookie.html +++ /dev/null @@ -1,112 +0,0 @@ - - - - Model List Cookie Demo - - - -
                                                                            -

                                                                            Cookie List Demo

                                                                            -

                                                                            This demo show keeping data stored in a cookie. Create a few contacts, - refresh the page, and they should still be present.

                                                                            -
                                                                            -
                                                                            -

                                                                            Create A Contact

                                                                            -
                                                                            - -
                                                                            - - - (must be like 1982-10-20)
                                                                            - -
                                                                            -

                                                                            List of Contacts

                                                                            -
                                                                            -
                                                                            - - - - - \ No newline at end of file diff --git a/model/list/cookie/cookie.js b/model/list/cookie/cookie.js deleted file mode 100644 index e28b98e1..00000000 --- a/model/list/cookie/cookie.js +++ /dev/null @@ -1,92 +0,0 @@ -steal('jquery/dom/cookie','jquery/model/list').then(function($){ - -/** - * @class jQuery.Model.List.Cookie - * @plugin jquery/model/list/cookie - * @test jquery/model/list/cookie/qunit.html - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/model/list/cookie/cookie.js - * @parent jQuery.Model.List - * - * Provides a store-able list of model instances. The following - * retrieves and saves a list of contacts: - * - * @codestart - * var contacts = new Contact.List([]).retrieve("contacts"); - * - * // add each contact to the page - * contacts.each(function(){ - addContact(this); - * }); - * - * // when a new cookie is crated - * $("#contact").submit(function(ev){ - * ev.preventDefault(); - * var data = $(this).formParams(); - * - * // gives it a random id - * data.id = +new Date(); - * var contact = new Contact(data); - * - * //add it to the list of contacts - * contacts.push(contact); - * - * //store the current list - * contacts.store("contacts"); - * - * //show the contact - * addContact(contact); - * }) - * @codeend - * - * You can see this in action in the following demo. Create a contact, then - * refresh the page. - * - * @demo jquery/model/list/cookie/cookie.html - */ -$.Model.List("jQuery.Model.List.Cookie", -/** - * @Prototype - */ -{ - days : null, - /** - * Deserializes a list of instances in the cookie with the provided name - * @param {String} name the name of the cookie to use. - * @return {jQuery.Model} returns this model instance. - */ - retrieve : function(name){ - // each also needs what they are referencd by ? - var props = $.cookie( name ) || {type : null, ids : []}, - instances = [], - Class = props.type ? $.String.getObject(props.type) : null; - for(var i =0; i < props.ids.length;i++){ - var identity = props.ids[i], - instanceData = $.cookie( identity ); - instances.push( new Class(instanceData) ) - } - this.push.apply(this,instances); - return this; - }, - /** - * Serializes and saves this list of model instances to the cookie in name. - * @param {String} name the name of the cookie - * @return {jQuery.Model} returns this model instance. - */ - store : function(name){ - // go through and listen to instance updating - var ids = [], days = this.days; - this.each(function(i, inst){ - $.cookie(inst.identity(), $.toJSON(inst.attrs()), { expires: days }); - ids.push(inst.identity()); - }); - - $.cookie(name, $.toJSON({ - type: this[0] && this[0].constructor.fullName, - ids: ids - }), { expires: this.days }); - return this; - } -}) - -}) - diff --git a/model/list/cookie/qunit.html b/model/list/cookie/qunit.html deleted file mode 100644 index 3cf020d0..00000000 --- a/model/list/cookie/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

                                                                            Model List Cookie Test Suite

                                                                            -

                                                                            -
                                                                            -

                                                                            -
                                                                            -
                                                                              -
                                                                              - - \ No newline at end of file diff --git a/model/list/cookie/qunit/qunit.js b/model/list/cookie/qunit/qunit.js deleted file mode 100644 index dc7c7deb..00000000 --- a/model/list/cookie/qunit/qunit.js +++ /dev/null @@ -1,27 +0,0 @@ -steal('funcunit/qunit','jquery/model/list/cookie').then(function($){ - -module("jquery/model/list/cookie",{ - setup: function(){ - // clear any existing cookie ... - $.cookie("list", "", {expires: -1}) - $.Model.extend("Search", {}, {}); - - $.Model.List.Cookie.extend("Search.Store") - } -}) - -test("storing and retrieving",function(){ - - var store = new Search.Store([]) //should be able to look up by namespace .... - - ok(!store.length, "empty list"); - - store.push( new Search({id: 1}), new Search({id: 2}) ) - store.store("list"); - - var store2 = new Search.Store([]).retrieve("list"); - equals(store2.length, 2, "there are 2 items") - -}) - -}) diff --git a/model/list/list-insert.html b/model/list/list-insert.html deleted file mode 100644 index 3e941291..00000000 --- a/model/list/list-insert.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - Model List Insert Demo - - - -
                                                                              -

                                                                              Model List Demo

                                                                              -

                                                                              This demo shows how you might use Lists to implement deleting a list - of contacts.

                                                                              -
                                                                              -
                                                                              -
                                                                              -
                                                                              -
                                                                              - - - - - - \ No newline at end of file diff --git a/model/list/list.html b/model/list/list.html deleted file mode 100644 index abb3395a..00000000 --- a/model/list/list.html +++ /dev/null @@ -1,103 +0,0 @@ - - - - List Helper Demo - - - -
                                                                              -

                                                                              Model List Helper Demo

                                                                              -

                                                                              This demo shows how you might use Lists to implement deleting a list - of contacts.

                                                                              -
                                                                              - - - - - - - \ No newline at end of file diff --git a/model/list/list.js b/model/list/list.js deleted file mode 100644 index 8a3ed8c2..00000000 --- a/model/list/list.js +++ /dev/null @@ -1,25 +0,0 @@ -steal('can/model/list','jquery/model').then(function() { - // List.get used to take a model or list of models - var getList = $.Model.List.prototype.get; - $.Model.List.prototype.get = function(arg) { - var ids, id; - if(arg instanceof $.Model.List) { - ids = []; - $.each(arg,function() { - ids.push(this.attr('id')); - }); - arg = ids; - } else if(arg.attr && arg.constructor && (id = arg.attr(arg.constructor.id))) { - arg = id; - } - return getList.apply(this,arguments); - }; - // restore the ability to push a list!arg - var push = $.Model.List.prototype.push; - $.Model.List.prototype.push = function(arg) { - if(arg instanceof $.Model.List) { - arg = can.makeArray(arg); - } - return push.apply(this,arguments); - }; -}); diff --git a/model/list/list_test.js b/model/list/list_test.js deleted file mode 100644 index 9391f0a3..00000000 --- a/model/list/list_test.js +++ /dev/null @@ -1,203 +0,0 @@ -steal("jquery/model/list",'funcunit/qunit', 'can/util/fixture', function(){ - -module("jquery/model/list", { - setup: function() { - $.Model.extend("Person") - - $.Model.List("Person.List",{ - destroy : "DELETE /person/destroyAll", - update : "PUT /person/updateAll" - },{}); - var people = [] - for(var i =0; i < 20; i++){ - people.push( new Person({id: "a"+i}) ) - } - this.people = new $.Model.List(people); - } -}) - -test("hookup with list", function(){ - - - - var div = $("
                                                                              ") - - for(var i =0; i < 20 ; i ++){ - var child = $("
                                                                              "); - var p = new Person({foo: "bar"+i, id: i}); - p.hookup( child[0] ); - div.append(child) - } - var models = div.children().models(); - ok(models.constructor === Person.List, "correct type"); - equals(models.length, 20, "Got 20 people") - - -}) - -test("create", function(){ - - equals(this.people.length, 20) - - equals(this.people.get("a2")[0].id,"a2" , "get works") -}) - - -test("splice", function(){ - ok(this.people.get("a1").length,"something where a1 is") - this.people.splice(1,1) - equals(this.people.length, 19) - ok(!this.people.get("a1").length,"nothing where a1 is") - -}) - -test("remove", function(){ - var res = this.people.remove("a1") - ok(!this.people.get("a1").length,"nothing where a1 is") - ok(res.length, "got something array like") - equals(res[0].id, "a1") -}) - - -test("list from models", function(){ - var people = Person.models([{id: 1}, {id: 2}]); - ok(people.elements, "we can find elements from a list") -}); - -test("destroy a list", function(){ - var people = Person.models([{id: 1}, {id: 2}]); - stop(); - // make sure a request is made - $.fixture('DELETE /person/destroyAll', function(){ - - ok(true, "called right fixture"); - return true; - }) - // make sure the people have a destroyed event - people[0].bind('destroyed', function(){ - ok(true, "destroyed event called") - }) - - people.destroy(function(deleted){ - ok(true, "destroy callback called"); - equals(people.length, 0, "objects removed"); - equals(deleted.length, 2, "got back deleted items") - start() - // make sure the list is empty - - }) - -}); - -test("destroy a list with nothing in it", function(){ - var people = Person.models([]); - stop(); - - // make sure a request is made - $.fixture('DELETE /person/destroyAll', function(){ - ok(true, "called right fixture"); - return true; - }); - - people.destroy(function(deleted){ - ok(true, "destroy callback called"); - equal(deleted.length, people.length, "got back deleted items") - start(); - }); -}); - -test("update a list", function(){ - var people = Person.models([{id: 1}, {id: 2}]), - updateWith = { - name: "Justin", - age : 29 - }, - newProps = { - newProp : "yes" - }; - stop(); - - // make sure a request is made - $.fixture('PUT /person/updateAll', function(orig){ - ok(true, "called right fixture"); - ok(orig.data.ids.length, 2, "got 2 ids") - same(orig.data.attrs, updateWith, "got the same attrs") - return newProps; - }) - - // make sure the people have a destroyed event - people[0].bind('updated', function(){ - ok(true, "updated event called") - }) - - people.update(updateWith,function(updated){ - ok(true, "updated callback called"); - ok(updated.length, 2, "got back deleted items"); - same(updated[0].attr(),$.extend({id : 1},newProps, updateWith )); - start(); - }); -}) - -test("update a list with nothing in it", function(){ - var people = Person.models([]), - updateWith = { - name: "Justin", - age : 29 - }; - stop(); - - // make sure a request is made - $.fixture('PUT /person/updateAll', function(orig){ - ok(true, "called right fixture"); - return newProps; - }); - - people.update(updateWith,function(updated){ - ok(true, "updated callback called"); - equal(updated.length, people.length, "nothing updated"); - start(); - }); -}) - -test("events - add", 4, function(){ - var list = new Person.List; - list.bind("add", function(ev, items){ - ok(1, "add called"); - equals(items.length, 1, "we get an array") - }); - - var person = new Person({id: 1, name: "alex"}); - - - list.push(person); - - // check that we are listening to updates on person ... - - // events are hooked internally now - // ok( $(person).data("events"), "person has events" ); - ok(jQuery._data(person, 'events'), "person has events" ); - - list.pop() - - // events are hooked internally now - // ok( !$(person).data("events"), "person has no events" ); - ok( !jQuery._data(person, 'events'), "person has no events" ); - -}); - -test("events - update", function(){ - var list = new Person.List; - list.bind("update", function(ev, updated){ - ok(1, "update called"); - ok(person === updated, "we get the person back"); - - equals(updated.name, "Alex", "got the right name") - }); - - var person = new Person({id: 1, name: "justin"}); - list.push(person); - - person.updated({name: "Alex"}) -}); - -}) diff --git a/model/list/local/local.js b/model/list/local/local.js deleted file mode 100644 index 568a63cb..00000000 --- a/model/list/local/local.js +++ /dev/null @@ -1,42 +0,0 @@ -steal('jquery/dom/cookie','jquery/model/list').then(function($){ -/** - * @class jQuery.Model.List.Local - * @plugin jquery/model/list/local - * @download http://jmvcsite.heroku.com/pluginify?plugins[]=jquery/model/list/local/local.js - * @parent jQuery.Model.List - * Works exactly the same as [jQuery.Model.List.Cookie] except uses - * a local store instead of cookies. - */ -$.Model.List("jQuery.Model.List.Local", -{ - retrieve : function(name){ - // each also needs what they are referencd by ? - var props = window.localStorage[ name ] || "[]", - instances = [], - Class = props.type ? $.String.getObject(props.type) : null; - for(var i =0; i < props.ids.length;i++){ - var identity = props.ids[i], - instanceData = window.localStorage[ identity ]; - instances.push( new Class(instanceData) ) - } - this.push.apply(this,instances); - return this; - }, - store : function(name){ - // go through and listen to instance updating - var ids = [], days = this.days; - this.each(function(i, inst){ - window.localStorage[inst.identity()] = instance.attrs(); - ids.push(inst.identity()); - }); - window.localStorage[name] = { - type: this[0] && this[0].constructor.fullName, - ids: ids - }; - return this; - } - -}); - -}) - diff --git a/model/list/memory.html b/model/list/memory.html deleted file mode 100644 index 94fbc973..00000000 --- a/model/list/memory.html +++ /dev/null @@ -1,87 +0,0 @@ - - - - List Helper Demo - - - - Start -
                                                                              - - - - - - \ No newline at end of file diff --git a/model/list/qunit.html b/model/list/qunit.html deleted file mode 100644 index 1ea6a1eb..00000000 --- a/model/list/qunit.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - -

                                                                              Model List Test Suite

                                                                              -

                                                                              -
                                                                              -

                                                                              -
                                                                              -
                                                                                -
                                                                                - - \ No newline at end of file diff --git a/model/model.js b/model/model.js deleted file mode 100644 index 72e2dc70..00000000 --- a/model/model.js +++ /dev/null @@ -1,16 +0,0 @@ -/*global OpenAjax: true */ - -steal('jquery', 'can/util', 'can/model','can/observe/attributes','can/observe/setter','can/model/elements', function($, can){ - $.Model = can.Model; - var get = $.Model.prototype.__get; - $.Model.prototype.__get = function(attr) { - var getter = attr && ("get" + can.classize(attr)); - return typeof this[getter] === 'function' ? this[getter]() : get.apply(this,arguments); - }; - - $.Model.prototype.update = function( attrs, success, error ) { - steal.dev.log('$.Model.update is deprecated. You can use attr + save instead.'); - this.attr(attrs); - return this.save(success, error); - }; -}); diff --git a/model/modelBinder.html b/model/modelBinder.html deleted file mode 100644 index cba4a743..00000000 --- a/model/modelBinder.html +++ /dev/null @@ -1,92 +0,0 @@ - - - - slider - - - -
                                                                                - - - - - - - - - - - - \ No newline at end of file diff --git a/model/pages/associations.html b/model/pages/associations.html deleted file mode 100644 index 68dc048f..00000000 --- a/model/pages/associations.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - Model Events Demo - - - -
                                                                                -

                                                                                Model Associations Demo

                                                                                -

                                                                                This demo shows how you can setup associations.

                                                                                -
                                                                                -
                                                                                -
                                                                                -
                                                                                - - - - - \ No newline at end of file diff --git a/model/pages/deferreds.md b/model/pages/deferreds.md deleted file mode 100644 index eaf4da9a..00000000 --- a/model/pages/deferreds.md +++ /dev/null @@ -1,48 +0,0 @@ -@page jquery.model.deferreds Deferreds -@parent jQuery.Model - -Models (and views) work -with [http://api.jquery.com/category/deferred-object/ jQuery.Deferred]. If -you properly fill out a model's [jquery.model.services service API], asynchronous -requests done via the model will return a jQuery.Deferred. - -## findAll example - -The following example, requests tasks and people and waits for both requests -to be complete before alerting the user: - - var tasksDef = Task.findAll(), - peopleDef = People.findAll(); - - $.when(tasksDef,peopleDef).done(function(taskResponse, peopleResponse){ - alert("There are "+taskRespone[0].length+" tasks and "+ - peopleResponse[0].length+" people."); - }); - -__Note__ taskResponse[0] is an Array of tasks. - -## save and destroy example - -Calls to [jQuery.Model.prototype.save save] and [jQuery.Model.prototype.destroy] also -return a deferred. The deferred is resolved to the newly created, destroyed, or updated -model instance. - -The following creates a task, updates it, and destroys it: - - var taskD = new Task({name: "dishes"}).save(); - - taskD.done(function(task){ - - var taskD2 = task.update({name: "all the dishes"}) - - taskD2.done(function(task){ - - var taskD3 = task.destroy(); - - taskD3.done(function(){ - console.log("task destroyed"); - }) - - }) - - }); diff --git a/model/pages/encapsulate.md b/model/pages/encapsulate.md deleted file mode 100644 index 4b8546cc..00000000 --- a/model/pages/encapsulate.md +++ /dev/null @@ -1,185 +0,0 @@ -@page jquery.model.encapsulate Service Encapsulation -@parent jQuery.Model - -Models encapsulate your application's raw data. This promotes reuse and provide a -standard interface for widgets to talk to services. - -The majority of the time, the raw data comes from -services your server provides. For example, -if you make a request to: - -
                                                                                GET /contacts.json
                                                                                - -The server might return something like: - -
                                                                                [{
                                                                                -  'id': 1,
                                                                                -  'name' : 'Justin Meyer',
                                                                                -  'birthday': '1982-10-20'
                                                                                -},
                                                                                -{
                                                                                -  'id': 2,
                                                                                -  'name' : 'Brian Moschel',
                                                                                -  'birthday': '1983-11-10'
                                                                                -}]
                                                                                - -In most jQuery code, you'll see something like the following to retrieve contacts -data: - - $.get('/contacts.json', - {type: 'tasty'}, - successCallback, - 'json') - -Instead, model encapsulates (wraps) this request so you call it like: - - Contact.findAll({type: 'old'}, successCallback); - -And instead of raw data, findAll returns contact instances that let you do things like: - -@codestart -// destroy the contact -contact.destroy() - -// update the contact -contact.update({name: "Jeremy"}) - -// create a contact -new Contact({name: "Alex"}).save(); -@codeend - -## Encapsulation Demo - -The Grid demo shows using two different models with the same widget. - -@demo jquery/model/demo-encapsulate.html - -## How to Encapsulate - -Think of models as a contract for creating, reading, updating, and deleting data. - -By filling out a model, you can pass that model to a widget and the widget will use -the model as a proxy for your data. - -The following chart shows the methods most models provide: - - - - - - - - - - - - - - -
                                                                                Create
                                                                                Contact.create(attrs, success, error)
                                                                                Read
                                                                                Contact.findAll(params,success,error)
                                                                                -Contact.findOne(params, success, error)
                                                                                Update
                                                                                Contact.update(id, attrs, success, error)
                                                                                Delete
                                                                                Contact.destroy(id, success, error)
                                                                                - -By filling out these methods, you get the benefits of encapsulation, -AND all the other magic Model provides. - -There are two ways to fill out these methods: - - - providing templated service urls - - implementing the method - -## Using Templated Service URLS - -If your server is REST-ish, you can simply provide -urls to your services. - -The following shows filling out a -Task model's urls. For each method it shows calling the function, -how the service request is made, and what the server's response -should look like: - - $.Model("Task",{ - - // Task.findAll({foo: "bar"}) - // -> GET /tasks.json?foo=bar - // <- [{id: 1, name: "foo"},{ ... }] - findAll : "/tasks.json", - - // Task.findOne({id: 5}) - // -> GET /tasks/5.json - findOne : "/tasks/{id}.json", - - // new Task({name: 'justin'}).save() - // -> POST /tasks.json id=5 - // <- {id : 5} - create : "/tasks.json", - - // task.update({name: 'justin'}) - // -> PUT /tasks/5.json name=justin - // <- {} - update : "/tasks/{id}.json", - - // task.destroy() - // -> DESTROY /tasks/5.json - // <- {} - destroy : "/tasks/{id}.json" - },{}) - -You can change the HTTP request type by putting a GET, POST, DELETE, PUT like: - - $.Model("Todo",{ - destroy: "POST /task/delete/{id}.json - },{}) - -Note: Even if your server doesn't respond with service data -in the same way, it's likely that $.Model will be able to figure it out. If not, -you can probably -overwrite [jQuery.Model.static.models models] -or [jQuery.Model.static.model model]. If that doesn't work, you can -always implement it yourself. - -## Implement Service Methods - -If providing a url doesn't work for you, you -might need to fill out the -service method yourself. Before doing this, it's good -to have an understanding of jQuery's Ajax converters and -deferreds. - - - - - -Lets see how we might fill out the -Contact.findAll function to work with JSONP: - -@codestart -$.Model('Contact', -{ - findAll : function(params, success, error){ - - // do the ajax request - return $.get('/contacts.jsonp', - params, - success, - 'jsonp contact.models'); - } -}, -{ - // Prototype properties of Contact. - // We'll learn about this soon! -}); -@codeend - - - -If we wanted to make a list of contacts, we could do it like: - -@codestart -Contact.findAll({},function(contacts){ - var html = []; - for(var i =0; i < contacts.length; i++){ - html.push('<li>'+contacts[i].name + '</li>') - } - $('#contacts').html( html.join('') ); -}); -@codeend diff --git a/model/pages/typeconversion.md b/model/pages/typeconversion.md deleted file mode 100644 index b32ac105..00000000 --- a/model/pages/typeconversion.md +++ /dev/null @@ -1,88 +0,0 @@ -@page jquery.model.typeconversion Type Conversion -@parent jQuery.Model - -You often want to convert from what the model sends you to -a form more useful to JavaScript. For example, -contacts might be returned from the server with dates that look like: -"1982-10-20". We can model to convert it to something closer -to new Date(1982,10,20). We can do this in two ways: - -## Way 1: Setters - -The [jQuery.Model.prototype.attrs attrs] -and [jQuery.Model.prototype.attr attr] function look for -a setATTRNAME function to handle setting the -date property. - -By providing a function that takes the raw data and returns -a form useful for JavaScript, we can make our models (which -use attrs and attr) automatically convert server data. - -The following demo shows converting a contact's birthday into -a string. - -@demo jquery/model/demo-setter.html - - -## Way 2: Convert - -If you have a lot of dates, Setters won't scale well. -Instead, you can set the type of -an attribute and provide a function to convert that type. - -The following sets the birthday attribute to "date" and provides a date conversion function: - -@codestart -$.Model("Contact", -{ - attributes : { - birthday : 'date' - }, - convert : { - date : function(raw){ - if(typeof raw == 'string'){ - var matches = raw.match(/(\d+)-(\d+)-(\d+)/) - return new Date( matches[1], - (+matches[2])-1, - matches[3] ) - }else if(raw instanceof Date){ - return raw; - } - } - }, - findAll : function( ... ){ ... } -}, -{ - // No prototype properties necessary -}) -@codeend - -@demo jquery/model/demo-convert.html - -# Serialization - -Serialization occurs before the model is saved. This allows you to prepare your model's attributes before they're sent to the server. - -By default every attribute will be passed through the 'default' serialization method that will return the value if the property holds a primitive value (string, number, ...), or it will call the "serialize" method if the property holds an object with the "serialize" method set. - -You can set the serialization methods similar to the convert methods: - -@codestart -$.Model("Contact", -{ - attributes : { - birthday : 'date' - }, - serialize : { - date : function( val, type ){ - return val.getYear() + "-" + (val.getMonth() + 1) + "-" + val.getDate(); - } - }, - findAll : function( ... ){ ... } -}, -{ - // No prototype properties necessary -}) -@codeend - -This code will format the 'birthday' attribute as '2011-11-24' before it will be sent to the server. \ No newline at end of file diff --git a/model/qunit.html b/model/qunit.html deleted file mode 100644 index 218735de..00000000 --- a/model/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

                                                                                Model Test Suite

                                                                                -

                                                                                -
                                                                                -

                                                                                -
                                                                                  -
                                                                                  - associations - list - - - \ No newline at end of file diff --git a/model/service/json_rest/json_rest.js b/model/service/json_rest/json_rest.js deleted file mode 100644 index 433c3412..00000000 --- a/model/service/json_rest/json_rest.js +++ /dev/null @@ -1,109 +0,0 @@ -steal('jquery/model/service').then(function(){ - -$.Model.service.jsonRest = $.Model.service({ - url : "", - type : ".json", - name : "", - getSingularUrl : function(Class, id){ - return this.singularUrl ? - this.singularUrl+"/"+id+this.type : - this.url+this.getName(Class)+"s/"+id+this.type - }, - getPluralUrl : function(Class, id){ - return this.pluralUrl || this.url+this.getName(Class)+"s"+this.type; - }, - getName : function(Class){ - return this.name || Class.name - }, - findAll : function(params){ - var plural = this._service.getPluralUrl(this); - $.ajax({ - url: plural, - type: 'get', - dataType: 'json', - data: params, - success: this.proxy(['wrapMany',success]), - error: error, - fixture: true - }) - }, - getParams : function(attrs){ - var name = this.getName(this), - params = {}; - for(var n in attrs){ - params[name+"["+n+"]"] = attrs[n]; - } - return params; - }, - update : function( id, attrs, success, error ) { - var params = this._service.getParams(attrs), - singular = this._service.getSingularUrl(this, id), - plural = this._service.getPluralUrl(this), - self = this; - - - - $.ajax({ - url: singular, - type: 'put', - dataType: 'text', - data: params, - complete: function(xhr, status ){ - if (/\w+/.test(xhr.responseText)) { - return error( eval('('+xhr.responseText+')') ); - } - success({}) - }, - fixture: "-restUpdate" - - }) - }, - destroy : function(id, success, error){ - var singular = this._service.getSingularUrl(this,id); - $.ajax({ - url: singular, - type: 'delete', - dataType: 'text', - success: success, - error: error, - fixture: "-restDestroy" - }) - }, - create: function( attrs, success, error ) { - var params = this._service.getParams(attrs), - plural = this._service.getPluralUrl(this), - self = this, - name = this._service.getName(this); - - $.ajax({ - url: plural, - type: 'post', - dataType: 'text', - complete: function(xhr, status){ - if (status != "success") { - error(xhr, status) - } - if (/\w+/.test(xhr.responseText)) { - var res = eval('('+xhr.responseText+')'); - if(res[name]){ - success(res[name]); - return; - } - return error( res ); - } - var loc = xhr.responseText; - try{loc = xhr.getResponseHeader("location");}catch(e){}; - if (loc) { - //todo check this with prototype - var mtcs = loc.match(/\/[^\/]*?(\w+)?$/); - if(mtcs) return success({id: parseInt(mtcs[1])}); - } - success({}); - }, - data: params, - fixture: "-restCreate" - }) - } -}); - -}); \ No newline at end of file diff --git a/model/service/service.js b/model/service/service.js deleted file mode 100644 index 2f4ab662..00000000 --- a/model/service/service.js +++ /dev/null @@ -1,30 +0,0 @@ -steal('jquery/model').then(function(){ - var convert = function(method, func){ - - return typeof method == 'function' ? function(){ - var old = this._service, - ret; - this._service = func; - ret = method.apply(this, arguments); - this._service = old; - return ret; - } : method - } - /** - * Creates a service - * @param {Object} defaults - * @param {Object} methods - */ - $.Model.service = function(properties){ - - var func = function(newProps){ - return $.Model.service( $.extend({}, properties, newProps) ); - }; - - for(var name in properties){ - func[name] = convert(properties[name], func) - } - - return func; - } -}); diff --git a/model/service/twitter/twitter.html b/model/service/twitter/twitter.html deleted file mode 100644 index 37ee0094..00000000 --- a/model/service/twitter/twitter.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - associations - - - -

                                                                                  JavaScriptMVC Tweets

                                                                                  -
                                                                                    - - - - \ No newline at end of file diff --git a/model/service/twitter/twitter.js b/model/service/twitter/twitter.js deleted file mode 100644 index 8aaa6740..00000000 --- a/model/service/twitter/twitter.js +++ /dev/null @@ -1,43 +0,0 @@ -steal('jquery/model/service').then(function(){ - - $.Model.service.twitter = $.Model.service({ - url : "http://api.twitter.com/1/", - select : "*", - from : "statuses/user_timeline.json", - where : {screen_name : "javascriptmvc"}, - /** - * - * @param {Object} params - */ - findAll : function(params, success, error){ - - - var url = (params.url || this._service.url)+(params.from || this._service.from), - self = this; - - var twitterJson = { - url: url, - dataType: "jsonp", - data: params.where || this._service.where, - error : error - } - - if(this.wrapMany){ - twitterJson.success = function (data) { - if(data.results){ - data = data.results - } - success(self.wrapMany(data)) - - } - }else{ - twitterJson.success = success; - } - - $.ajax(twitterJson); - } - }); - -}) - - diff --git a/model/service/yql/yql.html b/model/service/yql/yql.html deleted file mode 100644 index b398bde2..00000000 --- a/model/service/yql/yql.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - associations - - - - - - - \ No newline at end of file diff --git a/model/service/yql/yql.js b/model/service/yql/yql.js deleted file mode 100644 index d10a2ea7..00000000 --- a/model/service/yql/yql.js +++ /dev/null @@ -1,66 +0,0 @@ -steal('jquery/model/service').then(function(){ - - $.Model.service.yql = $.Model.service({ - select : "*", - from : "flickr.photos.search", - convert : function (query, params) { - $.each( params, function (key) { - var name = new RegExp( "#\{" + key + "\}","g" ); - var value = $.trim(this); - //if (!value.match(/^[0-9]+$/)) { - // value = '"' + value + '"'; - //} - query = query.replace(name, value); - } - ); - return query; - }, - /** - * - * @param {Object} params - */ - findAll : function(params, success, error){ - params = $.extend({}, this._service, params); - var query = ["SELECT",params.select,"FROM",params.from]; - - - if(params.where){ - query.push("WHERE",typeof params.where == "string" || this._service.convert(params.where[0],params.where[1])) - } - var self = this; - - - var yqlJson = { - url: "http://query.yahooapis.com/v1/public/yql", - dataType: "jsonp", - data: { - q: query.join(" "), - format: "json", - env: 'store://datatables.org/alltableswithkeys', - callback: "?" - } - } - if (error) { - yqlJson.error = error; - } - if(this.wrapMany){ - yqlJson.success = function (data) { - var results = data.query.results - if(results){ - for(var name in results){ - success(self.wrapMany(data.query.results[name])); - break; - } - }else{ - success([]); - } - } - }else{ - yqlJson.success = success; - } - - $.ajax(yqlJson); - } - }); - -}) \ No newline at end of file diff --git a/model/store/qunit.html b/model/store/qunit.html deleted file mode 100644 index d8a863b6..00000000 --- a/model/store/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - store QUnit Test - - - - -

                                                                                    store Test Suite

                                                                                    -

                                                                                    -
                                                                                    -

                                                                                    -
                                                                                    -
                                                                                      -
                                                                                      - - \ No newline at end of file diff --git a/model/store/store.html b/model/store/store.html deleted file mode 100644 index 12b928e0..00000000 --- a/model/store/store.html +++ /dev/null @@ -1,188 +0,0 @@ - - - - store - - - -

                                                                                      store Demo

                                                                                      -
                                                                                        - -
                                                                                      -
                                                                                        - -
                                                                                      - - - - - - \ No newline at end of file diff --git a/model/store/store.js b/model/store/store.js deleted file mode 100644 index ab73370a..00000000 --- a/model/store/store.js +++ /dev/null @@ -1,546 +0,0 @@ -steal('jquery/model/list','jquery/lang/object', function($){ - -var same = $.Object.same, - trigger = function(obj, event, args){ - $.event.trigger(event, args, obj, true) - }, - $method = function( name ) { - return function( eventType, handler ) { - return $.fn[name].apply($([this]), arguments); - } - }, - bind = $method('bind'), - unbind = $method('unbind'); - - -$.Class('jQuery.Model.Store', -{ - id: "id", - bind: bind, - unbind: unbind, - compare : {}, - - init : function(){ - if(this.fullName === 'jQuery.Model.Store'){ - return; - } - - this.sets = []; - this.data = {}; - - // listen on create and add ... listen on destroy and remove - this.namespace.bind('destroyed', this.proxy('destroyed')); - this.namespace.bind('updated', this.proxy('updated')); - this.namespace.bind("created", this.proxy('created')); - }, - - /** - * Internal compare method. - * - * @param {Object} prop - * @param {Object} itemData - * @param {Object} paramData - */ - _compare : function(prop, itemData, paramData){ - return same(itemData, paramData, this.compare[prop]); - }, - - /** - * Creates an item in the sets. Triggered from a model - * event indicating an item was created. - * - * @param {Object} event - * @param {Object} item - */ - created: function(ev,item){ - this.add([item]); - }, - - /** - * Updates an item in the sets. Triggered from a model - * event indicating an item was updated. - * - * @param {Object} event - * @param {Object} item - */ - updated: function(ev, item){ - // go through lists and remove this guy if he is in the list and should not be ... - var sets = this.sets.slice(0), - report = ["Store - updating "]; - - for(var i =0, length = this.sets.length; i < length; i++){ - var set = sets[i], - inSet = this.filter(item, set.params) !== false, - inList = set.list.get(item)[0]; - - if(inSet && !inList){ - report.push("adding to", set.params, "; "); - set.list.push(item) - } else if(!inSet && inList) { - report.push("removing from", set.params, "; "); - set.list.remove(item.id) - } - } - }, - - /** - * Destroy triggered by model event. - * Calls remove function to remove item from lists. - * - * @param {Object} event - * @param {Object} id - */ - destroyed : function(ev,id){ - this.remove(id); - }, - - /** - * @function remove - * - * Removes an item from the sets. - * - * @param {Object} id - */ - remove:function(id){ - var idProp = this.id; - - if(id[idProp] !== undefined){ - id = id[idProp]; - } - - var item = this.data[id]; - - if(!item){ - return; - } - - delete this.data[id]; - }, - - /** - * @function removeSet - * - * Removes a set given a parms object and - * removes each one of the items from the data. - * - * @param {Object} params - */ - removeSet: function(params){ - var matchIdx; - - $.each(this.sets, this.proxy(function(i,set){ - if($.Object.same(params, set.params, this.compare)){ - set.list.each(this.proxy(function(i,item){ - delete this.data[item[this.id]]; - })); - matchIdx = i; - return false; - } - })); - - matchIdx != undefined && this.sets.splice(matchIdx, 1); - }, - - /** - * @function add - * - * Adds items to the set(s) given the matching params. - * - * @param {Object} items - * @param {Object} params - */ - add : function(items, params){ - // need to check the filter rules, if we can even add this ... - - var len = items.length, - i=0, - item, - idProp = this.id, - id, - added = []; - - for(; i< len; i++){ - item = items[i]; - id = item[idProp]; - - if( this.data[id] ){ - - // if there is something there ... take care of it .. - this.update(this.data[id], item); - - // if the item already exists from say a 'findOne' call - // the item will already exist in 'data' but not the 'list' - added.push(item) - } else { - added.push(this.data[id] = item); - } - } - - // go through sets and add to them ... - // slice so that if in callback, the number of sets increases, you are ok - var sets = this.sets.slice(0), - report = ["Store - adding "]; - - for(var i=0, iLength = sets.length; i < iLength; i++){ - var set = sets[i], - itemsForSet = []; - - for(var j =0, jLength = added.length; j< jLength; j++){ - item = added[j] - if( this.filter(item, set.params) !== false) { - itemsForSet.push(item) - } - } - - if(itemsForSet.length) { - report.push(itemsForSet.length,"to", set.params, "; "); - set.list.push(itemsForSet); - } - } - }, - - /** - * @function update - * - * Updates the properties of currentItem - * - * @param {Object} currentItem - * @param {Object} newItem - */ - update : function(currentItem, newItem){ - currentItem.attrs(newItem.serialize()); - }, - - /** - * @function sort - * - * Returns if a set contains the parameters. - * - * @param {Object} params - **/ - has : function(params){ - // check if it has an evil param ... - return $.Object.subsets(params, this.sets).length - }, - - /** - * @function filter - * - * Called with the item and the current params. - * Should return __false__ if the item should be filtered out of the result. - * - * By default this goes through each param in params and see if it matches the - * same property in item (if item has the property defined). - * - * @param {Object} item - * @param {Object} params - */ - filter : function(item, params){ - // go through each param in params - var param, paramValue - for ( var param in params ) { - i=0; - paramValue = params[param]; - - // in fixtures we ignore null, I don't want to now - if ( paramValue !== undefined && item[param] !== undefined - && !this._compare(param, item[param], paramValue) ) { - return false; - } - } - }, - - /** - * @function sort - * - * Sorts the object in place. By default uses an order - * property in the param of the class. - * - * @codestart - * var models = $.Model.Store.sort(myModelListInstance); - * @codeend - * - * @param {Object} items - * @param {Object} params - */ - sort : function(items, params){ - $.each((params.order || []).slice(0).reverse(), function( i, name ) { - var split = name.split(" "); - items = items.sort(function( a, b ) { - if ( split[1].toUpperCase() !== "ASC" ) { - if( a[split[0]] < b[split[0]] ) { - return 1; - } else if(a[split[0]] == b[split[0]]){ - return 0 - } else { - return -1; - } - } - else { - if( a[split[0]] < b[split[0]] ) { - return -1; - } else if(a[split[0]] == b[split[0]]){ - return 0 - } else { - return 1; - } - } - }); - }); - return items - }, - - /** - * @function pagination - * - * Paginates the item in place. By default uses an order - * property in the param of the class. - * - * @codestart - * var models = $.Model.Store.pagination(myModelListInstance); - * @codeend - * - * @param {Object} items - * @param {Object} params - */ - pagination : function(items, params){ - var offset = parseInt(params.offset, 10) || 0, - limit = parseInt(params.limit, 10) || (items.length - offset); - - return items.slice(offset, offset + limit); - }, - - /** - * @function get - * - * Retrieves an item(s) given an id or array of ids from the global data - * set of the model store. If the item is not returned yet, it will return - * the deffered. - * - * @codestart - * var model = $.Model.Store.get(222); - * @codeend - * - * @codestart - * var models = $.Model.Store.get([222, 223, 224]); - * @codeend - * - * @param {Object} id int or array of ints - */ - get : function(id){ - if($.isArray(id)) { - var returnArr = []; - - $.each(id, this.proxy(function(i,d){ - var m = this.data[d]; - m && returnArr.push(m); - })); - - return returnArr; - } else { - return this.data[id]; - } - }, - - /** - * @function findOne - * - * FindOne attempts to retrieve an individual model - * from the sets of currently fetched data. If the model - * was not previously fetched, it will then execute a request on the - * static 'findOne' method of the model. It returns - * the deffered object. - * - * @codestart - * $.Model.Store.findOne(222).done(success); - * @codeend - * - * - * You can listen for 'findOne' to be triggered by - * binding to the 'findOne' event on the class. - * - * @codestart - * $.Model.Store.bind('findOne', function(id){ ... }); - * @codeend - * - * - * @param {Object} id of item - * @param {Function} success handler - * @param {Function} error handler - **/ - findOne : function(id, success, error){ - var data = this.data[id], - def; - - if(data){ - if(data.isRejected){ - return data; - } else { - def = $.Deferred(); - def.resolve(data); - } - } else { - this.data[id] = def = this.namespace.findOne({ id: id }); - - def.done(this.proxy(function(item){ - this.data[id] = item; - })); - } - - def.done(success); - trigger(this, 'findOne', id); - - return def; - }, - - /** - * @function findAll - * - * FindAll attempts to retrieve a list of model(s) - * from the sets of currently fetched data. If the model(s) - * were not previously fetched, it will then execute a request on the - * static 'findAll' method of the model. It returns - * the deffered object. - * - * @codestart - * $.Model.Store.findAll({ parentId: 2222 }).done(success); - * @codeend - * - * - * You can listen for 'findAll' to be triggered by - * binding to the 'findAll' event on the class. - * - * @codestart - * $.Model.Store.bind('findAll', function(params){ ... }); - * @codeend - * - * - * @param {Object} params - * @param {Boolean} register registers this list as owning some content, but does not - * @param {Boolean} ready - **/ - findAll : function(params, register, ready){ - // find the first set that is the same - // or is a subset with a def - var parentLoadedSet, - self = this, - list, - cb = function(){ - ready(list) - }; - - if(typeof register === 'function' ){ - ready = register; - register = false; - } - ready = ready || function(){}; - - for(var i =0, length = this.sets.length; i < length; i++){ - var set = this.sets[i]; - if( $.Object.subset(params, set.params, this.compare) ){ - parentLoadedSet = set; - - if( $.Object.same(set.params, params, this.compare) ){ - // what if it's not loaded - if(!set.def){ - var def = this.namespace.findAll(params); - set.def = def; - def.done(function(items){ - list = items; - self.add(items, params) - cb && cb(); - }) - } else { - list = set.list; - if(set.def.isResolved()){ - setTimeout(cb, 1); - } else { - set.def.done(cb); - } - } - - return set.list; - } - } - } - - // create a list, a set and add the set to our list of sets - list = new this.namespace.List(); - var sameSet = { - params: $.extend({},params), - list: list - }; - - this.sets.push(sameSet); - - // we have loaded or are loading what we need - if( parentLoadedSet ) { - // find the first set with a deferred - if( !parentLoadedSet.def ) { - - // we need to load this ... - - } else if( parentLoadedSet.def.isResolved() ){ - // add right away - var items = self.findAllCached(params); - list.push(items); - setTimeout(cb, 1);; - } else { - // this will be filled when add is called ... - parentLoadedSet.def.done(function(){ - var items = self.findAllCached(params); - list.push(items); - cb && cb(); - }) - } - - } else { - - if( !register ) { - // we need to load it - var def = sameSet.def = this.namespace.findAll(params); - - def.done(function(items){ - self.add(items, params); - cb && cb(); - }); - } - } - - trigger(this, 'findAll', params); - - return list; - }, - - /** - * @function findAllCached - * - * FindAll attempts to retrieve a list of model(s) - * only from the cache. - * - * @param {Object} params - **/ - findAllCached : function(params){ - // remove anything not filtering .... - // - sorting, grouping, limit, and offset - - var list = [], - data = this.data, - item; - - for(var id in data){ - item = data[id]; - if( this.filter(item, params) !== false) { - list.push(item) - } - } - - // do sorting / grouping - list = this.pagination(this.sort(list, params), params); - - // take limit and offset ... - return list; - } -},{ }); - -}); \ No newline at end of file diff --git a/model/store/store_test.js b/model/store/store_test.js deleted file mode 100644 index 4cccdefd..00000000 --- a/model/store/store_test.js +++ /dev/null @@ -1,201 +0,0 @@ -steal('funcunit/qunit','./store.js', - 'jquery/model', - 'jquery/model/list', - 'jquery/dom/fixture',function(){ - -module("store", { - setup : function(){ - - } -}); - - - -/* -test("smart findAll", function(){ - - $.Model('Item'); - - - - ok( this.store.has({parentId: 7}) , "store has everything with parentId 7"); - - - var items = this.store.findAll({parentId: 7}); - equals( items.length, 2 , "got the wrong number of items"); - $.each(items, function(i, item){ - if(item.parentId != 7){ - ok(false,"got a bad parentId") - } - }) -})*/ - -test("store findAll", 5, function(){ - - $.fixture.make('item',40, function(i){ - return { - name: "Name "+i, - parentId: i%4+1 - } - }) - - $.Model('Item',{},{}); - $.Model.List('Item.List'); - $.Model.Store('Item.Store'); - - - var list = Item.Store.findAll({}); - stop(); - list.bind("add", function(ev, items){ - console.log("here ...") - start(); - - ok(items, "add called with items"); - - equal( items.length,40, "add called with items"); - - var list2 = Item.Store.findAll({parentId: 2}); - - equal( list2.length , 10, "immediately loaded"); - - - list.unbind('add',arguments.callee); - - list.bind('add', function(){ - ok(true, "big list added to") - }) - - list2.bind('add', function(){ - ok(true, "small list added too") - }) - - Item.Store.add([new Item({id: 100, parentId: 2})]); - - }) - -}) - -test("Store Compare", function(){ - - - $.fixture.make('item',40, function(i){ - return { - name: "Name "+i, - parentId: i%4+1 - } - }) - - $.Model('Item',{},{}); - $.Model.List('Item.List'); - $.Model.Store('Item.Store',{ - compare : { - count : null - } - },{}); - - - var list = Item.Store.findAll({count: 2}); - stop(); - list.bind("add", function(ev, items){ - ok(items.length); - ok(list.length) - start() - var list2 = Item.Store.findAll({count: 500}); - equals(list2.length, list.length, "lists have the same items"); - ok(list2 === list,"lists are equal") - }) -}) - -test("Store Remove", function(){ - $.fixture.make('item',40, function(i){ - return { - name: "Name "+i, - parentId: i%4+1 - } - }) - - $.Model('Item',{},{}); - $.Model.List('Item.List'); - $.Model.Store('Item.Store',{ - compare : { - count : null - } - },{}); - - var list = Item.Store.findAll({parentId: 1}), - len = 0, - first; - stop(); - list.bind("add", function(ev, items){ - ok(items.length, "there should be items"); - len = items.length; - first = items[0] - first.destroy(); - }) - list.bind("remove", function(ev, items){ - ok(items[0] === first, "removed first item"); - equals(list.length, len - 1, "length adjusted") - var list2 = Item.Store.findAll({parentId: 1}); - ok(list2.get(first.id)[0] === undefined, "Model Store remove callback"); - start(); - }) -}); - -test("Store Update", function(){ - $.fixture.make('item',40, function(i){ - return { - name: "Name "+i, - parentId: i%4+1 - } - }) - - $.Model('Item',{},{}); - $.Model.List('Item.List'); - $.Model.Store('Item.Store',{ - compare : { - count : null - } - },{}); - - var list1 = Item.Store.findAll({parentId: 1}), - list2 = Item.Store.findAll({parentId: 2}), - len = 0, - first; - - stop(); - var def1 = $.Deferred(), - def2 = $.Deferred(), - first, - updating; - - list1.bind("add", function(ev, items){ - console.log("1 added") - def1.resolve(true) - first = items[0] - }); - list1.bind("remove", function(ev, items){ - console.log("1 removed") - equals(items[0].id, first.id, "first removed") - }) - list2.bind("add", function(ev, items){ - console.log("2 added") - if(!updating){ - def2.resolve(true); - } else { - equals(items[0].id, first.id, "item added to second list") - start(); - } - }); - - $.when(def1, def2).then(function(){ - console.log('both ready') - updating = true; - first.updated({parentId: 2}) - }); - -}); - - - -}); - diff --git a/model/test/4.json b/model/test/4.json deleted file mode 100644 index d05cb425..00000000 --- a/model/test/4.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id": 4, - "name" : "adler" -} \ No newline at end of file diff --git a/model/test/create.json b/model/test/create.json deleted file mode 100644 index 734e4916..00000000 --- a/model/test/create.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id": 4, - "name" : "Highland" -} \ No newline at end of file diff --git a/model/test/people.json b/model/test/people.json deleted file mode 100644 index b5f86a2e..00000000 --- a/model/test/people.json +++ /dev/null @@ -1,4 +0,0 @@ -[{ - "id" : 5, - "name" : "Justin" -}] diff --git a/model/test/person.json b/model/test/person.json deleted file mode 100644 index ea58f4ea..00000000 --- a/model/test/person.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id" : 5, - "name" : "Justin" -} diff --git a/model/test/qunit/associations_test.js b/model/test/qunit/associations_test.js deleted file mode 100644 index 7e8a8559..00000000 --- a/model/test/qunit/associations_test.js +++ /dev/null @@ -1,121 +0,0 @@ -module("jquery/model/associations",{ - setup: function() { - - $.Model("MyTest.Person", { - serialize: function() { - return "My name is " + this.name; - } - }); - $.Model("MyTest.Loan"); - $.Model("MyTest.Issue"); - - $.Model("MyTest.Customer", - { - attributes : { - person : "MyTest.Person.model", - loans : "MyTest.Loan.models", - issues : "MyTest.Issue.models" - }, - - update : function(id, attrs, success, error){ - return $.ajax({ - url : "/people/"+id, - data : attrs, - type : 'post', - dataType : "json", - fixture: function(){ - return [{ - loansAttr: attrs.loans, - personAttr: attrs.person - }] - }, - success : success - }) - } - }, - {}); - } -}); - -test("associations work", function(){ - var c = new MyTest.Customer({ - id: 5, - person : { - id: 1, - name: "Justin" - }, - issues : [], - loans : [ - { - amount : 1000, - id: 2 - }, - { - amount : 19999, - id: 3 - } - ] - }) - equals(c.person.name, "Justin", "association present"); - equals(c.person.Class, MyTest.Person, "belongs to association typed"); - - equals(c.issues.length, 0); - - equals(c.loans.length, 2); - - equals(c.loans[0].Class, MyTest.Loan); -}); - -test("Model association serialize on save", function(){ - var c = new MyTest.Customer({ - id: 5, - person : { - id: 1, - name: "thecountofzero" - }, - issues : [], - loans : [] - }), - cSave = c.save(); - - stop(); - cSave.then(function(customer){ - start() - equals(customer.personAttr, "My name is thecountofzero", "serialization works"); - - }); - -}); - -test("Model.List association serialize on save", function(){ - var c = new MyTest.Customer({ - id: 5, - person : { - id: 1, - name: "thecountofzero" - }, - issues : [], - loans : [ - { - amount : 1000, - id: 2 - }, - { - amount : 19999, - id: 3 - } - ] - }), - cSave = c.save(); - - stop(); - cSave.then(function(customer){ - start() - ok(customer.loansAttr._namespace === undefined, "_namespace does not exist"); - ok(customer.loansAttr._data === undefined, "_data does not exist"); - ok(customer.loansAttr._use_call === undefined, "_use_call does not exist"); - ok(customer.loansAttr._changed === undefined, "_changed does not exist"); - - }); - -}); \ No newline at end of file diff --git a/model/test/qunit/findAll.json b/model/test/qunit/findAll.json deleted file mode 100644 index 8dc242fa..00000000 --- a/model/test/qunit/findAll.json +++ /dev/null @@ -1,4 +0,0 @@ -[{ - "id" : 1, - "name" : "Thing 1" -}] diff --git a/model/test/qunit/model_test.js b/model/test/qunit/model_test.js deleted file mode 100644 index faf4f69c..00000000 --- a/model/test/qunit/model_test.js +++ /dev/null @@ -1,576 +0,0 @@ -steal('can/util', 'jquery', 'jquery/model', function(can, $) { -module("jquery/model", { - setup: function() { - var ids = 0; - $.Model("Person",{ - findAll: function( params) { - return $.Deferred().resolve([{name: "foo"}]) - }, - findOne: function( params, success, error ) { - return $.Deferred().resolve({name: "foo"}); - }, - create: function( params) { - return $.Deferred( ).resolve({zoo: "zed", id: (++ids)} ); - }, - destroy: function( id, success, error ) { - return $.Deferred().resolve(); - }, - update: function( id, attrs, success, error ) { - return $.Deferred().resolve({zoo: "monkeys"}); - } - },{ - prettyName: function() { - return "Mr. "+this.name; - } - }) - } -}) - - -test("CRUD", function(){ - - Person.findAll({}, function(response){ - equals("foo", response[0].name) - }) - Person.findOne({}, function(response){ - equals("foo", response.name) - }) - var person; - new Person({foo: "bar"}).save(function(inst, attrs){ - equals("bar", inst.foo) - equals("zed", inst.zoo) - ok(inst.save, "has save function"); - person = inst; - }); - person.attr({zoo: "monkey"}).save(function(inst, attrs, update){ - equals(inst, person, "we get back the same instance"); - equals(person.zoo, "monkeys", "updated to monkeys zoo! This tests that you callback with the attrs") - }) -}); - -test("findAll deferred", function(){ - $.Model.extend("Person",{ - findAll : function(params, success, error){ - return $.ajax({ - url : "/people", - data : params, - dataType : "json", - fixture: "//jquery/model/test/people.json" - }) - } - },{}); - stop(); - var people = Person.findAll({}); - people.then(function(people){ - equals(people.length, 1, "we got a person back"); - equals(people[0].name, "Justin", "Got a name back"); - equals(people[0].constructor.shortName, "Person", "got a class back"); - start(); - }) -}); - -test("findOne deferred", function(){ - $.Model.extend("Person",{ - findOne : function(params, success, error){ - return $.ajax({ - url : "/people/5", - data : params, - dataType : "json", - fixture: "//jquery/model/test/person.json" - }) - } - },{}); - stop(); - var person = Person.findOne({}); - person.then(function(person){ - equals(person.name, "Justin", "Got a name back"); - equals(person.constructor.shortName, "Person", "got a class back"); - start(); - }) -}); - -test("save deferred", function(){ - - $.Model("Person",{ - create : function(attrs, success, error){ - return $.ajax({ - url : "/people", - data : attrs, - type : 'post', - dataType : "json", - fixture: function(){ - return {id: 5} - }, - success : success - }) - } - },{}); - - var person = new Person({name: "Justin"}), - personD = person.save(); - - stop(); - personD.then(function(person){ - start() - console.log(person) - equals(person.id, 5, "we got an id") - }); - -}); - -test("update deferred", function(){ - - $.Model("Person",{ - update : function(id, attrs, success, error){ - return $.ajax({ - url : "/people/"+id, - data : attrs, - type : 'post', - dataType : "json", - fixture: function(){ - return {thing: "er"} - }, - success : success - }) - } - },{}); - - var person = new Person({name: "Justin", id:5}), - personD = person.save(); - - stop(); - personD.then(function(person){ - start() - equals(person.thing, "er", "we got updated") - - }); - -}); - -test("destroy deferred", function(){ - - $.Model("Person",{ - destroy : function(id, success, error){ - return $.ajax({ - url : "/people/"+id, - type : 'post', - dataType : "json", - fixture: function(){ - return {thing: "er"} - }, - success : success - }) - } - },{}); - - var person = new Person({name: "Justin", id:5}), - personD = person.destroy(); - - stop(); - personD.then(function(person){ - start() - equals(person.thing, "er", "we got destroyed") - - }); -}); - - -test("hookup and model", function(){ - var div = $("
                                                                                      ") - var p = new Person({foo: "bar2", id: 5}); - p.hookup( div[0] ); - ok(div.hasClass("person"), "has person"); - ok(div.hasClass("person_5"), "has person_5"); - equals(p, div.model(),"gets model" ) -}) -// test that models returns an array of unique instances -test("unique models", function(){ - var div1 = $("
                                                                                      ") - var div2 = $("
                                                                                      ") - var div3 = $("
                                                                                      ") - var p = new Person({foo: "bar2", id: 5}); - var p2 = new Person({foo: "bar3", id: 4}); - p.hookup( div1[0] ); - p.hookup( div2[0] ); - p2.hookup( div3[0] ); - var models = div1.add(div2).add(div3).models(); - equals(p, models[0], "gets models" ) - equals(p2, models[1], "gets models" ) - equals(2, models.length, "gets models" ) -}) - - -test("models", function(){ - var people = Person.models([ - {id: 1, name: "Justin"} - ]) - equals(people[0].prettyName(),"Mr. Justin","wraps wrapping works") -}); - - - -test("async setters", function(){ - - /* - $.Model("Test.AsyncModel",{ - setName : function(newVal, success, error){ - - - setTimeout(function(){ - success(newVal) - }, 100) - } - }); - - var model = new Test.AsyncModel({ - name : "justin" - }); - equals(model.name, "justin","property set right away") - - //makes model think it is no longer new - model.id = 1; - - var count = 0; - - model.bind('name', function(ev, newName){ - equals(newName, "Brian",'new name'); - equals(++count, 1, "called once"); - ok(new Date() - now > 0, "time passed") - start(); - }) - var now = new Date(); - model.attr('name',"Brian"); - stop();*/ -}) - -test("binding", 2,function(){ - var inst = new Person({foo: "bar"}); - - inst.bind("foo", function(ev, val){ - ok(true,"updated") - equals(val, "baz", "values match") - }); - - inst.attr("foo","baz"); - -}); - -test("error binding", 1, function(){ - $.Model.extend("School",{ - setName : function(name, success, error){ - if(!name){ - error("no name"); - } - return error; - } - }) - var school = new School(); - school.bind("error.name", function(ev, attr, error){ - equals(error, "no name", "error message provided") - }) - school.attr("name",""); - - -}) - -test("auto methods",function(){ - //turn off fixtures - $.fixture.on = false; - var School = $.Model.extend("Jquery.Model.Models.School",{ - findAll : steal.config().root.join("jquery/model/test")+"/{type}.json", - findOne : steal.config().root.join("jquery/model/test")+"/{id}.json", - create : "GET " + steal.config().root.join("can/model/test")+"/create.json", - update : "GET "+steal.config().root.join("can/model/test")+"/update{id}.json" - },{}) - stop(); - School.findAll({type:"schools"}, function(schools){ - ok(schools,"findAll Got some data back"); - equals(schools[0].constructor.shortName,"School","there are schools") - - School.findOne({id : "4"}, function(school){ - ok(school,"findOne Got some data back"); - equals(school.constructor.shortName,"School","a single school"); - - - new School({name: "Highland"}).save(function(school){ - equals(school.name,"Highland","create gets the right name") - school.attr({name: "LHS"}).save(function(school){ - start(); - equals(school.name,"LHS","create gets the right name") - - $.fixture.on = true; - }) - }) - - }) - - }) -}) - -test("isNew", function(){ - var p = new Person(); - ok(p.isNew(), "nothing provided is new"); - var p2 = new Person({id: null}) - ok(p2.isNew(), "null id is new"); - var p3 = new Person({id: 0}) - ok(!p3.isNew(), "0 is not new"); -}); -test("findAll string", function(){ - $.fixture.on = false; - $.Model("Test.Thing",{ - findAll : steal.config().root.join("jquery/model/test/qunit/findAll.json")+'' - },{}); - stop(); - Test.Thing.findAll({},function(things){ - equals(things.length, 1, "got an array"); - equals(things[0].id, 1, "an array of things"); - start(); - $.fixture.on = true; - }) -}); - -test("Model events" , function(){ - var order = 0; - $.Model("Test.Event",{ - create : function(attrs){ - return $.Deferred().resolve({id: 1}) - }, - update : function(id, attrs, success){ - return $.Deferred().resolve(attrs) - }, - destroy : function(id, success){ - return $.Deferred().resolve() - } - },{}); - - stop(); - $([Test.Event]).bind('created',function(ev, passedItem){ - - ok(this === Test.Event, "got model") - ok(passedItem === item, "got instance") - equals(++order, 1, "order"); - passedItem.attr({}).save(); - - }).bind('updated', function(ev, passedItem){ - equals(++order, 2, "order"); - ok(this === Test.Event, "got model") - ok(passedItem === item, "got instance") - - passedItem.destroy({}); - - }).bind('destroyed', function(ev, passedItem){ - equals(++order, 3, "order"); - ok(this === Test.Event, "got model") - ok(passedItem === item, "got instance") - - start(); - - }) - - var item = new Test.Event(); - item.save(); - -}); - - -test("converters and serializes", function(){ - $.Model("Task1",{ - attributes: { - createdAt: "date" - }, - convert: { - date: function(d){ - var months = ["jan", "feb", "mar"] - return months[d.getMonth()] - } - }, - serialize: { - date: function(d){ - var months = {"jan":0, "feb":1, "mar":2} - return months[d] - } - } - },{}); - $.Model("Task2",{ - attributes: { - createdAt: "date" - }, - convert: { - date: function(d){ - var months = ["apr", "may", "jun"] - return months[d.getMonth()] - } - }, - serialize: { - date: function(d){ - var months = {"apr":0, "may":1, "jun":2} - return months[d] - } - } - },{}); - var d = new Date(); - d.setDate(1); - d.setMonth(1); - var task1=new Task1({ - createdAt: d, - name:"Task1" - }); - d.setMonth(2) - var task2=new Task2({ - createdAt: d, - name:"Task2" - }); - equals(task1.createdAt, "feb", "Task1 model convert"); - equals(task2.createdAt, "jun", "Task2 model convert"); - equals(task1.serialize().createdAt, 1, "Task1 model serialize"); - equals(task2.serialize().createdAt, 2, "Task2 model serialize"); - equals(task1.serialize().name, "Task1", "Task1 model default serialized"); - equals(task2.serialize().name, "Task2", "Task2 model default serialized"); -}); - -test("default converters", function(){ - var num = 1318541064012; - equals( $.Model.convert.date(num).getTime(), num, "converted to a date with a number" ); -}) - -test("removeAttr test", function(){ - var person = new Person({foo: "bar"}) - equals(person.foo, "bar", "property set"); - person.removeAttr('foo') - - equals(person.foo, undefined, "property removed"); - var attrs = person.attr() - equals(attrs.foo, undefined, "attrs removed"); -}); - -test("identity should replace spaces with underscores", function(){ - $.Model("Task",{},{}); - t = new Task({ - id: "id with spaces" - }); - equals(t.identity(), "task_id_with_spaces") -}); - -test("save error args", function(){ - var Foo = $.Model('Testin.Models.Foo',{ - create : "/testinmodelsfoos.json" - },{ - - }) - var st = '{type: "unauthorized"}'; - - $.fixture("/testinmodelsfoos.json", function(headers, respond) { - respond(401,st); - }); - stop(); - var inst = new Foo({}).save().done(function(){ - ok(false, "success should not be called") - }).fail(function(jQXHR){ - ok(true, "error called") - ok(jQXHR.getResponseHeader,"jQXHR object") - start() - }) - - - -}); - -test("hookup and elements", function(){ - $.Model('Escaper',{ - escapeIdentity : true - },{}); - - var ul = $('
                                                                                      '), - li = ul.find('li'); - - var esc = new Escaper({id: " some crazy #/ %ing stuff"}); - - li.model(esc); - - var res = esc.elements(ul); - - equals(res.length,1, "1 item") - ok(res[0] === li[0], "items are equal") -}) - -test('aborting create update and destroy', function(){ - stop(); - var delay = $.fixture.delay; - $.fixture.delay = 1000; - - $.fixture("POST /abort", function(){ - ok(false, "we should not be calling the fixture"); - return {}; - }) - - $.Model('Abortion',{ - create : "POST /abort", - update : "POST /abort", - destroy: "POST /abort" - },{}); - - var deferred = new Abortion({name: "foo"}).save(function(){ - ok(false, "success create") - }, function(){ - ok(true, "create error called"); - - - deferred = new Abortion({name: "foo",id: 5}) - .save(function(){},function(){ - ok(true, "error called in update") - - deferred = new Abortion({name: "foo",id: 5}).destroy(function(){}, - function(){ - ok(true,"destroy error called") - $.fixture.delay = delay; - start(); - }) - - setTimeout(function(){ - deferred.abort(); - },10) - - }) - - setTimeout(function(){ - deferred.abort(); - },10) - }); - setTimeout(function(){ - deferred.abort(); - },10) - - -}); - -test("object definitions", function(){ - - $.Model('ObjectDef',{ - findAll : { - url : "/test/place" - }, - findOne : { - url : "/objectdef/{id}", - timeout : 1000 - }, - create : { - - }, - update : { - - }, - destroy : { - - } - },{}) - - $.fixture("GET /objectdef/{id}", function(original){ - equals(original.timeout,1000,"timeout set"); - return {yes: true} - }); - stop(); - ObjectDef.findOne({id: 5}, function(){ - start(); - }) -}) -}) \ No newline at end of file diff --git a/model/test/qunit/qunit.js b/model/test/qunit/qunit.js deleted file mode 100644 index e1117ddb..00000000 --- a/model/test/qunit/qunit.js +++ /dev/null @@ -1,9 +0,0 @@ -//we probably have to have this only describing where the tests are -steal("jquery/model","jquery/dom/fixture") //load your app - .then('funcunit/qunit') //load qunit - .then("./model_test.js")//,"./associations_test.js") - .then( - "jquery/model/backup/qunit", - "jquery/model/list/list_test.js" - ) - .then("jquery/model/validations/qunit/validations_test.js") diff --git a/model/test/schools.json b/model/test/schools.json deleted file mode 100644 index 1b596fa0..00000000 --- a/model/test/schools.json +++ /dev/null @@ -1,4 +0,0 @@ -[{ - "id": 1, - "name" : "adler" -}] diff --git a/model/test/update4.json b/model/test/update4.json deleted file mode 100644 index 9f705c98..00000000 --- a/model/test/update4.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "id": 4, - "name" : "LHS" -} \ No newline at end of file diff --git a/model/validations/demo.html b/model/validations/demo.html deleted file mode 100644 index 20cb9c0b..00000000 --- a/model/validations/demo.html +++ /dev/null @@ -1,105 +0,0 @@ - - - - Model Validations Demo - - - -
                                                                                      - -
                                                                                      -
                                                                                      - - - - \ No newline at end of file diff --git a/model/validations/qunit.html b/model/validations/qunit.html deleted file mode 100644 index c003f308..00000000 --- a/model/validations/qunit.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - -

                                                                                      Model Test Suite

                                                                                      -

                                                                                      -
                                                                                      -

                                                                                      -
                                                                                        -
                                                                                        - associations - list - - - \ No newline at end of file diff --git a/model/validations/qunit/validations_test.js b/model/validations/qunit/validations_test.js deleted file mode 100644 index f6ca726d..00000000 --- a/model/validations/qunit/validations_test.js +++ /dev/null @@ -1,169 +0,0 @@ -steal('funcunit/qunit','jquery/model/validations').then(function(){ - -var Person; - -module("jquery/model/validations",{ - setup : function(){ - Person = jQuery.Model({},{}); - } -}) - -test("models can validate, events, callbacks", 7 ,function(){ - Person.validate("age", {message : "it's a date type"},function(val){ - return ! ( this.date instanceof Date ) - }) - - - var task = new Person({age: "bad"}), - errors = task.errors() - - - ok(errors, "There are errors"); - equals(errors.age.length, 1, "there is one error"); - equals(errors.age[0], "it's a date type", "error message is right"); - - // TODO: bring this back eventually - task.bind("error.age", function(ev, attr, errs){ - ok(this === task, "we get task back by binding"); - - ok(errs, "There are errors"); - equals(errs.age.length, 1, "there is one error"); - equals(errs.age[0], "it's a date type", "error message is right"); - }) - - task.attr("age","blah"); - - - - task.unbind("error.age"); - - - - -}) - -test("validatesFormatOf", function(){ - Person.validateFormatOf("thing",/\d-\d/) - ok(!new Person({thing: "1-2"}).errors(),"no errors"); - - var errors = new Person({thing: "foobar"}).errors(); - - ok(errors, "there are errors") - equals(errors.thing.length,1,"one error on thing"); - - equals(errors.thing[0],"is invalid","basic message"); - - Person.validateFormatOf("otherThing",/\d/,{message: "not a digit"}) - - var errors2 = new Person({thing: "1-2", otherThing: "a"}).errors(); - - equals(errors2.otherThing[0],"not a digit", "can supply a custom message") -}); - -test("validatesInclusionOf", function(){ - Person.validateInclusionOf("thing", ["yes", "no", "maybe"]); - - ok(!new Person({thing: "yes"}).errors(),"no errors"); - - var errors = new Person({thing: "foobar"}).errors(); - - ok(errors, "there are errors"); - equals(errors.thing.length,1,"one error on thing"); - - equals(errors.thing[0],"is not a valid option (perhaps out of range)","basic message"); - - Person.validateInclusionOf("otherThing", ["yes", "no", "maybe"],{message: "not a valid option"}); - - var errors2 = new Person({thing: "yes", otherThing: "maybe not"}).errors(); - - equals(errors2.otherThing[0],"not a valid option", "can supply a custom message"); -}); - -test("validatesLengthOf", function(){ - Person.validateLengthOf("thing", 2, 5); - - ok(!new Person({thing: "yes"}).errors(),"no errors"); - - var errors = new Person({thing: "foobar"}).errors(); - - ok(errors, "there are errors"); - equals(errors.thing.length,1,"one error on thing"); - - equals(errors.thing[0],"is too long (max=5)","basic message"); - - Person.validateLengthOf("otherThing", 2, 5, {message: "invalid length"}); - - var errors2 = new Person({thing: "yes", otherThing: "too long"}).errors(); - - equals(errors2.otherThing[0],"invalid length", "can supply a custom message"); -}); - -test("validatesPresenceOf", function(){ - $.Model.extend("Task",{ - init : function(){ - this.validatePresenceOf("dueDate") - } - },{}); - - //test for undefined - var task = new Task(), - errors = task.errors(); - - ok(errors) - ok(errors.dueDate) - equals(errors.dueDate[0], "can't be empty" , "right message"); - - //test for null - task = new Task({dueDate: null}); - errors = task.errors(); - - ok(errors) - ok(errors.dueDate) - equals(errors.dueDate[0], "can't be empty" , "right message"); - - //test for "" - task = new Task({dueDate: ""}); - errors = task.errors(); - - ok(errors) - ok(errors.dueDate) - equals(errors.dueDate[0], "can't be empty" , "right message"); - - //Affirmative test - task = new Task({dueDate : "yes"}); - errors = task.errors();; - - ok(!errors, "no errors "+typeof errors); - - $.Model.extend("Task",{ - init : function(){ - this.validatePresenceOf("dueDate",{message : "You must have a dueDate"}) - } - },{}); - - task = new Task({dueDate : "yes"}); - errors = task.errors();; - - ok(!errors, "no errors "+typeof errors); -}) - -test("validatesRangeOf", function(){ - Person.validateRangeOf("thing", 2, 5); - - ok(!new Person({thing: 4}).errors(),"no errors"); - - var errors = new Person({thing: 6}).errors(); - - ok(errors, "there are errors") - equals(errors.thing.length,1,"one error on thing"); - - equals(errors.thing[0],"is out of range [2,5]","basic message"); - - Person.validateRangeOf("otherThing", 2, 5, {message: "value out of range"}); - - var errors2 = new Person({thing: 4, otherThing: 6}).errors(); - - equals(errors2.otherThing[0],"value out of range", "can supply a custom message"); -}); - -}); diff --git a/model/validations/validations.html b/model/validations/validations.html deleted file mode 100644 index 0eeb932c..00000000 --- a/model/validations/validations.html +++ /dev/null @@ -1,123 +0,0 @@ - - - - Model Validations Demo - - - -
                                                                                        -

                                                                                        Model Validations Demo

                                                                                        -

                                                                                        This demo demonstrates using validations to prevent - a person's birthday from being in the future.

                                                                                        -

                                                                                        Clicking a person's name will show a form to update - their birthday. Change the birthday and 'blur' the - input to update their listed age.

                                                                                        -
                                                                                        -
                                                                                        -
                                                                                        -
                                                                                        -
                                                                                        - - - - \ No newline at end of file diff --git a/model/validations/validations.js b/model/validations/validations.js deleted file mode 100644 index 4baa3aac..00000000 --- a/model/validations/validations.js +++ /dev/null @@ -1 +0,0 @@ -steal('jquery/model','can/observe/validations'); \ No newline at end of file diff --git a/package.json b/package.json index dec7a375..b9f56ede 100644 --- a/package.json +++ b/package.json @@ -1,27 +1,78 @@ { - "name" : "jquerypp", - "description" : "jQuery's missing utils and special events", - "version" : "1.0.0", - "maintainers" : [ - { - "name" : "Bitovi", - "email" : "contact@bitovi.com", - "web" : "http://bitovi.com/" - } - ], - "devDependencies" : { - "grunt" : "~0.3.11", - "http-server" : "0.5.1" + "name": "jquerypp", + "title": "jQuery++", + "description": "jQuery's missing utils and special events", + "version": "2.0.0", + "author": { + "name": "Bitovi", + "email": "contact@bitovi.com", + "web": "http://bitovi.com/" + }, + "peerDependencies": { + "jquery": ">1.9.0" }, - "homepage" : "http://jquerypp.com", - "repository" : { - "type" : "git", - "url" : "git://github.com/jupiterjs/jquerypp.git" + "scripts": { + "preversion": "npm test && npm run build", + "version": "git commit -am \"Update dist for release\" && git checkout -b release && git add -f dist/", + "postversion": "git push --tags && git checkout master && git branch -D release && git push", + "release:patch": "npm version patch && npm publish", + "release:minor": "npm version minor && npm publish", + "release:major": "npm version major && npm publish", + "test": "grunt test --stack", + "build": "grunt build" }, - "licenses" : [ + "devDependencies": { + "grunt": "^0.4.5", + "grunt-banner": "^0.3.1", + "grunt-cli": "^0.1.13", + "grunt-contrib-jshint": "^0.11.0", + "jquery": "^2.1.3", + "steal": "0.7.X", + "steal-qunit": "0.0.2", + "steal-tools": "^0.8.2", + "syn": "0.1.X", + "system-text": "0.1.0", + "testee": "^0.2.5" + }, + "main": "./index", + "system": { + "main": "index", + "ignoreBrowser": true, + "map": { + "jquery/jquery": "jquery", + "steal-qunit/steal-qunit": "steal-qunit" + }, + "npmIgnore":[ + "grunt", "grunt-banner", "grunt-cli", "grunt-contrib-jshint", "testee" + ] + }, + "homepage": "http://jquerypp.com", + "repository": { + "type": "git", + "url": "git@github.com:bitovi/jquerypp.git" + }, + "licenses": [ { - "type" : "MIT", - "url" : "http://opensource.org/licenses/mit-license.php" + "type": "MIT", + "url": "http://opensource.org/licenses/mit-license.php" } - ] + ], + "browser": { + "./jquerypp": "./dist/cjs/index", + "./dom/animate/animate": "./dist/cjs/dom/animate/animate", + "./dom/compare/compare": "./dist/cjs/dom/compare/compare", + "./dom/cookie/cookie": "./dist/cjs/dom/cookie/cookie", + "./dom/form_params/form_params": "./dist/cjs/dom/form_params/form_params", + "./dom/range/range": "./dist/cjs/dom/range/range", + "./dom/selection/selection": "./dist/cjs/dom/selection/selection", + "./dom/within/within": "./dist/cjs/dom/within/within", + "./dom/destroyed/removed": "./dist/cjs/event/destroyed/removed", + "./dom/drag/drag": "./dist/cjs/event/drag/drag", + "./dom/drop/drop": "./dist/cjs/event/drop/drop", + "./dom/hover/hover": "./dist/cjs/event/hover/hover", + "./dom/key/key": "./dist/cjs/event/key/key", + "./dom/pause/pause": "./dist/cjs/event/pause/pause", + "./dom/resize/resize": "./dist/cjs/event/resize/resize", + "./dom/swipe/swipe": "./dist/cjs/event/swipe/swipe" + } } diff --git a/qunit.html b/qunit.html deleted file mode 100644 index bb4ab011..00000000 --- a/qunit.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - jQuery++ QUnit Test - - - -

                                                                                        jQuery++ Test Suite

                                                                                        -

                                                                                        -
                                                                                        -

                                                                                        -
                                                                                        -
                                                                                          -
                                                                                          - - \ No newline at end of file diff --git a/readme.md b/readme.md index 1f2d6bf6..0b2a1e69 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -[![Build Status](https://secure.travis-ci.org/jupiterjs/jquerypp.png)](http://travis-ci.org/jupiterjs/jquerypp) + Visit [jquerypp.com](http://jquerypp.com) for the overview and [DoneJS](http://donejs.com#!jquerypp) for the API documentation. diff --git a/test.html b/test.html new file mode 100644 index 00000000..f2fe4a9c --- /dev/null +++ b/test.html @@ -0,0 +1,3 @@ +jquerypp tests + +
                                                                                          diff --git a/test/qunit/integration.js b/test/qunit/integration.js index a7859dcf..794130a7 100644 --- a/test/qunit/integration.js +++ b/test/qunit/integration.js @@ -1,20 +1,20 @@ -steal('funcunit/qunit', - 'jquery/model', - 'jquery/controller', - 'jquery/view/ejs', +steal('steal-qunit', + 'jquerypp/model', + 'jquerypp/controller', + 'jquerypp/view/ejs', 'can/util/fixture') .then(function(){ module('integration',{ setup : function(){ - $("#qunit-test-area").html("") + $("#qunit-fixture").html("") } }); test("controller can listen to model instances and model classes", function(){ - $("#qunit-test-area").html(""); + $("#qunit-fixture").html(""); @@ -44,7 +44,7 @@ test("controller can listen to model instances and model classes", function(){ var inst = new Test.ModelThing(); - $("
                                                                                          ").appendTo( $("#qunit-test-area") ) + $("
                                                                                          ").appendTo( $("#qunit-fixture") ) .test_binder_thing({ model : Test.ModelThing, instance: inst @@ -63,9 +63,9 @@ test("Model and Views", function(){ findOne : "/thing" },{}) - $.fixture("/thing","//jquery/test/thing.json") + $.fixture("/thing","//jquerypp/test/thing.json") - var res = $.View("//jquery/test/template.ejs", + var res = $.View("//jquerypp/test/template.ejs", Test.Thing.findOne()); res.done(function(resolved){ diff --git a/test/qunit/jmvc.js b/test/qunit/jmvc.js index 9c461107..df923f58 100644 --- a/test/qunit/jmvc.js +++ b/test/qunit/jmvc.js @@ -1,8 +1,8 @@ // Tests for the JavaScriptMVC compatibility layer. Will be removed eventually -steal('funcunit/qunit', 'jquery/controller/view/test/qunit' - , 'jquery/class/class_test.js' - , 'jquery/model/test/qunit' - , 'jquery/controller/controller_test.js' - , 'jquery/view/test/qunit' - , 'jquery/dom/route/route_test.js' +steal('steal-qunit', 'jquerypp/controller/view/test/qunit' + , 'jquerypp/class/class_test.js' + , 'jquerypp/model/test/qunit' + , 'jquerypp/controller/controller_test.js' + , 'jquerypp/view/test/qunit' + , 'jquerypp/dom/route/route_test.js' , './integration.js'); \ No newline at end of file diff --git a/test/run.js b/test/run.js index e6924913..e69f925b 100644 --- a/test/run.js +++ b/test/run.js @@ -1,8 +1,8 @@ // loads all of jquerymx's command line tests -//load("jquery/download/test/run.js"); +//load("jquerypp/download/test/run.js"); -load('jquery/view/test/compression/run.js'); +load('jquerypp/view/test/compression/run.js'); -load("jquery/generate/test/run.js"); +load("jquerypp/generate/test/run.js"); diff --git a/test/test.js b/test/test.js index b9881bae..e25779c8 100644 --- a/test/test.js +++ b/test/test.js @@ -1,23 +1,16 @@ -(function(){ steal( -// 'jquery/dom/animate/animate_test.js' -// , 'jquery/event/fastfix/fastfix_test.js' - 'jquery/dom/compare/compare_test.js' - , 'jquery/dom/dimensions/dimensions_test.js' - , 'jquery/dom/form_params/form_params_test.js' - , 'jquery/dom/styles/styles_test.js' - , 'jquery/event/default/default_test.js' - , 'jquery/event/default/default_pause_test.js' - , 'jquery/event/destroyed/destroyed_test.js' - , 'jquery/event/drag/drag_test.js' - ,'jquery/event/drop/drop_test.js' - , 'jquery/event/hover/hover_test.js' - , 'jquery/event/key/key_test.js' - , 'jquery/event/pause/pause_test.js' - , 'jquery/event/reverse/reverse_test.js' - , 'jquery/event/resize/resize_test.js' - , 'jquery/event/swipe/swipe_test.js' - , 'jquery/lang/lang_test.js' - , './qunit/jmvc.js' + '../dom/animate/animate_test.js', + '../dom/compare/compare_test.js', + '../dom/form_params/form_params_test.js', + '../dom/range/range_test.js', + '../dom/selection/selection_test.js', + '../event/drag/drag_test.js', + '../event/drop/drop_test.js', + '../event/hover/hover_test.js', + '../event/key/key_test.js', + '../event/pause/pause_test.js', + '../event/removed/removed_test.js', + '../event/resize/resize_test.js', + '../event/swipe/swipe_test.js', + '../lang/vector/vector_test.js' ); -})(); diff --git a/update b/update deleted file mode 100644 index 581cdbe1..00000000 --- a/update +++ /dev/null @@ -1,5 +0,0 @@ -load('steal/rhino/rhino.js') - -steal('steal/get', function(s) { - s.get('http://github.com/jupiterjs/jquerypp/', {name: 'jquery'}); -}) diff --git a/view/compress.js b/view/compress.js deleted file mode 100644 index 20b0ae2c..00000000 --- a/view/compress.js +++ /dev/null @@ -1,7 +0,0 @@ -//js view/compress.js - -var compressPage = 'view/view.html'; -var outputFolder = 'view'; -load("steal/compress/compress.js") -var compress = new Steal.Compress([compressPage, outputFolder]); -compress.init(); \ No newline at end of file diff --git a/view/ejs/easyhookup.ejs b/view/ejs/easyhookup.ejs deleted file mode 100644 index 82aef45b..00000000 --- a/view/ejs/easyhookup.ejs +++ /dev/null @@ -1 +0,0 @@ -
                                                                                          <%= (el)-> el.addClass(text) %>> \ No newline at end of file diff --git a/view/ejs/ejs.js b/view/ejs/ejs.js deleted file mode 100644 index 81c131ce..00000000 --- a/view/ejs/ejs.js +++ /dev/null @@ -1,4 +0,0 @@ -/*jslint evil: true */ -steal('jquery', 'can/util', 'jquery/view', 'can/view/ejs', function($, can){ - $.EJS = can.EJS; -}); \ No newline at end of file diff --git a/view/ejs/ejs_test.js b/view/ejs/ejs_test.js deleted file mode 100644 index 0b7c98ca..00000000 --- a/view/ejs/ejs_test.js +++ /dev/null @@ -1,119 +0,0 @@ -steal('funcunit/qunit','jquery/view/ejs', function(){ -module("jquery/view/ejs, rendering",{ - setup : function(){ - - this.animals = ['sloth', 'bear', 'monkey'] - if(!this.animals.each){ - this.animals.each = function(func){ - for(var i =0; i < this.length; i++){ - func(this[i]) - } - } - } - - this.squareBrackets = "
                                                                                            <% this.animals.each(function(animal){%>" + - "
                                                                                          • <%= animal %>
                                                                                          • " + - "<%});%>
                                                                                          " - this.squareBracketsNoThis = "
                                                                                            <% animals.each(function(animal){ %>" + - "
                                                                                          • <%= animal %>
                                                                                          • " + - "<%});%>
                                                                                          " - this.angleBracketsNoThis = "
                                                                                            <% animals.each(function(animal){%>" + - "
                                                                                          • <%= animal %>
                                                                                          • " + - "<%});%>
                                                                                          "; - - } -}) -test("render with left bracket", function(){ - var compiled = new $.EJS({text: this.squareBrackets}).render({animals: this.animals}) - equals(compiled, "
                                                                                          • sloth
                                                                                          • bear
                                                                                          • monkey
                                                                                          ", "renders with bracket") -}) -test("render with with", function(){ - var compiled = new $.EJS({text: this.squareBracketsNoThis}).render({animals: this.animals}) ; - equals(compiled, "
                                                                                          • sloth
                                                                                          • bear
                                                                                          • monkey
                                                                                          ", "renders bracket with no this") -}) -test("default carrot", function(){ - var compiled = new $.EJS({text: this.angleBracketsNoThis}).render({animals: this.animals}) ; - - equals(compiled, "
                                                                                          • sloth
                                                                                          • bear
                                                                                          • monkey
                                                                                          ") -}) -test("render with double angle", function(){ - var text = "<%% replace_me %>"+ - "
                                                                                            <% animals.each(function(animal){%>" + - "
                                                                                          • <%= animal %>
                                                                                          • " + - "<%});%>
                                                                                          "; - var compiled = new $.EJS({text: text}).render({animals: this.animals}) ; - equals(compiled, "<% replace_me %>
                                                                                          • sloth
                                                                                          • bear
                                                                                          • monkey
                                                                                          ", "works") -}); - -test("comments", function(){ - var text = "<%# replace_me %>"+ - "
                                                                                            <% animals.each(function(animal){%>" + - "
                                                                                          • <%= animal %>
                                                                                          • " + - "<%});%>
                                                                                          "; - var compiled = new $.EJS({text: text}).render({animals: this.animals}) ; - equals(compiled,"
                                                                                          • sloth
                                                                                          • bear
                                                                                          • monkey
                                                                                          " ) -}); - -test("multi line", function(){ - var text = "a \n b \n c", - result = new $.EJS({text: text}).render({}) ; - - equals(result, text) -}) - -test("escapedContent", function(){ - var text = "<%= tags %><%= number %>"; - var compiled = new $.EJS({text: text}).render({tags: "foo < bar < car > zar > poo", - quotes : "I use 'quote' fingers \"a lot\"", - number : 123}) ; - - var div = $('
                                                                                          ').html(compiled) - equals(div.find('span').text(), "foo < bar < car > zar > poo" ); - equals(div.find('strong').text(), 123 ); - equals(div.find('input').val(), "I use 'quote' fingers \"a lot\"" ); - equals(div.find('label').html(), "&" ); -}) - - - -test("returning blocks", function(){ - var somethingHelper = function(cb){ - return cb([1,2,3,4]) - } - - var res = $.View("//jquery/view/ejs/test_template.ejs",{something: somethingHelper, - items: ['a','b']}); - // make sure expected values are in res - //ok(/\s4\s/.test(res), "first block called" ); - //equals(res.match(/ItemsLength4/g).length, 4, "innerBlock and each") -}); - -test("easy hookup", function(){ - var div = $('
                                                                                          ').html("//jquery/view/ejs/easyhookup.ejs",{text: "yes"}) - ok( div.find('div').hasClass('yes'), "has yes" ) -}); - -test("helpers", function() { - $.EJS.Helpers.prototype.simpleHelper = function() - { - return 'Simple'; - } - - $.EJS.Helpers.prototype.elementHelper = function() - { - return function(el) { - el.innerHTML = 'Simple'; - } - } - - var text = "
                                                                                          <%= simpleHelper() %>
                                                                                          "; - var compiled = new $.EJS({text: text}).render() ; - equals(compiled, "
                                                                                          Simple
                                                                                          "); - - text = "
                                                                                          <%= elementHelper() %>>
                                                                                          "; - compiled = new $.EJS({text: text}).render() ; - $('#qunit-test-area').append($(compiled)); - equals($('#hookup').html(), "Simple"); -}); - -}) diff --git a/view/ejs/qunit.html b/view/ejs/qunit.html deleted file mode 100644 index 3d65b557..00000000 --- a/view/ejs/qunit.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - -

                                                                                          ejs Test Suite

                                                                                          -

                                                                                          -
                                                                                          -

                                                                                          -
                                                                                          -
                                                                                            -
                                                                                            - - \ No newline at end of file diff --git a/view/ejs/test_template.ejs b/view/ejs/test_template.ejs deleted file mode 100644 index 23347b00..00000000 --- a/view/ejs/test_template.ejs +++ /dev/null @@ -1,8 +0,0 @@ -<%# Test Something Produces Items%> -<%== something(function(items){ %> -<%== items.length%> -<% $.each(items, function(){ %><%# Test Something Produces Items%> -<%== something(function(items){ %>ItemsLength<%== items.length %><% }) %> -<% }) %> -<% }) %> -<% for( var i =0; i < items.length; i++) { %>for <%= items[i] %><% } %> \ No newline at end of file diff --git a/view/fulljslint.js b/view/fulljslint.js deleted file mode 100644 index 1a924f2f..00000000 --- a/view/fulljslint.js +++ /dev/null @@ -1,3774 +0,0 @@ -// jslint.js -// 2007-12-10 -/* -Copyright (c) 2002 Douglas Crockford (www.JSLint.com) - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ - -/* - JSLINT is a global function. It takes two parameters. - - var myResult = JSLINT(source, option); - - The first parameter is either a string or an array of strings. If it is a - string, it will be split on '\n' or '\r'. If it is an array of strings, it - is assumed that each string represents one line. The source can be a - JavaScript text, or HTML text, or a Konfabulator text. - - The second parameter is an optional object of options which control the - operation of JSLINT. All of the options are booleans. All are optional and - have a default value of false. - - If it checks out, JSLINT returns true. Otherwise, it returns false. - - If false, you can inspect JSLINT.errors to find out the problems. - JSLINT.errors is an array of objects containing these members: - - { - line : The line (relative to 0) at which the lint was found - character : The character (relative to 0) at which the lint was found - reason : The problem - evidence : The text line in which the problem occurred - raw : The raw message before the details were inserted - a : The first detail - b : The second detail - c : The third detail - d : The fourth detail - } - - If a fatal error was found, a null will be the last element of the - JSLINT.errors array. - - You can request a Function Report, which shows all of the functions - and the parameters and vars that they use. This can be used to find - implied global variables and other problems. The report is in HTML and - can be inserted in a . - - var myReport = JSLINT.report(option); - - If the option is true, then the report will be limited to only errors. -*/ - -/*jslint evil: true, nomen: false */ - -/*members "\b", "\t", "\n", "\f", "\r", "\"", "(begin)", "(context)", - "(end)", "(global)", "(identifier)", "(line)", "(name)", "(params)", - "(scope)", "(verb)", ")", "++", "--", "\/", ADSAFE, Array, Boolean, COM, - Canvas, CustomAnimation, Date, Debug, Error, EvalError, FadeAnimation, - Frame, Function, HotKey, Image, Math, MenuItem, MoveAnimation, Number, - Object, Point, RangeError, ReferenceError, RegExp, RotateAnimation, - ScrollBar, String, SyntaxError, Text, TextArea, TypeError, URIError, - URL, Window, XMLDOM, XMLHttpRequest, "\\", "]", a, abbr, "about-box", - "about-image", "about-text", "about-version", acronym, action, address, - adsafe, alert, alignment, anchorstyle, animator, appleScript, applet, - apply, area, author, autohide, b, background, base, bdo, beep, beget, - bgcolor, bgcolour, bgopacity, big, bitwise, block, blockquote, blur, - body, br, browser, button, bytesToUIString, c, call, callee, caller, - canvas, cap, caption, cases, center, charAt, charCodeAt, character, - checked, chooseColor, chooseFile, chooseFolder, cite, clearInterval, - clearTimeout, cliprect, clone, close, closeWidget, closed, code, col, - colgroup, color, colorize, colour, columns, combine, company, condition, - confirm, console, constructor, content, contextmenuitems, - convertPathToHFS, convertPathToPlatform, copyright, d, data, dd, debug, - decodeURI, decodeURIComponent, defaultStatus, defaulttracking, - defaultvalue, defineClass, del, description, deserialize, dfn, dir, - directory, div, dl, doAttribute, doBegin, doIt, doTagName, document, dt, - dynsrc, editable, em, embed, empty, enabled, encodeURI, - encodeURIComponent, entityify, eqeqeq, errors, escape, eval, event, - evidence, evil, exec, exps, extension, fieldset, file, filesystem, - fillmode, flags, floor, focus, focusWidget, font, fontstyle, forin, - form, fragment, frame, frames, frameset, from, fromCharCode, fud, - function, gc, getComputedStyle, group, h1, h2, h3, h4, h5, h6, halign, - handlelinks, hasOwnProperty, head, height, help, hidden, history, - hlinesize, hoffset, hotkey, hr, href, hregistrationpoint, hscrollbar, - hsladjustment, hsltinting, html, i, iTunes, icon, id, identifier, - iframe, image, img, include, indexOf, init, input, ins, interval, - isAlpha, isApplicationRunning, isDigit, isFinite, isNaN, join, kbd, key, - kind, konfabulatorVersion, label, labelled, laxbreak, lbp, led, left, - legend, length, level, li, line, lines, link, load, loadClass, - loadingsrc, location, locked, log, lowsrc, map, match, max, maxlength, - menu, menuitem, message, meta, min, minimumversion, minlength, - missingsrc, modifier, moveBy, moveTo, name, navigator, new, noframes, - nomen, noscript, notsaved, nud, object, ol, on, onblur, onclick, - oncontextmenu, ondragdrop, ondragenter, ondragexit, onerror, - onfirstdisplay, onfocus, ongainfocus, onimageloaded, onkeydown, - onkeypress, onkeyup, onload, onlosefocus, onmousedown, onmousedrag, - onmouseenter, onmouseexit, onmousemove, onmouseup, onmousewheel, - onmulticlick, onresize, onselect, ontextinput, ontimerfired, onunload, - onvaluechanged, opacity, open, openURL, opener, opera, optgroup, option, - optionvalue, order, orientation, p, pagesize, param, parent, parseFloat, - parseInt, passfail, play, plusplus, pop, popupMenu, pre, preference, - preferenceGroups, preferencegroup, preferences, print, prompt, - prototype, push, q, quit, random, raw, reach, readFile, readUrl, reason, - reloadWidget, remoteasync, replace, report, requiredplatform, reserved, - resizeBy, resizeTo, resolvePath, resumeUpdates, rhino, right, root, - rotation, runCommand, runCommandInBg, samp, saveAs, savePreferences, - screen, script, scroll, scrollBy, scrollTo, scrollbar, scrolling, - scrollx, scrolly, seal, search, secure, select, self, serialize, - setInterval, setTimeout, setting, settings, shadow, shift, - showWidgetPreferences, size, skip, sleep, slice, small, sort, source, - span, spawn, speak, special, spellcheck, split, src, srcheight, - srcwidth, status, strong, style, sub, substr, subviews, sup, superview, - supplant, suppressUpdates, sync, system, table, tag, tbody, td, - tellWidget, test, text, textarea, tfoot, th, thead, this, thumbcolor, - ticking, ticklabel, ticks, tileorigin, timer, title, toLowerCase, - toSource, toString, toint32, token, tooltip, top, tr, tracking, trigger, - truncation, tt, type, u, ul, undef, unescape, unwatch, updateNow, url, - usefileicon, valign, value, valueOf, var, version, visible, vlinesize, - voffset, vregistrationpoint, vscrollbar, watch, white, widget, width, - window, wrap, yahooCheckLogin, yahooLogin, yahooLogout, zorder -*/ - -// We build the application inside a function so that we produce only a single -// global variable. The function will be invoked, its return value is the JSLINT -// function itself. - -var JSLINT; -JSLINT = function () { - -// These are words that should not be permitted in third party ads. - - var adsafe = { - apply : true, - call : true, - callee : true, - caller : true, - clone : true, - constructor : true, - 'eval' : true, - 'new' : true, - prototype : true, - source : true, - 'this' : true, - toSource : true, - toString : true, - unwatch : true, - valueOf : true, - watch : true - }, - -// These are all of the JSLint options. - - allOptions = { - adsafe : true, // if use of some browser features should be restricted - bitwise : true, // if bitwise operators should not be allowed - browser : true, // if the standard browser globals should be predefined - cap : true, // if upper case HTML should be allowed - debug : true, // if debugger statements should be allowed - eqeqeq : true, // if === should be required - evil : true, // if eval should be allowed - forin : true, // if for in statements must filter - fragment : true, // if HTML fragments should be allowed - laxbreak : true, // if line breaks should not be checked - nomen : true, // if names should be checked - on : true, // if HTML event handlers should be allowed - passfail : true, // if the scan should stop on first error - plusplus : true, // if increment/decrement should not be allowed - rhino : true, // if the Rhino environment globals should be predefined - undef : true, // if variables should be declared before used - white : true, // if strict whitespace rules apply - widget : true // if the Yahoo Widgets globals should be predefined - }, - - anonname, // The guessed name for anonymous functions. - -// browser contains a set of global names which are commonly provided by a -// web browser environment. - - browser = { - alert : true, - blur : true, - clearInterval : true, - clearTimeout : true, - close : true, - closed : true, - confirm : true, - console : true, - Debug : true, - defaultStatus : true, - document : true, - event : true, - focus : true, - frames : true, - getComputedStyle: true, - history : true, - Image : true, - length : true, - location : true, - moveBy : true, - moveTo : true, - name : true, - navigator : true, - onblur : true, - onerror : true, - onfocus : true, - onload : true, - onresize : true, - onunload : true, - open : true, - opener : true, - opera : true, - parent : true, - print : true, - prompt : true, - resizeBy : true, - resizeTo : true, - screen : true, - scroll : true, - scrollBy : true, - scrollTo : true, - self : true, - setInterval : true, - setTimeout : true, - status : true, - top : true, - window : true, - XMLHttpRequest : true - }, - - escapes = { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '"' : '\\"', - '/' : '\\/', - '\\': '\\\\' - }, - - funct, // The current function - functions, // All of the functions - - href = { - background : true, - content : true, - data : true, - dynsrc : true, - href : true, - lowsrc : true, - value : true, - src : true, - style : true - }, - - global, // The global object - globals, // The current globals - implied, // Implied globals - inblock, - indent, - jsonmode, - lines, - lookahead, - member, - membersOnly, - nexttoken, - noreach, - option, - prereg, - prevtoken, - - rhino = { - defineClass : true, - deserialize : true, - gc : true, - help : true, - load : true, - loadClass : true, - print : true, - quit : true, - readFile : true, - readUrl : true, - runCommand : true, - seal : true, - serialize : true, - spawn : true, - sync : true, - toint32 : true, - version : true - }, - - scope, // The current scope - src, - stack, - -// standard contains the global names that are provided by the -// ECMAScript standard. - - standard = { - Array : true, - Boolean : true, - Date : true, - decodeURI : true, - decodeURIComponent : true, - encodeURI : true, - encodeURIComponent : true, - Error : true, - escape : true, - 'eval' : true, - EvalError : true, - Function : true, - isFinite : true, - isNaN : true, - Math : true, - Number : true, - Object : true, - parseInt : true, - parseFloat : true, - RangeError : true, - ReferenceError : true, - RegExp : true, - String : true, - SyntaxError : true, - TypeError : true, - unescape : true, - URIError : true - }, - - syntax = {}, - token, - warnings, - -// widget contains the global names which are provided to a Yahoo -// (fna Konfabulator) widget. - - widget = { - alert : true, - appleScript : true, - animator : true, - appleScript : true, - beep : true, - bytesToUIString : true, - Canvas : true, - chooseColor : true, - chooseFile : true, - chooseFolder : true, - convertPathToHFS : true, - convertPathToPlatform : true, - closeWidget : true, - COM : true, - CustomAnimation : true, - escape : true, - FadeAnimation : true, - filesystem : true, - focusWidget : true, - form : true, - Frame : true, - HotKey : true, - Image : true, - include : true, - isApplicationRunning : true, - iTunes : true, - konfabulatorVersion : true, - log : true, - MenuItem : true, - MoveAnimation : true, - openURL : true, - play : true, - Point : true, - popupMenu : true, - preferenceGroups : true, - preferences : true, - print : true, - prompt : true, - random : true, - reloadWidget : true, - resolvePath : true, - resumeUpdates : true, - RotateAnimation : true, - runCommand : true, - runCommandInBg : true, - saveAs : true, - savePreferences : true, - screen : true, - ScrollBar : true, - showWidgetPreferences : true, - sleep : true, - speak : true, - suppressUpdates : true, - system : true, - tellWidget : true, - Text : true, - TextArea : true, - unescape : true, - updateNow : true, - URL : true, - widget : true, - Window : true, - XMLDOM : true, - XMLHttpRequest : true, - yahooCheckLogin : true, - yahooLogin : true, - yahooLogout : true - }, - -// xmode is used to adapt to the exceptions in XML parsing. -// It can have these states: -// false .js script file -// " A " attribute -// ' A ' attribute -// content The content of a script tag -// CDATA A CDATA block - - xmode, - -// xtype identifies the type of document being analyzed. -// It can have these states: -// false .js script file -// html .html file -// widget .kon Konfabulator file - - xtype, - -// unsafe comment - ax = /@cc|<\/?script|\]\]|&/i, -// unsafe character - cx = /[\u0000-\u0008\u000a-\u001f\u007f-\u009f\u2028\u2029\ufff0-\uffff]/, -// token - tx = /^\s*([(){}\[.,:;'"~]|\](\]>)?|\?>?|==?=?|\/(\*(global|extern|jslint|member|members)?|=|\/)?|\*[\/=]?|\+[+=]?|-[\-=]?|%[=>]?|&[&=]?|\|[|=]?|>>?>?=?|<([\/=%\?]|\!(\[|--)?|<=?)?|\^=?|\!=?=?|[a-zA-Z_$][a-zA-Z0-9_$]*|[0-9]+([xX][0-9a-fA-F]+|\.[0-9]*)?([eE][+\-]?[0-9]+)?)/, -// star slash - lx = /\*\/|\/\*/, -// identifier - ix = /^([a-zA-Z_$][a-zA-Z0-9_$]*)$/, -// javascript url - jx = /(?:javascript|jscript|ecmascript|vbscript|mocha|livescript)\s*:/i, -// url badness - ux = /&|\+|\u00AD|\.\.|\/\*|%[^;]|base64|url|expression|data|mailto/i; - - function object(o) { - function F() {} - F.prototype = o; - return new F(); - } - - object_combine = function (object, o) { - var n; - for (n in o) if (o.hasOwnProperty(n)) { - object[n] = o[n]; - } - }; - - String.prototype.entityify = function () { - return this. - replace(/&/g, '&'). - replace(//g, '>'); - }; - - String.prototype.isAlpha = function () { - return (this >= 'a' && this <= 'z\uffff') || - (this >= 'A' && this <= 'Z\uffff'); - }; - - - String.prototype.isDigit = function () { - return (this >= '0' && this <= '9'); - }; - - - String.prototype.supplant = function (o) { - return this.replace(/\{([^{}]*)\}/g, function (a, b) { - var r = o[b]; - return typeof r === 'string' || typeof r === 'number' ? r : a; - }); - }; - - String.prototype.name = function () { - -// If the string looks like an identifier, then we can return it as is. -// If the string contains no control characters, no quote characters, and no -// backslash characters, then we can simply slap some quotes around it. -// Otherwise we must also replace the offending characters with safe -// sequences. - - - if (ix.test(this)) { - return this; - } - if (/[&<"\/\\\x00-\x1f]/.test(this)) { - return '"' + this.replace(/[&<"\/\\\x00-\x1f]/g, function (a) { - var c = escapes[a]; - if (c) { - return c; - } - c = a.charCodeAt(); - return '\\u00' + - Math.floor(c / 16).toString(16) + - (c % 16).toString(16); - }) + '"'; - } - return '"' + this + '"'; - }; - - - function populateGlobals() { - if (option.adsafe) { - object_combine(globals, {ADSAFE: true}); - } else { - if (option.rhino) { - object_combine(globals, rhino); - } - if (option.browser) { - object_combine(globals, browser); - } - if (option.widget) { - object_combine(globals, widget); - } - } - } - - -// Produce an error warning. - - function quit(m, l, ch) { - throw { - name: 'JSLintError', - line: l, - character: ch, - message: m + " (" + Math.floor((l / lines.length) * 100) + - "% scanned)." - }; - } - - function warning(m, t, a, b, c, d) { - var ch, l, w; - t = t || nexttoken; - if (t.id === '(end)') { - t = token; - } - l = t.line || 0; - ch = t.from || 0; - w = { - id: '(error)', - raw: m, - evidence: lines[l] || '', - line: l, - character: ch, - a: a, - b: b, - c: c, - d: d - }; - w.reason = m.supplant(w); - JSLINT.errors.push(w); - if (option.passfail) { - quit('Stopping. ', l, ch); - } - warnings += 1; - if (warnings === 50) { - quit("Too many errors.", l, ch); - } - return w; - } - - function warningAt(m, l, ch, a, b, c, d) { - return warning(m, { - line: l, - from: ch - }, a, b, c, d); - } - - function error(m, t, a, b, c, d) { - var w = warning(m, t, a, b, c, d); - quit("Stopping, unable to continue.", w.line, w.character); - } - - function errorAt(m, l, ch, a, b, c, d) { - return error(m, { - line: l, - from: ch - }, a, b, c, d); - } - - - -// lexical analysis - - var lex = function () { - var character, from, line, s; - -// Private lex methods - - function nextLine() { - var at; - line += 1; - if (line >= lines.length) { - return false; - } - character = 0; - s = lines[line]; - at = s.search(cx); - if (at >= 0) { - warningAt("Unsafe character.", line, at); - } - return true; - } - -// Produce a token object. The token inherits from a syntax symbol. - - function it(type, value) { - var i, t; - if (type === '(punctuator)' || - (type === '(identifier)' && syntax.hasOwnProperty(value))) { - t = syntax[value]; - -// Mozilla bug workaround. - - if (!t.id) { - t = syntax[type]; - } - } else { - t = syntax[type]; - } - t = object(t); - if (type === '(string)') { - if (jx.test(value)) { - warningAt("Script URL.", line, from); - } - } else if (type === '(identifier)') { - if (option.nomen && value.charAt(0) === '_') { - warningAt("Unexpected '_' in '{a}'.", line, from, value); - } else if (option.adsafe && - (adsafe[value] === true || value.slice(-2) === '__')) { - warning("ADsafe restricted word '{a}'.", - {line: line, from: character}, value); - } - } - t.value = value; - t.line = line; - t.character = character; - t.from = from; - i = t.id; - if (i !== '(endline)') { - prereg = i && - (('(,=:[!&|?{};'.indexOf(i.charAt(i.length - 1)) >= 0) || - i === 'return'); - } - return t; - } - -// Public lex methods - - return { - init: function (source) { - if (typeof source === 'string') { - lines = source. - replace(/\r\n/g, '\n'). - replace(/\r/g, '\n'). - split('\n'); - } else { - lines = source; - } - line = -1; - nextLine(); - from = 0; - }, - -// token -- this is called by advance to get the next token. - - token: function () { - var b, c, captures, d, depth, high, i, l, low, q, t; - - function match(x) { - var r = x.exec(s), r1; - if (r) { - l = r[0].length; - r1 = r[1]; - c = r1.charAt(0); - s = s.substr(l); - character += l; - from = character - r1.length; - return r1; - } - } - - function string(x) { - var c, j, r = ''; - - if (jsonmode && x !== '"') { - warningAt("Strings must use doublequote.", - line, character); - } - - if (xmode === x || xmode === 'string') { - return it('(punctuator)', x); - } - - function esc(n) { - var i = parseInt(s.substr(j + 1, n), 16); - j += n; - if (i >= 32 && i <= 127 && - i !== 34 && i !== 92 && i !== 39) { - warningAt("Unnecessary escapement.", line, character); - } - character += n; - c = String.fromCharCode(i); - } - j = 0; - for (;;) { - while (j >= s.length) { - j = 0; - if (xmode !== 'xml' || !nextLine()) { - errorAt("Unclosed string.", line, from); - } - } - c = s.charAt(j); - if (c === x) { - character += 1; - s = s.substr(j + 1); - return it('(string)', r, x); - } - if (c < ' ') { - if (c === '\n' || c === '\r') { - break; - } - warningAt("Control character in string: {a}.", - line, character + j, s.slice(0, j)); - } else if (c === '<') { - if (option.adsafe && xmode === 'xml') { - warningAt("ADsafe string violation.", - line, character + j); - } else if (s.charAt(j + 1) === '/' && ((xmode && xmode !== 'CDATA') || option.adsafe)) { - warningAt("Expected '<\\/' and instead saw '= 0) { - break; - } - if (!nextLine()) { - errorAt("Unclosed comment.", line, character); - } else { - if (option.adsafe && ax.test(s)) { - warningAt("ADsafe comment violation.", line, character); - } - } - } - character += i + 2; - if (s.substr(i, 1) === '/') { - errorAt("Nested comment.", line, character); - } - s = s.substr(i + 2); - break; - -// /*global /*extern /*members /*jslint */ - - case '/*global': - case '/*extern': - case '/*members': - case '/*member': - case '/*jslint': - case '*/': - return { - value: t, - type: 'special', - line: line, - character: character, - from: from - }; - - case '': - break; -// / - case '/': - if (prereg) { - depth = 0; - captures = 0; - l = 0; - for (;;) { - b = true; - c = s.charAt(l); - l += 1; - switch (c) { - case '': - errorAt("Unclosed regular expression.", line, from); - return; - case '/': - if (depth > 0) { - warningAt("Unescaped '{a}'.", line, from + l, '/'); - } - c = s.substr(0, l - 1); - if (s.charAt(l) === 'g') { - l += 1; - } - if (s.charAt(l) === 'i') { - l += 1; - } - if (s.charAt(l) === 'm') { - l += 1; - } - character += l; - s = s.substr(l); - return it('(regex)', c); - case '\\': - l += 1; - break; - case '(': - depth += 1; - b = false; - if (s.charAt(l) === '?') { - l += 1; - switch (s.charAt(l)) { - case ':': - case '=': - case '!': - l += 1; - break; - default: - warningAt("Expected '{a}' and instead saw '{b}'.", line, from + l, ':', s.charAt(l)); - } - } else { - captures += 1; - } - break; - case ')': - if (depth === 0) { - warningAt("Unescaped '{a}'.", line, from + l, ')'); - } else { - depth -= 1; - } - break; - case ' ': - q = 1; - while (s.charAt(l) === ' ') { - l += 1; - q += 1; - } - if (q > 1) { - warningAt("Spaces are hard to count. Use {{a}}.", line, from + l, q); - } - break; - case '[': - if (s.charAt(l) === '^') { - l += 1; - } - q = false; -klass: for (;;) { - c = s.charAt(l); - l += 1; - switch (c) { - case '[': - case '^': - warningAt("Unescaped '{a}'.", line, from + l, c); - q = true; - break; - case '-': - if (q) { - q = false; - } else { - warningAt("Unescaped '{a}'.", line, from + l, '-'); - q = true; - } - break; - case ']': - if (!q) { - warningAt("Unescaped '{a}'.", line, from + l - 1, '-'); - } - break klass; - case '\\': - l += 1; - q = true; - break; - default: - if (c < ' ') { - errorAt(c ? "Control character in a regular expression" : - "Unclosed regular expression.", line, from + l); - } - q = true; - } - } - break; - case ']': - case '?': - case '{': - case '}': - case '+': - case '*': - warningAt("Unescaped '{a}'.", line, from + l, c); - break; - default: - if (c < ' ') { - warningAt("Control character in a regular expression", line, from + l); - } - } - if (b) { - switch (s.charAt(l)) { - case '?': - case '+': - case '*': - l += 1; - if (s.charAt(l) === '?') { - l += 1; - } - break; - case '{': - l += 1; - c = s.charAt(l); - if (c < '0' || c > '9') { - warningAt("Expected a number and instead saw '{a}'.", line, from + l, c); - } - l += 1; - low = +c; - for (;;) { - c = s.charAt(l); - if (c < '0' || c > '9') { - break; - } - l += 1; - low = +c + (low * 10); - } - high = low; - if (c === ',') { - l += 1; - high = Infinity; - c = s.charAt(l); - if (c >= '0' && c <= '9') { - l += 1; - high = +c; - for (;;) { - c = s.charAt(l); - if (c < '0' || c > '9') { - break; - } - l += 1; - high = +c + (high * 10); - } - } - } - if (s.charAt(l) !== '}') { - warningAt("Expected '{a}' and instead saw '{b}'.", line, from + l, '}', c); - } else { - l += 1; - } - if (s.charAt(l) === '?') { - l += 1; - } - if (low > high) { - warningAt("'{a}' should not be greater than '{b}'.", line, from + l, low, high); - } - } - } - } - c = s.substr(0, l - 1); - character += l; - s = s.substr(l); - return it('(regex)', c); - } - return it('(punctuator)', t); - -// punctuator - - default: - return it('(punctuator)', t); - } - } - }, - -// skip -- skip past the next occurrence of a particular string. -// If the argument is empty, skip to just before the next '<' character. -// This is used to ignore HTML content. Return false if it isn't found. - - skip: function (p) { - var i, t = p; - if (nexttoken.id) { - if (!t) { - t = ''; - if (nexttoken.id.substr(0, 1) === '<') { - lookahead.push(nexttoken); - return true; - } - } else if (nexttoken.id.indexOf(t) >= 0) { - return true; - } - } - token = nexttoken; - nexttoken = syntax['(end)']; - for (;;) { - i = s.indexOf(t || '<'); - if (i >= 0) { - character += i + t.length; - s = s.substr(i + t.length); - return true; - } - if (!nextLine()) { - break; - } - } - return false; - } - }; - }(); - - - function addlabel(t, type) { - - if (t === 'hasOwnProperty') { - error("'hasOwnProperty' is a really bad name."); - } - if (option.adsafe && scope === global) { - warning('ADsafe global: ' + t + '.', token); - } - -// Define t in the current function in the current scope. - - if (funct.hasOwnProperty(t)) { - warning(funct[t] === true ? - "'{a}' was used before it was defined." : - "'{a}' is already defined.", - nexttoken, t); - } - scope[t] = funct; - funct[t] = type; - if (funct['(global)'] && implied.hasOwnProperty(t)) { - warning("'{a}' was used before it was defined.", - nexttoken, t); - delete implied[t]; - } - } - - - function doOption() { - var b, obj, filter, o = nexttoken.value, t, v; - switch (o) { - case '*/': - error("Unbegun comment."); - break; - case '/*global': - case '/*extern': - if (option.adsafe) { - warning("ADsafe restriction."); - } - obj = globals; - break; - case '/*members': - case '/*member': - o = '/*members'; - if (!membersOnly) { - membersOnly = {}; - } - obj = membersOnly; - break; - case '/*jslint': - if (option.adsafe) { - warning("ADsafe restriction."); - } - obj = option; - filter = allOptions; - } - for (;;) { - t = lex.token(); - if (t.id === ',') { - t = lex.token(); - } - while (t.id === '(endline)') { - t = lex.token(); - } - if (t.type === 'special' && t.value === '*/') { - break; - } - if (t.type !== '(string)' && t.type !== '(identifier)' && - o !== '/*members') { - error("Bad option.", t); - } - if (filter) { - if (filter[t.value] !== true) { - error("Bad option.", t); - } - v = lex.token(); - if (v.id !== ':') { - error("Expected '{a}' and instead saw '{b}'.", - t, ':', t.value); - } - v = lex.token(); - if (v.value === 'true') { - b = true; - } else if (v.value === 'false') { - b = false; - } else { - error("Expected '{a}' and instead saw '{b}'.", - t, 'true', t.value); - } - } else { - b = true; - } - obj[t.value] = b; - } - if (filter) { - populateGlobals(); - } - } - - -// We need a peek function. If it has an argument, it peeks that much farther -// ahead. It is used to distinguish -// for ( var i in ... -// from -// for ( var i = ... - - function peek(p) { - var i = p || 0, j = 0, t; - - while (j <= i) { - t = lookahead[j]; - if (!t) { - t = lookahead[j] = lex.token(); - } - j += 1; - } - return t; - } - - - var badbreak = { - ')': true, - ']': true, - '++': true, - '--': true - }; - -// Produce the next token. It looks for programming errors. - - function advance(id, t) { - var l; - switch (token.id) { - case '(number)': - if (nexttoken.id === '.') { - warning( -"A dot following a number can be confused with a decimal point.", token); - } - break; - case '-': - if (nexttoken.id === '-' || nexttoken.id === '--') { - warning("Confusing minusses."); - } - break; - case '+': - if (nexttoken.id === '+' || nexttoken.id === '++') { - warning("Confusing plusses."); - } - break; - } - if (token.type === '(string)' || token.identifier) { - anonname = token.value; - } - - if (id && nexttoken.id !== id) { - if (t) { - if (nexttoken.id === '(end)') { - warning("Unmatched '{a}'.", t, t.id); - } else { - warning("Expected '{a}' to match '{b}' from line {c} and instead saw '{d}'.", - nexttoken, id, t.id, t.line + 1, nexttoken.value); - } - } else { - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, id, nexttoken.value); - } - } - prevtoken = token; - token = nexttoken; - for (;;) { - nexttoken = lookahead.shift() || lex.token(); - if (nexttoken.type === 'special') { - doOption(); - } else { - if (nexttoken.id === ''); - } else { - error("Unexpected '{a}'.", nexttoken, '') { - if (xmode === 'CDATA') { - xmode = 'script'; - } else { - error("Unexpected '{a}'.", nexttoken, ']]>'); - } - } else if (nexttoken.id !== '(endline)') { - break; - } - if (xmode === '"' || xmode === "'") { - error("Missing '{a}'.", token, xmode); - } - l = !xmode && !option.laxbreak && - (token.type === '(string)' || token.type === '(number)' || - token.type === '(identifier)' || badbreak[token.id]); - } - } - if (l) { - switch (nexttoken.id) { - case '{': - case '}': - case ']': - break; - case ')': - switch (token.id) { - case ')': - case '}': - case ']': - break; - default: - warning("Line breaking error '{a}'.", token, ')'); - } - break; - default: - warning("Line breaking error '{a}'.", - token, token.value); - } - } - if (xtype === 'widget' && xmode === 'script' && nexttoken.id) { - l = nexttoken.id.charAt(0); - if (l === '<' || l === '&') { - nexttoken.nud = nexttoken.led = null; - nexttoken.lbp = 0; - nexttoken.reach = true; - } - } - } - - -// This is the heart of JSLINT, the Pratt parser. In addition to parsing, it -// is looking for ad hoc lint patterns. We add to Pratt's model .fud, which is -// like nud except that it is only used on the first token of a statement. -// Having .fud makes it much easier to define JavaScript. I retained Pratt's -// nomenclature. - -// .nud Null denotation -// .fud First null denotation -// .led Left denotation -// lbp Left binding power -// rbp Right binding power - -// They are key to the parsing method called Top Down Operator Precedence. - - function parse(rbp, initial) { - var left; - var o; - if (nexttoken.id === '(end)') { - error("Unexpected early end of program.", token); - } - advance(); - if (option.adsafe && token.value === 'ADSAFE') { - if (nexttoken.id !== '.' || !(peek(0).identifier) || - peek(1).id !== '(') { - warning('ADsafe violation.', token); - } - } - if (initial) { - anonname = 'anonymous'; - funct['(verb)'] = token.value; - } - if (initial && token.fud) { - left = token.fud(); - } else { - if (token.nud) { - o = token.exps; - left = token.nud(); - } else { - if (nexttoken.type === '(number)' && token.id === '.') { - warning( -"A leading decimal point can be confused with a dot: '.{a}'.", - token, nexttoken.value); - advance(); - return token; - } else { - error("Expected an identifier and instead saw '{a}'.", - token, token.id); - } - } - while (rbp < nexttoken.lbp) { - o = nexttoken.exps; - advance(); - if (token.led) { - left = token.led(left); - } else { - error("Expected an operator and instead saw '{a}'.", - token, token.id); - } - } - if (initial && !o) { - warning( -"Expected an assignment or function call and instead saw an expression.", - token); - } - } - if (!option.evil && left && left.value === 'eval') { - warning("eval is evil.", left); - } - return left; - } - - -// Functions for conformance of style. - - function adjacent(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white) { - if (left.character !== right.from) { - warning("Unexpected space after '{a}'.", - nexttoken, left.value); - } - } - } - - - function nospace(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white) { - if (left.line === right.line) { - adjacent(left, right); - } - } - } - - - function nonadjacent(left, right) { - left = left || token; - right = right || nexttoken; - if (option.white) { - if (left.character === right.from) { - warning("Missing space after '{a}'.", - nexttoken, left.value); - } - } - } - - function indentation(bias) { - var i; - if (option.white && nexttoken.id !== '(end)') { - i = indent + (bias || 0); - if (nexttoken.from !== i) { - warning("Expected '{a}' to have an indentation of {b} instead of {c}.", - nexttoken, nexttoken.value, i, nexttoken.from); - } - } - } - - function nolinebreak(t) { - if (t.line !== nexttoken.line) { - warning("Line breaking error '{a}'.", t, t.id); - } - } - - -// Parasitic constructors for making the symbols that will be inherited by -// tokens. - - function symbol(s, p) { - var x = syntax[s]; - if (!x || typeof x !== 'object') { - syntax[s] = x = { - id: s, - lbp: p, - value: s - }; - } - return x; - } - - - function delim(s) { - return symbol(s, 0); - } - - - function stmt(s, f) { - var x = delim(s); - x.identifier = x.reserved = true; - x.fud = f; - return x; - } - - - function blockstmt(s, f) { - var x = stmt(s, f); - x.block = true; - return x; - } - - - function reserveName(x) { - var c = x.id.charAt(0); - if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { - x.identifier = x.reserved = true; - } - return x; - } - - - function prefix(s, f) { - var x = symbol(s, 150); - reserveName(x); - x.nud = (typeof f === 'function') ? f: function () { - if (option.plusplus && (this.id === '++' || this.id === '--')) { - warning("Unexpected use of '{a}'.", this, this.id); - } - parse(150); - return this; - }; - return x; - } - - - function type(s, f) { - var x = delim(s); - x.type = s; - x.nud = f; - return x; - } - - - function reserve(s, f) { - var x = type(s, f); - x.identifier = x.reserved = true; - return x; - } - - - function reservevar(s) { - return reserve(s, function () { - return this; - }); - } - - - function infix(s, f, p) { - var x = symbol(s, p); - reserveName(x); - x.led = (typeof f === 'function') ? f: function (left) { - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - return [this.id, left, parse(p)]; - }; - return x; - } - - - function relation(s, f) { - var x = symbol(s, 100); - x.led = function (left) { - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - var right = parse(100); - if ((left && left.id === 'NaN') || (right && right.id === 'NaN')) { - warning("Use the isNaN function to compare with NaN.", this); - } else if (f) { - f.apply(this, [left, right]); - } - return [this.id, left, right]; - }; - return x; - } - - - function isPoorRelation(node) { - return (node.type === '(number)' && !+node.value) || - (node.type === '(string)' && !node.value) || - node.type === 'true' || - node.type === 'false' || - node.type === 'undefined' || - node.type === 'null'; - } - - - function assignop(s, f) { - symbol(s, 20).exps = true; - return infix(s, function (left) { - var l; - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - if (adsafe) { - l = left; - do { - if (l.value === 'ADSAFE') { - warning('ADsafe violation.', l); - } - l = l.left; - } while (l); - } - if (left) { - if (left.id === '.' || left.id === '[' || - (left.identifier && !left.reserved)) { - parse(19); - return left; - } - if (left === syntax['function']) { - warning( -"Expected an identifier in an assignment and instead saw a function invocation.", - token); - } - } - error("Bad assignment.", this); - }, 20); - } - - function bitwise(s, f, p) { - var x = symbol(s, p); - reserveName(x); - x.led = (typeof f === 'function') ? f: function (left) { - if (option.bitwise) { - warning("Unexpected use of '{a}'.", this, this.id); - } - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - return [this.id, left, parse(p)]; - }; - return x; - } - - function bitwiseassignop(s) { - symbol(s, 20).exps = true; - return infix(s, function (left) { - if (option.bitwise) { - warning("Unexpected use of '{a}'.", this, this.id); - } - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - if (left) { - if (left.id === '.' || left.id === '[' || - (left.identifier && !left.reserved)) { - parse(19); - return left; - } - if (left === syntax['function']) { - warning( -"Expected an identifier in an assignment, and instead saw a function invocation.", - token); - } - } - error("Bad assignment.", this); - }, 20); - } - - - function suffix(s, f) { - var x = symbol(s, 150); - x.led = function (left) { - if (option.plusplus) { - warning("Unexpected use of '{a}'.", this, this.id); - } - return [f, left]; - }; - return x; - } - - - function optionalidentifier() { - if (nexttoken.reserved) { - warning("Expected an identifier and instead saw '{a}' (a reserved word).", - nexttoken, nexttoken.id); - } - if (nexttoken.identifier) { - advance(); - return token.value; - } - } - - - function identifier() { - var i = optionalidentifier(); - if (i) { - return i; - } - if (token.id === 'function' && nexttoken.id === '(') { - warning("Missing name in function statement."); - } else { - error("Expected an identifier and instead saw '{a}'.", - nexttoken, nexttoken.value); - } - } - - function reachable(s) { - var i = 0, t; - if (nexttoken.id !== ';' || noreach) { - return; - } - for (;;) { - t = peek(i); - if (t.reach) { - return; - } - if (t.id !== '(endline)') { - if (t.id === 'function') { - warning( -"Inner functions should be listed at the top of the outer function.", t); - break; - } - warning("Unreachable '{a}' after '{b}'.", t, t.value, s); - break; - } - i += 1; - } - } - - - function statement(noindent) { - var i = indent, r, s = scope, t = nexttoken; - -// We don't like the empty statement. - - if (t.id === ';') { - warning("Unnecessary semicolon.", t); - advance(';'); - return; - } - -// Is this a labelled statement? - - if (t.identifier && !t.reserved && peek().id === ':') { - advance(); - advance(':'); - scope = object(s); - addlabel(t.value, 'label'); - if (!nexttoken.labelled) { - warning("Label '{a}' on {b} statement.", - nexttoken, t.value, nexttoken.value); - } - if (jx.test(t.value + ':')) { - warning("Label '{a}' looks like a javascript url.", - t, t.value); - } - nexttoken.label = t.value; - t = nexttoken; - } - -// Parse the statement. - - if (!noindent) { - indentation(); - } - r = parse(0, true); - -// Look for the final semicolon. - - if (!t.block) { - if (nexttoken.id !== ';') { - warningAt("Missing semicolon.", token.line, - token.from + token.value.length); - } else { - adjacent(token, nexttoken); - advance(';'); - nonadjacent(token, nexttoken); - } - } - -// Restore the indentation. - - indent = i; - scope = s; - return r; - } - - - function statements() { - var a = []; - while (!nexttoken.reach && nexttoken.id !== '(end)') { - if (nexttoken.id === ';') { - warning("Unnecessary semicolon."); - advance(';'); - } else { - a.push(statement()); - } - } - return a; - } - - - function block(f) { - var a, b = inblock, s = scope; - inblock = f; - if (f) { - scope = object(scope); - } - nonadjacent(token, nexttoken); - var t = nexttoken; - if (nexttoken.id === '{') { - advance('{'); - if (nexttoken.id !== '}' || token.line !== nexttoken.line) { - indent += 4; - if (!f && nexttoken.from === indent + 4) { - indent += 4; - } - a = statements(); - indent -= 4; - indentation(); - } - advance('}', t); - } else { - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '{', nexttoken.value); - noreach = true; - a = [statement()]; - noreach = false; - } - funct['(verb)'] = null; - scope = s; - inblock = b; - return a; - } - - -// An identity function, used by string and number tokens. - - function idValue() { - return this; - } - - - function countMember(m) { - if (membersOnly && membersOnly[m] !== true) { - warning("Unexpected /*member '{a}'.", nexttoken, m); - } - if (typeof member[m] === 'number') { - member[m] += 1; - } else { - member[m] = 1; - } - } - - function note_implied(token) { - var name = token.value, line = token.line + 1, a = implied[name]; - if (!a) { - a = [line]; - implied[name] = a; - } else if (a[a.length - 1] !== line) { - a.push(line); - } - } - - -// XML types. Currently we support html and widget. - - var xmltype = { - html: { - doBegin: function (n) { - xtype = 'html'; - option.browser = true; - populateGlobals(); - }, - doTagName: function (n, p) { - var i, t = xmltype.html.tag[n], x; - src = false; - if (!t) { - error("Unrecognized tag '<{a}>'.", - nexttoken, - n === n.toLowerCase() ? n : - n + ' (capitalization error)'); - } - x = t.parent; - if (!option.fragment || stack.length !== 1 || !stack[0].fragment) { - if (x) { - if (x.indexOf(' ' + p + ' ') < 0) { - error("A '<{a}>' must be within '<{b}>'.", - token, n, x); - } - } else { - i = stack.length; - do { - if (i <= 0) { - error("A '<{a}>' must be within '<{b}>'.", - token, n, 'body'); - } - i -= 1; - } while (stack[i].name !== 'body'); - } - } - return t.empty; - }, - doAttribute: function (n, a) { - if (!a) { - warning("Missing attribute name.", token); - } - a = a.toLowerCase(); - if (n === 'script') { - if (a === 'src') { - src = true; - return 'href'; - } else if (a === 'language') { - warning("The 'language' attribute is deprecated.", - token); - return false; - } - } else if (n === 'style') { - if (a === 'type' && option.adsafe) { - warning("Don't bother with 'type'.", token); - } - } - if (href[a] === true) { - return 'href'; - } - if (a.slice(0, 2) === 'on') { - if (!option.on) { - warning("Avoid HTML event handlers."); - } - return 'script'; - } else { - return 'value'; - } - }, - doIt: function (n) { - return n === 'script' ? 'script' : n !== 'html' && - xmltype.html.tag[n].special && 'special'; - }, - tag: { - a: {}, - abbr: {}, - acronym: {}, - address: {}, - applet: {}, - area: {empty: true, parent: ' map '}, - b: {}, - base: {empty: true, parent: ' head '}, - bdo: {}, - big: {}, - blockquote: {}, - body: {parent: ' html noframes '}, - br: {empty: true}, - button: {}, - canvas: {parent: ' body p div th td '}, - caption: {parent: ' table '}, - center: {}, - cite: {}, - code: {}, - col: {empty: true, parent: ' table colgroup '}, - colgroup: {parent: ' table '}, - dd: {parent: ' dl '}, - del: {}, - dfn: {}, - dir: {}, - div: {}, - dl: {}, - dt: {parent: ' dl '}, - em: {}, - embed: {}, - fieldset: {}, - font: {}, - form: {}, - frame: {empty: true, parent: ' frameset '}, - frameset: {parent: ' html frameset '}, - h1: {}, - h2: {}, - h3: {}, - h4: {}, - h5: {}, - h6: {}, - head: {parent: ' html '}, - html: {}, - hr: {empty: true}, - i: {}, - iframe: {}, - img: {empty: true}, - input: {empty: true}, - ins: {}, - kbd: {}, - label: {}, - legend: {parent: ' fieldset '}, - li: {parent: ' dir menu ol ul '}, - link: {empty: true, parent: ' head '}, - map: {}, - menu: {}, - meta: {empty: true, parent: ' head noframes noscript '}, - noframes: {parent: ' html body '}, - noscript: {parent: ' head html noframes '}, - object: {}, - ol: {}, - optgroup: {parent: ' select '}, - option: {parent: ' optgroup select '}, - p: {}, - param: {empty: true, parent: ' applet object '}, - pre: {}, - q: {}, - samp: {}, - script: {parent: ' body div frame head iframe p pre span '}, - select: {}, - small: {}, - span: {}, - strong: {}, - style: {parent: ' head ', special: true}, - sub: {}, - sup: {}, - table: {}, - tbody: {parent: ' table '}, - td: {parent: ' tr '}, - textarea: {}, - tfoot: {parent: ' table '}, - th: {parent: ' tr '}, - thead: {parent: ' table '}, - title: {parent: ' head '}, - tr: {parent: ' table tbody thead tfoot '}, - tt: {}, - u: {}, - ul: {}, - 'var': {} - } - }, - widget: { - doBegin: function (n) { - xtype = 'widget'; - option.widget = true; - option.cap = true; - populateGlobals(); - }, - doTagName: function (n, p) { - var t = xmltype.widget.tag[n]; - if (!t) { - error("Unrecognized tag '<{a}>'.", nexttoken, n); - } - var x = t.parent; - if (x.indexOf(' ' + p + ' ') < 0) { - error("A '<{a}>' must be within '<{b}>'.", - token, n, x); - } - }, - doAttribute: function (n, a) { - var t = xmltype.widget.tag[a]; - if (!t) { - error("Unrecognized attribute '<{a} {b}>'.", nexttoken, n, a); - } - var x = t.parent; - if (x.indexOf(' ' + n + ' ') < 0) { - error("Attribute '{a}' does not belong in '<{b}>'.", nexttoken, a, n); - } - return t.script ? - 'script' : - a === 'name' && n !== 'setting' ? - 'define' : 'string'; - }, - doIt: function (n) { - var x = xmltype.widget.tag[n]; - return x && x.script && 'script'; - }, - tag: { - "about-box": {parent: ' widget '}, - "about-image": {parent: ' about-box '}, - "about-text": {parent: ' about-box '}, - "about-version": {parent: ' about-box '}, - action: {parent: ' widget ', script: true}, - alignment: {parent: ' canvas frame image scrollbar text textarea window '}, - anchorstyle: {parent: ' text '}, - author: {parent: ' widget '}, - autohide: {parent: ' scrollbar '}, - beget: {parent: ' canvas frame image scrollbar text window '}, - bgcolor: {parent: ' text textarea '}, - bgcolour: {parent: ' text textarea '}, - bgopacity: {parent: ' text textarea '}, - canvas: {parent: ' frame window '}, - charset: {parent: ' script '}, - checked: {parent: ' image menuitem '}, - cliprect: {parent: ' image '}, - color: {parent: ' about-text about-version shadow text textarea '}, - colorize: {parent: ' image '}, - colour: {parent: ' about-text about-version shadow text textarea '}, - columns: {parent: ' textarea '}, - company: {parent: ' widget '}, - contextmenuitems: {parent: ' canvas frame image scrollbar text textarea window '}, - copyright: {parent: ' widget '}, - data: {parent: ' about-text about-version text textarea '}, - debug: {parent: ' widget '}, - defaultvalue: {parent: ' preference '}, - defaulttracking: {parent: ' widget '}, - description: {parent: ' preference '}, - directory: {parent: ' preference '}, - editable: {parent: ' textarea '}, - enabled: {parent: ' menuitem '}, - extension: {parent: ' preference '}, - file: {parent: ' action preference '}, - fillmode: {parent: ' image '}, - font: {parent: ' about-text about-version text textarea '}, - fontstyle: {parent: ' textarea '}, - frame: {parent: ' frame window '}, - group: {parent: ' preference '}, - halign: {parent: ' canvas frame image scrollbar text textarea '}, - handlelinks: {parent: ' textarea '}, - height: {parent: ' canvas frame image scrollbar text textarea window '}, - hidden: {parent: ' preference '}, - hlinesize: {parent: ' frame '}, - hoffset: {parent: ' about-text about-version canvas frame image scrollbar shadow text textarea window '}, - hotkey: {parent: ' widget '}, - hregistrationpoint: {parent: ' canvas frame image scrollbar text '}, - hscrollbar: {parent: ' frame '}, - hsladjustment: {parent: ' image '}, - hsltinting: {parent: ' image '}, - icon: {parent: ' preferencegroup '}, - id: {parent: ' canvas frame hotkey image preference text textarea timer scrollbar widget window '}, - image: {parent: ' about-box frame window widget '}, - interval: {parent: ' action timer '}, - key: {parent: ' hotkey '}, - kind: {parent: ' preference '}, - level: {parent: ' window '}, - lines: {parent: ' textarea '}, - loadingsrc: {parent: ' image '}, - locked: {parent: ' window '}, - max: {parent: ' scrollbar '}, - maxlength: {parent: ' preference '}, - menuitem: {parent: ' contextmenuitems '}, - min: {parent: ' scrollbar '}, - minimumversion: {parent: ' widget '}, - minlength: {parent: ' preference '}, - missingsrc: {parent: ' image '}, - modifier: {parent: ' hotkey '}, - name: {parent: ' canvas frame hotkey image preference preferencegroup scrollbar setting text textarea timer widget window '}, - notsaved: {parent: ' preference '}, - onclick: {parent: ' canvas frame image scrollbar text textarea ', script: true}, - oncontextmenu: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - ondragdrop: {parent: ' canvas frame image scrollbar text textarea ', script: true}, - ondragenter: {parent: ' canvas frame image scrollbar text textarea ', script: true}, - ondragexit: {parent: ' canvas frame image scrollbar text textarea ', script: true}, - onfirstdisplay: {parent: ' window ', script: true}, - ongainfocus: {parent: ' textarea window ', script: true}, - onkeydown: {parent: ' hotkey text textarea window ', script: true}, - onkeypress: {parent: ' textarea window ', script: true}, - onkeyup: {parent: ' hotkey text textarea window ', script: true}, - onimageloaded: {parent: ' image ', script: true}, - onlosefocus: {parent: ' textarea window ', script: true}, - onmousedown: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmousedrag: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmouseenter: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmouseexit: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmousemove: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmouseup: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onmousewheel: {parent: ' frame ', script: true}, - onmulticlick: {parent: ' canvas frame image scrollbar text textarea window ', script: true}, - onselect: {parent: ' menuitem ', script: true}, - ontextinput: {parent: ' window ', script: true}, - ontimerfired: {parent: ' timer ', script: true}, - onvaluechanged: {parent: ' scrollbar ', script: true}, - opacity: {parent: ' canvas frame image scrollbar shadow text textarea window '}, - option: {parent: ' preference widget '}, - optionvalue: {parent: ' preference '}, - order: {parent: ' preferencegroup '}, - orientation: {parent: ' scrollbar '}, - pagesize: {parent: ' scrollbar '}, - preference: {parent: ' widget '}, - preferencegroup: {parent: ' widget '}, - remoteasync: {parent: ' image '}, - requiredplatform: {parent: ' widget '}, - root: {parent: ' window '}, - rotation: {parent: ' canvas frame image scrollbar text '}, - script: {parent: ' widget ', script: true}, - scrollbar: {parent: ' frame text textarea window '}, - scrolling: {parent: ' text '}, - scrollx: {parent: ' frame '}, - scrolly: {parent: ' frame '}, - secure: {parent: ' preference textarea '}, - setting: {parent: ' settings '}, - settings: {parent: ' widget '}, - shadow: {parent: ' about-text about-version text window '}, - size: {parent: ' about-text about-version text textarea '}, - spellcheck: {parent: ' textarea '}, - src: {parent: ' image script '}, - srcheight: {parent: ' image '}, - srcwidth: {parent: ' image '}, - style: {parent: ' about-text about-version canvas frame image preference scrollbar text textarea window '}, - subviews: {parent: ' frame '}, - superview: {parent: ' canvas frame image scrollbar text textarea '}, - text: {parent: ' frame text textarea window '}, - textarea: {parent: ' frame window '}, - timer: {parent: ' widget '}, - thumbcolor: {parent: ' scrollbar textarea '}, - ticking: {parent: ' timer '}, - ticks: {parent: ' preference '}, - ticklabel: {parent: ' preference '}, - tileorigin: {parent: ' image '}, - title: {parent: ' menuitem preference preferencegroup window '}, - tooltip: {parent: ' frame image text textarea '}, - tracking: {parent: ' canvas image '}, - trigger: {parent: ' action '}, - truncation: {parent: ' text '}, - type: {parent: ' preference '}, - url: {parent: ' about-box about-text about-version '}, - usefileicon: {parent: ' image '}, - valign: {parent: ' canvas frame image scrollbar text textarea '}, - value: {parent: ' preference scrollbar setting '}, - version: {parent: ' widget '}, - visible: {parent: ' canvas frame image scrollbar text textarea window '}, - vlinesize: {parent: ' frame '}, - voffset: {parent: ' about-text about-version canvas frame image scrollbar shadow text textarea window '}, - vregistrationpoint: {parent: ' canvas frame image scrollbar text '}, - vscrollbar: {parent: ' frame '}, - width: {parent: ' canvas frame image scrollbar text textarea window '}, - window: {parent: ' canvas frame image scrollbar text textarea widget '}, - wrap: {parent: ' text '}, - zorder: {parent: ' canvas frame image scrollbar text textarea window '} - } - } - }; - - function xmlword(tag) { - var w = nexttoken.value; - if (!nexttoken.identifier) { - if (nexttoken.id === '<') { - if (tag) { - error("Expected '{a}' and instead saw '{b}'.", - token, '<', '<'); - } else { - error("Missing '{a}'.", token, '>'); - } - } else if (nexttoken.id === '(end)') { - error("Bad structure."); - } else { - warning("Missing quote.", token); - } - } - advance(); - while (nexttoken.id === '-' || nexttoken.id === ':') { - w += nexttoken.id; - advance(); - if (!nexttoken.identifier) { - error("Bad name '{a}'.", nexttoken, w + nexttoken.value); - } - w += nexttoken.value; - advance(); - } - if (option.cap) { - w = w.toLowerCase(); - } - return w; - } - - function closetag(n) { - return ''; - } - - function xml() { - var a, e, n, q, t, wmode; - xmode = 'xml'; - stack = null; - for (;;) { - switch (nexttoken.value) { - case '<': - if (!stack) { - stack = []; - } - advance('<'); - t = nexttoken; - n = xmlword(true); - t.name = n; - if (!xtype) { - if (option.fragment && option.adsafe && - n !== 'div' && n !== 'iframe') { - error("ADsafe HTML fragment violation.", token); - } - if (xmltype[n]) { - xmltype[n].doBegin(); - n = xtype; - e = false; - } else { - if (option.fragment) { - xmltype.html.doBegin(); - } else { - error("Unrecognized tag '<{a}>'.", nexttoken, n); - } - } - } else { - if (stack.length === 0) { - error("What the hell is this?"); - } - e = xmltype[xtype].doTagName(n, - stack[stack.length - 1].name); - } - t.type = n; - for (;;) { - if (nexttoken.id === '/') { - advance('/'); - if (nexttoken.id !== '>') { - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '>', nexttoken.value); - } - e = true; - break; - } - if (nexttoken.id && nexttoken.id.substr(0, 1) === '>') { - break; - } - a = xmlword(); - switch (xmltype[xtype].doAttribute(n, a)) { - case 'script': - xmode = 'string'; - advance('='); - q = nexttoken.id; - if (q !== '"' && q !== "'") { - error("Missing quote."); - } - xmode = q; - wmode = option.white; - option.white = false; - advance(q); - statements(); - option.white = wmode; - if (nexttoken.id !== q) { - error("Missing close quote on script attribute."); - } - xmode = 'xml'; - advance(q); - break; - case 'value': - advance('='); - if (!nexttoken.identifier && - nexttoken.type !== '(string)' && - nexttoken.type !== '(number)') { - error("Bad value '{a}'.", - nexttoken, nexttoken.value); - } - advance(); - break; - case 'string': - advance('='); - if (nexttoken.type !== '(string)') { - error("Bad value '{a}'.", - nexttoken, nexttoken.value); - } - advance(); - break; - case 'href': - advance('='); - if (nexttoken.type !== '(string)') { - error("Bad value '{a}'.", - nexttoken, nexttoken.value); - } - if (option.adsafe && ux.test(nexttoken.value)) { - error("ADsafe URL violation."); - } - advance(); - break; - case 'define': - advance('='); - if (nexttoken.type !== '(string)') { - error("Bad value '{a}'.", - nexttoken, nexttoken.value); - } - addlabel(nexttoken.value, 'var'); - advance(); - break; - default: - if (nexttoken.id === '=') { - advance('='); - if (!nexttoken.identifier && - nexttoken.type !== '(string)' && - nexttoken.type !== '(number)') { - error("Bad value '{a}'.", - nexttoken, nexttoken.value); - } - advance(); - } - } - } - switch (xmltype[xtype].doIt(n)) { - case 'script': - xmode = 'script'; - advance('>'); - indent = nexttoken.from; - if (src) { - if (option.fragment && option.adsafe) { - warning("ADsafe script violation.", token); - } - } else { - statements(); - } - if (nexttoken.id !== '', nexttoken.value); - } - xmode = 'xml'; - break; - case 'special': - e = true; - n = closetag(t.name); - if (!lex.skip(n)) { - error("Missing '{a}'.", t, n); - } - break; - default: - lex.skip('>'); - } - if (!e) { - stack.push(t); - } - break; - case '') { - error("Missing '{a}'.", nexttoken, '>'); - } - if (stack.length > 0) { - lex.skip('>'); - } else { - advance('>'); - } - break; - case '') { - break; - } - if (nexttoken.id === '<' || nexttoken.id === '(end)') { - error("Missing '{a}'.", token, '>'); - } - } - lex.skip('>'); - break; - case ''); - break; - case '<%': - if (option.adsafe) { - error("ADsafe HTML violation."); - } - lex.skip('%>'); - break; - case '') { - break; - } - if (nexttoken.id === '' || nexttoken.id === '(end)') { - error("Missing '{a}'.", token, '?>'); - } - } - lex.skip('?>'); - break; - case '<=': - case '<<': - case '<<=': - error("Missing '{a}'.", nexttoken, '<'); - break; - case '(end)': - return; - } - if (stack && stack.length === 0) { - return; - } - if (!lex.skip('')) { - if (!stack) { - error("Bad XML."); - } - t = stack.pop(); - if (t.value) { - error("Missing '{a}'.", t, closetag(t.name)); - } else { - return; - } - } - advance(); - } - } - - -// Build the syntax table by declaring the syntactic elements of the language. - - type('(number)', idValue); - type('(string)', idValue); - - syntax['(identifier)'] = { - type: '(identifier)', - lbp: 0, - identifier: true, - nud: function () { - var v = this.value, - s = scope[v]; - -// The name is in scope and defined in the current function. - - if (s && (s === funct || s === funct['(global)'])) { - -// If we are not also in the global scope, change 'unused' to 'var', -// and reject labels. - - if (!funct['(global)']) { - switch (funct[v]) { - case 'unused': - funct[v] = 'var'; - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - break; - } - } - -// The name is not defined in the function. If we are in the global scope, -// then we have an undefined variable. - - } else if (funct['(global)']) { - if (option.undef) { - warning("'{a}' is undefined.", token, v); - } - note_implied(token); - -// If the name is already defined in the current -// function, but not as outer, then there is a scope error. - - } else { - switch (funct[v]) { - case 'closure': - case 'function': - case 'var': - case 'unused': - warning("'{a}' used out of scope.", token, v); - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - break; - case 'outer': - case true: - break; - default: - -// If the name is defined in an outer function, make an outer entry, and if -// it was unused, make it var. - - if (s === true) { - funct[v] = true; - } else if (typeof s !== 'object') { - if (option.undef) { - warning("'{a}' is undefined.", token, v); - } else { - funct[v] = true; - } - note_implied(token); - } else { - switch (s[v]) { - case 'function': - case 'var': - case 'unused': - s[v] = 'closure'; - funct[v] = 'outer'; - break; - case 'closure': - case 'parameter': - funct[v] = 'outer'; - break; - case 'label': - warning("'{a}' is a statement label.", token, v); - } - } - } - } - return this; - }, - led: function () { - error("Expected an operator and instead saw '{a}'.", - nexttoken, nexttoken.value); - } - }; - - type('(regex)', function () { - return [this.id, this.value, this.flags]; - }); - - delim('(endline)'); - delim('(begin)'); - delim('(end)').reach = true; - delim(''); - delim('?>'); - delim('(error)').reach = true; - delim('}').reach = true; - delim(')'); - delim(']'); - delim(']]>').reach = true; - delim('"').reach = true; - delim("'").reach = true; - delim(';'); - delim(':').reach = true; - delim(','); - reserve('else'); - reserve('case').reach = true; - reserve('catch'); - reserve('default').reach = true; - reserve('finally'); - reservevar('arguments'); - reservevar('eval'); - reservevar('false'); - reservevar('Infinity'); - reservevar('NaN'); - reservevar('null'); - reservevar('this'); - reservevar('true'); - reservevar('undefined'); - assignop('=', 'assign', 20); - assignop('+=', 'assignadd', 20); - assignop('-=', 'assignsub', 20); - assignop('*=', 'assignmult', 20); - assignop('/=', 'assigndiv', 20).nud = function () { - error("A regular expression literal can be confused with '/='."); - }; - assignop('%=', 'assignmod', 20); - bitwiseassignop('&=', 'assignbitand', 20); - bitwiseassignop('|=', 'assignbitor', 20); - bitwiseassignop('^=', 'assignbitxor', 20); - bitwiseassignop('<<=', 'assignshiftleft', 20); - bitwiseassignop('>>=', 'assignshiftright', 20); - bitwiseassignop('>>>=', 'assignshiftrightunsigned', 20); - infix('?', function (left) { - parse(10); - advance(':'); - parse(10); - }, 30); - - infix('||', 'or', 40); - infix('&&', 'and', 50); - bitwise('|', 'bitor', 70); - bitwise('^', 'bitxor', 80); - bitwise('&', 'bitand', 90); - relation('==', function (left, right) { - if (option.eqeqeq) { - warning("Expected '{a}' and instead saw '{b}'.", - this, '===', '=='); - } else if (isPoorRelation(left)) { - warning("Use '{a}' to compare with '{b}'.", - this, '===', left.value); - } else if (isPoorRelation(right)) { - warning("Use '{a}' to compare with '{b}'.", - this, '===', right.value); - } - return ['==', left, right]; - }); - relation('==='); - relation('!=', function (left, right) { - if (option.eqeqeq) { - warning("Expected '{a}' and instead saw '{b}'.", - this, '!==', '!='); - } else if (isPoorRelation(left)) { - warning("Use '{a}' to compare with '{b}'.", - this, '!==', left.value); - } else if (isPoorRelation(right)) { - warning("Use '{a}' to compare with '{b}'.", - this, '!==', right.value); - } - return ['!=', left, right]; - }); - relation('!=='); - relation('<'); - relation('>'); - relation('<='); - relation('>='); - bitwise('<<', 'shiftleft', 120); - bitwise('>>', 'shiftright', 120); - bitwise('>>>', 'shiftrightunsigned', 120); - infix('in', 'in', 120); - infix('instanceof', 'instanceof', 120); - infix('+', function (left) { - nonadjacent(prevtoken, token); - nonadjacent(token, nexttoken); - var right = parse(130); - if (left && right && left.id === '(string)' && right.id === '(string)') { - left.value += right.value; - left.character = right.character; - if (jx.test(left.value)) { - warning("JavaScript URL.", left); - } - return left; - } - return [this.id, left, right]; - }, 130); - prefix('+', 'num'); - infix('-', 'sub', 130); - prefix('-', 'neg'); - infix('*', 'mult', 140); - infix('/', 'div', 140); - infix('%', 'mod', 140); - - suffix('++', 'postinc'); - prefix('++', 'preinc'); - syntax['++'].exps = true; - - suffix('--', 'postdec'); - prefix('--', 'predec'); - syntax['--'].exps = true; - prefix('delete', function () { - var p = parse(0); - if (p.id !== '.' && p.id !== '[') { - warning("Expected '{a}' and instead saw '{b}'.", - nexttoken, '.', nexttoken.value); - } - }).exps = true; - - - prefix('~', function () { - if (option.bitwise) { - warning("Unexpected '{a}'.", this, '~'); - } - parse(150); - return this; - }); - prefix('!', 'not'); - prefix('typeof', 'typeof'); - prefix('new', function () { - var c = parse(155), i; - if (c) { - if (c.identifier) { - c['new'] = true; - switch (c.value) { - case 'Object': - warning("Use the object literal notation {}.", token); - break; - case 'Array': - warning("Use the array literal notation [].", token); - break; - case 'Number': - case 'String': - case 'Boolean': - warning("Do not use the {a} function as a constructor.", - token, c.value); - break; - case 'Function': - if (!option.evil) { - warning("The Function constructor is eval."); - } - break; - default: - if (c.id !== 'function') { - i = c.value.substr(0, 1); - if (i < 'A' || i > 'Z') { - warning( - "A constructor name should start with an uppercase letter.", - token); - } - } - } - } else { - if (c.id !== '.' && c.id !== '[' && c.id !== '(') { - warning("Bad constructor.", token); - } - } - } else { - warning("Weird construction. Delete 'new'.", this); - } - adjacent(token, nexttoken); - if (nexttoken.id === '(') { - advance('('); - nospace(); - if (nexttoken.id !== ')') { - for (;;) { - parse(10); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance(')'); - nospace(prevtoken, token); - } else { - warning("Missing '()' invoking a constructor."); - } - return syntax['function']; - }); - syntax['new'].exps = true; - - infix('.', function (left) { - adjacent(prevtoken, token); - var m = identifier(); - if (typeof m === 'string') { - countMember(m); - } - if (!option.evil && left && left.value === 'document' && - (m === 'write' || m === 'writeln')) { - warning("document.write can be a form of eval.", left); - } - this.left = left; - this.right = m; - return this; - }, 160); - - infix('(', function (left) { - adjacent(prevtoken, token); - nospace(); - var n = 0; - var p = []; - if (left && left.type === '(identifier)') { - if (left.value.match(/^[A-Z](.*[a-z].*)?$/)) { - if (left.value !== 'Number' && left.value !== 'String' && - left.value !== 'Boolean' && left.value !== 'Date') { - warning("Missing 'new' prefix when invoking a constructor.", - left); - } - } - } - if (nexttoken.id !== ')') { - for (;;) { - p[p.length] = parse(10); - n += 1; - if (nexttoken.id !== ',') { - break; - } - advance(','); - nonadjacent(token, nexttoken); - } - } - advance(')'); - nospace(prevtoken, token); - if (typeof left === 'object') { - if (left.value === 'parseInt' && n === 1) { - warning("Missing radix parameter.", left); - } - if (!option.evil) { - if (left.value === 'eval' || left.value === 'Function') { - warning("eval is evil.", left); - } else if (p[0] && p[0].id === '(string)' && - (left.value === 'setTimeout' || - left.value === 'setInterval')) { - warning( - "Implied eval is evil. Pass a function instead of a string.", left); - } - } - if (!left.identifier && left.id !== '.' && - left.id !== '[' && left.id !== '(') { - warning("Bad invocation.", left); - } - - } - return syntax['function']; - }, 155).exps = true; - - prefix('(', function () { - nospace(); - var v = parse(0); - advance(')', this); - nospace(prevtoken, token); - return v; - }); - - infix('[', function (left) { - if (option.adsafe) { - warning('ADsafe subscripting.'); - } - nospace(); - var e = parse(0), s; - if (e && e.type === '(string)') { - countMember(e.value); - if (ix.test(e.value)) { - s = syntax[e.value]; - if (!s || !s.reserved) { - warning("['{a}'] is better written in dot notation.", - e, e.value); - } - } - } - advance(']', this); - nospace(prevtoken, token); - this.left = left; - this.right = e; - return this; - }, 160); - - prefix('[', function () { - if (nexttoken.id === ']') { - advance(']'); - return; - } - var b = token.line !== nexttoken.line; - if (b) { - indent += 4; - if (nexttoken.from === indent + 4) { - indent += 4; - } - } - for (;;) { - if (b && token.line !== nexttoken.line) { - indentation(); - } - parse(10); - if (nexttoken.id === ',') { - adjacent(token, nexttoken); - advance(','); - if (nexttoken.id === ',' || nexttoken.id === ']') { - warning("Extra comma.", token); - } - nonadjacent(token, nexttoken); - } else { - if (b) { - indent -= 4; - indentation(); - } - advance(']', this); - return; - } - } - }, 160); - - (function (x) { - x.nud = function () { - var i, s; - if (nexttoken.id === '}') { - advance('}'); - return; - } - var b = token.line !== nexttoken.line; - if (b) { - indent += 4; - if (nexttoken.from === indent + 4) { - indent += 4; - } - } - for (;;) { - if (b) { - indentation(); - } - i = optionalidentifier(true); - if (!i) { - if (nexttoken.id === '(string)') { - i = nexttoken.value; - if (ix.test(i)) { - s = syntax[i]; - } - advance(); - } else if (nexttoken.id === '(number)') { - i = nexttoken.value.toString(); - advance(); - } else { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, '}', nexttoken.value); - } - } - countMember(i); - advance(':'); - nonadjacent(token, nexttoken); - parse(10); - if (nexttoken.id === ',') { - adjacent(token, nexttoken); - advance(','); - if (nexttoken.id === ',' || nexttoken.id === '}') { - warning("Extra comma.", token); - } - nonadjacent(token, nexttoken); - } else { - if (b) { - indent -= 4; - indentation(); - } - advance('}', this); - return; - } - } - }; - x.fud = function () { - error("Expected to see a statement and instead saw a block.", token); - }; - })(delim('{')); - - - function varstatement() { - -// JavaScript does not have block scope. It only has function scope. So, -// declaring a variable in a block can have unexpected consequences. - - for (;;) { - nonadjacent(token, nexttoken); - addlabel(identifier(), 'unused'); - if (nexttoken.id === '=') { - nonadjacent(token, nexttoken); - advance('='); - nonadjacent(token, nexttoken); - if (peek(0).id === '=') { - error("Variable {a} was not declared correctly.", - nexttoken, nexttoken.value); - } - parse(20); - } - if (nexttoken.id !== ',') { - return; - } - adjacent(token, nexttoken); - advance(','); - nonadjacent(token, nexttoken); - } - } - - - stmt('var', varstatement); - - stmt('new', function () { - error("'new' should not be used as a statement."); - }); - - - function functionparams() { - var i, t = nexttoken, p = []; - advance('('); - nospace(); - if (nexttoken.id === ')') { - advance(')'); - nospace(prevtoken, token); - return; - } - for (;;) { - i = identifier(); - p.push(i); - addlabel(i, 'parameter'); - if (nexttoken.id === ',') { - advance(','); - nonadjacent(token, nexttoken); - } else { - advance(')', t); - nospace(prevtoken, token); - return p.join(', '); - } - } - } - - function doFunction(i) { - var s = scope; - scope = object(s); - funct = { - '(name)' : i || '"' + anonname + '"', - '(line)' : nexttoken.line + 1, - '(context)' : funct, - '(scope)' : scope - }; - functions.push(funct); - if (i) { - addlabel(i, 'function'); - } - funct['(params)'] = functionparams(); - - block(false); - scope = s; - funct = funct['(context)']; - } - - - blockstmt('function', function () { - if (inblock) { - warning( -"Function statements cannot be placed in blocks. Use a function expression or move the statement to the top of the outer function.", token); - - } - var i = identifier(); - adjacent(token, nexttoken); - addlabel(i, 'unused'); - doFunction(i); - if (nexttoken.id === '(' && nexttoken.line === token.line) { - error( -"Function statements are not invocable. Wrap the function expression in parens."); - } - }); - - prefix('function', function () { - var i = optionalidentifier(); - if (i) { - adjacent(token, nexttoken); - } else { - nonadjacent(token, nexttoken); - } - doFunction(i); - }); - - blockstmt('if', function () { - var t = nexttoken; - advance('('); - nonadjacent(this, t); - nospace(); - parse(20); - if (nexttoken.id === '=') { - warning("Assignment in control part."); - advance('='); - parse(20); - } - advance(')', t); - nospace(prevtoken, token); - block(true); - if (nexttoken.id === 'else') { - nonadjacent(token, nexttoken); - advance('else'); - if (nexttoken.id === 'if' || nexttoken.id === 'switch') { - statement(true); - } else { - block(true); - } - } - return this; - }); - - blockstmt('try', function () { - var b, e, s; - block(false); - if (nexttoken.id === 'catch') { - advance('catch'); - nonadjacent(token, nexttoken); - advance('('); - s = scope; - scope = object(s); - e = nexttoken.value; - if (nexttoken.type !== '(identifier)') { - warning("Expected an identifier and instead saw '{a}'.", - nexttoken, e); - } else { - addlabel(e, 'unused'); - } - advance(); - advance(')'); - block(false); - b = true; - scope = s; - } - if (nexttoken.id === 'finally') { - advance('finally'); - block(false); - return; - } else if (!b) { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'catch', nexttoken.value); - } - }); - - blockstmt('while', function () { - var t = nexttoken; - advance('('); - nonadjacent(this, t); - nospace(); - parse(20); - if (nexttoken.id === '=') { - warning("Assignment in control part."); - advance('='); - parse(20); - } - advance(')', t); - nospace(prevtoken, token); - block(true); - }).labelled = true; - - reserve('with'); - - blockstmt('switch', function () { - var t = nexttoken; - var g = false; - advance('('); - nonadjacent(this, t); - nospace(); - this.condition = parse(20); - advance(')', t); - nospace(prevtoken, token); - nonadjacent(token, nexttoken); - t = nexttoken; - advance('{'); - nonadjacent(token, nexttoken); - indent += 4; - this.cases = []; - for (;;) { - switch (nexttoken.id) { - case 'case': - switch (funct['(verb)']) { - case 'break': - case 'case': - case 'continue': - case 'return': - case 'switch': - case 'throw': - break; - default: - warning( - "Expected a 'break' statement before 'case'.", - token); - } - indentation(-4); - advance('case'); - this.cases.push(parse(20)); - g = true; - advance(':'); - funct['(verb)'] = 'case'; - break; - case 'default': - switch (funct['(verb)']) { - case 'break': - case 'continue': - case 'return': - case 'throw': - break; - default: - warning( - "Expected a 'break' statement before 'default'.", - token); - } - indentation(-4); - advance('default'); - g = true; - advance(':'); - break; - case '}': - indent -= 4; - indentation(); - advance('}', t); - if (this.cases.length === 1 || this.condition.id === 'true' || - this.condition.id === 'false') { - warning("This 'switch' should be an 'if'.", this); - } - return; - case '(end)': - error("Missing '{a}'.", nexttoken, '}'); - return; - default: - if (g) { - switch (token.id) { - case ',': - error("Each value should have its own case label."); - return; - case ':': - statements(); - break; - default: - error("Missing ':' on a case clause.", token); - } - } else { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, 'case', nexttoken.value); - } - } - } - }).labelled = true; - - stmt('debugger', function () { - if (!option.debug) { - warning("All 'debugger' statements should be removed."); - } - }); - - stmt('do', function () { - block(true); - advance('while'); - var t = nexttoken; - nonadjacent(token, t); - advance('('); - nospace(); - parse(20); - advance(')', t); - nospace(prevtoken, token); - }).labelled = true; - - blockstmt('for', function () { - var s, t = nexttoken; - advance('('); - nonadjacent(this, t); - nospace(); - if (peek(nexttoken.id === 'var' ? 1 : 0).id === 'in') { - if (nexttoken.id === 'var') { - advance('var'); - addlabel(identifier(), 'var'); - } else { - advance(); - } - advance('in'); - parse(20); - advance(')', t); - if (nexttoken.id === 'if') { - nolinebreak(token); - statement(true); - } else { - s = block(true); - if (!option.forin && (s.length > 1 || typeof s[0] !== 'object' || - s[0].value !== 'if')) { - warning("The body of a for in should be wrapped in an if statement to filter unwanted properties from the prototype.", this); - } - } - return this; - } else { - if (nexttoken.id !== ';') { - if (nexttoken.id === 'var') { - advance('var'); - varstatement(); - } else { - for (;;) { - parse(0); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - } - advance(';'); - if (nexttoken.id !== ';') { - parse(20); - } - advance(';'); - if (nexttoken.id === ';') { - error("Expected '{a}' and instead saw '{b}'.", - nexttoken, ')', ';'); - } - if (nexttoken.id !== ')') { - for (;;) { - parse(0); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance(')', t); - nospace(prevtoken, token); - block(true); - } - }).labelled = true; - - - stmt('break', function () { - var v = nexttoken.value; - nolinebreak(this); - if (nexttoken.id !== ';') { - if (funct[v] !== 'label') { - warning("'{a}' is not a statement label.", nexttoken, v); - } else if (scope[v] !== funct) { - warning("'{a}' is out of scope.", nexttoken, v); - } - advance(); - } - reachable('break'); - }); - - - stmt('continue', function () { - var v = nexttoken.value; - nolinebreak(this); - if (nexttoken.id !== ';') { - if (funct[v] !== 'label') { - warning("'{a}' is not a statement label.", nexttoken, v); - } else if (scope[v] !== funct) { - warning("'{a}' is out of scope.", nexttoken, v); - } - advance(); - } - reachable('continue'); - }); - - - stmt('return', function () { - nolinebreak(this); - if (nexttoken.id !== ';' && !nexttoken.reach) { - nonadjacent(token, nexttoken); - parse(20); - } - reachable('return'); - }); - - - stmt('throw', function () { - nolinebreak(this); - nonadjacent(token, nexttoken); - parse(20); - reachable('throw'); - }); - - -// Superfluous reserved words - - reserve('abstract'); - reserve('boolean'); - reserve('byte'); - reserve('char'); - reserve('class'); - reserve('const'); - reserve('double'); - reserve('enum'); - reserve('export'); - reserve('extends'); - reserve('final'); - reserve('float'); - reserve('goto'); - reserve('implements'); - reserve('import'); - reserve('int'); - reserve('interface'); - reserve('long'); - reserve('native'); - reserve('package'); - reserve('private'); - reserve('protected'); - reserve('public'); - reserve('short'); - reserve('static'); - reserve('super'); - reserve('synchronized'); - reserve('throws'); - reserve('transient'); - reserve('void'); - reserve('volatile'); - - - function jsonValue() { - - function jsonObject() { - var t = nexttoken; - advance('{'); - if (nexttoken.id !== '}') { - for (;;) { - if (nexttoken.id === '(end)') { - error("Missing '}' to match '{' from line {a}.", - nexttoken, t.line + 1); - } else if (nexttoken.id === '}') { - warning("Unexpected comma.", token); - break; - } else if (nexttoken.id === ',') { - error("Unexpected comma.", nexttoken); - } else if (nexttoken.id !== '(string)') { - warning("Expected a string and instead saw {a}.", - nexttoken, nexttoken.value); - } - advance(); - advance(':'); - jsonValue(); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance('}'); - } - - function jsonArray() { - var t = nexttoken; - advance('['); - if (nexttoken.id !== ']') { - for (;;) { - if (nexttoken.id === '(end)') { - error("Missing ']' to match '[' from line {a}.", - nexttoken, t.line + 1); - } else if (nexttoken.id === ']') { - warning("Unexpected comma.", token); - break; - } else if (nexttoken.id === ',') { - error("Unexpected comma.", nexttoken); - } - jsonValue(); - if (nexttoken.id !== ',') { - break; - } - advance(','); - } - } - advance(']'); - } - - switch (nexttoken.id) { - case '{': - jsonObject(); - break; - case '[': - jsonArray(); - break; - case 'true': - case 'false': - case 'null': - case '(number)': - case '(string)': - advance(); - break; - case '-': - advance('-'); - if (token.character !== nexttoken.from) { - warning("Unexpected space after '-'.", token); - } - adjacent(token, nexttoken); - advance('(number)'); - break; - default: - error("Expected a JSON value.", nexttoken); - } - } - - -// The actual JSLINT function itself. - - var itself = function (s, o) { - if (o) { - if (o.adsafe) { - o.browser = false; - o.debug = false; - o.eqeqeq = true; - o.evil = false; - o.forin = false; - o.on = false; - o.rhino = false; - o.undef = true; - o.widget = false; - } - option = o; - } else { - option = {}; - } - globals = option.adsafe ? {} : object(standard); - JSLINT.errors = []; - global = object(globals); - scope = global; - funct = {'(global)': true, '(name)': '(global)', '(scope)': scope}; - functions = []; - src = false; - xmode = false; - xtype = ''; - stack = null; - member = {}; - membersOnly = null; - implied = {}; - inblock = false; - lookahead = []; - indent = 0; - jsonmode = false; - warnings = 0; - lex.init(s); - prereg = true; - - prevtoken = token = nexttoken = syntax['(begin)']; - populateGlobals(); - - try { - advance(); - if (nexttoken.value.charAt(0) === '<') { - xml(); - } else if (nexttoken.id === '{' || nexttoken.id === '[') { - option.laxbreak = true; - jsonmode = true; - jsonValue(); - } else { - statements(); - } - advance('(end)'); - } catch (e) { - if (e) { - JSLINT.errors.push({ - reason : e.message, - line : e.line || nexttoken.line, - character : e.character || nexttoken.from - }, null); - } - } - return JSLINT.errors.length === 0; - }; - - function to_array(o) { - var a = [], k; - for (k in o) if (o.hasOwnProperty(k)) { - a.push(k); - } - return a; - } - -// Report generator. - - itself.report = function (option) { - var a = [], c, e, f, i, k, l, m = '', n, o = [], s, v, cl, va, un, ou, gl, la; - - function detail(h, s) { - if (s.length) { - o.push('
                                                                                            ' + h + ' ' + - s.sort().join(', ') + '
                                                                                            '); - } - } - - s = to_array(implied); - - k = JSLINT.errors.length; - if (k || s.length > 0) { - o.push('
                                                                                            Error:'); - if (s.length > 0) { - s.sort(); - for (i = 0; i < s.length; i += 1) { - s[i] = '' + s[i] + ' ' + - implied[s[i]].join(' ') + - ''; - } - o.push('

                                                                                            Implied global: ' + s.join(', ') + '

                                                                                            '); - c = true; - } - for (i = 0; i < k; i += 1) { - c = JSLINT.errors[i]; - if (c) { - e = c.evidence || ''; - o.push('

                                                                                            Problem' + (isFinite(c.line) ? ' at line ' + (c.line + 1) + - ' character ' + (c.character + 1) : '') + - ': ' + c.reason.entityify() + - '

                                                                                            ' + - (e && (e.length > 80 ? e.slice(0, 77) + '...' : - e).entityify()) + '

                                                                                            '); - } - } - o.push('
                                                                                            '); - if (!c) { - return o.join(''); - } - } - - if (!option) { - - o.push('
                                                                                            '); - - s = to_array(scope); - if (s.length === 0) { - o.push('
                                                                                            No new global variables introduced.
                                                                                            '); - } else { - o.push('
                                                                                            Global ' + s.sort().join(', ') + '
                                                                                            '); - } - - for (i = 0; i < functions.length; i += 1) { - f = functions[i]; - cl = []; - va = []; - un = []; - ou = []; - gl = []; - la = []; - for (k in f) if (f.hasOwnProperty(k)) { - v = f[k]; - switch (v) { - case 'closure': - cl.push(k); - break; - case 'var': - va.push(k); - break; - case 'unused': - un.push(k); - break; - case 'label': - la.push(k); - break; - case 'outer': - ou.push(k); - break; - case true: - if (k !== '(context)') { - gl.push(k); - } - break; - } - } - o.push('
                                                                                            ' + f['(line)'] + ' ' + - (f['(name)'] || '') + '(' + - (f['(params)'] || '') + ')
                                                                                            '); - detail('Closure', cl); - detail('Variable', va); - detail('Unused', un); - detail('Label', la); - detail('Outer', ou); - detail('Global', gl); - } - a = []; - for (k in member) { - if (typeof member[k] === 'number') { - a.push(k); - } - } - if (a.length) { - a = a.sort(); - m = '
                                                                                            /*members ';
                                                                                            -                l = 10;
                                                                                            -                for (i = 0; i < a.length; i += 1) {
                                                                                            -                    k = a[i];
                                                                                            -                    n = k.name();
                                                                                            -                    if (l + n.length > 72) {
                                                                                            -                        o.push(m + '
                                                                                            '); - m = ' '; - l = 1; - } - l += n.length + 2; - if (member[k] === 1) { - n = '' + n + ''; - } - if (i < a.length - 1) { - n += ', '; - } - m += n; - } - o.push(m + '
                                                                                            */
                                                                                            '); - } - o.push('
                                                                                            '); - } - return o.join(''); - }; - - return itself; - -}(); \ No newline at end of file diff --git a/view/helpers/helpers.js b/view/helpers/helpers.js deleted file mode 100644 index 93554d84..00000000 --- a/view/helpers/helpers.js +++ /dev/null @@ -1,348 +0,0 @@ -steal('jquery/view/ejs').then(function($){ - -/** - * @add jQuery.EJS.Helpers.prototype - */ -$.extend($.EJS.Helpers.prototype, { - /** - * Converts response to text. - */ - text: function( input, null_text ) { - if ( input == null || input === undefined ) return null_text || ''; - if ( input instanceof Date ) return input.toDateString(); - if ( input.toString ) return input.toString().replace(/\n/g, '
                                                                                            ').replace(/''/g, "'"); - return ''; - }, - - // treyk 06/11/2009 - Pulled from old MVC.Date plugin for now. Will look for a suitable jQuery Date plugin - month_names: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"], - - /** - * Creates a check box tag - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} options - * @param {Object} checked - */ - check_box_tag: function( name, value, options, checked ) { - options = options || {}; - if(checked) options.checked = "checked"; - return this.input_field_tag(name, value, 'checkbox', options); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - date_tag: function( name, value , html_options ) { - if(! (value instanceof Date)) value = new Date(); - - var years = [], months = [], days =[]; - var year = value.getFullYear(), month = value.getMonth(), day = value.getDate(); - for(var y = year - 15; y < year+15 ; y++) years.push({value: y, text: y}); - for(var m = 0; m < 12; m++) months.push({value: (m), text: $View.Helpers.month_names[m]}); - for(var d = 0; d < 31; d++) days.push({value: (d+1), text: (d+1)}); - - var year_select = this.select_tag(name+'[year]', year, years, {id: name+'[year]'} ); - var month_select = this.select_tag(name+'[month]', month, months, {id: name+'[month]'}); - var day_select = this.select_tag(name+'[day]', day, days, {id: name+'[day]'}); - - return year_select+month_select+day_select; - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - * @param {Object} interval - specified in minutes - */ - time_tag: function( name, value, html_options, interval ) { - var times = []; - - if (interval == null || interval == 0) - interval = 60; - - for(var h = 0; h < 24 ; h++) - for(var m = 0; m < 60; m+=interval) - { - var time = (h < 10 ? '0' : '') + h + ':' + (m < 10 ? '0' : '') + m; - times.push({ text: time, value: time }); - } - - return this.select_tag(name, value, times, html_options ); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - file_tag: function( name, value, html_options ) { - return this.input_field_tag(name+'[file]', value , 'file', html_options); - }, - /** - * @plugin view/helpers - * @param {Object} url_for_options - * @param {Object} html_options - */ - form_tag: function( url_for_options, html_options ) { - html_options = html_options || {}; - if(html_options.multipart == true) { - html_options.method = 'post'; - html_options.enctype = 'multipart/form-data'; - } - html_options.action = url_for_options; - return this.start_tag_for('form', html_options); - }, - /** - * @plugin view/helpers - */ - form_tag_end: function() { return this.tag_end('form'); }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - hidden_field_tag: function( name, value, html_options ) { - return this.input_field_tag(name, value, 'hidden', html_options); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} inputType - * @param {Object} html_options - */ - input_field_tag: function( name, value , inputType, html_options ) { - html_options = html_options || {}; - html_options.id = html_options.id || name; - html_options.value = value || ''; - html_options.type = inputType || 'text'; - html_options.name = name; - return this.single_tag_for('input', html_options); - }, - /** - * @plugin view/helpers - * @param {Object} text - * @param {Object} html_options - */ - label_tag: function( text, html_options ) { - html_options = html_options || {}; - return this.start_tag_for('label', html_options) + text + this.tag_end('label'); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} url - * @param {Object} html_options - */ - link_to: function( name, url, html_options ) { - if(!name) var name = 'null'; - if(!html_options) var html_options = {}; - this.set_confirm(html_options); - html_options.href=url; - return this.start_tag_for('a', html_options)+name+ this.tag_end('a'); - }, - /** - * @plugin view/helpers - * @param {Object} condition - * @param {Object} name - * @param {Object} url - * @param {Object} html_options - */ - link_to_if: function( condition, name, url, html_options ) { - return this.link_to_unless((!condition), name, url, html_options); - }, - /** - * @plugin view/helpers - * @param {Object} condition - * @param {Object} name - * @param {Object} url - * @param {Object} html_options - */ - link_to_unless: function( condition, name, url, html_options ) { - if(condition) return name; - return this.link_to(name, url, html_options); - }, - /** - * @plugin view/helpers - * @param {Object} html_options - */ - set_confirm: function( html_options ) { - if(html_options.confirm){ - html_options.onclick = html_options.onclick || ''; - html_options.onclick = html_options.onclick+ - "; var ret_confirm = confirm(\""+html_options.confirm+"\"); if(!ret_confirm){ return false;} "; - html_options.confirm = null; - } - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} options - * @param {Object} html_options - * @param {Object} post - */ - submit_link_to: function( name, options, html_options, post ) { - if(!name) var name = 'null'; - if(!html_options) html_options = {}; - html_options.type = 'submit'; - html_options.value = name; - this.set_confirm(html_options); - html_options.onclick=html_options.onclick+';window.location="'+options+'"; return false;'; - return this.single_tag_for('input', html_options); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - password_field_tag: function( name, value, html_options ) { return this.input_field_tag(name, value, 'password', html_options); }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} choices - * @param {Object} html_options - */ - select_tag: function( name, value, choices, html_options ) { - html_options = html_options || {}; - html_options.id = html_options.id || name; - //html_options.value = value; - html_options.name = name; - var txt = ''; - txt += this.start_tag_for('select', html_options); - for(var i = 0; i < choices.length; i++) - { - var choice = choices[i]; - if(typeof choice == 'string') choice = {value: choice}; - if(!choice.text) choice.text = choice.value; - if(!choice.value) choice.text = choice.text; - - var optionOptions = {value: choice.value}; - if(choice.value == value) - optionOptions.selected ='selected'; - txt += this.start_tag_for('option', optionOptions )+choice.text+this.tag_end('option'); - } - txt += this.tag_end('select'); - return txt; - }, - /** - * @plugin view/helpers - * @param {Object} tag - * @param {Object} html_options - */ - single_tag_for: function( tag, html_options ) { return this.tag(tag, html_options, '/>');}, - /** - * @plugin view/helpers - * @param {Object} tag - * @param {Object} html_options - */ - start_tag_for: function( tag, html_options ) { return this.tag(tag, html_options); }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} html_options - */ - submit_tag: function( name, html_options ) { - html_options = html_options || {}; - html_options.type = html_options.type || 'submit'; - html_options.value = name || 'Submit'; - return this.single_tag_for('input', html_options); - }, - /** - * @plugin view/helpers - * @param {Object} tag - * @param {Object} html_options - * @param {Object} end - */ - tag: function( tag, html_options, end ) { - end = end || '>'; - var txt = ' '; - for(var attr in html_options) { - if(html_options.hasOwnProperty(attr)){ - value = html_options[attr] != null ? html_options[attr].toString() : ''; - - if(attr == "Class" || attr == "klass") attr = "class"; - if( value.indexOf("'") != -1 ) - txt += attr+'=\"'+value+'\" ' ; - else - txt += attr+"='"+value+"' " ; - } - } - return '<'+tag+txt+end; - }, - /** - * @plugin view/helpers - * @param {Object} tag - */ - tag_end: function( tag ) { return ''; }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - text_area_tag: function( name, value, html_options ) { - html_options = html_options || {}; - html_options.id = html_options.id || name; - html_options.name = html_options.name || name; - value = value || ''; - if(html_options.size) { - html_options.cols = html_options.size.split('x')[0]; - html_options.rows = html_options.size.split('x')[1]; - delete html_options.size; - } - html_options.cols = html_options.cols || 50; - html_options.rows = html_options.rows || 4; - return this.start_tag_for('textarea', html_options)+value+this.tag_end('textarea'); - }, - /** - * @plugin view/helpers - * @param {Object} name - * @param {Object} value - * @param {Object} html_options - */ - text_field_tag: function( name, value, html_options ) { return this.input_field_tag(name, value, 'text', html_options); }, - /** - * @plugin view/helpers - * @param {Object} image_location - * @param {Object} options - */ - img_tag: function( image_location, options ) { - options = options || {}; - options.src = steal.config().root.join("resources/images/"+image_location)+''; - return this.single_tag_for('img', options); - } - -}); - -$.EJS.Helpers.prototype.text_tag = $.EJS.Helpers.prototype.text_area_tag; - -// Private variables (in the (function($){})(jQuery) scope) -var data = {}; -var name = 0; - -$.EJS.Helpers.link_data = function(store){ - var functionName = name++; - data[functionName] = store; - return "_data='"+functionName+"'"; -}; -$.EJS.Helpers.get_data = function(el){ - if(!el) return null; - var dataAt = el.getAttribute('_data'); - if(!dataAt) return null; - return data[parseInt(dataAt)]; -}; -$.EJS.Helpers.prototype.link_data = function(store){ - return $.EJS.Helpers.link_data(store) -}; -$.EJS.Helpers.prototype.get_data = function(el){ - return $.EJS.Helpers.get_data(el) -}; - -}); \ No newline at end of file diff --git a/view/jaml/jaml.js b/view/jaml/jaml.js deleted file mode 100644 index 65513ef4..00000000 --- a/view/jaml/jaml.js +++ /dev/null @@ -1,372 +0,0 @@ -steal("jquery/view").then(function(){ - - - -/** - * @class Jaml - * @plugin jquery/view/jaml - * @parent jQuery.View - * @author Ed Spencer (http://edspencer.net) - * Jaml is a simple JavaScript library which makes - * HTML generation easy and pleasurable. - * - * Instead of magic tags, Jaml is pure JS. It looks like: - * - * @codestart - * function(data) { - * h3(data.message); - * } - * @codeend - * - * Jaml is integrated into jQuery.View so you can use it like: - * - * @codestart - * $("#foo").html('//app/views/template.jaml',{}); - * @codeend - * - * ## Use - * - * For more info check out: - * - * - [http://edspencer.net/2009/11/jaml-beautiful-html-generation-for-javascript.html introduction] - * - [http://edspencer.github.com/jaml examples] - * - */ -Jaml = function() { - return { - templates: {}, - helpers : {}, - - /** - * Registers a template by name - * @param {String} name The name of the template - * @param {Function} template The template function - */ - register: function(name, template ) { - this.templates[name] = template; - }, - - /** - * Renders the given template name with an optional data object - * @param {String} name The name of the template to render - * @param {Object} data Optional data object - */ - render: function(name, data ) { - var template = this.templates[name], - renderer = new Jaml.Template(template); - - return renderer.render(data); - }, - - /** - * Registers a helper function - * @param {String} name The name of the helper - * @param {Function} helperFn The helper function - */ - registerHelper: function(name, helperFn ) { - this.helpers[name] = helperFn; - } - }; -}(); - - - -/** - * @class - * @constructor - * @param {String} tagName The tag name this node represents (e.g. 'p', 'div', etc) - */ -Jaml.Node = function(tagName) { - /** - * @attribute tagName - * @type String - * This node's current tag - */ - this.tagName = tagName; - - /** - * @attribute attributes - * @type Object - * Sets of attributes on this node (e.g. 'cls', 'id', etc) - */ - this.attributes = {}; - - /** - * @attribute children - * @type Array - * Array of rendered child nodes that will be steald as this node's innerHTML - */ - this.children = []; -}; - -Jaml.Node.prototype = { - /** - * Adds attributes to this node - * @param {Object} attrs Object containing key: value pairs of node attributes - */ - setAttributes: function(attrs ) { - for (var key in attrs) { - //convert cls to class - var mappedKey = key == 'cls' ? 'class' : key; - - this.attributes[mappedKey] = attrs[key]; - } - }, - - /** - * Adds a child string to this node. This can be called as often as needed to add children to a node - * @param {String} childText The text of the child node - */ - addChild: function(childText ) { - this.children.push(childText); - }, - - /** - * Renders this node with its attributes and children - * @param {Number} lpad Amount of whitespace to add to the left of the string (defaults to 0) - * @return {String} The rendered node - */ - render: function(lpad ) { - lpad = lpad || 0; - - var node = [], - attrs = [], - textnode = (this instanceof Jaml.TextNode), - multiline = this.multiLineTag(); - - for (var key in this.attributes) { - attrs.push(key + '=' + this.attributes[key]); - } - - //add any left padding - if (!textnode) node.push(this.getPadding(lpad)); - - //open the tag - node.push("<" + this.tagName); - - //add any tag attributes - for (var key in this.attributes) { - node.push(" " + key + "=\"" + this.attributes[key] + "\""); - } - - if (this.isSelfClosing()) { - node.push(" />\n"); - } else { - node.push(">"); - - if (multiline) node.push("\n"); - - for (var i=0; i < this.children.length; i++) { - node.push(this.children[i].render(lpad + 2)); - } - - if (multiline) node.push(this.getPadding(lpad)); - node.push("\n"); - } - - return node.join(""); - }, - - /** - * Returns true if this tag should be rendered with multiple newlines (e.g. if it contains child nodes) - * @return {Boolean} True to render this tag as multi-line - */ - multiLineTag: function() { - var childLength = this.children.length, - multiLine = childLength > 0; - - if (childLength == 1 && this.children[0] instanceof Jaml.TextNode) multiLine = false; - - return multiLine; - }, - - /** - * Returns a string with the given number of whitespace characters, suitable for padding - * @param {Number} amount The number of whitespace characters to add - * @return {String} A padding string - */ - getPadding: function(amount ) { - return new Array(amount + 1).join(" "); - }, - - /** - * Returns true if this tag should close itself (e.g. no element) - * @return {Boolean} True if this tag should close itself - */ - isSelfClosing: function() { - var selfClosing = false; - - for (var i = this.selfClosingTags.length - 1; i >= 0; i--){ - if (this.tagName == this.selfClosingTags[i]) selfClosing = true; - } - - return selfClosing; - }, - - /** - * @attribute selfClosingTags - * @type Array - * An array of all tags that should be self closing - */ - selfClosingTags: ['img', 'meta', 'br', 'hr'] -}; - -Jaml.TextNode = function(text) { - this.text = text; -}; - -Jaml.TextNode.prototype = { - render: function() { - return this.text; - } -}; - -/** - * Represents a single registered template. Templates consist of an arbitrary number - * of trees (e.g. there may be more than a single root node), and are not compiled. - * When a template is rendered its node structure is computed with any provided template - * data, culminating in one or more root nodes. The root node(s) are then joined together - * and returned as a single output string. - * - * The render process uses two dirty but necessary hacks. First, the template function is - * decompiled into a string (but is not modified), so that it can be eval'ed within the scope - * of Jaml.Template.prototype. This allows the second hack, which is the use of the 'with' keyword. - * This allows us to keep the pretty DSL-like syntax, though is not as efficient as it could be. - */ -Jaml.Template = function(tpl) { - /** - * @attribute tpl - * @type Function - * The function this template was created from - */ - this.tpl = tpl; - - this.nodes = []; -}; - -Jaml.Template.prototype = { - /** - * Renders this template given the supplied data - * @param {Object} data Optional data object - * @return {String} The rendered HTML string - */ - render: function(data ) { - data = data || {}; - - //the 'data' argument can come in two flavours - array or non-array. Normalise it - //here so that it always looks like an array. - if (data.constructor.toString().indexOf("Array") == -1) { - data = [data]; - } - - with(this) { - for (var i=0; i < data.length; i++) { - eval("(" + this.tpl.toString() + ")(data[i])"); - }; - } - - var roots = this.getRoots(), - output = ""; - - for (var i=0; i < roots.length; i++) { - output += roots[i].render(); - }; - - return output; - }, - - /** - * Returns all top-level (root) nodes in this template tree. - * Templates are tree structures, but there is no guarantee that there is a - * single root node (e.g. a single DOM element that all other elements nest within) - * @return {Array} The array of root nodes - */ - getRoots: function() { - var roots = []; - - for (var i=0; i < this.nodes.length; i++) { - var node = this.nodes[i]; - - if (node.parent == undefined) roots.push(node); - }; - - return roots; - }, - - tags: [ - "html", "head", "body", "script", "meta", "title", "link", "script", - "div", "p", "span", "a", "img", "br", "hr", - "table", "tr", "th", "td", "thead", "tbody", - "ul", "ol", "li", - "dl", "dt", "dd", - "h1", "h2", "h3", "h4", "h5", "h6", "h7", - "form", "input", "label" - ] -}; - -/** - * Adds a function for each tag onto Template's prototype - */ -(function() { - var tags = Jaml.Template.prototype.tags; - - for (var i = tags.length - 1; i >= 0; i--){ - var tagName = tags[i]; - - /** - * This function is created for each tag name and assigned to Template's - * prototype below - */ - var fn = function(tagName) { - return function(attrs) { - var node = new Jaml.Node(tagName); - - var firstArgIsAttributes = (typeof attrs == 'object') - && !(attrs instanceof Jaml.Node) - && !(attrs instanceof Jaml.TextNode); - - if (firstArgIsAttributes) node.setAttributes(attrs); - - var startIndex = firstArgIsAttributes ? 1 : 0; - - for (var i=startIndex; i < arguments.length; i++) { - var arg = arguments[i]; - - if (typeof arg == "string" || arg == undefined) { - arg = new Jaml.TextNode(arg || ""); - } - - if (arg instanceof Jaml.Node || arg instanceof Jaml.TextNode) { - arg.parent = node; - } - - node.addChild(arg); - }; - - this.nodes.push(node); - - return node; - }; - }; - - Jaml.Template.prototype[tagName] = fn(tagName); - }; -})(); - -$.View.register({ - suffix : "jaml", - script: function(id, str ) { - return "((function(){ Jaml.register("+id+", "+str+"); return function(data){return Jaml.render("+id+", data)} })())" - }, - renderer: function(id, text ) { - var func; - eval("func = ("+text+")"); - Jaml.register(id, func); - return function(data){ - return Jaml.render(id, data) - } - } -}) - - -}); \ No newline at end of file diff --git a/view/micro/micro.js b/view/micro/micro.js deleted file mode 100644 index c900bf5a..00000000 --- a/view/micro/micro.js +++ /dev/null @@ -1,3 +0,0 @@ -steal('jquery', 'jquery/view', 'can/view/micro', function($) { - return $; -}); diff --git a/view/pages/deferreds.md b/view/pages/deferreds.md deleted file mode 100644 index a65400bc..00000000 --- a/view/pages/deferreds.md +++ /dev/null @@ -1,73 +0,0 @@ -@page view.deferreds Using Deferreds with Views -@parent jQuery.View 1 - -jQuery 1.6 brought [http://api.jquery.com/category/deferred-object/ Deferred] support. They are a great feature that promise to make a lot of asynchronous functionality easier to write and manage. jQuery.View uses Deferreds to simplify a common but annoying task into a one-liner: loading data and a template and rendering the result into an element. - -## Templates Consume Deferreds - -Here's what rendering templates looks like with deferreds: - - $('#todos').html('temps/todos.ejs', $.get('/todos',{},'json') ); - -This will make two parallel ajax requests. One request -is made for the template at `temps/todos.ejs`: - -
                                                                                            <% for(var i =0; i < this.length; i++) { %>
                                                                                            -  <li><%= this[i].name %></li>
                                                                                            -<% } %>
                                                                                            -
                                                                                            - -The second request for `/todos` might respond with a JSON array: - - [ - {"id" : 1, "name": "Take out the Trash"}, - {"id" : 2, "name": "Do the Laundry"} - ] - -When both have been loaded, the template is rendered with the todos data. The resulting HTML is placed in the `#todos` element. - -This is fab fast! The AJAX and template request are made in parallel and rendered -when both are complete. Before deferreds, this was a lot uglier: - - var template, - data, - done = function(){ - if( template && data ) { - var html = new EJS({text: template}) - .render(data); - $('#todos').html( html ) - } - } - $.get('temps/todos.ejs', function(text){ - template = text; - done(); - },'text') - $.get('/todos',{}, function(json){ - data = json - done(); - },'json') - -## Models Return Deferreds - -Model AJAX functions now return deferreds. Creating models like: - - $.Model('User',{ - findAll: '/users' - },{}); - - $.Model('Todo',{ - findAll: '/todos' - },{}) - -Lets you request todos and users and get back a deferred that can be -used in functions that accept deferreds like $.when: - - $.when( User.findAll(), - Todo.findAll() ) - -Or $.View: - - $('#content').html('temps/content.ejs',{ - users : User.findAll(), - todos: Todo.findAll() - }) \ No newline at end of file diff --git a/view/qunit.html b/view/qunit.html deleted file mode 100644 index c8e18a46..00000000 --- a/view/qunit.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - -

                                                                                            view Test Suite

                                                                                            -

                                                                                            -
                                                                                            -

                                                                                            -
                                                                                            -
                                                                                              -
                                                                                              - - \ No newline at end of file diff --git a/view/test/compression/compression.html b/view/test/compression/compression.html deleted file mode 100644 index 4893e11a..00000000 --- a/view/test/compression/compression.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - compression - -
                                                                                              - - - \ No newline at end of file diff --git a/view/test/compression/compression.js b/view/test/compression/compression.js deleted file mode 100644 index 59901998..00000000 --- a/view/test/compression/compression.js +++ /dev/null @@ -1,13 +0,0 @@ -steal('jquery/view/ejs', 'jquery/view/tmpl') - .then('./views/relative.ejs', - 'jquery/view/test/compression/views/absolute.ejs', - './views/tmplTest.tmpl', - './views/test.ejs', - function(){ - - $(document).ready(function(){ - $("#target").append('//jquery/view/test/compression/views/relative.ejs', {}) - .append($.View('//jquery/view/test/compression/views/absolute.ejs', {} )) - .append($.View('//jquery/view/test/compression/views/tmplTest.tmpl', {message: "Jquery Tmpl"} )) - }) - }) diff --git a/view/test/compression/run.js b/view/test/compression/run.js deleted file mode 100644 index d3c7d20a..00000000 --- a/view/test/compression/run.js +++ /dev/null @@ -1,51 +0,0 @@ -// load('steal/compress/test/run.js') - -/** - * Tests compressing a very basic page and one that is using steal - */ - -load('steal/rhino/rhino.js') -steal('steal/test', function(s){ - - s.test.module("jquery/view/compression") - STEALPRINT = false; - - s.test.test("templates" , function(t){ - - - steal.File("jquery/view/test/compression/views/absolute.ejs").save("

                                                                                              Absolute

                                                                                              \n

                                                                                              ok

                                                                                              "); - steal.File("jquery/view/test/compression/views/relative.ejs").save("

                                                                                              Relative

                                                                                              "); - steal.File("jquery/view/test/compression/views/tmplTest.tmpl").save("

                                                                                              ${message}

                                                                                              "); - s.test.clear(); - - load("steal/rhino/rhino.js"); - steal('steal/build','steal/build/scripts',function(){ - steal.build('jquery/view/test/compression/compression.html',{to: 'jquery/view/test/compression'}); - }); - s.test.clear(); - s.test.remove("jquery/view/test/compression/views/absolute.ejs") - s.test.remove("jquery/view/test/compression/views/relative.ejs") - s.test.remove("jquery/view/test/compression/views/tmplTest.tmpl") - - - steal = {env: "production"}; - - s.test.open('jquery/view/test/compression/compression.html') - s.test.ok( /Relative/i.test( $(document.body).text() ), "Relative not in page!" ); - - s.test.ok( /Absolute/i.test( $(document.body).text() ), "Absolute not in page!" ); - - s.test.ok( /Jquery Tmpl/i.test( $(document.body).text() ), "Jquery Tmpl not in page!" ); - - s.test.clear(); - s.test.remove("jquery/view/test/compression/production.js") - - }) - - - - - - - -}); \ No newline at end of file diff --git a/view/test/compression/views/keep.me b/view/test/compression/views/keep.me deleted file mode 100644 index e69de29b..00000000 diff --git a/view/test/compression/views/test.ejs b/view/test/compression/views/test.ejs deleted file mode 100644 index dff991ff..00000000 --- a/view/test/compression/views/test.ejs +++ /dev/null @@ -1,3 +0,0 @@ -<%for(var i = 0; i < 5 ; i++){%> -
                                                                                            1. hi
                                                                                            2. -<%}%> \ No newline at end of file diff --git a/view/test/qunit/deferred.ejs b/view/test/qunit/deferred.ejs deleted file mode 100644 index 75a4bdd5..00000000 --- a/view/test/qunit/deferred.ejs +++ /dev/null @@ -1 +0,0 @@ -<%= foo %> \ No newline at end of file diff --git a/view/test/qunit/deferreds.ejs b/view/test/qunit/deferreds.ejs deleted file mode 100644 index 884157f5..00000000 --- a/view/test/qunit/deferreds.ejs +++ /dev/null @@ -1 +0,0 @@ -<%= foo %> and <%= bar %> \ No newline at end of file diff --git a/view/test/qunit/hookup.ejs b/view/test/qunit/hookup.ejs deleted file mode 100644 index ab7cb687..00000000 --- a/view/test/qunit/hookup.ejs +++ /dev/null @@ -1 +0,0 @@ -
                                                                                              <%= function(){} %> /> \ No newline at end of file diff --git a/view/test/qunit/hookupvalcall.ejs b/view/test/qunit/hookupvalcall.ejs deleted file mode 100644 index 7e0a8d49..00000000 --- a/view/test/qunit/hookupvalcall.ejs +++ /dev/null @@ -1,4 +0,0 @@ - -
                                                                                              <%= function(){}%>>
                                                                                              \ No newline at end of file diff --git a/view/test/qunit/large.ejs b/view/test/qunit/large.ejs deleted file mode 100644 index 75636104..00000000 --- a/view/test/qunit/large.ejs +++ /dev/null @@ -1,373 +0,0 @@ - - -

                                                                                              Complex JavaScript applications are mostly about making it easy to create, -read, update, and delete (CRUD) data. But being so close to the UI, -most JavaScript developers ignore the data layer and focus on -making animated drag-drop effects. -

                                                                                              -

                                                                                              We're doing ourselves a disservice! A strong Model layer can make an architecture infinitely more robust, reusable, and maintainable. -

                                                                                              -

                                                                                              JavaScriptMVC's model layer is designed to be as flexible and lightweight as possible. - The remainder of this article highlights the features of jQuery.Model, - how to use them, and why they are important. -

                                                                                              -

                                                                                              Downloads

                                                                                              - -

                                                                                              Features

                                                                                              -
                                                                                                -
                                                                                              • Service / Ajax encapsulation
                                                                                              • -
                                                                                              • Type Conversion
                                                                                              • -
                                                                                              • Data Helper Methods
                                                                                              • -
                                                                                              • DOM Helper Functions
                                                                                              • -
                                                                                              • Events and Propety Binding
                                                                                              • -
                                                                                              • Lists
                                                                                              • -
                                                                                              • Local Storage
                                                                                              • -
                                                                                              • Associations
                                                                                              • -
                                                                                              • Backup / Restore
                                                                                              • -
                                                                                              • Validations
                                                                                              • -
                                                                                              - - -

                                                                                              Service / Ajax Encapsulation

                                                                                              - -

                                                                                              Models encapsulate your application's raw data. -The majority of the time, the raw data comes from services your server provides. For example, if you make a request to: -

                                                                                              -
                                                                                              GET /contacts.json
                                                                                              -

                                                                                              -The server might return something like: -

                                                                                              -
                                                                                              
                                                                                              -[{
                                                                                              -  'id': 1,
                                                                                              -  'name' : 'Justin Meyer',
                                                                                              -  'birthday': '1982-10-20'
                                                                                              -},
                                                                                              -{
                                                                                              -  'id': 2,
                                                                                              -  'name' : 'Brian Moschel',
                                                                                              -  'birthday': '1983-11-10'
                                                                                              -}]
                                                                                              -

                                                                                              -In most jQuery code, you'll see something like the following to retrieve contacts -data: -

                                                                                              -
                                                                                              
                                                                                              -$.get('/contacts.json',
                                                                                              -      {type: 'tasty'}, 
                                                                                              -      successCallback,
                                                                                              -      'json')
                                                                                              -

                                                                                              -Instead, model encapsulates (wraps) this request so you call it like: -

                                                                                              -
                                                                                              
                                                                                              -Contact.findAll({type: 'old'}, successCallback);
                                                                                              -
                                                                                              -

                                                                                              -This might seem like unnecessary overhead, but by encapsulating your -application's data, your application benefits in two significant ways: -

                                                                                              - -

                                                                                              Benefit 1: Localized Changes

                                                                                              - - -

                                                                                              -Over the development lifecycle of an application, is very likely that -your services will change. Models help localize your application's use of -services to a single (TESTABLE!) location. -

                                                                                              - -

                                                                                              Benefit 2: Normalized Service Requests

                                                                                              - -

                                                                                              -Complex widgets, like Grids and Trees, need to make Ajax requests to operate correctly. Often these widgets need to be configured by a variety of options and callbacks. There's no uniformity, and sometimes you have to change your service to match the needs of the widget. -

                                                                                              -

                                                                                              -Instead, models normalize how widgets access your services, making it easy to use -different models for the same widget. -

                                                                                              -

                                                                                              Encapsulation Demo

                                                                                              - -

                                                                                              The encapsulation demo shows using two different models with the same widget.

                                                                                              -

                                                                                              How to Encapsulate

                                                                                              -

                                                                                              -Think of models as a contract for creating, reading, updating, and deleting data. -By filling out a model, you can pass that model to a widget and the -widget will use the model as a proxy for your data. -

                                                                                              -

                                                                                              -The following chart shows the methods most models provide: -

                                                                                              - - - - - - - - - - - - - -
                                                                                              Create
                                                                                              Contact.create(attrs, success, error
                                                                                              Read
                                                                                              Contact.findAll(params,success,error)
                                                                                              -Contact.findOne(params, success, error)
                                                                                              Update
                                                                                              Contact.update(id, attrs, success, error)
                                                                                              Delete
                                                                                              Contact.destroy(id, success, error)
                                                                                              -

                                                                                              By filling out these methods, you get the benefits of encapsulation, -AND all the other magic Model provides. Lets see how we might fill out the -Contact.findAll function:

                                                                                              -
                                                                                              $.Model.extend('Contact',
                                                                                              -{
                                                                                              -  findAll : function(params, success, error){
                                                                                              -  
                                                                                              -    // do the ajax request
                                                                                              -    $.get('/contacts.json',
                                                                                              -      params, 
                                                                                              -      function( json ){ 
                                                                                              -        
                                                                                              -        // on success, create new Contact
                                                                                              -        // instances for each contact
                                                                                              -        var wrapped = [];
                                                                                              -        
                                                                                              -        for(var i =0; i< json.length;i++){
                                                                                              -          wrapped.push( new Contact(json[i] ) );
                                                                                              -        }
                                                                                              -        
                                                                                              -        //call success with the contacts
                                                                                              -        success( wrapped );
                                                                                              -        
                                                                                              -      },
                                                                                              -      'json');
                                                                                              -  }
                                                                                              -},
                                                                                              -{
                                                                                              -  // Prototype properties of Contact.
                                                                                              -  // We'll learn about this soon!
                                                                                              -});
                                                                                              - -

                                                                                              Well, that would be annoying to write out every time. Fortunately, -models have -the wrapMany method which will make it easier:

                                                                                              -
                                                                                                findAll : function(params, success, error){
                                                                                              -    $.get('/contacts.json',
                                                                                              -      params, 
                                                                                              -      function( json ){ 
                                                                                              -        success(Contact.wrapMany(json));		
                                                                                              -      },
                                                                                              -      'json');
                                                                                              -  }
                                                                                              -
                                                                                              -

                                                                                              Model is based off JavaScriptMVC's -jQuery.Class. It's -callback method allows us to pipe -wrapMany into the success handler and make our code even shorter:

                                                                                              -
                                                                                                findAll : function(params, success, error){
                                                                                              -    $.get('/contacts.json',
                                                                                              -    params, 
                                                                                              -    this.proxy(['wrapMany', success]),
                                                                                              -    'json')
                                                                                              -  }
                                                                                              -
                                                                                              -

                                                                                              If we wanted to make a list of contacts, we could do it like:

                                                                                              -
                                                                                              Contact.findAll({},function(contacts){
                                                                                              -  var html = [];
                                                                                              -  for(var i =0; i < contacts.length; i++){
                                                                                              -    html.push('<li>'+contacts[i].name + '</li>')
                                                                                              -  }
                                                                                              -  $('#contacts').html( html.join('') );
                                                                                              -});
                                                                                              -

                                                                                              Read JavaScriptMVC's - encapsulation documentation on how to fill out the other CRUD methods -of the CRUD-Contract. Once this is done, you'll get all the following magic.

                                                                                              -

                                                                                              Type Conversion

                                                                                              -

                                                                                              By creating instances of Contact with the data from the server, it -lets us wrap and manipulate the data into a more usable format. -

                                                                                              -

                                                                                              - You notice that the server sends back Contact birthdays like: - '1982-10-20'. - A string representation of dates - is not terribly convient. - We can use our model to convert it to something closer to - new Date(1982,10,20). We can do this in two ways: - -

                                                                                              - -

                                                                                              Way 1: Setters

                                                                                              -

                                                                                              In our Contact model, we can add a setBirthday method -that will convert the raw -data passed from the server to a -format more useful for JavaScript:

                                                                                              -
                                                                                              $.Model.extend("Contact",
                                                                                              -{
                                                                                              -  findAll : function( ... ){ ... }
                                                                                              -},
                                                                                              -{
                                                                                              -  setBirthday : function(raw){
                                                                                              -    if(typeof raw == 'string'){
                                                                                              -      var matches = raw.match(/(\d+)-(\d+)-(\d+)/)
                                                                                              -      return new Date( matches[1], 
                                                                                              -                      (+matches[2])-1, 
                                                                                              -                       matches[3] )
                                                                                              -    }else if(raw instanceof Date){
                                                                                              -      return raw;
                                                                                              -    }
                                                                                              -  }
                                                                                              -})
                                                                                              -

                                                                                              The setBirthday setter function takes the -raw string date, parses it returns the JavaScript friendly -date.

                                                                                              -

                                                                                              Way 2: Attributes and Converters

                                                                                              -

                                                                                              If you have a lot of dates, Setters won't scale well. Instead, you can -set the type of an attribute and provide a function to convert that type.

                                                                                              -

                                                                                              The following sets the birthday attribute to "date" and provides a date -conversion function:

                                                                                              -
                                                                                              $.Model.extend("Contact",
                                                                                              -{
                                                                                              -  attributes : { 
                                                                                              -    birthday : 'date'
                                                                                              -  },
                                                                                              -  convert : {
                                                                                              -    date : function(raw){
                                                                                              -      if(typeof raw == 'string'){
                                                                                              -        var matches = raw.match(/(\d+)-(\d+)-(\d+)/)
                                                                                              -        return new Date( matches[1], 
                                                                                              -                        (+matches[2])-1, 
                                                                                              -                         matches[3] )
                                                                                              -      }else if(raw instanceof Date){
                                                                                              -        return raw;
                                                                                              -      }
                                                                                              -    }
                                                                                              -  },
                                                                                              -  findAll : function( ... ){ ... }
                                                                                              -},
                                                                                              -{
                                                                                              -  // No prototype properties necessary
                                                                                              -})
                                                                                              -

                                                                                              This technique uses a Model's - - attributes and - - convert properties.

                                                                                              - -

                                                                                              Now our recipe instances will have a nice Date -birthday property. -We can use it to list how old each person will be this year: - -

                                                                                              -
                                                                                              
                                                                                              -var age = function(birthday){
                                                                                              -   return new Date().getFullYear() - 
                                                                                              -          birthday.getFullYear()
                                                                                              -}
                                                                                              -
                                                                                              -Contact.findAll({},function(contacts){
                                                                                              -  var html = [];
                                                                                              -  for(var i =0; i < contacts.length; i++){
                                                                                              -    html.push('<li>'+age(contacts[i].birthday) + '</li>')
                                                                                              -  }
                                                                                              -  $('#contacts').html( html.join('') );
                                                                                              -});
                                                                                              -

                                                                                              But what if some other code wants to use age? Well, they'll have to use ...

                                                                                              - -

                                                                                              Data Helper Methods

                                                                                              - - - -

                                                                                              You can add domain specific helper methods to your models. The following adds -ageThisYear to contact instances:

                                                                                              -
                                                                                              $.Model.extend("Contact",
                                                                                              -{
                                                                                              -  attributes : { ... },
                                                                                              -  convert : { ... },
                                                                                              -  findAll : function( ... ){ ... }
                                                                                              -},
                                                                                              -{
                                                                                              -  ageThisYear : function(){
                                                                                              -    return new Date().getFullYear() - 
                                                                                              -          this.birthday.getFullYear()
                                                                                              -  }
                                                                                              -})
                                                                                              -

                                                                                              Now we can write out the ages a little cleaner:

                                                                                              -
                                                                                              Contact.findAll({},function(contacts){
                                                                                              -  var html = [];
                                                                                              -  for(var i =0; i < contacts.length; i++){
                                                                                              -    html.push('<li>'+ contacts[i].ageThisYear() + '</li>')
                                                                                              -  }
                                                                                              -  $('#contacts').html( html.join('') );
                                                                                              -});
                                                                                              - -

                                                                                              Now that we are showing contacts on the page, lets do something with them. - First, we'll need a way to get back our models from the page. For this we'll use ... -

                                                                                              - -

                                                                                              DOM Helper Functions

                                                                                              -

                                                                                              It's common practice with jQuery to put additional data 'on' html elements -with -jQuery.data. -It's a great technique because you can remove the elements -and jQuery will clean the data (letting the Garbage Collector do its work). -

                                                                                              -

                                                                                              Model supports something similar with the -model and models helpers. -They let us set and retrieve model instances on elements. -

                                                                                              -

                                                                                              For example, lets say we wanted to let developer delete contacts like -in the - Model DOM Demo.

                                                                                              -

                                                                                              First, we'll add a DELETE link like:

                                                                                              -
                                                                                              Contact.findAll({},function(contacts){
                                                                                              -  var contactsEl = $('#contacts');
                                                                                              -  for(var i =0; i < contacts.length; i++){
                                                                                              -   $('<li>').model(contacts[i])
                                                                                              -            .html(contacts[i].ageThisYear()+
                                                                                              -                  " <a>DELETE</a>")
                                                                                              -            .appendTo(contactsEl)
                                                                                              -  }
                                                                                              -});
                                                                                              -

                                                                                              When a model is added to an element's data, it also adds it's name a unique -identifier to the element. For example, the first li element -will look like:

                                                                                              -
                                                                                              <li class='contact contact_5'> ... </li>
                                                                                              -

                                                                                              When someone clicks on DELETE, we want to remove that contact. -We implement it like:

                                                                                              -
                                                                                              $("#contacts a").live('click', function(){
                                                                                              -  //get the element for this recipe
                                                                                              -  var contactEl = $(this).closest('.contact')
                                                                                              -  
                                                                                              -  // get the conctact instance
                                                                                              -  contactEl.model()
                                                                                              -           // call destroy on the instance
                                                                                              -           .destroy(function(){
                                                                                              -                      // remove the element
                                                                                              -                      contactEl.remove();
                                                                                              -                    })
                                                                                              -		  
                                                                                              -})
                                                                                              -

                                                                                              This assumes we've filled out Contact.destroy. -

                                                                                              -

                                                                                              There's one more very useful DOM helper: contact.elements(). -Elements returns the elements that -have a particular model instance. -We'll see how this helps us in the next section. -

                                                                                              - - -

                                                                                              Events

                                                                                              -

                                                                                              Consider the case where we have two representations of the -same recipe data on the page. Maybe when we click a contact, -we show additional information on the page, like an input to change the -contact's birthday. -

                                                                                              -

                                                                                              See this in action in the events demo.

                                                                                              -

                                                                                              When the birthday is updated, we want the list's contact -display to also update it's age. Model provides two ways of doing this.

                                                                                              \ No newline at end of file diff --git a/view/test/qunit/nested_plugin.ejs b/view/test/qunit/nested_plugin.ejs deleted file mode 100644 index 4895410b..00000000 --- a/view/test/qunit/nested_plugin.ejs +++ /dev/null @@ -1 +0,0 @@ -
                                                                                              <%=plugin("text", "Here is something")%> id='something'>
                                                                                              \ No newline at end of file diff --git a/view/test/qunit/plugin.ejs b/view/test/qunit/plugin.ejs deleted file mode 100644 index a9ab605f..00000000 --- a/view/test/qunit/plugin.ejs +++ /dev/null @@ -1 +0,0 @@ -
                                                                                              <%=plugin("html", "Here is something")%> id='something'>
                                                                                              \ No newline at end of file diff --git a/view/test/qunit/qunit.js b/view/test/qunit/qunit.js deleted file mode 100644 index 84f2493f..00000000 --- a/view/test/qunit/qunit.js +++ /dev/null @@ -1,8 +0,0 @@ -//we probably have to have this only describing where the tests are -steal("jquery/view", - "can/view/micro", - "can/view/ejs", - "can/view/jaml", - "can/view/tmpl") //load your app - .then('funcunit/qunit') //load qunit - .then("./view_test.js"); \ No newline at end of file diff --git a/view/test/qunit/temp.ejs b/view/test/qunit/temp.ejs deleted file mode 100644 index 01caddd7..00000000 --- a/view/test/qunit/temp.ejs +++ /dev/null @@ -1 +0,0 @@ -

                                                                                              <%= message %>

                                                                                              diff --git a/view/test/qunit/template.ejs b/view/test/qunit/template.ejs deleted file mode 100644 index 01caddd7..00000000 --- a/view/test/qunit/template.ejs +++ /dev/null @@ -1 +0,0 @@ -

                                                                                              <%= message %>

                                                                                              diff --git a/view/test/qunit/template.jaml b/view/test/qunit/template.jaml deleted file mode 100644 index 2b75f22f..00000000 --- a/view/test/qunit/template.jaml +++ /dev/null @@ -1,3 +0,0 @@ -function(data) { - h3(data.message); -} \ No newline at end of file diff --git a/view/test/qunit/template.micro b/view/test/qunit/template.micro deleted file mode 100644 index 16fa3525..00000000 --- a/view/test/qunit/template.micro +++ /dev/null @@ -1 +0,0 @@ -

                                                                                              {%= message %}

                                                                                              diff --git a/view/test/qunit/template.tmpl b/view/test/qunit/template.tmpl deleted file mode 100644 index 0b02edfa..00000000 --- a/view/test/qunit/template.tmpl +++ /dev/null @@ -1 +0,0 @@ -

                                                                                              ${message}

                                                                                              \ No newline at end of file diff --git a/view/test/qunit/view_test.js b/view/test/qunit/view_test.js deleted file mode 100644 index 92de92f3..00000000 --- a/view/test/qunit/view_test.js +++ /dev/null @@ -1,168 +0,0 @@ - -module("jquery/view"); - - - - -test("multiple template types work", function(){ - - $.each(["micro","ejs","jaml", "tmpl"], function(){ - $("#qunit-test-area").html(""); - ok($("#qunit-test-area").children().length == 0,this+ ": Empty To Start") - - $("#qunit-test-area").html("//jquery/view/test/qunit/template."+this,{"message" :"helloworld"}) - ok($("#qunit-test-area").find('h3').length, this+": h3 written for ") - ok( /helloworld\s*/.test( $("#qunit-test-area").text()), this+": hello world present for ") - }) -}) - - - -test("async templates, and caching work", function(){ - $("#qunit-test-area").html(""); - stop(); - var i = 0; - $("#qunit-test-area").html("//jquery/view/test/qunit/temp.ejs",{"message" :"helloworld"}, function(text){ - ok( /helloworld\s*/.test( $("#qunit-test-area").text())) - ok(/helloworld\s*/.test(text), "we got a rendered template"); - i++; - equals(i, 2, "Ajax is not synchronous"); - equals(this.attr("id"), "qunit-test-area" ) - start(); - }); - i++; - equals(i, 1, "Ajax is not synchronous") -}) -test("caching works", function(){ - // this basically does a large ajax request and makes sure - // that the second time is always faster - $("#qunit-test-area").html(""); - stop(); - var startT = new Date(), - first; - $("#qunit-test-area").html("//jquery/view/test/qunit/large.ejs",{"message" :"helloworld"}, function(text){ - first = new Date(); - ok(text, "we got a rendered template"); - - - $("#qunit-test-area").html(""); - $("#qunit-test-area").html("//jquery/view/test/qunit/large.ejs",{"message" :"helloworld"}, function(text){ - var lap2 = (new Date()) - first, - lap1 = first-startT; - // ok( lap1 > lap2, "faster this time "+(lap1 - lap2) ) - - start(); - $("#qunit-test-area").html(""); - }) - - }) -}) -test("hookup", function(){ - $("#qunit-test-area").html(""); - - $("#qunit-test-area").html("//jquery/view/test/qunit/hookup.ejs",{}); //makes sure no error happens -}) - -test("inline templates other than 'tmpl' like ejs", function(){ - $("#qunit-test-area").html(""); - - $("#qunit-test-area").html($('')); - - $("#qunit-test-area").html('test_ejs', {name: 'Henry'}); - equal( $("#new_name").text(), 'Henry'); - $("#qunit-test-area").html(""); -}); - -test("object of deferreds", function(){ - var foo = $.Deferred(), - bar = $.Deferred(); - stop(); - $.View("//jquery/view/test/qunit/deferreds.ejs",{ - foo : foo.promise(), - bar : bar - }).then(function(result){ - ok(result, "FOO and BAR"); - start(); - }); - setTimeout(function(){ - foo.resolve("FOO"); - },100); - bar.resolve("BAR"); - -}); - -test("deferred", function(){ - var foo = $.Deferred(); - stop(); - $.View("//jquery/view/test/qunit/deferred.ejs",foo).then(function(result){ - ok(result, "FOO"); - start(); - }); - setTimeout(function(){ - foo.resolve({ - foo: "FOO" - }); - },100); - -}); - - -test("modifier with a deferred", function(){ - $("#qunit-test-area").html(""); - stop(); - - var foo = $.Deferred(); - $("#qunit-test-area").html("//jquery/view/test/qunit/deferred.ejs", foo ); - setTimeout(function(){ - foo.resolve({ - foo: "FOO" - }); - start(); - equals($("#qunit-test-area").html(), "FOO", "worked!"); - },100); - -}); - -test("jQuery.fn.hookup", function(){ - $("#qunit-test-area").html(""); - var els = $($.View("//jquery/view/test/qunit/hookup.ejs",{})).hookup(); - $("#qunit-test-area").html(els); //makes sure no error happens -}); - -test("non-HTML content in hookups", function(){ - $("#qunit-test-area").html(""); - $.View.hookup(function(){}); - $("#qunit-test-area textarea").val("asdf"); - equals($("#qunit-test-area textarea").val(), "asdf"); -}); - -test("html takes promise", function(){ - var d = $.Deferred(); - $("#qunit-test-area").html(d); - stop(); - d.done(function(){ - equals($("#qunit-test-area").html(), "Hello World", "deferred is working"); - start(); - }) - setTimeout(function(){ - d.resolve("Hello World") - },10) -}); - -test("val set with a template within a hookup within another template", function(){ - $("#qunit-test-area").html("//jquery/view/test/qunit/hookupvalcall.ejs",{}); -}) - -/*test("bad url", function(){ - $.View("//asfdsaf/sadf.ejs") -});*/ - -test("hyphen in type", function(){ - $(document.body).append("") - - $("#qunit-test-area").html('hyphenEjs',{}); - - ok( /Hyphen/.test( $("#qunit-test-area").html() ), "has hyphen" ); -}) - - diff --git a/view/tmpl/test.tmpl b/view/tmpl/test.tmpl deleted file mode 100644 index f06c7690..00000000 --- a/view/tmpl/test.tmpl +++ /dev/null @@ -1 +0,0 @@ -{{if 1}}

                                                                                              Hello World

                                                                                              {{/if}} \ No newline at end of file diff --git a/view/tmpl/tmpl.js b/view/tmpl/tmpl.js deleted file mode 100644 index 393279ea..00000000 --- a/view/tmpl/tmpl.js +++ /dev/null @@ -1,523 +0,0 @@ -// jQuery Templates Plugin -// http://github.com/jquery/jquery-tmpl -// -// Copyright Software Freedom Conservancy, Inc. -// Dual licensed under the MIT or GPL Version 2 licenses. -// http://$.org/license - -/** - * @class $.tmpl - * @parent $.View - * @plugin jquery/view/tmpl - * Provides basic templating with magic tags that look like: - * @codestart - * ${value} - * @codeend - * [$.View] integrates $.tmpl templates into - * your build process. You can use a $.tmpl like: - * - * @codestart - * $('#area').html('//path/to/template.tmpl',{ data }); - * @codeend - * - * For more information on $.tmpl read - * [http://api.$.com/category/plugins/templates/ it's documentation]. - */ -steal('jquery', 'can/util', 'jquery/view').then(function($, can){ - // Override the DOM manipulation function - var oldManip = $.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /, - newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = []; - - function newTmplItem( options, parentItem, fn, data ) { - // Returns a template item data structure for a new rendered instance of a template (a 'template item'). - // The content field is a hierarchical array of strings and nested items (to be - // removed and replaced by nodes field of dom elements, once inserted in DOM). - var newItem = { - data: data || (parentItem ? parentItem.data : {}), - _wrap: parentItem ? parentItem._wrap : null, - tmpl: null, - parent: parentItem || null, - nodes: [], - calls: tiCalls, - nest: tiNest, - wrap: tiWrap, - html: tiHtml, - update: tiUpdate - }; - if ( options ) { - $.extend( newItem, options, { nodes: [], parent: parentItem } ); - } - if ( fn ) { - // Build the hierarchical content to be used during insertion into DOM - newItem.tmpl = fn; - newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem ); - newItem.key = ++itemKey; - // Keep track of new template item, until it is stored as jQuery Data on DOM element - (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem; - } - return newItem; - } - - // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core). - $.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" - }, function( name, original ) { - $.fn[ name ] = function( selector ) { - var ret = [], insert = jQuery( selector ), elems, i, l, tmplItems, - parent = this.length === 1 && this[0].parentNode; - - appendToTmplItems = newTmplItems || {}; - if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) { - insert[ original ]( this[0] ); - ret = this; - } else { - for ( i = 0, l = insert.length; i < l; i++ ) { - cloneIndex = i; - elems = (i > 0 ? this.clone(true) : this).get(); - $.fn[ original ].apply( jQuery(insert[i]), elems ); - ret = ret.concat( elems ); - } - cloneIndex = 0; - ret = this.pushStack( ret, name, insert.selector ); - } - tmplItems = appendToTmplItems; - appendToTmplItems = null; - $.tmpl.complete( tmplItems ); - return ret; - }; - }); - - $.fn.extend({ - // Use first wrapped element as template markup. - // Return wrapped set of template items, obtained by rendering template against data. - tmpl: function( data, options, parentItem ) { - return $.tmpl( this[0], data, options, parentItem ); - }, - - // Find which rendered template item the first wrapped DOM element belongs to - tmplItem: function() { - return $.tmplItem( this[0] ); - }, - - // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template. - template: function( name ) { - return $.template( name, this[0] ); - }, - - domManip: function( args, table, callback, options ) { - // This appears to be a bug in the appendTo, etc. implementation - // it should be doing .call() instead of .apply(). See #6227 - if ( args[0] && args[0].nodeType ) { - var dmArgs = $.makeArray( arguments ), argsLength = args.length, i = 0, tmplItem; - while ( i < argsLength && !(tmplItem = $.data( args[i++], "tmplItem" ))) {} - if ( argsLength > 1 ) { - dmArgs[0] = [$.makeArray( args )]; - } - if ( tmplItem && cloneIndex ) { - dmArgs[2] = function( fragClone ) { - // Handler called by oldManip when rendered template has been inserted into DOM. - $.tmpl.afterManip( this, fragClone, callback ); - }; - } - oldManip.apply( this, dmArgs ); - } else { - oldManip.apply( this, arguments ); - } - cloneIndex = 0; - if ( !appendToTmplItems ) { - $.tmpl.complete( newTmplItems ); - } - return this; - } - }); - - $.extend({ - // Return wrapped set of template items, obtained by rendering template against data. - tmpl: function( tmpl, data, options, parentItem ) { - var ret, topLevel = !parentItem; - if ( topLevel ) { - // This is a top-level tmpl call (not from a nested template using {{tmpl}}) - parentItem = topTmplItem; - tmpl = $.template[tmpl] || $.template( null, tmpl ); - wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level - } else if ( !tmpl ) { - // The template item is already associated with DOM - this is a refresh. - // Re-evaluate rendered template for the parentItem - tmpl = parentItem.tmpl; - newTmplItems[parentItem.key] = parentItem; - parentItem.nodes = []; - if ( parentItem.wrapped ) { - updateWrapped( parentItem, parentItem.wrapped ); - } - // Rebuild, without creating a new template item - return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) )); - } - if ( !tmpl ) { - return []; // Could throw... - } - if ( typeof data === "function" ) { - data = data.call( parentItem || {} ); - } - if ( options && options.wrapped ) { - updateWrapped( options, options.wrapped ); - } - ret = $.isArray( data ) ? - $.map( data, function( dataItem ) { - return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null; - }) : - [ newTmplItem( options, parentItem, tmpl, data ) ]; - return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret; - }, - - // Return rendered template item for an element. - tmplItem: function( elem ) { - var tmplItem; - if ( elem instanceof jQuery ) { - elem = elem[0]; - } - while ( elem && elem.nodeType === 1 && !(tmplItem = $.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {} - return tmplItem || topTmplItem; - }, - - // Set: - // Use $.template( name, tmpl ) to cache a named template, - // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc. - // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration. - - // Get: - // Use $.template( name ) to access a cached template. - // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString ) - // will return the compiled template, without adding a name reference. - // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent - // to $.template( null, templateString ) - template: function( name, tmpl ) { - if (tmpl) { - // Compile template and associate with name - if ( typeof tmpl === "string" ) { - // This is an HTML string being passed directly in. - tmpl = buildTmplFn( tmpl ) - } else if ( tmpl instanceof jQuery ) { - tmpl = tmpl[0] || {}; - } - if ( tmpl.nodeType ) { - // If this is a template block, use cached copy, or generate tmpl function and cache. - tmpl = $.data( tmpl, "tmpl" ) || $.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); - } - return typeof name === "string" ? ($.template[name] = tmpl) : tmpl; - } - // Return named compiled template - return name ? (typeof name !== "string" ? $.template( null, name ): - ($.template[name] || - // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) - $.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; - }, - - encode: function( text ) { - // Do HTML encoding replacing < > & and ' and " by corresponding entities. - return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'"); - } - }); - - $.extend( $.tmpl, { - tag: { - "tmpl": { - _default: { $2: "null" }, - open: "if($notnull_1){_=_.concat($item.nest($1,$2));}" - // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions) - // This means that {{tmpl foo}} treats foo as a template (which IS a function). - // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}. - }, - "wrap": { - _default: { $2: "null" }, - open: "$item.calls(_,$1,$2);_=[];", - close: "call=$item.calls();_=call._.concat($item.wrap(call,_));" - }, - "each": { - _default: { $2: "$index, $value" }, - open: "if($notnull_1){$.each($1a,function($2){with(this){", - close: "}});}" - }, - "if": { - open: "if(($notnull_1) && $1a){", - close: "}" - }, - "else": { - _default: { $1: "true" }, - open: "}else if(($notnull_1) && $1a){" - }, - "html": { - // Unecoded expression evaluation. - open: "if($notnull_1){_.push($1a);}" - }, - "=": { - // Encoded expression evaluation. Abbreviated form is ${}. - _default: { $1: "$data" }, - open: "if($notnull_1){_.push($.encode($1a));}" - }, - "!": { - // Comment tag. Skipped by parser - open: "" - } - }, - - // This stub can be overridden, e.g. in $.tmplPlus for providing rendered events - complete: function( items ) { - newTmplItems = {}; - }, - - // Call this from code which overrides domManip, or equivalent - // Manage cloning/storing template items etc. - afterManip: function afterManip( elem, fragClone, callback ) { - // Provides cloned fragment ready for fixup prior to and after insertion into DOM - var content = fragClone.nodeType === 11 ? - $.makeArray(fragClone.childNodes) : - fragClone.nodeType === 1 ? [fragClone] : []; - - // Return fragment to original caller (e.g. append) for DOM insertion - callback.call( elem, fragClone ); - - // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by $.data. - storeTmplItems( content ); - cloneIndex++; - } - }); - - //========================== Private helper functions, used by code above ========================== - - function build( tmplItem, nested, content ) { - // Convert hierarchical content into flat string array - // and finally return array of fragments ready for DOM insertion - var frag, ret = content ? $.map( content, function( item ) { - return (typeof item === "string") ? - // Insert template item annotations, to be converted to $.data( "tmplItem" ) when elems are inserted into DOM. - (tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) : - // This is a child template item. Build nested template. - build( item, tmplItem, item._ctnt ); - }) : - // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. - tmplItem; - if ( nested ) { - return ret; - } - - // top-level template - ret = ret.join(""); - - // Support templates which have initial or final text nodes, or consist only of text - // Also support HTML entities within the HTML markup. - ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) { - frag = jQuery( middle ).get(); - - storeTmplItems( frag ); - if ( before ) { - frag = unencode( before ).concat(frag); - } - if ( after ) { - frag = frag.concat(unencode( after )); - } - }); - return frag ? frag : unencode( ret ); - } - - function unencode( text ) { - // Use createElement, since createTextNode will not render HTML entities correctly - var el = document.createElement( "div" ); - el.innerHTML = text; - return $.makeArray(el.childNodes); - } - - // Generate a reusable function that will serve to render a template against data - function buildTmplFn( markup ) { - return new Function("jQuery","$item", - "var $=jQuery,call,_=[],$data=$item.data;" + - - // Introduce the data as local variables using with(){} - "with($data){_.push('" + - - // Convert the template into pure JavaScript - $.trim(markup) - .replace( /([\\'])/g, "\\$1" ) - .replace( /[\r\t\n]/g, " " ) - .replace( /\$\{([^\}]*)\}/g, "{{= $1}}" ) - .replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g, - function( all, slash, type, fnargs, target, parens, args ) { - var tag = $.tmpl.tag[ type ], def, expr, exprAutoFnDetect; - if ( !tag ) { - throw "Template command not found: " + type; - } - def = tag._default || []; - if ( parens && !/\w$/.test(target)) { - target += parens; - parens = ""; - } - if ( target ) { - target = unescape( target ); - args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : ""); - // Support for target being things like a.toLowerCase(); - // In that case don't call with template item as 'this' pointer. Just evaluate... - expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target; - exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))"; - } else { - exprAutoFnDetect = expr = def.$1 || "null"; - } - fnargs = unescape( fnargs ); - return "');" + - tag[ slash ? "close" : "open" ] - .split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" ) - .split( "$1a" ).join( exprAutoFnDetect ) - .split( "$1" ).join( expr ) - .split( "$2" ).join( fnargs ? - fnargs.replace( /\s*([^\(]+)\s*(\((.*?)\))?/g, function( all, name, parens, params ) { - params = params ? ("," + params + ")") : (parens ? ")" : ""); - return params ? ("(" + name + ").call($item" + params) : all; - }) - : (def.$2||"") - ) + - "_.push('"; - }) + - "');}return _;" - ); - } - function updateWrapped( options, wrapped ) { - // Build the wrapped content. - options._wrap = build( options, true, - // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string. - $.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()] - ).join(""); - } - - function unescape( args ) { - return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null; - } - function outerHtml( elem ) { - var div = document.createElement("div"); - div.appendChild( elem.cloneNode(true) ); - return div.innerHTML; - } - - // Store template items in $.data(), ensuring a unique tmplItem data data structure for each rendered template instance. - function storeTmplItems( content ) { - var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m; - for ( i = 0, l = content.length; i < l; i++ ) { - if ( (elem = content[i]).nodeType !== 1 ) { - continue; - } - elems = elem.getElementsByTagName("*"); - for ( m = elems.length - 1; m >= 0; m-- ) { - processItemKey( elems[m] ); - } - processItemKey( elem ); - } - function processItemKey( el ) { - var pntKey, pntNode = el, pntItem, tmplItem, key; - // Ensure that each rendered template inserted into the DOM has its own template item, - if ( (key = el.getAttribute( tmplItmAtt ))) { - while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { } - if ( pntKey !== key ) { - // The next ancestor with a _tmplitem expando is on a different key than this one. - // So this is a top-level element within this template item - // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment. - pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0; - if ( !(tmplItem = newTmplItems[key]) ) { - // The item is for wrapped content, and was copied from the temporary parent wrappedItem. - tmplItem = wrappedItems[key]; - tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode], null, true ); - tmplItem.key = ++itemKey; - newTmplItems[itemKey] = tmplItem; - } - if ( cloneIndex ) { - cloneTmplItem( key ); - } - } - el.removeAttribute( tmplItmAtt ); - } else if ( cloneIndex && (tmplItem = $.data( el, "tmplItem" )) ) { - // This was a rendered element, cloned during append or appendTo etc. - // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem. - cloneTmplItem( tmplItem.key ); - newTmplItems[tmplItem.key] = tmplItem; - pntNode = $.data( el.parentNode, "tmplItem" ); - pntNode = pntNode ? pntNode.key : 0; - } - if ( tmplItem ) { - pntItem = tmplItem; - // Find the template item of the parent element. - // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string) - while ( pntItem && pntItem.key != pntNode ) { - // Add this element as a top-level node for this rendered template item, as well as for any - // ancestor items between this item and the item of its parent element - pntItem.nodes.push( el ); - pntItem = pntItem.parent; - } - // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering... - delete tmplItem._ctnt; - delete tmplItem._wrap; - // Store template item as jQuery data on the element - $.data( el, "tmplItem", tmplItem ); - } - function cloneTmplItem( key ) { - key = key + keySuffix; - tmplItem = newClonedItems[key] = - (newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true )); - } - } - } - - //---- Helper functions for template item ---- - - function tiCalls( content, tmpl, data, options ) { - if ( !content ) { - return stack.pop(); - } - stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options }); - } - - function tiNest( tmpl, data, options ) { - // nested template, using {{tmpl}} tag - return $.tmpl( $.template( tmpl ), data, options, this ); - } - - function tiWrap( call, wrapped ) { - // nested template, using {{wrap}} tag - var options = call.options || {}; - options.wrapped = wrapped; - // Apply the template, which may incorporate wrapped content, - return $.tmpl( $.template( call.tmpl ), call.data, options, call.item ); - } - - function tiHtml( filter, textOnly ) { - var wrapped = this._wrap; - return $.map( - jQuery( $.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ), - function(e) { - return textOnly ? - e.innerText || e.textContent : - e.outerHTML || outerHtml(e); - }); - } - - function tiUpdate() { - var coll = this.nodes; - $.tmpl( null, null, null, this).insertBefore( coll[0] ); - jQuery( coll ).remove(); - } - - $.View.register({ - suffix : "tmpl", - renderer: function( id, text ) { - var tmpl = $.template( null, text ); - return function(data){ - return tmpl.call($, $, {data: data}).join(''); - //$(text).tmpl(data);//$.render( text, data ); - }; - }, - script: function( id, str ) { - var tmpl = $.template( null, str ); - return "function(data){return ("+tmpl+").call(jQuery, jQuery, {data: data}).join(''); }"; - } - }) - $.View.ext = ".tmpl" -}) diff --git a/view/tmpl/tmpl_test.js b/view/tmpl/tmpl_test.js deleted file mode 100644 index 92ac9a7a..00000000 --- a/view/tmpl/tmpl_test.js +++ /dev/null @@ -1,11 +0,0 @@ -steal('funcunit/qunit','jquery/view/tmpl').then(function(){ -// use the view/qunit.html test to run this test script -module("jquery/view/tmpl") - -test("ifs work", function(){ - $("#qunit-test-area").html(""); - - $("#qunit-test-area").html("//jquery/view/tmpl/test.tmpl",{}); - ok($("#qunit-test-area").find('h1').length, "There's an h1") -}) -}); diff --git a/view/view.html b/view/view.html deleted file mode 100644 index da9669b5..00000000 --- a/view/view.html +++ /dev/null @@ -1,80 +0,0 @@ - - - - view - - - - -

                                                                                              JAML

                                                                                              -
                                                                                              $("#jaml").html("template.jaml",{message: "Hello World"})
                                                                                              -
                                                                                              function(data) {
                                                                                              -  h3(data.message);
                                                                                              -}
                                                                                              -
                                                                                              -

                                                                                              EJS

                                                                                              -
                                                                                              $("#ejs").html("template.ejs",{message: "Hello World"})
                                                                                              -
                                                                                              <h3><%= message %></h3>
                                                                                              -
                                                                                              -

                                                                                              MICRO

                                                                                              -
                                                                                              $("#micro").html("template.micro",{message: "Hello World"})
                                                                                              -
                                                                                              <h3>{%= message %}</h3>
                                                                                              -
                                                                                              -

                                                                                              TMPL

                                                                                              -
                                                                                              $("#tmpl").html("template.tmpl",{message: "Hello World"})
                                                                                              -
                                                                                              <h3>{%= message %}</h3>
                                                                                              -
                                                                                              - - - - \ No newline at end of file diff --git a/view/view.js b/view/view.js deleted file mode 100644 index 5a27d973..00000000 --- a/view/view.js +++ /dev/null @@ -1,4 +0,0 @@ -steal("jquery", "can/util", "can/view", "can/view/modifiers",function($, can) { - $.View = can.view; - return $; -});