├── .gitignore ├── .settings └── launch.json ├── ExpressMvp.sln ├── ExpressMvp ├── .ntvs_analysis.dat ├── ExpressMvp.njsproj ├── README.md ├── app.js ├── bin │ └── www ├── package.json ├── public │ └── stylesheets │ │ ├── style.css │ │ └── style.styl ├── routes │ ├── index.js │ └── users.js ├── src │ └── users.js └── views │ ├── error.jade │ ├── index.jade │ ├── layout.jade │ └── user.jade ├── LICENSE ├── README.md ├── demo-modules ├── app.json ├── config-example.js ├── config.js ├── module-usage.js ├── sql.js ├── temperature-example.js └── temperature.js ├── demo1 └── index.js ├── demo2 └── index.js ├── demo3 ├── hello.js └── index.js ├── demo4 ├── hello.js └── index.js ├── demo5 └── index.js ├── edge-demos ├── 101-hello-world.js ├── 102-hello-file.js ├── 103-data-marshalling.js ├── 104-hello-sql.js ├── 105-hello-assembly.js ├── data-marshalling.cs ├── file-demo.cs └── sql-demo.cs ├── express-demo ├── ExpressApp1 │ ├── .ntvs_analysis.dat │ ├── ExpressApp1.njsproj │ ├── ExpressApp1.sln │ ├── ExpressApp1.v12.suo │ ├── README.md │ ├── app.js │ ├── package.json │ ├── public │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ └── glyphicons-halflings-regular.woff │ │ ├── javascripts │ │ │ ├── _references.js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ ├── jquery-1.10.2.intellisense.js │ │ │ ├── jquery-1.10.2.js │ │ │ ├── jquery-1.10.2.min.js │ │ │ ├── jquery-1.10.2.min.map │ │ │ ├── jquery.validate-vsdoc.js │ │ │ ├── jquery.validate.js │ │ │ ├── jquery.validate.min.js │ │ │ ├── jquery.validate.unobtrusive.js │ │ │ ├── jquery.validate.unobtrusive.min.js │ │ │ ├── modernizr-2.6.2.js │ │ │ ├── respond.js │ │ │ └── respond.min.js │ │ └── stylesheets │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.min.css │ │ │ └── style.styl │ ├── routes │ │ └── index.js │ └── views │ │ ├── about.jade │ │ ├── contact.jade │ │ ├── index.jade │ │ └── layout.jade └── express-demo │ ├── .ntvs_analysis.dat │ ├── README.md │ ├── app.js │ ├── express-demo.njsproj │ ├── express-demo.sln │ ├── express-demo.v12.suo │ ├── package.json │ ├── public │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ └── glyphicons-halflings-regular.woff │ ├── javascripts │ │ ├── _references.js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ ├── jquery-1.10.2.intellisense.js │ │ ├── jquery-1.10.2.js │ │ ├── jquery-1.10.2.min.js │ │ ├── jquery-1.10.2.min.map │ │ ├── jquery.validate-vsdoc.js │ │ ├── jquery.validate.js │ │ ├── jquery.validate.min.js │ │ ├── jquery.validate.unobtrusive.js │ │ ├── jquery.validate.unobtrusive.min.js │ │ ├── modernizr-2.6.2.js │ │ ├── respond.js │ │ └── respond.min.js │ └── stylesheets │ │ ├── bootstrap.css │ │ ├── bootstrap.min.css │ │ ├── style.css │ │ └── style.styl │ ├── routes │ └── index.js │ └── views │ ├── about.jade │ ├── contact.jade │ ├── index.jade │ └── layout.jade ├── package.json └── test └── hello.specs.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # Compiled binary addons (http://nodejs.org/api/addons.html) 20 | build/Release 21 | 22 | # Dependency directory 23 | # Commenting this out is preferred by some people, see 24 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- 25 | node_modules 26 | 27 | # Users Environment Variables 28 | .lock-wscript 29 | -------------------------------------------------------------------------------- /.settings/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | // List of configurations. Add new configurations or edit existing ones. 4 | // ONLY "node" and "mono" are supported, change "type" to switch. 5 | "configurations": [ 6 | { 7 | // Name of configuration; appears in the launch configuration drop down menu. 8 | "name": "Launch app.js", 9 | // Type of configuration. Possible values: "node", "mono". 10 | "type": "node", 11 | // Workspace relative or absolute path to the program. 12 | "program": "./ExpressMvp/bin/www", 13 | // Automatically stop program after launch. 14 | "stopOnEntry": false, 15 | // Command line arguments passed to the program. 16 | "args": [], 17 | // Workspace relative or absolute path to the working directory of the program being debugged. Default is the current workspace. 18 | "cwd": ".", 19 | // Workspace relative or absolute path to the runtime executable to be used. Default is the runtime executable on the PATH. 20 | "runtimeExecutable": null, 21 | // Environment variables passed to the program. 22 | "env": { } 23 | }, 24 | { 25 | "name": "Attach", 26 | "type": "node", 27 | // TCP/IP address. Default is "localhost". 28 | "address": "localhost", 29 | // Port to attach to. 30 | "port": 5858 31 | } 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /ExpressMvp.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.31101.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "ExpressMvp", "ExpressMvp\ExpressMvp.njsproj", "{9C5320A4-DEB2-4A7B-B1D9-B1A0A6291647}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {9C5320A4-DEB2-4A7B-B1D9-B1A0A6291647}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {9C5320A4-DEB2-4A7B-B1D9-B1A0A6291647}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {9C5320A4-DEB2-4A7B-B1D9-B1A0A6291647}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {9C5320A4-DEB2-4A7B-B1D9-B1A0A6291647}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /ExpressMvp/.ntvs_analysis.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/ExpressMvp/.ntvs_analysis.dat -------------------------------------------------------------------------------- /ExpressMvp/ExpressMvp.njsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | ExpressMvp 7 | ExpressMvp 8 | 9 | 10 | 11 | Debug 12 | 2.0 13 | 9c5320a4-deb2-4a7b-b1d9-b1a0a6291647 14 | . 15 | bin\www 16 | 17 | 18 | . 19 | . 20 | v4.0 21 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 22 | ShowAllFiles 23 | 1337 24 | true 25 | 26 | 27 | true 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | False 61 | True 62 | 0 63 | / 64 | http://localhost:48022/ 65 | False 66 | True 67 | http://localhost:1337 68 | False 69 | 70 | 71 | 72 | 73 | 74 | 75 | CurrentPage 76 | True 77 | False 78 | False 79 | False 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | False 89 | False 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /ExpressMvp/README.md: -------------------------------------------------------------------------------- 1 | # ExpressMvp 2 | 3 | 4 | -------------------------------------------------------------------------------- /ExpressMvp/app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var routes = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | 11 | var app = express(); 12 | 13 | // view engine setup 14 | app.set('views', path.join(__dirname, 'views')); 15 | app.set('view engine', 'jade'); 16 | 17 | // uncomment after placing your favicon in /public 18 | //app.use(favicon(__dirname + '/public/favicon.ico')); 19 | app.use(logger('dev')); 20 | app.use(bodyParser.json()); 21 | app.use(bodyParser.urlencoded({ extended: false })); 22 | app.use(cookieParser()); 23 | app.use(require('stylus').middleware(path.join(__dirname, 'public'))); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | app.use('/', routes); 27 | app.use('/users', users); 28 | 29 | // catch 404 and forward to error handler 30 | app.use(function (req, res, next) { 31 | var err = new Error('Not Found'); 32 | err.status = 404; 33 | next(err); 34 | }); 35 | 36 | // error handlers 37 | 38 | // development error handler 39 | // will print stacktrace 40 | if (app.get('env') === 'development') { 41 | app.use(function (err, req, res, next) { 42 | res.status(err.status || 500); 43 | res.render('error', { 44 | message: err.message, 45 | error: err 46 | }); 47 | }); 48 | } 49 | 50 | // production error handler 51 | // no stacktraces leaked to user 52 | app.use(function (err, req, res, next) { 53 | res.status(err.status || 500); 54 | res.render('error', { 55 | message: err.message, 56 | error: {} 57 | }); 58 | }); 59 | 60 | 61 | module.exports = app; 62 | -------------------------------------------------------------------------------- /ExpressMvp/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | var debug = require('debug')('ExpressMvp'); 3 | var app = require('../app'); 4 | 5 | app.set('port', process.env.PORT || 3000); 6 | 7 | var server = app.listen(app.get('port'), function() { 8 | debug('Express server listening on port ' + server.address().port); 9 | }); 10 | -------------------------------------------------------------------------------- /ExpressMvp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ExpressMvp", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "description": "ExpressMvp", 9 | "author": { 10 | "name": "david", 11 | "email": "" 12 | }, 13 | "dependencies": { 14 | "body-parser": "~1.8.1", 15 | "cookie-parser": "~1.3.3", 16 | "debug": "~4.1.1", 17 | "express": "~4.9.0", 18 | "jade": "~1.6.0", 19 | "morgan": "~1.10.0", 20 | "serve-favicon": "~2.1.3", 21 | "stylus": "0.42.3", 22 | "underscore": "^1.8.3" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ExpressMvp/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | a { 6 | color: #00b7ff; 7 | } 8 | -------------------------------------------------------------------------------- /ExpressMvp/public/stylesheets/style.styl: -------------------------------------------------------------------------------- 1 | body 2 | padding: 50px 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif 4 | a 5 | color: #00B7FF -------------------------------------------------------------------------------- /ExpressMvp/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function (req, res) { 6 | 7 | res.render('index', { title: 'Attendees' }); 8 | 9 | }); 10 | 11 | module.exports = router; 12 | -------------------------------------------------------------------------------- /ExpressMvp/routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var users = require('../src/users')( { /* our config info */ } ); 4 | 5 | /* GET users listing. */ 6 | router.get('/', function (req, res) { 7 | res.send('respond with a list of users'); 8 | }); 9 | 10 | router.get('/:id', function (req, res) { 11 | var user = users.getUserById(req.params.id); 12 | console.log("User:", user); 13 | res.render('user', user); 14 | }); 15 | 16 | module.exports = router; -------------------------------------------------------------------------------- /ExpressMvp/src/users.js: -------------------------------------------------------------------------------- 1 | var users = function(config) { 2 | var getUserById = function(id) { 3 | // Look up user in database by id 4 | return { 5 | id: id, 6 | firstName: "David", 7 | lastName: "Neal", 8 | emailAddress: "david@reverentgeek.com" 9 | }; 10 | }; 11 | 12 | return { 13 | getUserById: getUserById 14 | }; 15 | }; 16 | 17 | module.exports = users; -------------------------------------------------------------------------------- /ExpressMvp/views/error.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} -------------------------------------------------------------------------------- /ExpressMvp/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | p Thank you for attending my session! -------------------------------------------------------------------------------- /ExpressMvp/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content -------------------------------------------------------------------------------- /ExpressMvp/views/user.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1 User #{id} 5 | p This is #{firstName} #{lastName} 6 | p= emailAddress 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 David Neal 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node.js Crash Course 2 | aka Node.js Crash Course for .NET Developers 3 | 4 | * Get the latest slides at [SpeakerDeck](https://speakerdeck.com/reverentgeek) 5 | * [About me](https://about.me/reverentgeek) | [reverentgeek.com](http://reverentgeek.com) | [@reverentgeek](https://twitter.com/reverentgeek) 6 | 7 | ## Download Node.js 8 | 9 | Download and install [Node.js](http://nodejs.org) 10 | 11 | ## Editors 12 | 13 | * [Visual Studio Code](https://code.visualstudio.com/) (free cross-platform editor for Windows, Mac OS X, and Linux) 14 | * [Visual Studio Community 2015](https://www.visualstudio.com/products/visual-studio-community-vs) (free Visual Studio IDE for Windows) 15 | * [Atom](https://atom.io/) (free cross-platform editor from GitHub) 16 | 17 | ## Tools available for Visual Studio 2012+ 18 | 19 | * [Node.js Tools for Visual Studio](https://github.com/Microsoft/nodejstools) 20 | * [Package Intellisense](http://visualstudiogallery.msdn.microsoft.com/65748cdb-4087-497e-a394-2e3449c8e61e) 21 | * [Task Runner Explorer](http://visualstudiogallery.msdn.microsoft.com/8e1b4368-4afb-467a-bc13-9650572db708) 22 | * [Grunt Launcher](http://visualstudiogallery.msdn.microsoft.com/dcbc5325-79ef-4b72-960e-0a51ee33a0ff) 23 | 24 | ## Tools 25 | 26 | * [Express](http://expressjs.com/) - fast, unopinionated, minimalist web framework 27 | * [Vash](https://github.com/kirbysayshi/vash) template engine with Razor syntax 28 | * [Electron](http://electron.atom.io/) - Desktop application shell that [Atom](https://atom.io/) uses 29 | * [Edge.js GitHub project](https://github.com/tjanczuk/edge) - run .NET code/libraries from Node.js (and vice versa) 30 | * [Edge.js overview](http://tjanczuk.github.io/edge/) 31 | 32 | ## Articles 33 | 34 | * [Why Node.js is Becoming the Go-To Technology in the Enterprise](http://www.nearform.com/nodecrunch/node-js-becoming-go-technology-enterprise/) by Cian O'Maidin 35 | * [What is Node.js used for: The 2015 Node.js Overview Report](http://blog.risingstack.com/what-is-nodejs-used-for-the-2015-nodejs-overview-report/) by Gabor Nagy 36 | * [Hosting Node.js on Microsoft Azure](http://reverentgeek.com/hosting-node-js-on-microsoft-azure/) by David Neal 37 | * [Introducing Gulp, Grunt, Bower, and npm support for Visual Studio](http://www.hanselman.com/blog/IntroducingGulpGruntBowerAndNpmSupportForVisualStudio.aspx) by Scott Hanselman 38 | * [Painless SQL Server with Node.js and Seriate](http://developer.leankit.com/painless-sql-server-with-nodejs-and-seriate/) by David Neal 39 | * [UPDATED for 2015: How to install the nodejs Ghost blog software on Azure Web Apps (and the Deploy to Azure Button)](http://www.hanselman.com/blog/UPDATEDFor2015HowToInstallTheNodejsGhostBlogSoftwareOnAzureWebAppsAndTheDeployToAzureButton.aspx) by Scott Hanselman 40 | 41 | ## Even MOAR Resources 42 | 43 | * [Awesome Node.js](https://github.com/sindresorhus/awesome-nodejs/) - Curated list of Node.js packages and resources 44 | * [Node.js for Beginners](https://github.com/rockbot/node-for-beginners) - Huge list of resources for Node.js newbies 45 | * [NPM Library](https://www.npmjs.org/) 46 | * WatchMeCode [Intro to NodeJS](https://sub.watchmecode.net/downloads/intro-to-nodejs/) training videos 47 | * WatchMeCode [Pro ExpressJS](https://sub.watchmecode.net/downloads/pro-expressjs/) training videos 48 | * Pluralsight video course: [Node.js for .NET Developers](http://www.pluralsight.com/courses/nodejs-dotnet-developers) 49 | * Pluralsight video course: [RESTful Web Services with Node.js and Express](http://www.pluralsight.com/courses/node-js-express-rest-web-services) 50 | * ["Node.js in Action"](http://www.manning.com/cantelon/) by Mike Cantelon, Marc Harter, T.J. Holowaychuk and Nathan Rajlich 51 | * ["Node.js in Practice"](http://www.manning.com/young/) by Alex Young and Marc Harter 52 | -------------------------------------------------------------------------------- /demo-modules/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "minWidth": 250, 3 | "maxWidth": 900, 4 | "minHeight": 250, 5 | "maxHeight": 1200 6 | } 7 | -------------------------------------------------------------------------------- /demo-modules/config-example.js: -------------------------------------------------------------------------------- 1 | const Config = require( "./config" ); 2 | const appConfig = new Config( "./app.json" ); 3 | 4 | const mw = appConfig.get( "minWidth", 100 ); 5 | 6 | console.log( mw ); 7 | // output: 250 8 | -------------------------------------------------------------------------------- /demo-modules/config.js: -------------------------------------------------------------------------------- 1 | const fs = require( "fs" ); 2 | 3 | const configModule = function( path ) { 4 | const configData = fs.readFileSync( path, "utf8" ); 5 | const config = JSON.parse( configData ); 6 | 7 | const get = function( property, defaultValue ) { 8 | return config[ property ] || defaultValue; 9 | }; 10 | const set = function( property, value ) { 11 | config[ property ] = value; 12 | }; 13 | const internalFunction = function() { 14 | /* stuff */ 15 | }; 16 | const save = function( callback ) { 17 | internalFunction(); 18 | callback(); 19 | }; 20 | 21 | return { 22 | get, 23 | set, 24 | save 25 | }; 26 | }; 27 | 28 | module.exports = configModule; 29 | -------------------------------------------------------------------------------- /demo-modules/module-usage.js: -------------------------------------------------------------------------------- 1 | var fs = require( "fs" ); // Built-in Node.js module 2 | 3 | var express = require( "express" ); // Module installed via npm 4 | 5 | var ApiService = require( "./app/ApiService" ); // Local module 6 | 7 | var api = new ApiService( { port: 8888 } ); 8 | 9 | api.someMethod( "val1", 22, function( err, results ) { 10 | if ( err ) { 11 | // Do something 12 | } 13 | // Do stuff with results 14 | } ); 15 | -------------------------------------------------------------------------------- /demo-modules/sql.js: -------------------------------------------------------------------------------- 1 | const sql = require( "seriate" ); 2 | 3 | // Read from environment variables or local config file 4 | const config = { server: "127.0.0.1", user: "user1", password: "mypass", database: "mydb" }; 5 | sql.setDefaultConfig( config ); 6 | 7 | sql.execute( { 8 | query: "SELECT userId, email FROM accounts" 9 | } ).then( function( results ) { 10 | // Do something with the results 11 | console.log( results ); 12 | } ).catch( function( err ) { 13 | console.log( "Something bad happened:", err ); 14 | } ); 15 | 16 | -------------------------------------------------------------------------------- /demo-modules/temperature-example.js: -------------------------------------------------------------------------------- 1 | const t = require( "./temperature" ); 2 | 3 | const c = t.boilingCelcius; 4 | const f = t.convertToFarenheit( c ); 5 | 6 | console.log( `${c} C is ${f} F` ); 7 | // output: 100 C is 212 F 8 | -------------------------------------------------------------------------------- /demo-modules/temperature.js: -------------------------------------------------------------------------------- 1 | function convertToCelcius( f ) { 2 | return ( f - 32 ) * ( 5 / 9 ); 3 | } 4 | 5 | function convertToFarenheit( c ) { 6 | return ( c * ( 9 / 5 ) ) + 32; 7 | } 8 | 9 | const temp = { 10 | freezingCelcius: 0, 11 | freezingFarenheit: 32, 12 | boilingCelcius: 100, 13 | boilingFarenheit: 212, 14 | convertToCelcius, 15 | convertToFarenheit 16 | }; 17 | 18 | module.exports = temp; 19 | -------------------------------------------------------------------------------- /demo1/index.js: -------------------------------------------------------------------------------- 1 | console.log( "Hello, everybody!" ); 2 | -------------------------------------------------------------------------------- /demo2/index.js: -------------------------------------------------------------------------------- 1 | function sayHello( name ) { 2 | console.log( "Hello, " + name + "!" ); 3 | } 4 | 5 | sayHello( "everybody" ); 6 | -------------------------------------------------------------------------------- /demo3/hello.js: -------------------------------------------------------------------------------- 1 | var Hello = { 2 | version: 1, 3 | getHello: function( name, callback ) { 4 | var err = null; 5 | if ( name === null || name === "" ) { 6 | callback( new Error( "You must provide a valid name!" ) ); 7 | } else { 8 | callback( null, "Hello, " + name + "!" ); 9 | } 10 | } 11 | }; 12 | 13 | module.exports = Hello; 14 | -------------------------------------------------------------------------------- /demo3/index.js: -------------------------------------------------------------------------------- 1 | var hello = require( "./hello" ); 2 | 3 | // console.log(hello); 4 | 5 | hello.getHello( "Microsoft MVP V-Conf", function( err, response ) { 6 | if ( err ) 7 | throw err; 8 | console.log( "Version:", hello.version ); 9 | console.log( response ); 10 | } ); 11 | 12 | // hello.getHello( null, function( err, response ) { 13 | // if ( err ) 14 | // throw err; 15 | // console.log( response ); 16 | // } ); 17 | -------------------------------------------------------------------------------- /demo4/hello.js: -------------------------------------------------------------------------------- 1 | var Hello = function( name ) { 2 | var getHello = function( callback ) { 3 | var err = null; 4 | if ( name === null || name === "" ) { 5 | callback( new Error( "You must provide a valid name!" ) ); 6 | } else { 7 | callback( null, "Hello, " + name + "!" ); 8 | } 9 | }; 10 | 11 | return { 12 | version: 2, 13 | getHello: getHello 14 | }; 15 | }; 16 | 17 | module.exports = Hello; 18 | -------------------------------------------------------------------------------- /demo4/index.js: -------------------------------------------------------------------------------- 1 | var Hello = require( "./hello" ); 2 | 3 | // console.log( "Hello module:", Hello ); 4 | 5 | var hello1 = Hello( "Microsoft MVP V-Conf 2015" ); 6 | 7 | // console.log( "hello1 instance:", hello1 ); 8 | 9 | hello1.getHello( function( err, response ) { 10 | if ( err ) 11 | throw err; 12 | console.log( "Version:", hello1.version ); 13 | console.log( response ); 14 | } ); 15 | 16 | // var hello2 = Hello( "y'all" ); 17 | 18 | // hello2.getHello( function( err, response ) { 19 | // if ( err ) 20 | // throw err; 21 | // console.log( "Version:", hello2.version ); 22 | // console.log( response ); 23 | // } ); 24 | -------------------------------------------------------------------------------- /demo5/index.js: -------------------------------------------------------------------------------- 1 | var http = require( "http" ); 2 | 3 | http.createServer( function( req, res ) { 4 | res.writeHead( 200, { "Content-Type": "text/plain" } ); 5 | res.end( "Hello, y'all!" ); 6 | } ).listen( 3000 ); 7 | 8 | console.log( "Server started o'var on port 3000" ); 9 | 10 | // http.createServer( function( req, res ) { 11 | // var path = req.url.replace( /\/?(?:\?.*)?$/, "" ).toLowerCase(); 12 | // switch (path) { 13 | // case "": 14 | // res.writeHead( 200, { "Content-Type": "text/plain" } ); 15 | // res.end( "Homepage, y'all!" ); 16 | // break; 17 | // case "/about": 18 | // res.writeHead( 200, { "Content-Type": "text/plain" } ); 19 | // res.end( "About this here web site!" ); 20 | // break; 21 | // default: 22 | // res.writeHead( 404, { "Content-Type": "text/plain" } ); 23 | // res.end( "Cain't find it!" ); 24 | // break; 25 | // } 26 | // } ).listen( 3000 ); 27 | 28 | // console.log( "Server started o'var on port 3000" ); 29 | -------------------------------------------------------------------------------- /edge-demos/101-hello-world.js: -------------------------------------------------------------------------------- 1 | var edge = require('edge'); 2 | 3 | var hello = edge.func(function () {/* 4 | async (input) => 5 | { 6 | return "I tell you what I need... " + input.ToString(); 7 | } 8 | */}); 9 | 10 | hello('MORE CAFFEINE!!', function (err, result) { 11 | if (err) throw err; 12 | console.log(result); 13 | }); 14 | -------------------------------------------------------------------------------- /edge-demos/102-hello-file.js: -------------------------------------------------------------------------------- 1 | var edge = require('edge'); 2 | 3 | var hello = edge.func('./file-demo.cs'); 4 | 5 | hello('MORE CAFFEINE!!', function (err, result) { 6 | if (err) throw err; 7 | console.log(result); 8 | }); 9 | -------------------------------------------------------------------------------- /edge-demos/103-data-marshalling.js: -------------------------------------------------------------------------------- 1 | var edge = require( 'edge' ); 2 | 3 | var dataToSendToDotNET = { 4 | anInteger: 1, 5 | aNumber: 3.1415, 6 | aString: 'String from Node.js', 7 | aBool: true, 8 | anObject: { a: '1' }, 9 | anArray: [ 'a', 1, true ], 10 | aBuffer: new Buffer(1024) 11 | } 12 | 13 | var testMarshalling = edge.func('./data-marshalling.cs'); 14 | 15 | testMarshalling(dataToSendToDotNET, function (err, result) { 16 | if (err) throw err; 17 | console.log('Data from .NET to Node.js') 18 | console.log('=========================') 19 | console.log(result); 20 | }); -------------------------------------------------------------------------------- /edge-demos/104-hello-sql.js: -------------------------------------------------------------------------------- 1 | var edge = require('edge'); 2 | 3 | var getUsers = edge.func('./sql-demo.cs'); 4 | 5 | var page = { currentPage: 1, pageSize: 3 }; 6 | 7 | getUsers(page, function (err, result) { 8 | if (err) throw err; 9 | console.log(result); 10 | console.log('FirstName', result[0].FirstName) 11 | }); 12 | -------------------------------------------------------------------------------- /edge-demos/105-hello-assembly.js: -------------------------------------------------------------------------------- 1 | var edge = require('edge'); 2 | 3 | var getUsers = edge.func({ 4 | assemblyFile: '../edge-demos/bin/Debug/edge-demos.dll', 5 | typeName: 'edgedemos.DapperTests', 6 | methodName: 'QueryUsers' 7 | }); 8 | 9 | var page = { currentPage: 1, pageSize: 3 }; 10 | 11 | getUsers(page, function(err, res) { 12 | if (err) throw err; 13 | console.log(res); 14 | }); 15 | -------------------------------------------------------------------------------- /edge-demos/data-marshalling.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | async (input) => 3 | { 4 | Console.WriteLine(""); 5 | Console.WriteLine("Data from Node.js to .NET :"); 6 | Console.WriteLine("==========================="); 7 | var data = (IDictionary) input; 8 | foreach (var kv in data) 9 | { 10 | Console.Write("{0} ({1})", kv.Key, kv.Value.GetType()); 11 | if (kv.Value is System.Dynamic.ExpandoObject) { 12 | var values = kv.Value as IDictionary; 13 | if (values != null) { 14 | Console.WriteLine(", Values:"); 15 | foreach(var kv2 in values) { 16 | Console.WriteLine(" - {0} ({1}): {2}", kv2.Key, kv2.Value.GetType(), kv2.Value); 17 | } 18 | } else { 19 | Console.WriteLine(": dynamic"); 20 | } 21 | } 22 | else if (kv.Value is System.Object[]) { 23 | var values = kv.Value as System.Object[]; 24 | Console.WriteLine(", Values: "); 25 | for(var i = 0; i < values.Length; i++) { 26 | Console.WriteLine(" - {0}: {1}", values[i].GetType(), values[i]); 27 | } 28 | } 29 | else if (kv.Value is System.Byte[]) { 30 | var bytes = kv.Value as System.Byte[]; 31 | Console.WriteLine(": byte array size {0:#,###}", bytes.Length); 32 | } 33 | else { 34 | Console.WriteLine(": {0}", kv.Value); 35 | } 36 | } 37 | Console.WriteLine(""); 38 | 39 | var result = new { 40 | anInteger = 1, 41 | aNumber = 3.1415, 42 | sString = "String Value", 43 | aBool = true, 44 | anObject = new { a = "1", b = "2" }, 45 | anArray = new int[] { 1, 2, 3 }, 46 | aBuffer = new byte[1024] 47 | }; 48 | 49 | return result; 50 | } 51 | -------------------------------------------------------------------------------- /edge-demos/file-demo.cs: -------------------------------------------------------------------------------- 1 | async (input) => 2 | { 3 | return "I tell you what I need... " + input.ToString(); 4 | } 5 | -------------------------------------------------------------------------------- /edge-demos/sql-demo.cs: -------------------------------------------------------------------------------- 1 | //#r "System.dll" 2 | //#r "System.Data.dll" 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Data; 7 | using System.Data.SqlClient; 8 | using System.Dynamic; 9 | using System.Threading.Tasks; 10 | 11 | public class Startup 12 | { 13 | public async Task Invoke(IDictionary input) 14 | { 15 | var query = @" 16 | DECLARE @RowStart int, @RowEnd int; 17 | SET @RowStart = (@currentPage - 1) * @pageSize + 1; 18 | SET @RowEnd = @currentPage * @pageSize; 19 | 20 | WITH Paging AS 21 | ( 22 | SELECT ROW_NUMBER() OVER (ORDER BY CreateDate DESC) AS RowNum, 23 | Id, FirstName, LastName, Email, CreateDate 24 | FROM SampleUsers 25 | ) 26 | SELECT Id, FirstName, LastName, Email, CreateDate 27 | FROM Paging 28 | WHERE RowNum BETWEEN @RowStart AND @RowEnd 29 | ORDER BY RowNum; 30 | "; 31 | // This runs the query using the CLR thread pool 32 | var queryTask = Task.Factory.StartNew (() => ExecuteQuery (query, input)); 33 | return await queryTask; 34 | } 35 | 36 | public object ExecuteQuery(string query, IDictionary parameters) 37 | { 38 | var connectionString = Environment.GetEnvironmentVariable("EDGE_SQL_CONNECTION_STRING"); 39 | var rows = new List(); 40 | 41 | using (var connection = new SqlConnection(connectionString)) 42 | { 43 | using (var command = new SqlCommand(query, connection)) 44 | { 45 | if (parameters != null) { 46 | foreach (KeyValuePair parameter in parameters) { 47 | command.Parameters.AddWithValue (parameter.Key, parameter.Value); 48 | } 49 | } 50 | connection.Open(); 51 | using (SqlDataReader reader = command.ExecuteReader(CommandBehavior.CloseConnection)) 52 | { 53 | var record = (IDataRecord)reader; 54 | while (reader.Read()) 55 | { 56 | var dataObject = new ExpandoObject() as IDictionary; 57 | var resultRecord = new object[record.FieldCount]; 58 | record.GetValues(resultRecord); 59 | 60 | for (int i = 0; i < record.FieldCount; i++) 61 | { 62 | var type = record.GetFieldType(i); 63 | if (type == typeof(byte[]) || type == typeof(char[])) 64 | { 65 | resultRecord[i] = Convert.ToBase64String((byte[])resultRecord[i]); 66 | } 67 | else if (type == typeof(Guid) || type == typeof(DateTime)) 68 | { 69 | resultRecord[i] = resultRecord[i].ToString(); 70 | } 71 | else if (type == typeof(IDataReader)) 72 | { 73 | resultRecord[i] = ""; 74 | } 75 | 76 | dataObject.Add(record.GetName(i), resultRecord[i]); 77 | } 78 | rows.Add(dataObject); 79 | } 80 | } 81 | } 82 | } 83 | 84 | return rows; 85 | } 86 | } 87 | 88 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/.ntvs_analysis.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/.ntvs_analysis.dat -------------------------------------------------------------------------------- /express-demo/ExpressApp1/ExpressApp1.njsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | ExpressApp1 7 | ExpressApp1 8 | 9 | 10 | 11 | Debug 12 | 2.0 13 | a3d8b004-ad4b-4a31-8c81-d8d62be0e3ce 14 | . 15 | app.js 16 | 17 | 18 | . 19 | . 20 | v4.0 21 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 22 | ShowAllFiles 23 | 1337 24 | true 25 | 26 | 27 | true 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | False 81 | True 82 | 0 83 | / 84 | http://localhost:48022/ 85 | False 86 | True 87 | http://localhost:1337 88 | False 89 | 90 | 91 | 92 | 93 | 94 | 95 | CurrentPage 96 | True 97 | False 98 | False 99 | False 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | False 109 | False 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/ExpressApp1.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "ExpressApp1", "ExpressApp1.njsproj", "{A3D8B004-AD4B-4A31-8C81-D8D62BE0E3CE}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {A3D8B004-AD4B-4A31-8C81-D8D62BE0E3CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {A3D8B004-AD4B-4A31-8C81-D8D62BE0E3CE}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {A3D8B004-AD4B-4A31-8C81-D8D62BE0E3CE}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {A3D8B004-AD4B-4A31-8C81-D8D62BE0E3CE}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/ExpressApp1.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/ExpressApp1.v12.suo -------------------------------------------------------------------------------- /express-demo/ExpressApp1/README.md: -------------------------------------------------------------------------------- 1 | # ExpressApp1 2 | 3 | 4 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/app.js: -------------------------------------------------------------------------------- 1 |  2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var express = require('express'); 7 | var routes = require('./routes'); 8 | var http = require('http'); 9 | var path = require('path'); 10 | 11 | var app = express(); 12 | 13 | // all environments 14 | app.set('port', process.env.PORT || 3000); 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'jade'); 17 | app.use(express.favicon()); 18 | app.use(express.logger('dev')); 19 | app.use(express.json()); 20 | app.use(express.urlencoded()); 21 | app.use(express.methodOverride()); 22 | app.use(app.router); 23 | app.use(require('stylus').middleware(path.join(__dirname, 'public'))); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | // development only 27 | if ('development' == app.get('env')) { 28 | app.use(express.errorHandler()); 29 | } 30 | 31 | app.get('/', routes.index); 32 | app.get('/about', routes.about); 33 | app.get('/contact', routes.contact); 34 | 35 | http.createServer(app).listen(app.get('port'), function () { 36 | console.log('Express server listening on port ' + app.get('port')); 37 | }); 38 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ExpressApp1", 3 | "version": "0.0.0", 4 | "description": "ExpressApp1", 5 | "main": "app.js", 6 | "author": { 7 | "name": "david", 8 | "email": "" 9 | }, 10 | "dependencies": { 11 | "express": "3.4.4", 12 | "jade": "*", 13 | "stylus": "*" 14 | } 15 | } -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/ExpressApp1/public/javascripts/_references.js -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | 16 | /** 17 | * bootstrap.js v3.0.0 by @fat and @mdo 18 | * Copyright 2013 Twitter Inc. 19 | * http://www.apache.org/licenses/LICENSE-2.0 20 | */ 21 | if(!jQuery)throw new Error("Bootstrap requires jQuery");+function(a){"use strict";function b(){var a=document.createElement("bootstrap"),b={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"};for(var c in b)if(void 0!==a.style[c])return{end:b[c]}}a.fn.emulateTransitionEnd=function(b){var c=!1,d=this;a(this).one(a.support.transition.end,function(){c=!0});var e=function(){c||a(d).trigger(a.support.transition.end)};return setTimeout(e,b),this},a(function(){a.support.transition=b()})}(window.jQuery),+function(a){"use strict";var b='[data-dismiss="alert"]',c=function(c){a(c).on("click",b,this.close)};c.prototype.close=function(b){function c(){f.trigger("closed.bs.alert").remove()}var d=a(this),e=d.attr("data-target");e||(e=d.attr("href"),e=e&&e.replace(/.*(?=#[^\s]*$)/,""));var f=a(e);b&&b.preventDefault(),f.length||(f=d.hasClass("alert")?d:d.parent()),f.trigger(b=a.Event("close.bs.alert")),b.isDefaultPrevented()||(f.removeClass("in"),a.support.transition&&f.hasClass("fade")?f.one(a.support.transition.end,c).emulateTransitionEnd(150):c())};var d=a.fn.alert;a.fn.alert=function(b){return this.each(function(){var d=a(this),e=d.data("bs.alert");e||d.data("bs.alert",e=new c(this)),"string"==typeof b&&e[b].call(d)})},a.fn.alert.Constructor=c,a.fn.alert.noConflict=function(){return a.fn.alert=d,this},a(document).on("click.bs.alert.data-api",b,c.prototype.close)}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d)};b.DEFAULTS={loadingText:"loading..."},b.prototype.setState=function(a){var b="disabled",c=this.$element,d=c.is("input")?"val":"html",e=c.data();a+="Text",e.resetText||c.data("resetText",c[d]()),c[d](e[a]||this.options[a]),setTimeout(function(){"loadingText"==a?c.addClass(b).attr(b,b):c.removeClass(b).removeAttr(b)},0)},b.prototype.toggle=function(){var a=this.$element.closest('[data-toggle="buttons"]');if(a.length){var b=this.$element.find("input").prop("checked",!this.$element.hasClass("active")).trigger("change");"radio"===b.prop("type")&&a.find(".active").removeClass("active")}this.$element.toggleClass("active")};var c=a.fn.button;a.fn.button=function(c){return this.each(function(){var d=a(this),e=d.data("bs.button"),f="object"==typeof c&&c;e||d.data("bs.button",e=new b(this,f)),"toggle"==c?e.toggle():c&&e.setState(c)})},a.fn.button.Constructor=b,a.fn.button.noConflict=function(){return a.fn.button=c,this},a(document).on("click.bs.button.data-api","[data-toggle^=button]",function(b){var c=a(b.target);c.hasClass("btn")||(c=c.closest(".btn")),c.button("toggle"),b.preventDefault()})}(window.jQuery),+function(a){"use strict";var b=function(b,c){this.$element=a(b),this.$indicators=this.$element.find(".carousel-indicators"),this.options=c,this.paused=this.sliding=this.interval=this.$active=this.$items=null,"hover"==this.options.pause&&this.$element.on("mouseenter",a.proxy(this.pause,this)).on("mouseleave",a.proxy(this.cycle,this))};b.DEFAULTS={interval:5e3,pause:"hover",wrap:!0},b.prototype.cycle=function(b){return b||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(a.proxy(this.next,this),this.options.interval)),this},b.prototype.getActiveIndex=function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},b.prototype.to=function(b){var c=this,d=this.getActiveIndex();return b>this.$items.length-1||0>b?void 0:this.sliding?this.$element.one("slid",function(){c.to(b)}):d==b?this.pause().cycle():this.slide(b>d?"next":"prev",a(this.$items[b]))},b.prototype.pause=function(b){return b||(this.paused=!0),this.$element.find(".next, .prev").length&&a.support.transition.end&&(this.$element.trigger(a.support.transition.end),this.cycle(!0)),this.interval=clearInterval(this.interval),this},b.prototype.next=function(){return this.sliding?void 0:this.slide("next")},b.prototype.prev=function(){return this.sliding?void 0:this.slide("prev")},b.prototype.slide=function(b,c){var d=this.$element.find(".item.active"),e=c||d[b](),f=this.interval,g="next"==b?"left":"right",h="next"==b?"first":"last",i=this;if(!e.length){if(!this.options.wrap)return;e=this.$element.find(".item")[h]()}this.sliding=!0,f&&this.pause();var j=a.Event("slide.bs.carousel",{relatedTarget:e[0],direction:g});if(!e.hasClass("active")){if(this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var b=a(i.$indicators.children()[i.getActiveIndex()]);b&&b.addClass("active")})),a.support.transition&&this.$element.hasClass("slide")){if(this.$element.trigger(j),j.isDefaultPrevented())return;e.addClass(b),e[0].offsetWidth,d.addClass(g),e.addClass(g),d.one(a.support.transition.end,function(){e.removeClass([b,g].join(" ")).addClass("active"),d.removeClass(["active",g].join(" ")),i.sliding=!1,setTimeout(function(){i.$element.trigger("slid")},0)}).emulateTransitionEnd(600)}else{if(this.$element.trigger(j),j.isDefaultPrevented())return;d.removeClass("active"),e.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return f&&this.cycle(),this}};var c=a.fn.carousel;a.fn.carousel=function(c){return this.each(function(){var d=a(this),e=d.data("bs.carousel"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c),g="string"==typeof c?c:f.slide;e||d.data("bs.carousel",e=new b(this,f)),"number"==typeof c?e.to(c):g?e[g]():f.interval&&e.pause().cycle()})},a.fn.carousel.Constructor=b,a.fn.carousel.noConflict=function(){return a.fn.carousel=c,this},a(document).on("click.bs.carousel.data-api","[data-slide], [data-slide-to]",function(b){var c,d=a(this),e=a(d.attr("data-target")||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,"")),f=a.extend({},e.data(),d.data()),g=d.attr("data-slide-to");g&&(f.interval=!1),e.carousel(f),(g=d.attr("data-slide-to"))&&e.data("bs.carousel").to(g),b.preventDefault()}),a(window).on("load",function(){a('[data-ride="carousel"]').each(function(){var b=a(this);b.carousel(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.$element=a(c),this.options=a.extend({},b.DEFAULTS,d),this.transitioning=null,this.options.parent&&(this.$parent=a(this.options.parent)),this.options.toggle&&this.toggle()};b.DEFAULTS={toggle:!0},b.prototype.dimension=function(){var a=this.$element.hasClass("width");return a?"width":"height"},b.prototype.show=function(){if(!this.transitioning&&!this.$element.hasClass("in")){var b=a.Event("show.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.$parent&&this.$parent.find("> .panel > .in");if(c&&c.length){var d=c.data("bs.collapse");if(d&&d.transitioning)return;c.collapse("hide"),d||c.data("bs.collapse",null)}var e=this.dimension();this.$element.removeClass("collapse").addClass("collapsing")[e](0),this.transitioning=1;var f=function(){this.$element.removeClass("collapsing").addClass("in")[e]("auto"),this.transitioning=0,this.$element.trigger("shown.bs.collapse")};if(!a.support.transition)return f.call(this);var g=a.camelCase(["scroll",e].join("-"));this.$element.one(a.support.transition.end,a.proxy(f,this)).emulateTransitionEnd(350)[e](this.$element[0][g])}}},b.prototype.hide=function(){if(!this.transitioning&&this.$element.hasClass("in")){var b=a.Event("hide.bs.collapse");if(this.$element.trigger(b),!b.isDefaultPrevented()){var c=this.dimension();this.$element[c](this.$element[c]())[0].offsetHeight,this.$element.addClass("collapsing").removeClass("collapse").removeClass("in"),this.transitioning=1;var d=function(){this.transitioning=0,this.$element.trigger("hidden.bs.collapse").removeClass("collapsing").addClass("collapse")};return a.support.transition?(this.$element[c](0).one(a.support.transition.end,a.proxy(d,this)).emulateTransitionEnd(350),void 0):d.call(this)}}},b.prototype.toggle=function(){this[this.$element.hasClass("in")?"hide":"show"]()};var c=a.fn.collapse;a.fn.collapse=function(c){return this.each(function(){var d=a(this),e=d.data("bs.collapse"),f=a.extend({},b.DEFAULTS,d.data(),"object"==typeof c&&c);e||d.data("bs.collapse",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.collapse.Constructor=b,a.fn.collapse.noConflict=function(){return a.fn.collapse=c,this},a(document).on("click.bs.collapse.data-api","[data-toggle=collapse]",function(b){var c,d=a(this),e=d.attr("data-target")||b.preventDefault()||(c=d.attr("href"))&&c.replace(/.*(?=#[^\s]+$)/,""),f=a(e),g=f.data("bs.collapse"),h=g?"toggle":d.data(),i=d.attr("data-parent"),j=i&&a(i);g&&g.transitioning||(j&&j.find('[data-toggle=collapse][data-parent="'+i+'"]').not(d).addClass("collapsed"),d[f.hasClass("in")?"addClass":"removeClass"]("collapsed")),f.collapse(h)})}(window.jQuery),+function(a){"use strict";function b(){a(d).remove(),a(e).each(function(b){var d=c(a(this));d.hasClass("open")&&(d.trigger(b=a.Event("hide.bs.dropdown")),b.isDefaultPrevented()||d.removeClass("open").trigger("hidden.bs.dropdown"))})}function c(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}var d=".dropdown-backdrop",e="[data-toggle=dropdown]",f=function(b){a(b).on("click.bs.dropdown",this.toggle)};f.prototype.toggle=function(d){var e=a(this);if(!e.is(".disabled, :disabled")){var f=c(e),g=f.hasClass("open");if(b(),!g){if("ontouchstart"in document.documentElement&&!f.closest(".navbar-nav").length&&a(''}),b.prototype=a.extend({},a.fn.tooltip.Constructor.prototype),b.prototype.constructor=b,b.prototype.getDefaults=function(){return b.DEFAULTS},b.prototype.setContent=function(){var a=this.tip(),b=this.getTitle(),c=this.getContent();a.find(".popover-title")[this.options.html?"html":"text"](b),a.find(".popover-content")[this.options.html?"html":"text"](c),a.removeClass("fade top bottom left right in"),a.find(".popover-title").html()||a.find(".popover-title").hide()},b.prototype.hasContent=function(){return this.getTitle()||this.getContent()},b.prototype.getContent=function(){var a=this.$element,b=this.options;return a.attr("data-content")||("function"==typeof b.content?b.content.call(a[0]):b.content)},b.prototype.arrow=function(){return this.$arrow=this.$arrow||this.tip().find(".arrow")},b.prototype.tip=function(){return this.$tip||(this.$tip=a(this.options.template)),this.$tip};var c=a.fn.popover;a.fn.popover=function(c){return this.each(function(){var d=a(this),e=d.data("bs.popover"),f="object"==typeof c&&c;e||d.data("bs.popover",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.popover.Constructor=b,a.fn.popover.noConflict=function(){return a.fn.popover=c,this}}(window.jQuery),+function(a){"use strict";function b(c,d){var e,f=a.proxy(this.process,this);this.$element=a(c).is("body")?a(window):a(c),this.$body=a("body"),this.$scrollElement=this.$element.on("scroll.bs.scroll-spy.data-api",f),this.options=a.extend({},b.DEFAULTS,d),this.selector=(this.options.target||(e=a(c).attr("href"))&&e.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.offsets=a([]),this.targets=a([]),this.activeTarget=null,this.refresh(),this.process()}b.DEFAULTS={offset:10},b.prototype.refresh=function(){var b=this.$element[0]==window?"offset":"position";this.offsets=a([]),this.targets=a([]);var c=this;this.$body.find(this.selector).map(function(){var d=a(this),e=d.data("target")||d.attr("href"),f=/^#\w/.test(e)&&a(e);return f&&f.length&&[[f[b]().top+(!a.isWindow(c.$scrollElement.get(0))&&c.$scrollElement.scrollTop()),e]]||null}).sort(function(a,b){return a[0]-b[0]}).each(function(){c.offsets.push(this[0]),c.targets.push(this[1])})},b.prototype.process=function(){var a,b=this.$scrollElement.scrollTop()+this.options.offset,c=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,d=c-this.$scrollElement.height(),e=this.offsets,f=this.targets,g=this.activeTarget;if(b>=d)return g!=(a=f.last()[0])&&this.activate(a);for(a=e.length;a--;)g!=f[a]&&b>=e[a]&&(!e[a+1]||b<=e[a+1])&&this.activate(f[a])},b.prototype.activate=function(b){this.activeTarget=b,a(this.selector).parents(".active").removeClass("active");var c=this.selector+'[data-target="'+b+'"],'+this.selector+'[href="'+b+'"]',d=a(c).parents("li").addClass("active");d.parent(".dropdown-menu").length&&(d=d.closest("li.dropdown").addClass("active")),d.trigger("activate")};var c=a.fn.scrollspy;a.fn.scrollspy=function(c){return this.each(function(){var d=a(this),e=d.data("bs.scrollspy"),f="object"==typeof c&&c;e||d.data("bs.scrollspy",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.scrollspy.Constructor=b,a.fn.scrollspy.noConflict=function(){return a.fn.scrollspy=c,this},a(window).on("load",function(){a('[data-spy="scroll"]').each(function(){var b=a(this);b.scrollspy(b.data())})})}(window.jQuery),+function(a){"use strict";var b=function(b){this.element=a(b)};b.prototype.show=function(){var b=this.element,c=b.closest("ul:not(.dropdown-menu)"),d=b.attr("data-target");if(d||(d=b.attr("href"),d=d&&d.replace(/.*(?=#[^\s]*$)/,"")),!b.parent("li").hasClass("active")){var e=c.find(".active:last a")[0],f=a.Event("show.bs.tab",{relatedTarget:e});if(b.trigger(f),!f.isDefaultPrevented()){var g=a(d);this.activate(b.parent("li"),c),this.activate(g,g.parent(),function(){b.trigger({type:"shown.bs.tab",relatedTarget:e})})}}},b.prototype.activate=function(b,c,d){function e(){f.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),b.addClass("active"),g?(b[0].offsetWidth,b.addClass("in")):b.removeClass("fade"),b.parent(".dropdown-menu")&&b.closest("li.dropdown").addClass("active"),d&&d()}var f=c.find("> .active"),g=d&&a.support.transition&&f.hasClass("fade");g?f.one(a.support.transition.end,e).emulateTransitionEnd(150):e(),f.removeClass("in")};var c=a.fn.tab;a.fn.tab=function(c){return this.each(function(){var d=a(this),e=d.data("bs.tab");e||d.data("bs.tab",e=new b(this)),"string"==typeof c&&e[c]()})},a.fn.tab.Constructor=b,a.fn.tab.noConflict=function(){return a.fn.tab=c,this},a(document).on("click.bs.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(b){b.preventDefault(),a(this).tab("show")})}(window.jQuery),+function(a){"use strict";var b=function(c,d){this.options=a.extend({},b.DEFAULTS,d),this.$window=a(window).on("scroll.bs.affix.data-api",a.proxy(this.checkPosition,this)).on("click.bs.affix.data-api",a.proxy(this.checkPositionWithEventLoop,this)),this.$element=a(c),this.affixed=this.unpin=null,this.checkPosition()};b.RESET="affix affix-top affix-bottom",b.DEFAULTS={offset:0},b.prototype.checkPositionWithEventLoop=function(){setTimeout(a.proxy(this.checkPosition,this),1)},b.prototype.checkPosition=function(){if(this.$element.is(":visible")){var c=a(document).height(),d=this.$window.scrollTop(),e=this.$element.offset(),f=this.options.offset,g=f.top,h=f.bottom;"object"!=typeof f&&(h=g=f),"function"==typeof g&&(g=f.top()),"function"==typeof h&&(h=f.bottom());var i=null!=this.unpin&&d+this.unpin<=e.top?!1:null!=h&&e.top+this.$element.height()>=c-h?"bottom":null!=g&&g>=d?"top":!1;this.affixed!==i&&(this.unpin&&this.$element.css("top",""),this.affixed=i,this.unpin="bottom"==i?e.top-d:null,this.$element.removeClass(b.RESET).addClass("affix"+(i?"-"+i:"")),"bottom"==i&&this.$element.offset({top:document.body.offsetHeight-h-this.$element.height()}))}};var c=a.fn.affix;a.fn.affix=function(c){return this.each(function(){var d=a(this),e=d.data("bs.affix"),f="object"==typeof c&&c;e||d.data("bs.affix",e=new b(this,f)),"string"==typeof c&&e[c]()})},a.fn.affix.Constructor=b,a.fn.affix.noConflict=function(){return a.fn.affix=c,this},a(window).on("load",function(){a('[data-spy="affix"]').each(function(){var b=a(this),c=b.data();c.offset=c.offset||{},c.offsetBottom&&(c.offset.bottom=c.offsetBottom),c.offsetTop&&(c.offset.top=c.offsetTop),b.affix(c)})})}(window.jQuery); -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/jquery.validate.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation 16 | * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t("").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 20 | /*global document: false, jQuery: false */ 21 | (function ($) { 22 | var $jQval = $.validator, 23 | adapters, 24 | data_validation = "unobtrusiveValidation"; 25 | function setValidationValues(options, ruleName, value) { 26 | options.rules[ruleName] = value; 27 | if (options.message) { 28 | options.messages[ruleName] = options.message; 29 | } 30 | } 31 | function splitAndTrim(value) { 32 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 33 | } 34 | function escapeAttributeValue(value) { 35 | // As mentioned on http://api.jquery.com/category/selectors/ 36 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 37 | } 38 | function getModelPrefix(fieldName) { 39 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 40 | } 41 | function appendModelPrefix(value, prefix) { 42 | if (value.indexOf("*.") === 0) { 43 | value = value.replace("*.", prefix); 44 | } 45 | return value; 46 | } 47 | function onError(error, inputElement) { // 'this' is the form element 48 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 49 | replaceAttrValue = container.attr("data-valmsg-replace"), 50 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 51 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 52 | error.data("unobtrusiveContainer", container); 53 | if (replace) { 54 | container.empty(); 55 | error.removeClass("input-validation-error").appendTo(container); 56 | } 57 | else { 58 | error.hide(); 59 | } 60 | } 61 | function onErrors(event, validator) { // 'this' is the form element 62 | var container = $(this).find("[data-valmsg-summary=true]"), 63 | list = container.find("ul"); 64 | if (list && list.length && validator.errorList.length) { 65 | list.empty(); 66 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 67 | $.each(validator.errorList, function () { 68 | $("
  • ").html(this.message).appendTo(list); 69 | }); 70 | } 71 | } 72 | function onSuccess(error) { // 'this' is the form element 73 | var container = error.data("unobtrusiveContainer"), 74 | replaceAttrValue = container.attr("data-valmsg-replace"), 75 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 76 | if (container) { 77 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 78 | error.removeData("unobtrusiveContainer"); 79 | if (replace) { 80 | container.empty(); 81 | } 82 | } 83 | } 84 | function onReset(event) { // 'this' is the form element 85 | var $form = $(this); 86 | $form.data("validator").resetForm(); 87 | $form.find(".validation-summary-errors") 88 | .addClass("validation-summary-valid") 89 | .removeClass("validation-summary-errors"); 90 | $form.find(".field-validation-error") 91 | .addClass("field-validation-valid") 92 | .removeClass("field-validation-error") 93 | .removeData("unobtrusiveContainer") 94 | .find(">*") // If we were using valmsg-replace, get the underlying error 95 | .removeData("unobtrusiveContainer"); 96 | } 97 | function validationInfo(form) { 98 | var $form = $(form), 99 | result = $form.data(data_validation), 100 | onResetProxy = $.proxy(onReset, form); 101 | if (!result) { 102 | result = { 103 | options: { // options structure passed to jQuery Validate's validate() method 104 | errorClass: "input-validation-error", 105 | errorElement: "span", 106 | errorPlacement: $.proxy(onError, form), 107 | invalidHandler: $.proxy(onErrors, form), 108 | messages: {}, 109 | rules: {}, 110 | success: $.proxy(onSuccess, form) 111 | }, 112 | attachValidation: function () { 113 | $form 114 | .unbind("reset." + data_validation, onResetProxy) 115 | .bind("reset." + data_validation, onResetProxy) 116 | .validate(this.options); 117 | }, 118 | validate: function () { // a validation function that is called by unobtrusive Ajax 119 | $form.validate(); 120 | return $form.valid(); 121 | } 122 | }; 123 | $form.data(data_validation, result); 124 | } 125 | return result; 126 | } 127 | $jQval.unobtrusive = { 128 | adapters: [], 129 | parseElement: function (element, skipAttach) { 130 | /// 131 | /// Parses a single HTML element for unobtrusive validation attributes. 132 | /// 133 | /// The HTML element to be parsed. 134 | /// [Optional] true to skip attaching the 135 | /// validation to the form. If parsing just this single element, you should specify true. 136 | /// If parsing several elements, you should specify false, and manually attach the validation 137 | /// to the form when you are finished. The default is false. 138 | var $element = $(element), 139 | form = $element.parents("form")[0], 140 | valInfo, rules, messages; 141 | if (!form) { // Cannot do client-side validation without a form 142 | return; 143 | } 144 | valInfo = validationInfo(form); 145 | valInfo.options.rules[element.name] = rules = {}; 146 | valInfo.options.messages[element.name] = messages = {}; 147 | $.each(this.adapters, function () { 148 | var prefix = "data-val-" + this.name, 149 | message = $element.attr(prefix), 150 | paramValues = {}; 151 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 152 | prefix += "-"; 153 | $.each(this.params, function () { 154 | paramValues[this] = $element.attr(prefix + this); 155 | }); 156 | this.adapt({ 157 | element: element, 158 | form: form, 159 | message: message, 160 | params: paramValues, 161 | rules: rules, 162 | messages: messages 163 | }); 164 | } 165 | }); 166 | $.extend(rules, { "__dummy__": true }); 167 | if (!skipAttach) { 168 | valInfo.attachValidation(); 169 | } 170 | }, 171 | parse: function (selector) { 172 | /// 173 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 174 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 175 | /// attribute values. 176 | /// 177 | /// Any valid jQuery selector. 178 | var $forms = $(selector) 179 | .parents("form") 180 | .andSelf() 181 | .add($(selector).find("form")) 182 | .filter("form"); 183 | // :input is a psuedoselector provided by jQuery which selects input and input-like elements 184 | // combining :input with other selectors significantly decreases performance. 185 | $(selector).find(":input").filter("[data-val=true]").each(function () { 186 | $jQval.unobtrusive.parseElement(this, true); 187 | }); 188 | $forms.each(function () { 189 | var info = validationInfo(this); 190 | if (info) { 191 | info.attachValidation(); 192 | } 193 | }); 194 | } 195 | }; 196 | adapters = $jQval.unobtrusive.adapters; 197 | adapters.add = function (adapterName, params, fn) { 198 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 199 | /// The name of the adapter to be added. This matches the name used 200 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 201 | /// [Optional] An array of parameter names (strings) that will 202 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 203 | /// mmmm is the parameter name). 204 | /// The function to call, which adapts the values from the HTML 205 | /// attributes into jQuery Validate rules and/or messages. 206 | /// 207 | if (!fn) { // Called with no params, just a function 208 | fn = params; 209 | params = []; 210 | } 211 | this.push({ name: adapterName, params: params, adapt: fn }); 212 | return this; 213 | }; 214 | adapters.addBool = function (adapterName, ruleName) { 215 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 216 | /// the jQuery Validate validation rule has no parameter values. 217 | /// The name of the adapter to be added. This matches the name used 218 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 219 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 220 | /// of adapterName will be used instead. 221 | /// 222 | return this.add(adapterName, function (options) { 223 | setValidationValues(options, ruleName || adapterName, true); 224 | }); 225 | }; 226 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 227 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 228 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 229 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 230 | /// The name of the adapter to be added. This matches the name used 231 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 232 | /// The name of the jQuery Validate rule to be used when you only 233 | /// have a minimum value. 234 | /// The name of the jQuery Validate rule to be used when you only 235 | /// have a maximum value. 236 | /// The name of the jQuery Validate rule to be used when you 237 | /// have both a minimum and maximum value. 238 | /// [Optional] The name of the HTML attribute that 239 | /// contains the minimum value. The default is "min". 240 | /// [Optional] The name of the HTML attribute that 241 | /// contains the maximum value. The default is "max". 242 | /// 243 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 244 | var min = options.params.min, 245 | max = options.params.max; 246 | if (min && max) { 247 | setValidationValues(options, minMaxRuleName, [min, max]); 248 | } 249 | else if (min) { 250 | setValidationValues(options, minRuleName, min); 251 | } 252 | else if (max) { 253 | setValidationValues(options, maxRuleName, max); 254 | } 255 | }); 256 | }; 257 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 258 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 259 | /// the jQuery Validate validation rule has a single value. 260 | /// The name of the adapter to be added. This matches the name used 261 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 262 | /// [Optional] The name of the HTML attribute that contains the value. 263 | /// The default is "val". 264 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 265 | /// of adapterName will be used instead. 266 | /// 267 | return this.add(adapterName, [attribute || "val"], function (options) { 268 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 269 | }); 270 | }; 271 | $jQval.addMethod("__dummy__", function (value, element, params) { 272 | return true; 273 | }); 274 | $jQval.addMethod("regex", function (value, element, params) { 275 | var match; 276 | if (this.optional(element)) { 277 | return true; 278 | } 279 | match = new RegExp(params).exec(value); 280 | return (match && (match.index === 0) && (match[0].length === value.length)); 281 | }); 282 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 283 | var match; 284 | if (nonalphamin) { 285 | match = value.match(/\W/g); 286 | match = match && match.length >= nonalphamin; 287 | } 288 | return match; 289 | }); 290 | if ($jQval.methods.extension) { 291 | adapters.addSingleVal("accept", "mimtype"); 292 | adapters.addSingleVal("extension", "extension"); 293 | } else { 294 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 295 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 296 | // validating the extension, and ignore mime-type validations as they are not supported. 297 | adapters.addSingleVal("extension", "extension", "accept"); 298 | } 299 | adapters.addSingleVal("regex", "pattern"); 300 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 301 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 302 | adapters.add("equalto", ["other"], function (options) { 303 | var prefix = getModelPrefix(options.element.name), 304 | other = options.params.other, 305 | fullOtherName = appendModelPrefix(other, prefix), 306 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 307 | setValidationValues(options, "equalTo", element); 308 | }); 309 | adapters.add("required", function (options) { 310 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 311 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 312 | setValidationValues(options, "required", true); 313 | } 314 | }); 315 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 316 | var value = { 317 | url: options.params.url, 318 | type: options.params.type || "GET", 319 | data: {} 320 | }, 321 | prefix = getModelPrefix(options.element.name); 322 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 323 | var paramName = appendModelPrefix(fieldName, prefix); 324 | value.data[paramName] = function () { 325 | return $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']").val(); 326 | }; 327 | }); 328 | setValidationValues(options, "remote", value); 329 | }); 330 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 331 | if (options.params.min) { 332 | setValidationValues(options, "minlength", options.params.min); 333 | } 334 | if (options.params.nonalphamin) { 335 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 336 | } 337 | if (options.params.regex) { 338 | setValidationValues(options, "regex", options.params.regex); 339 | } 340 | }); 341 | $(function () { 342 | $jQval.unobtrusive.parse(document); 343 | }); 344 | }(jQuery)); 345 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /* 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("
  • ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this);b.data("validator").resetForm();b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(c){var b=a(c),d=b.data(e),f=a.proxy(n,c);if(!d){d={options:{errorClass:"input-validation-error",errorElement:"span",errorPlacement:a.proxy(m,c),invalidHandler:a.proxy(l,c),messages:{},rules:{},success:a.proxy(k,c)},attachValidation:function(){b.unbind("reset."+e,f).bind("reset."+e,f).validate(this.options)},validate:function(){b.validate();return b.valid()}};b.data(e,d)}return d}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(b){var c=a(b).parents("form").andSelf().add(a(b).find("form")).filter("form");a(b).find(":input").filter("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});c.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){return a(b.form).find(":input").filter("[name='"+f(c)+"']").val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery); 20 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/respond.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 17 | window.matchMedia = window.matchMedia || (function(doc, undefined){ 18 | 19 | var bool, 20 | docElem = doc.documentElement, 21 | refNode = docElem.firstElementChild || docElem.firstChild, 22 | // fakeBody required for 23 | fakeBody = doc.createElement('body'), 24 | div = doc.createElement('div'); 25 | 26 | div.id = 'mq-test-1'; 27 | div.style.cssText = "position:absolute;top:-100em"; 28 | fakeBody.style.background = "none"; 29 | fakeBody.appendChild(div); 30 | 31 | return function(q){ 32 | 33 | div.innerHTML = '­'; 34 | 35 | docElem.insertBefore(fakeBody, refNode); 36 | bool = div.offsetWidth == 42; 37 | docElem.removeChild(fakeBody); 38 | 39 | return { matches: bool, media: q }; 40 | }; 41 | 42 | })(document); 43 | 44 | 45 | 46 | 47 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 48 | (function( win ){ 49 | //exposed namespace 50 | win.respond = {}; 51 | 52 | //define update even in native-mq-supporting browsers, to avoid errors 53 | respond.update = function(){}; 54 | 55 | //expose media query support flag for external use 56 | respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches; 57 | 58 | //if media queries are supported, exit here 59 | if( respond.mediaQueriesSupported ){ return; } 60 | 61 | //define vars 62 | var doc = win.document, 63 | docElem = doc.documentElement, 64 | mediastyles = [], 65 | rules = [], 66 | appendedEls = [], 67 | parsedSheets = {}, 68 | resizeThrottle = 30, 69 | head = doc.getElementsByTagName( "head" )[0] || docElem, 70 | base = doc.getElementsByTagName( "base" )[0], 71 | links = head.getElementsByTagName( "link" ), 72 | requestQueue = [], 73 | 74 | //loop stylesheets, send text content to translate 75 | ripCSS = function(){ 76 | var sheets = links, 77 | sl = sheets.length, 78 | i = 0, 79 | //vars for loop: 80 | sheet, href, media, isCSS; 81 | 82 | for( ; i < sl; i++ ){ 83 | sheet = sheets[ i ], 84 | href = sheet.href, 85 | media = sheet.media, 86 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 87 | 88 | //only links plz and prevent re-parsing 89 | if( !!href && isCSS && !parsedSheets[ href ] ){ 90 | // selectivizr exposes css through the rawCssText expando 91 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 92 | translate( sheet.styleSheet.rawCssText, href, media ); 93 | parsedSheets[ href ] = true; 94 | } else { 95 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) 96 | || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ 97 | requestQueue.push( { 98 | href: href, 99 | media: media 100 | } ); 101 | } 102 | } 103 | } 104 | } 105 | makeRequests(); 106 | }, 107 | 108 | //recurse through request queue, get css text 109 | makeRequests = function(){ 110 | if( requestQueue.length ){ 111 | var thisRequest = requestQueue.shift(); 112 | 113 | ajax( thisRequest.href, function( styles ){ 114 | translate( styles, thisRequest.href, thisRequest.media ); 115 | parsedSheets[ thisRequest.href ] = true; 116 | makeRequests(); 117 | } ); 118 | } 119 | }, 120 | 121 | //find media blocks in css text, convert to style blocks 122 | translate = function( styles, href, media ){ 123 | var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ), 124 | ql = qs && qs.length || 0, 125 | //try to get CSS path 126 | href = href.substring( 0, href.lastIndexOf( "/" )), 127 | repUrls = function( css ){ 128 | return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" ); 129 | }, 130 | useMedia = !ql && media, 131 | //vars used in loop 132 | i = 0, 133 | j, fullq, thisq, eachq, eql; 134 | 135 | //if path exists, tack on trailing slash 136 | if( href.length ){ href += "/"; } 137 | 138 | //if no internal queries exist, but media attr does, use that 139 | //note: this currently lacks support for situations where a media attr is specified on a link AND 140 | //its associated stylesheet has internal CSS media queries. 141 | //In those cases, the media attribute will currently be ignored. 142 | if( useMedia ){ 143 | ql = 1; 144 | } 145 | 146 | 147 | for( ; i < ql; i++ ){ 148 | j = 0; 149 | 150 | //media attr 151 | if( useMedia ){ 152 | fullq = media; 153 | rules.push( repUrls( styles ) ); 154 | } 155 | //parse for styles 156 | else{ 157 | fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1; 158 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); 159 | } 160 | 161 | eachq = fullq.split( "," ); 162 | eql = eachq.length; 163 | 164 | for( ; j < eql; j++ ){ 165 | thisq = eachq[ j ]; 166 | mediastyles.push( { 167 | media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all", 168 | rules : rules.length - 1, 169 | hasquery: thisq.indexOf("(") > -1, 170 | minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ), 171 | maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ) 172 | } ); 173 | } 174 | } 175 | 176 | applyMedia(); 177 | }, 178 | 179 | lastCall, 180 | 181 | resizeDefer, 182 | 183 | // returns the value of 1em in pixels 184 | getEmValue = function() { 185 | var ret, 186 | div = doc.createElement('div'), 187 | body = doc.body, 188 | fakeUsed = false; 189 | 190 | div.style.cssText = "position:absolute;font-size:1em;width:1em"; 191 | 192 | if( !body ){ 193 | body = fakeUsed = doc.createElement( "body" ); 194 | body.style.background = "none"; 195 | } 196 | 197 | body.appendChild( div ); 198 | 199 | docElem.insertBefore( body, docElem.firstChild ); 200 | 201 | ret = div.offsetWidth; 202 | 203 | if( fakeUsed ){ 204 | docElem.removeChild( body ); 205 | } 206 | else { 207 | body.removeChild( div ); 208 | } 209 | 210 | //also update eminpx before returning 211 | ret = eminpx = parseFloat(ret); 212 | 213 | return ret; 214 | }, 215 | 216 | //cached container for 1em value, populated the first time it's needed 217 | eminpx, 218 | 219 | //enable/disable styles 220 | applyMedia = function( fromResize ){ 221 | var name = "clientWidth", 222 | docElemProp = docElem[ name ], 223 | currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp, 224 | styleBlocks = {}, 225 | lastLink = links[ links.length-1 ], 226 | now = (new Date()).getTime(); 227 | 228 | //throttle resize calls 229 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){ 230 | clearTimeout( resizeDefer ); 231 | resizeDefer = setTimeout( applyMedia, resizeThrottle ); 232 | return; 233 | } 234 | else { 235 | lastCall = now; 236 | } 237 | 238 | for( var i in mediastyles ){ 239 | var thisstyle = mediastyles[ i ], 240 | min = thisstyle.minw, 241 | max = thisstyle.maxw, 242 | minnull = min === null, 243 | maxnull = max === null, 244 | em = "em"; 245 | 246 | if( !!min ){ 247 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 248 | } 249 | if( !!max ){ 250 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 251 | } 252 | 253 | // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true 254 | if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){ 255 | if( !styleBlocks[ thisstyle.media ] ){ 256 | styleBlocks[ thisstyle.media ] = []; 257 | } 258 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); 259 | } 260 | } 261 | 262 | //remove any existing respond style element(s) 263 | for( var i in appendedEls ){ 264 | if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){ 265 | head.removeChild( appendedEls[ i ] ); 266 | } 267 | } 268 | 269 | //inject active styles, grouped by media type 270 | for( var i in styleBlocks ){ 271 | var ss = doc.createElement( "style" ), 272 | css = styleBlocks[ i ].join( "\n" ); 273 | 274 | ss.type = "text/css"; 275 | ss.media = i; 276 | 277 | //originally, ss was appended to a documentFragment and sheets were appended in bulk. 278 | //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one! 279 | head.insertBefore( ss, lastLink.nextSibling ); 280 | 281 | if ( ss.styleSheet ){ 282 | ss.styleSheet.cssText = css; 283 | } 284 | else { 285 | ss.appendChild( doc.createTextNode( css ) ); 286 | } 287 | 288 | //push to appendedEls to track for later removal 289 | appendedEls.push( ss ); 290 | } 291 | }, 292 | //tweaked Ajax functions from Quirksmode 293 | ajax = function( url, callback ) { 294 | var req = xmlHttp(); 295 | if (!req){ 296 | return; 297 | } 298 | req.open( "GET", url, true ); 299 | req.onreadystatechange = function () { 300 | if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){ 301 | return; 302 | } 303 | callback( req.responseText ); 304 | } 305 | if ( req.readyState == 4 ){ 306 | return; 307 | } 308 | req.send( null ); 309 | }, 310 | //define ajax obj 311 | xmlHttp = (function() { 312 | var xmlhttpmethod = false; 313 | try { 314 | xmlhttpmethod = new XMLHttpRequest(); 315 | } 316 | catch( e ){ 317 | xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" ); 318 | } 319 | return function(){ 320 | return xmlhttpmethod; 321 | }; 322 | })(); 323 | 324 | //translate CSS 325 | ripCSS(); 326 | 327 | //expose update for re-running respond later on 328 | respond.update = ripCSS; 329 | 330 | //adjust on resize 331 | function callMedia(){ 332 | applyMedia( true ); 333 | } 334 | if( win.addEventListener ){ 335 | win.addEventListener( "resize", callMedia, false ); 336 | } 337 | else if( win.attachEvent ){ 338 | win.attachEvent( "onresize", callMedia ); 339 | } 340 | })(this); 341 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/javascripts/respond.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 17 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); 18 | 19 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 20 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this); -------------------------------------------------------------------------------- /express-demo/ExpressApp1/public/stylesheets/style.styl: -------------------------------------------------------------------------------- 1 | body 2 | padding-top: 50px 3 | padding-bottom: 20px 4 | 5 | /* Set padding to keep content from hitting the edges */ 6 | .body-content 7 | padding-left: 15px 8 | padding-right: 15px 9 | 10 | /* Set width on the form input elements since they're 100% wide by default */ 11 | input, 12 | select, 13 | textarea 14 | max-width: 280px 15 | 16 | /* styles for validation helpers */ 17 | .field-validation-error 18 | color: #b94a48 19 | 20 | .field-validation-valid 21 | display: none 22 | 23 | input.input-validation-error 24 | border: 1px solid #b94a48 25 | 26 | input[type="checkbox"].input-validation-error 27 | border: 0 none 28 | 29 | .validation-summary-errors 30 | color: #b94a48 31 | 32 | .validation-summary-valid 33 | display: none 34 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/routes/index.js: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * GET home page. 4 | */ 5 | 6 | exports.index = function (req, res) { 7 | res.render('index', { title: 'Express', year: new Date().getFullYear() }); 8 | }; 9 | 10 | exports.about = function (req, res) { 11 | res.render('about', { title: 'About', year: new Date().getFullYear(), message: 'Your application description page.' }); 12 | }; 13 | 14 | exports.contact = function (req, res) { 15 | res.render('contact', { title: 'Contact', year: new Date().getFullYear(), message: 'Your contact page.' }); 16 | }; 17 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/views/about.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h2 #{title}. 5 | h3 #{message} 6 | p Use this area to provide additional information. 7 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/views/contact.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h2 #{title}. 5 | h3 #{message} 6 | address 7 | | One Microsoft Way 8 | br 9 | | Redmond, WA 98052-6399 10 | br 11 | abbr(title='Phone') P: 12 | | 425.555.0100 13 | 14 | address 15 | strong Support: 16 | a(href='mailto:Support@example.com') Support@example.com 17 | br 18 | strong Marketing: 19 | a(href='mailto:Marketing@example.com') Marketing@example.com 20 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | .jumbotron 5 | h1 Express 6 | p.lead Express is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript. 7 | p 8 | a.btn.btn-primary.btn-large(href='http://expressjs.com/') Learn more » 9 | .row 10 | .col-md-4 11 | h2 Getting started 12 | p Express gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. 13 | p 14 | a.btn.btn-default(href='http://expressjs.com/') Learn more » 15 | .col-md-4 16 | h2 Get more libraries 17 | p Node Packaged Modules is a repository of software for Node.js. 18 | p 19 | a.btn.btn-default(href='https://www.npmjs.org/') Learn more » 20 | .col-md-4 21 | h2 Microsoft Azure 22 | p You can easily publish to Microsoft Azure using Node.js Tools for Visual Studio. Find out how you can host your application using a free trial today. 23 | p 24 | a.btn.btn-default(href='http://azure.microsoft.com') Learn more » 25 | -------------------------------------------------------------------------------- /express-demo/ExpressApp1/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | meta(charset='utf-8') 5 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 6 | title #{title} - My Express Application 7 | link(rel='stylesheet', type='text/css', href='/stylesheets/bootstrap.min.css') 8 | link(rel='stylesheet', type='text/css', href='/stylesheets/style.css') 9 | script(src='/javascripts/modernizr-2.6.2.js') 10 | body 11 | .navbar.navbar-inverse.navbar-fixed-top 12 | .container 13 | .navbar-header 14 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 15 | span.icon-bar 16 | span.icon-bar 17 | span.icon-bar 18 | a.navbar-brand(href='/') Application name 19 | .navbar-collapse.collapse 20 | ul.nav.navbar-nav 21 | li 22 | a(href='/') Home 23 | li 24 | a(href='/about') About 25 | li 26 | a(href='/contact') Contact 27 | .container.body-content 28 | block content 29 | hr 30 | footer 31 | p © #{year} - My Express Application 32 | 33 | script(src='/javascripts/jquery-1.10.2.js') 34 | script(src='/javascripts/bootstrap.js') 35 | script(src='/javascripts/respond.js') 36 | 37 | block scripts 38 | -------------------------------------------------------------------------------- /express-demo/express-demo/.ntvs_analysis.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/.ntvs_analysis.dat -------------------------------------------------------------------------------- /express-demo/express-demo/README.md: -------------------------------------------------------------------------------- 1 | # express-demo 2 | 3 | 4 | -------------------------------------------------------------------------------- /express-demo/express-demo/app.js: -------------------------------------------------------------------------------- 1 |  2 | /** 3 | * Module dependencies. 4 | */ 5 | 6 | var express = require('express'); 7 | var routes = require('./routes'); 8 | var http = require('http'); 9 | var path = require('path'); 10 | 11 | var app = express(); 12 | 13 | // all environments 14 | app.set('port', process.env.PORT || 3000); 15 | app.set('views', path.join(__dirname, 'views')); 16 | app.set('view engine', 'jade'); 17 | app.use(express.favicon()); 18 | app.use(express.logger('dev')); 19 | app.use(express.json()); 20 | app.use(express.urlencoded()); 21 | app.use(express.methodOverride()); 22 | app.use(app.router); 23 | app.use(require('stylus').middleware(path.join(__dirname, 'public'))); 24 | app.use(express.static(path.join(__dirname, 'public'))); 25 | 26 | // development only 27 | if ('development' == app.get('env')) { 28 | app.use(express.errorHandler()); 29 | } 30 | 31 | app.get('/', routes.index); 32 | app.get('/about', routes.about); 33 | app.get('/contact', routes.contact); 34 | 35 | http.createServer(app).listen(app.get('port'), function () { 36 | console.log('Express server listening on port ' + app.get('port')); 37 | }); 38 | -------------------------------------------------------------------------------- /express-demo/express-demo/express-demo.njsproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 11.0 5 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) 6 | express-demo 7 | express-demo 8 | 9 | 10 | 11 | Debug 12 | 2.0 13 | 21a74279-5ba0-4ecd-8dbc-e20384a06712 14 | . 15 | app.js 16 | 17 | 18 | . 19 | . 20 | v4.0 21 | {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{349c5851-65df-11da-9384-00065b846f21};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} 22 | ShowAllFiles 23 | 1337 24 | true 25 | 26 | 27 | true 28 | 29 | 30 | true 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | False 81 | True 82 | 0 83 | / 84 | http://localhost:48022/ 85 | False 86 | True 87 | http://localhost:1337 88 | False 89 | 90 | 91 | 92 | 93 | 94 | 95 | CurrentPage 96 | True 97 | False 98 | False 99 | False 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | False 109 | False 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /express-demo/express-demo/express-demo.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.30723.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "express-demo", "express-demo.njsproj", "{21A74279-5BA0-4ECD-8DBC-E20384A06712}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {21A74279-5BA0-4ECD-8DBC-E20384A06712}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {21A74279-5BA0-4ECD-8DBC-E20384A06712}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {21A74279-5BA0-4ECD-8DBC-E20384A06712}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {21A74279-5BA0-4ECD-8DBC-E20384A06712}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | EndGlobal 23 | -------------------------------------------------------------------------------- /express-demo/express-demo/express-demo.v12.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/express-demo.v12.suo -------------------------------------------------------------------------------- /express-demo/express-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "express_demo", 3 | "version": "0.0.0", 4 | "description": "express-demo", 5 | "main": "app.js", 6 | "author": { 7 | "name": "david", 8 | "email": "" 9 | }, 10 | "dependencies": { 11 | "express": "3.4.4", 12 | "jade": "*", 13 | "stylus": "*" 14 | } 15 | } -------------------------------------------------------------------------------- /express-demo/express-demo/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /express-demo/express-demo/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /express-demo/express-demo/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reverentgeek/nodejs-demos/7255daa3295b35045954d72fc5700d8de8d77709/express-demo/express-demo/public/javascripts/_references.js -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/jquery.validate.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! jQuery Validation Plugin - v1.11.1 - 3/22/2013\n* https://github.com/jzaefferer/jquery-validation 16 | * Copyright (c) 2013 Jörn Zaefferer; Licensed MIT */(function(t){t.extend(t.fn,{validate:function(e){if(!this.length)return e&&e.debug&&window.console&&console.warn("Nothing selected, can't validate, returning nothing."),void 0;var i=t.data(this[0],"validator");return i?i:(this.attr("novalidate","novalidate"),i=new t.validator(e,this[0]),t.data(this[0],"validator",i),i.settings.onsubmit&&(this.validateDelegate(":submit","click",function(e){i.settings.submitHandler&&(i.submitButton=e.target),t(e.target).hasClass("cancel")&&(i.cancelSubmit=!0),void 0!==t(e.target).attr("formnovalidate")&&(i.cancelSubmit=!0)}),this.submit(function(e){function s(){var s;return i.settings.submitHandler?(i.submitButton&&(s=t("").attr("name",i.submitButton.name).val(t(i.submitButton).val()).appendTo(i.currentForm)),i.settings.submitHandler.call(i,i.currentForm,e),i.submitButton&&s.remove(),!1):!0}return i.settings.debug&&e.preventDefault(),i.cancelSubmit?(i.cancelSubmit=!1,s()):i.form()?i.pendingRequest?(i.formSubmitted=!0,!1):s():(i.focusInvalid(),!1)})),i)},valid:function(){if(t(this[0]).is("form"))return this.validate().form();var e=!0,i=t(this[0].form).validate();return this.each(function(){e=e&&i.element(this)}),e},removeAttrs:function(e){var i={},s=this;return t.each(e.split(/\s/),function(t,e){i[e]=s.attr(e),s.removeAttr(e)}),i},rules:function(e,i){var s=this[0];if(e){var r=t.data(s.form,"validator").settings,n=r.rules,a=t.validator.staticRules(s);switch(e){case"add":t.extend(a,t.validator.normalizeRule(i)),delete a.messages,n[s.name]=a,i.messages&&(r.messages[s.name]=t.extend(r.messages[s.name],i.messages));break;case"remove":if(!i)return delete n[s.name],a;var u={};return t.each(i.split(/\s/),function(t,e){u[e]=a[e],delete a[e]}),u}}var o=t.validator.normalizeRules(t.extend({},t.validator.classRules(s),t.validator.attributeRules(s),t.validator.dataRules(s),t.validator.staticRules(s)),s);if(o.required){var l=o.required;delete o.required,o=t.extend({required:l},o)}return o}}),t.extend(t.expr[":"],{blank:function(e){return!t.trim(""+t(e).val())},filled:function(e){return!!t.trim(""+t(e).val())},unchecked:function(e){return!t(e).prop("checked")}}),t.validator=function(e,i){this.settings=t.extend(!0,{},t.validator.defaults,e),this.currentForm=i,this.init()},t.validator.format=function(e,i){return 1===arguments.length?function(){var i=t.makeArray(arguments);return i.unshift(e),t.validator.format.apply(this,i)}:(arguments.length>2&&i.constructor!==Array&&(i=t.makeArray(arguments).slice(1)),i.constructor!==Array&&(i=[i]),t.each(i,function(t,i){e=e.replace(RegExp("\\{"+t+"\\}","g"),function(){return i})}),e)},t.extend(t.validator,{defaults:{messages:{},groups:{},rules:{},errorClass:"error",validClass:"valid",errorElement:"label",focusInvalid:!0,errorContainer:t([]),errorLabelContainer:t([]),onsubmit:!0,ignore:":hidden",ignoreTitle:!1,onfocusin:function(t){this.lastActive=t,this.settings.focusCleanup&&!this.blockFocusCleanup&&(this.settings.unhighlight&&this.settings.unhighlight.call(this,t,this.settings.errorClass,this.settings.validClass),this.addWrapper(this.errorsFor(t)).hide())},onfocusout:function(t){this.checkable(t)||!(t.name in this.submitted)&&this.optional(t)||this.element(t)},onkeyup:function(t,e){(9!==e.which||""!==this.elementValue(t))&&(t.name in this.submitted||t===this.lastElement)&&this.element(t)},onclick:function(t){t.name in this.submitted?this.element(t):t.parentNode.name in this.submitted&&this.element(t.parentNode)},highlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).addClass(i).removeClass(s):t(e).addClass(i).removeClass(s)},unhighlight:function(e,i,s){"radio"===e.type?this.findByName(e.name).removeClass(i).addClass(s):t(e).removeClass(i).addClass(s)}},setDefaults:function(e){t.extend(t.validator.defaults,e)},messages:{required:"This field is required.",remote:"Please fix this field.",email:"Please enter a valid email address.",url:"Please enter a valid URL.",date:"Please enter a valid date.",dateISO:"Please enter a valid date (ISO).",number:"Please enter a valid number.",digits:"Please enter only digits.",creditcard:"Please enter a valid credit card number.",equalTo:"Please enter the same value again.",maxlength:t.validator.format("Please enter no more than {0} characters."),minlength:t.validator.format("Please enter at least {0} characters."),rangelength:t.validator.format("Please enter a value between {0} and {1} characters long."),range:t.validator.format("Please enter a value between {0} and {1}."),max:t.validator.format("Please enter a value less than or equal to {0}."),min:t.validator.format("Please enter a value greater than or equal to {0}.")},autoCreateRanges:!1,prototype:{init:function(){function e(e){var i=t.data(this[0].form,"validator"),s="on"+e.type.replace(/^validate/,"");i.settings[s]&&i.settings[s].call(i,this[0],e)}this.labelContainer=t(this.settings.errorLabelContainer),this.errorContext=this.labelContainer.length&&this.labelContainer||t(this.currentForm),this.containers=t(this.settings.errorContainer).add(this.settings.errorLabelContainer),this.submitted={},this.valueCache={},this.pendingRequest=0,this.pending={},this.invalid={},this.reset();var i=this.groups={};t.each(this.settings.groups,function(e,s){"string"==typeof s&&(s=s.split(/\s/)),t.each(s,function(t,s){i[s]=e})});var s=this.settings.rules;t.each(s,function(e,i){s[e]=t.validator.normalizeRule(i)}),t(this.currentForm).validateDelegate(":text, [type='password'], [type='file'], select, textarea, [type='number'], [type='search'] ,[type='tel'], [type='url'], [type='email'], [type='datetime'], [type='date'], [type='month'], [type='week'], [type='time'], [type='datetime-local'], [type='range'], [type='color'] ","focusin focusout keyup",e).validateDelegate("[type='radio'], [type='checkbox'], select, option","click",e),this.settings.invalidHandler&&t(this.currentForm).bind("invalid-form.validate",this.settings.invalidHandler)},form:function(){return this.checkForm(),t.extend(this.submitted,this.errorMap),this.invalid=t.extend({},this.errorMap),this.valid()||t(this.currentForm).triggerHandler("invalid-form",[this]),this.showErrors(),this.valid()},checkForm:function(){this.prepareForm();for(var t=0,e=this.currentElements=this.elements();e[t];t++)this.check(e[t]);return this.valid()},element:function(e){e=this.validationTargetFor(this.clean(e)),this.lastElement=e,this.prepareElement(e),this.currentElements=t(e);var i=this.check(e)!==!1;return i?delete this.invalid[e.name]:this.invalid[e.name]=!0,this.numberOfInvalids()||(this.toHide=this.toHide.add(this.containers)),this.showErrors(),i},showErrors:function(e){if(e){t.extend(this.errorMap,e),this.errorList=[];for(var i in e)this.errorList.push({message:e[i],element:this.findByName(i)[0]});this.successList=t.grep(this.successList,function(t){return!(t.name in e)})}this.settings.showErrors?this.settings.showErrors.call(this,this.errorMap,this.errorList):this.defaultShowErrors()},resetForm:function(){t.fn.resetForm&&t(this.currentForm).resetForm(),this.submitted={},this.lastElement=null,this.prepareForm(),this.hideErrors(),this.elements().removeClass(this.settings.errorClass).removeData("previousValue")},numberOfInvalids:function(){return this.objectLength(this.invalid)},objectLength:function(t){var e=0;for(var i in t)e++;return e},hideErrors:function(){this.addWrapper(this.toHide).hide()},valid:function(){return 0===this.size()},size:function(){return this.errorList.length},focusInvalid:function(){if(this.settings.focusInvalid)try{t(this.findLastActive()||this.errorList.length&&this.errorList[0].element||[]).filter(":visible").focus().trigger("focusin")}catch(e){}},findLastActive:function(){var e=this.lastActive;return e&&1===t.grep(this.errorList,function(t){return t.element.name===e.name}).length&&e},elements:function(){var e=this,i={};return t(this.currentForm).find("input, select, textarea").not(":submit, :reset, :image, [disabled]").not(this.settings.ignore).filter(function(){return!this.name&&e.settings.debug&&window.console&&console.error("%o has no name assigned",this),this.name in i||!e.objectLength(t(this).rules())?!1:(i[this.name]=!0,!0)})},clean:function(e){return t(e)[0]},errors:function(){var e=this.settings.errorClass.replace(" ",".");return t(this.settings.errorElement+"."+e,this.errorContext)},reset:function(){this.successList=[],this.errorList=[],this.errorMap={},this.toShow=t([]),this.toHide=t([]),this.currentElements=t([])},prepareForm:function(){this.reset(),this.toHide=this.errors().add(this.containers)},prepareElement:function(t){this.reset(),this.toHide=this.errorsFor(t)},elementValue:function(e){var i=t(e).attr("type"),s=t(e).val();return"radio"===i||"checkbox"===i?t("input[name='"+t(e).attr("name")+"']:checked").val():"string"==typeof s?s.replace(/\r/g,""):s},check:function(e){e=this.validationTargetFor(this.clean(e));var i,s=t(e).rules(),r=!1,n=this.elementValue(e);for(var a in s){var u={method:a,parameters:s[a]};try{if(i=t.validator.methods[a].call(this,n,e,u.parameters),"dependency-mismatch"===i){r=!0;continue}if(r=!1,"pending"===i)return this.toHide=this.toHide.not(this.errorsFor(e)),void 0;if(!i)return this.formatAndAdd(e,u),!1}catch(o){throw this.settings.debug&&window.console&&console.log("Exception occurred when checking element "+e.id+", check the '"+u.method+"' method.",o),o}}return r?void 0:(this.objectLength(s)&&this.successList.push(e),!0)},customDataMessage:function(e,i){return t(e).data("msg-"+i.toLowerCase())||e.attributes&&t(e).attr("data-msg-"+i.toLowerCase())},customMessage:function(t,e){var i=this.settings.messages[t];return i&&(i.constructor===String?i:i[e])},findDefined:function(){for(var t=0;arguments.length>t;t++)if(void 0!==arguments[t])return arguments[t];return void 0},defaultMessage:function(e,i){return this.findDefined(this.customMessage(e.name,i),this.customDataMessage(e,i),!this.settings.ignoreTitle&&e.title||void 0,t.validator.messages[i],"Warning: No message defined for "+e.name+"")},formatAndAdd:function(e,i){var s=this.defaultMessage(e,i.method),r=/\$?\{(\d+)\}/g;"function"==typeof s?s=s.call(this,i.parameters,e):r.test(s)&&(s=t.validator.format(s.replace(r,"{$1}"),i.parameters)),this.errorList.push({message:s,element:e}),this.errorMap[e.name]=s,this.submitted[e.name]=s},addWrapper:function(t){return this.settings.wrapper&&(t=t.add(t.parent(this.settings.wrapper))),t},defaultShowErrors:function(){var t,e;for(t=0;this.errorList[t];t++){var i=this.errorList[t];this.settings.highlight&&this.settings.highlight.call(this,i.element,this.settings.errorClass,this.settings.validClass),this.showLabel(i.element,i.message)}if(this.errorList.length&&(this.toShow=this.toShow.add(this.containers)),this.settings.success)for(t=0;this.successList[t];t++)this.showLabel(this.successList[t]);if(this.settings.unhighlight)for(t=0,e=this.validElements();e[t];t++)this.settings.unhighlight.call(this,e[t],this.settings.errorClass,this.settings.validClass);this.toHide=this.toHide.not(this.toShow),this.hideErrors(),this.addWrapper(this.toShow).show()},validElements:function(){return this.currentElements.not(this.invalidElements())},invalidElements:function(){return t(this.errorList).map(function(){return this.element})},showLabel:function(e,i){var s=this.errorsFor(e);s.length?(s.removeClass(this.settings.validClass).addClass(this.settings.errorClass),s.html(i)):(s=t("<"+this.settings.errorElement+">").attr("for",this.idOrName(e)).addClass(this.settings.errorClass).html(i||""),this.settings.wrapper&&(s=s.hide().show().wrap("<"+this.settings.wrapper+"/>").parent()),this.labelContainer.append(s).length||(this.settings.errorPlacement?this.settings.errorPlacement(s,t(e)):s.insertAfter(e))),!i&&this.settings.success&&(s.text(""),"string"==typeof this.settings.success?s.addClass(this.settings.success):this.settings.success(s,e)),this.toShow=this.toShow.add(s)},errorsFor:function(e){var i=this.idOrName(e);return this.errors().filter(function(){return t(this).attr("for")===i})},idOrName:function(t){return this.groups[t.name]||(this.checkable(t)?t.name:t.id||t.name)},validationTargetFor:function(t){return this.checkable(t)&&(t=this.findByName(t.name).not(this.settings.ignore)[0]),t},checkable:function(t){return/radio|checkbox/i.test(t.type)},findByName:function(e){return t(this.currentForm).find("[name='"+e+"']")},getLength:function(e,i){switch(i.nodeName.toLowerCase()){case"select":return t("option:selected",i).length;case"input":if(this.checkable(i))return this.findByName(i.name).filter(":checked").length}return e.length},depend:function(t,e){return this.dependTypes[typeof t]?this.dependTypes[typeof t](t,e):!0},dependTypes:{"boolean":function(t){return t},string:function(e,i){return!!t(e,i.form).length},"function":function(t,e){return t(e)}},optional:function(e){var i=this.elementValue(e);return!t.validator.methods.required.call(this,i,e)&&"dependency-mismatch"},startRequest:function(t){this.pending[t.name]||(this.pendingRequest++,this.pending[t.name]=!0)},stopRequest:function(e,i){this.pendingRequest--,0>this.pendingRequest&&(this.pendingRequest=0),delete this.pending[e.name],i&&0===this.pendingRequest&&this.formSubmitted&&this.form()?(t(this.currentForm).submit(),this.formSubmitted=!1):!i&&0===this.pendingRequest&&this.formSubmitted&&(t(this.currentForm).triggerHandler("invalid-form",[this]),this.formSubmitted=!1)},previousValue:function(e){return t.data(e,"previousValue")||t.data(e,"previousValue",{old:null,valid:!0,message:this.defaultMessage(e,"remote")})}},classRuleSettings:{required:{required:!0},email:{email:!0},url:{url:!0},date:{date:!0},dateISO:{dateISO:!0},number:{number:!0},digits:{digits:!0},creditcard:{creditcard:!0}},addClassRules:function(e,i){e.constructor===String?this.classRuleSettings[e]=i:t.extend(this.classRuleSettings,e)},classRules:function(e){var i={},s=t(e).attr("class");return s&&t.each(s.split(" "),function(){this in t.validator.classRuleSettings&&t.extend(i,t.validator.classRuleSettings[this])}),i},attributeRules:function(e){var i={},s=t(e),r=s[0].getAttribute("type");for(var n in t.validator.methods){var a;"required"===n?(a=s.get(0).getAttribute(n),""===a&&(a=!0),a=!!a):a=s.attr(n),/min|max/.test(n)&&(null===r||/number|range|text/.test(r))&&(a=Number(a)),a?i[n]=a:r===n&&"range"!==r&&(i[n]=!0)}return i.maxlength&&/-1|2147483647|524288/.test(i.maxlength)&&delete i.maxlength,i},dataRules:function(e){var i,s,r={},n=t(e);for(i in t.validator.methods)s=n.data("rule-"+i.toLowerCase()),void 0!==s&&(r[i]=s);return r},staticRules:function(e){var i={},s=t.data(e.form,"validator");return s.settings.rules&&(i=t.validator.normalizeRule(s.settings.rules[e.name])||{}),i},normalizeRules:function(e,i){return t.each(e,function(s,r){if(r===!1)return delete e[s],void 0;if(r.param||r.depends){var n=!0;switch(typeof r.depends){case"string":n=!!t(r.depends,i.form).length;break;case"function":n=r.depends.call(i,i)}n?e[s]=void 0!==r.param?r.param:!0:delete e[s]}}),t.each(e,function(s,r){e[s]=t.isFunction(r)?r(i):r}),t.each(["minlength","maxlength"],function(){e[this]&&(e[this]=Number(e[this]))}),t.each(["rangelength","range"],function(){var i;e[this]&&(t.isArray(e[this])?e[this]=[Number(e[this][0]),Number(e[this][1])]:"string"==typeof e[this]&&(i=e[this].split(/[\s,]+/),e[this]=[Number(i[0]),Number(i[1])]))}),t.validator.autoCreateRanges&&(e.min&&e.max&&(e.range=[e.min,e.max],delete e.min,delete e.max),e.minlength&&e.maxlength&&(e.rangelength=[e.minlength,e.maxlength],delete e.minlength,delete e.maxlength)),e},normalizeRule:function(e){if("string"==typeof e){var i={};t.each(e.split(/\s/),function(){i[this]=!0}),e=i}return e},addMethod:function(e,i,s){t.validator.methods[e]=i,t.validator.messages[e]=void 0!==s?s:t.validator.messages[e],3>i.length&&t.validator.addClassRules(e,t.validator.normalizeRule(e))},methods:{required:function(e,i,s){if(!this.depend(s,i))return"dependency-mismatch";if("select"===i.nodeName.toLowerCase()){var r=t(i).val();return r&&r.length>0}return this.checkable(i)?this.getLength(e,i)>0:t.trim(e).length>0},email:function(t,e){return this.optional(e)||/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i.test(t)},url:function(t,e){return this.optional(e)||/^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(t)},date:function(t,e){return this.optional(e)||!/Invalid|NaN/.test(""+new Date(t))},dateISO:function(t,e){return this.optional(e)||/^\d{4}[\/\-]\d{1,2}[\/\-]\d{1,2}$/.test(t)},number:function(t,e){return this.optional(e)||/^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(t)},digits:function(t,e){return this.optional(e)||/^\d+$/.test(t)},creditcard:function(t,e){if(this.optional(e))return"dependency-mismatch";if(/[^0-9 \-]+/.test(t))return!1;var i=0,s=0,r=!1;t=t.replace(/\D/g,"");for(var n=t.length-1;n>=0;n--){var a=t.charAt(n);s=parseInt(a,10),r&&(s*=2)>9&&(s-=9),i+=s,r=!r}return 0===i%10},minlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s},maxlength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||s>=r},rangelength:function(e,i,s){var r=t.isArray(e)?e.length:this.getLength(t.trim(e),i);return this.optional(i)||r>=s[0]&&s[1]>=r},min:function(t,e,i){return this.optional(e)||t>=i},max:function(t,e,i){return this.optional(e)||i>=t},range:function(t,e,i){return this.optional(e)||t>=i[0]&&i[1]>=t},equalTo:function(e,i,s){var r=t(s);return this.settings.onfocusout&&r.unbind(".validate-equalTo").bind("blur.validate-equalTo",function(){t(i).valid()}),e===r.val()},remote:function(e,i,s){if(this.optional(i))return"dependency-mismatch";var r=this.previousValue(i);if(this.settings.messages[i.name]||(this.settings.messages[i.name]={}),r.originalMessage=this.settings.messages[i.name].remote,this.settings.messages[i.name].remote=r.message,s="string"==typeof s&&{url:s}||s,r.old===e)return r.valid;r.old=e;var n=this;this.startRequest(i);var a={};return a[i.name]=e,t.ajax(t.extend(!0,{url:s,mode:"abort",port:"validate"+i.name,dataType:"json",data:a,success:function(s){n.settings.messages[i.name].remote=r.originalMessage;var a=s===!0||"true"===s;if(a){var u=n.formSubmitted;n.prepareElement(i),n.formSubmitted=u,n.successList.push(i),delete n.invalid[i.name],n.showErrors()}else{var o={},l=s||n.defaultMessage(i,"remote");o[i.name]=r.message=t.isFunction(l)?l(e):l,n.invalid[i.name]=!0,n.showErrors(o)}r.valid=a,n.stopRequest(i,a)}},s)),"pending"}}}),t.format=t.validator.format})(jQuery),function(t){var e={};if(t.ajaxPrefilter)t.ajaxPrefilter(function(t,i,s){var r=t.port;"abort"===t.mode&&(e[r]&&e[r].abort(),e[r]=s)});else{var i=t.ajax;t.ajax=function(s){var r=("mode"in s?s:t.ajaxSettings).mode,n=("port"in s?s:t.ajaxSettings).port;return"abort"===r?(e[n]&&e[n].abort(),e[n]=i.apply(this,arguments),e[n]):i.apply(this,arguments)}}}(jQuery),function(t){t.extend(t.fn,{validateDelegate:function(e,i,s){return this.bind(i,function(i){var r=t(i.target);return r.is(e)?s.apply(r,arguments):void 0})}})}(jQuery); -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/jquery.validate.unobtrusive.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | /*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */ 20 | /*global document: false, jQuery: false */ 21 | (function ($) { 22 | var $jQval = $.validator, 23 | adapters, 24 | data_validation = "unobtrusiveValidation"; 25 | function setValidationValues(options, ruleName, value) { 26 | options.rules[ruleName] = value; 27 | if (options.message) { 28 | options.messages[ruleName] = options.message; 29 | } 30 | } 31 | function splitAndTrim(value) { 32 | return value.replace(/^\s+|\s+$/g, "").split(/\s*,\s*/g); 33 | } 34 | function escapeAttributeValue(value) { 35 | // As mentioned on http://api.jquery.com/category/selectors/ 36 | return value.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g, "\\$1"); 37 | } 38 | function getModelPrefix(fieldName) { 39 | return fieldName.substr(0, fieldName.lastIndexOf(".") + 1); 40 | } 41 | function appendModelPrefix(value, prefix) { 42 | if (value.indexOf("*.") === 0) { 43 | value = value.replace("*.", prefix); 44 | } 45 | return value; 46 | } 47 | function onError(error, inputElement) { // 'this' is the form element 48 | var container = $(this).find("[data-valmsg-for='" + escapeAttributeValue(inputElement[0].name) + "']"), 49 | replaceAttrValue = container.attr("data-valmsg-replace"), 50 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) !== false : null; 51 | container.removeClass("field-validation-valid").addClass("field-validation-error"); 52 | error.data("unobtrusiveContainer", container); 53 | if (replace) { 54 | container.empty(); 55 | error.removeClass("input-validation-error").appendTo(container); 56 | } 57 | else { 58 | error.hide(); 59 | } 60 | } 61 | function onErrors(event, validator) { // 'this' is the form element 62 | var container = $(this).find("[data-valmsg-summary=true]"), 63 | list = container.find("ul"); 64 | if (list && list.length && validator.errorList.length) { 65 | list.empty(); 66 | container.addClass("validation-summary-errors").removeClass("validation-summary-valid"); 67 | $.each(validator.errorList, function () { 68 | $("
  • ").html(this.message).appendTo(list); 69 | }); 70 | } 71 | } 72 | function onSuccess(error) { // 'this' is the form element 73 | var container = error.data("unobtrusiveContainer"), 74 | replaceAttrValue = container.attr("data-valmsg-replace"), 75 | replace = replaceAttrValue ? $.parseJSON(replaceAttrValue) : null; 76 | if (container) { 77 | container.addClass("field-validation-valid").removeClass("field-validation-error"); 78 | error.removeData("unobtrusiveContainer"); 79 | if (replace) { 80 | container.empty(); 81 | } 82 | } 83 | } 84 | function onReset(event) { // 'this' is the form element 85 | var $form = $(this); 86 | $form.data("validator").resetForm(); 87 | $form.find(".validation-summary-errors") 88 | .addClass("validation-summary-valid") 89 | .removeClass("validation-summary-errors"); 90 | $form.find(".field-validation-error") 91 | .addClass("field-validation-valid") 92 | .removeClass("field-validation-error") 93 | .removeData("unobtrusiveContainer") 94 | .find(">*") // If we were using valmsg-replace, get the underlying error 95 | .removeData("unobtrusiveContainer"); 96 | } 97 | function validationInfo(form) { 98 | var $form = $(form), 99 | result = $form.data(data_validation), 100 | onResetProxy = $.proxy(onReset, form); 101 | if (!result) { 102 | result = { 103 | options: { // options structure passed to jQuery Validate's validate() method 104 | errorClass: "input-validation-error", 105 | errorElement: "span", 106 | errorPlacement: $.proxy(onError, form), 107 | invalidHandler: $.proxy(onErrors, form), 108 | messages: {}, 109 | rules: {}, 110 | success: $.proxy(onSuccess, form) 111 | }, 112 | attachValidation: function () { 113 | $form 114 | .unbind("reset." + data_validation, onResetProxy) 115 | .bind("reset." + data_validation, onResetProxy) 116 | .validate(this.options); 117 | }, 118 | validate: function () { // a validation function that is called by unobtrusive Ajax 119 | $form.validate(); 120 | return $form.valid(); 121 | } 122 | }; 123 | $form.data(data_validation, result); 124 | } 125 | return result; 126 | } 127 | $jQval.unobtrusive = { 128 | adapters: [], 129 | parseElement: function (element, skipAttach) { 130 | /// 131 | /// Parses a single HTML element for unobtrusive validation attributes. 132 | /// 133 | /// The HTML element to be parsed. 134 | /// [Optional] true to skip attaching the 135 | /// validation to the form. If parsing just this single element, you should specify true. 136 | /// If parsing several elements, you should specify false, and manually attach the validation 137 | /// to the form when you are finished. The default is false. 138 | var $element = $(element), 139 | form = $element.parents("form")[0], 140 | valInfo, rules, messages; 141 | if (!form) { // Cannot do client-side validation without a form 142 | return; 143 | } 144 | valInfo = validationInfo(form); 145 | valInfo.options.rules[element.name] = rules = {}; 146 | valInfo.options.messages[element.name] = messages = {}; 147 | $.each(this.adapters, function () { 148 | var prefix = "data-val-" + this.name, 149 | message = $element.attr(prefix), 150 | paramValues = {}; 151 | if (message !== undefined) { // Compare against undefined, because an empty message is legal (and falsy) 152 | prefix += "-"; 153 | $.each(this.params, function () { 154 | paramValues[this] = $element.attr(prefix + this); 155 | }); 156 | this.adapt({ 157 | element: element, 158 | form: form, 159 | message: message, 160 | params: paramValues, 161 | rules: rules, 162 | messages: messages 163 | }); 164 | } 165 | }); 166 | $.extend(rules, { "__dummy__": true }); 167 | if (!skipAttach) { 168 | valInfo.attachValidation(); 169 | } 170 | }, 171 | parse: function (selector) { 172 | /// 173 | /// Parses all the HTML elements in the specified selector. It looks for input elements decorated 174 | /// with the [data-val=true] attribute value and enables validation according to the data-val-* 175 | /// attribute values. 176 | /// 177 | /// Any valid jQuery selector. 178 | var $forms = $(selector) 179 | .parents("form") 180 | .andSelf() 181 | .add($(selector).find("form")) 182 | .filter("form"); 183 | // :input is a psuedoselector provided by jQuery which selects input and input-like elements 184 | // combining :input with other selectors significantly decreases performance. 185 | $(selector).find(":input").filter("[data-val=true]").each(function () { 186 | $jQval.unobtrusive.parseElement(this, true); 187 | }); 188 | $forms.each(function () { 189 | var info = validationInfo(this); 190 | if (info) { 191 | info.attachValidation(); 192 | } 193 | }); 194 | } 195 | }; 196 | adapters = $jQval.unobtrusive.adapters; 197 | adapters.add = function (adapterName, params, fn) { 198 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation. 199 | /// The name of the adapter to be added. This matches the name used 200 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 201 | /// [Optional] An array of parameter names (strings) that will 202 | /// be extracted from the data-val-nnnn-mmmm HTML attributes (where nnnn is the adapter name, and 203 | /// mmmm is the parameter name). 204 | /// The function to call, which adapts the values from the HTML 205 | /// attributes into jQuery Validate rules and/or messages. 206 | /// 207 | if (!fn) { // Called with no params, just a function 208 | fn = params; 209 | params = []; 210 | } 211 | this.push({ name: adapterName, params: params, adapt: fn }); 212 | return this; 213 | }; 214 | adapters.addBool = function (adapterName, ruleName) { 215 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 216 | /// the jQuery Validate validation rule has no parameter values. 217 | /// The name of the adapter to be added. This matches the name used 218 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 219 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 220 | /// of adapterName will be used instead. 221 | /// 222 | return this.add(adapterName, function (options) { 223 | setValidationValues(options, ruleName || adapterName, true); 224 | }); 225 | }; 226 | adapters.addMinMax = function (adapterName, minRuleName, maxRuleName, minMaxRuleName, minAttribute, maxAttribute) { 227 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 228 | /// the jQuery Validate validation has three potential rules (one for min-only, one for max-only, and 229 | /// one for min-and-max). The HTML parameters are expected to be named -min and -max. 230 | /// The name of the adapter to be added. This matches the name used 231 | /// in the data-val-nnnn HTML attribute (where nnnn is the adapter name). 232 | /// The name of the jQuery Validate rule to be used when you only 233 | /// have a minimum value. 234 | /// The name of the jQuery Validate rule to be used when you only 235 | /// have a maximum value. 236 | /// The name of the jQuery Validate rule to be used when you 237 | /// have both a minimum and maximum value. 238 | /// [Optional] The name of the HTML attribute that 239 | /// contains the minimum value. The default is "min". 240 | /// [Optional] The name of the HTML attribute that 241 | /// contains the maximum value. The default is "max". 242 | /// 243 | return this.add(adapterName, [minAttribute || "min", maxAttribute || "max"], function (options) { 244 | var min = options.params.min, 245 | max = options.params.max; 246 | if (min && max) { 247 | setValidationValues(options, minMaxRuleName, [min, max]); 248 | } 249 | else if (min) { 250 | setValidationValues(options, minRuleName, min); 251 | } 252 | else if (max) { 253 | setValidationValues(options, maxRuleName, max); 254 | } 255 | }); 256 | }; 257 | adapters.addSingleVal = function (adapterName, attribute, ruleName) { 258 | /// Adds a new adapter to convert unobtrusive HTML into a jQuery Validate validation, where 259 | /// the jQuery Validate validation rule has a single value. 260 | /// The name of the adapter to be added. This matches the name used 261 | /// in the data-val-nnnn HTML attribute(where nnnn is the adapter name). 262 | /// [Optional] The name of the HTML attribute that contains the value. 263 | /// The default is "val". 264 | /// [Optional] The name of the jQuery Validate rule. If not provided, the value 265 | /// of adapterName will be used instead. 266 | /// 267 | return this.add(adapterName, [attribute || "val"], function (options) { 268 | setValidationValues(options, ruleName || adapterName, options.params[attribute]); 269 | }); 270 | }; 271 | $jQval.addMethod("__dummy__", function (value, element, params) { 272 | return true; 273 | }); 274 | $jQval.addMethod("regex", function (value, element, params) { 275 | var match; 276 | if (this.optional(element)) { 277 | return true; 278 | } 279 | match = new RegExp(params).exec(value); 280 | return (match && (match.index === 0) && (match[0].length === value.length)); 281 | }); 282 | $jQval.addMethod("nonalphamin", function (value, element, nonalphamin) { 283 | var match; 284 | if (nonalphamin) { 285 | match = value.match(/\W/g); 286 | match = match && match.length >= nonalphamin; 287 | } 288 | return match; 289 | }); 290 | if ($jQval.methods.extension) { 291 | adapters.addSingleVal("accept", "mimtype"); 292 | adapters.addSingleVal("extension", "extension"); 293 | } else { 294 | // for backward compatibility, when the 'extension' validation method does not exist, such as with versions 295 | // of JQuery Validation plugin prior to 1.10, we should use the 'accept' method for 296 | // validating the extension, and ignore mime-type validations as they are not supported. 297 | adapters.addSingleVal("extension", "extension", "accept"); 298 | } 299 | adapters.addSingleVal("regex", "pattern"); 300 | adapters.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"); 301 | adapters.addMinMax("length", "minlength", "maxlength", "rangelength").addMinMax("range", "min", "max", "range"); 302 | adapters.add("equalto", ["other"], function (options) { 303 | var prefix = getModelPrefix(options.element.name), 304 | other = options.params.other, 305 | fullOtherName = appendModelPrefix(other, prefix), 306 | element = $(options.form).find(":input").filter("[name='" + escapeAttributeValue(fullOtherName) + "']")[0]; 307 | setValidationValues(options, "equalTo", element); 308 | }); 309 | adapters.add("required", function (options) { 310 | // jQuery Validate equates "required" with "mandatory" for checkbox elements 311 | if (options.element.tagName.toUpperCase() !== "INPUT" || options.element.type.toUpperCase() !== "CHECKBOX") { 312 | setValidationValues(options, "required", true); 313 | } 314 | }); 315 | adapters.add("remote", ["url", "type", "additionalfields"], function (options) { 316 | var value = { 317 | url: options.params.url, 318 | type: options.params.type || "GET", 319 | data: {} 320 | }, 321 | prefix = getModelPrefix(options.element.name); 322 | $.each(splitAndTrim(options.params.additionalfields || options.element.name), function (i, fieldName) { 323 | var paramName = appendModelPrefix(fieldName, prefix); 324 | value.data[paramName] = function () { 325 | return $(options.form).find(":input").filter("[name='" + escapeAttributeValue(paramName) + "']").val(); 326 | }; 327 | }); 328 | setValidationValues(options, "remote", value); 329 | }); 330 | adapters.add("password", ["min", "nonalphamin", "regex"], function (options) { 331 | if (options.params.min) { 332 | setValidationValues(options, "minlength", options.params.min); 333 | } 334 | if (options.params.nonalphamin) { 335 | setValidationValues(options, "nonalphamin", options.params.nonalphamin); 336 | } 337 | if (options.params.regex) { 338 | setValidationValues(options, "regex", options.params.regex); 339 | } 340 | }); 341 | $(function () { 342 | $jQval.unobtrusive.parse(document); 343 | }); 344 | }(jQuery)); 345 | -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /* 16 | ** Unobtrusive validation support library for jQuery and jQuery Validate 17 | ** Copyright (C) Microsoft Corporation. All rights reserved. 18 | */ 19 | (function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("
  • ").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this);b.data("validator").resetForm();b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(c){var b=a(c),d=b.data(e),f=a.proxy(n,c);if(!d){d={options:{errorClass:"input-validation-error",errorElement:"span",errorPlacement:a.proxy(m,c),invalidHandler:a.proxy(l,c),messages:{},rules:{},success:a.proxy(k,c)},attachValidation:function(){b.unbind("reset."+e,f).bind("reset."+e,f).validate(this.options)},validate:function(){b.validate();return b.valid()}};b.data(e,d)}return d}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(b){var c=a(b).parents("form").andSelf().add(a(b).find("form")).filter("form");a(b).find(":input").filter("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});c.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){return a(b.form).find(":input").filter("[name='"+f(c)+"']").val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery); 20 | -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/respond.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 17 | window.matchMedia = window.matchMedia || (function(doc, undefined){ 18 | 19 | var bool, 20 | docElem = doc.documentElement, 21 | refNode = docElem.firstElementChild || docElem.firstChild, 22 | // fakeBody required for 23 | fakeBody = doc.createElement('body'), 24 | div = doc.createElement('div'); 25 | 26 | div.id = 'mq-test-1'; 27 | div.style.cssText = "position:absolute;top:-100em"; 28 | fakeBody.style.background = "none"; 29 | fakeBody.appendChild(div); 30 | 31 | return function(q){ 32 | 33 | div.innerHTML = '­'; 34 | 35 | docElem.insertBefore(fakeBody, refNode); 36 | bool = div.offsetWidth == 42; 37 | docElem.removeChild(fakeBody); 38 | 39 | return { matches: bool, media: q }; 40 | }; 41 | 42 | })(document); 43 | 44 | 45 | 46 | 47 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 48 | (function( win ){ 49 | //exposed namespace 50 | win.respond = {}; 51 | 52 | //define update even in native-mq-supporting browsers, to avoid errors 53 | respond.update = function(){}; 54 | 55 | //expose media query support flag for external use 56 | respond.mediaQueriesSupported = win.matchMedia && win.matchMedia( "only all" ).matches; 57 | 58 | //if media queries are supported, exit here 59 | if( respond.mediaQueriesSupported ){ return; } 60 | 61 | //define vars 62 | var doc = win.document, 63 | docElem = doc.documentElement, 64 | mediastyles = [], 65 | rules = [], 66 | appendedEls = [], 67 | parsedSheets = {}, 68 | resizeThrottle = 30, 69 | head = doc.getElementsByTagName( "head" )[0] || docElem, 70 | base = doc.getElementsByTagName( "base" )[0], 71 | links = head.getElementsByTagName( "link" ), 72 | requestQueue = [], 73 | 74 | //loop stylesheets, send text content to translate 75 | ripCSS = function(){ 76 | var sheets = links, 77 | sl = sheets.length, 78 | i = 0, 79 | //vars for loop: 80 | sheet, href, media, isCSS; 81 | 82 | for( ; i < sl; i++ ){ 83 | sheet = sheets[ i ], 84 | href = sheet.href, 85 | media = sheet.media, 86 | isCSS = sheet.rel && sheet.rel.toLowerCase() === "stylesheet"; 87 | 88 | //only links plz and prevent re-parsing 89 | if( !!href && isCSS && !parsedSheets[ href ] ){ 90 | // selectivizr exposes css through the rawCssText expando 91 | if (sheet.styleSheet && sheet.styleSheet.rawCssText) { 92 | translate( sheet.styleSheet.rawCssText, href, media ); 93 | parsedSheets[ href ] = true; 94 | } else { 95 | if( (!/^([a-zA-Z:]*\/\/)/.test( href ) && !base) 96 | || href.replace( RegExp.$1, "" ).split( "/" )[0] === win.location.host ){ 97 | requestQueue.push( { 98 | href: href, 99 | media: media 100 | } ); 101 | } 102 | } 103 | } 104 | } 105 | makeRequests(); 106 | }, 107 | 108 | //recurse through request queue, get css text 109 | makeRequests = function(){ 110 | if( requestQueue.length ){ 111 | var thisRequest = requestQueue.shift(); 112 | 113 | ajax( thisRequest.href, function( styles ){ 114 | translate( styles, thisRequest.href, thisRequest.media ); 115 | parsedSheets[ thisRequest.href ] = true; 116 | makeRequests(); 117 | } ); 118 | } 119 | }, 120 | 121 | //find media blocks in css text, convert to style blocks 122 | translate = function( styles, href, media ){ 123 | var qs = styles.match( /@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi ), 124 | ql = qs && qs.length || 0, 125 | //try to get CSS path 126 | href = href.substring( 0, href.lastIndexOf( "/" )), 127 | repUrls = function( css ){ 128 | return css.replace( /(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g, "$1" + href + "$2$3" ); 129 | }, 130 | useMedia = !ql && media, 131 | //vars used in loop 132 | i = 0, 133 | j, fullq, thisq, eachq, eql; 134 | 135 | //if path exists, tack on trailing slash 136 | if( href.length ){ href += "/"; } 137 | 138 | //if no internal queries exist, but media attr does, use that 139 | //note: this currently lacks support for situations where a media attr is specified on a link AND 140 | //its associated stylesheet has internal CSS media queries. 141 | //In those cases, the media attribute will currently be ignored. 142 | if( useMedia ){ 143 | ql = 1; 144 | } 145 | 146 | 147 | for( ; i < ql; i++ ){ 148 | j = 0; 149 | 150 | //media attr 151 | if( useMedia ){ 152 | fullq = media; 153 | rules.push( repUrls( styles ) ); 154 | } 155 | //parse for styles 156 | else{ 157 | fullq = qs[ i ].match( /@media *([^\{]+)\{([\S\s]+?)$/ ) && RegExp.$1; 158 | rules.push( RegExp.$2 && repUrls( RegExp.$2 ) ); 159 | } 160 | 161 | eachq = fullq.split( "," ); 162 | eql = eachq.length; 163 | 164 | for( ; j < eql; j++ ){ 165 | thisq = eachq[ j ]; 166 | mediastyles.push( { 167 | media : thisq.split( "(" )[ 0 ].match( /(only\s+)?([a-zA-Z]+)\s?/ ) && RegExp.$2 || "all", 168 | rules : rules.length - 1, 169 | hasquery: thisq.indexOf("(") > -1, 170 | minw : thisq.match( /\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ), 171 | maxw : thisq.match( /\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/ ) && parseFloat( RegExp.$1 ) + ( RegExp.$2 || "" ) 172 | } ); 173 | } 174 | } 175 | 176 | applyMedia(); 177 | }, 178 | 179 | lastCall, 180 | 181 | resizeDefer, 182 | 183 | // returns the value of 1em in pixels 184 | getEmValue = function() { 185 | var ret, 186 | div = doc.createElement('div'), 187 | body = doc.body, 188 | fakeUsed = false; 189 | 190 | div.style.cssText = "position:absolute;font-size:1em;width:1em"; 191 | 192 | if( !body ){ 193 | body = fakeUsed = doc.createElement( "body" ); 194 | body.style.background = "none"; 195 | } 196 | 197 | body.appendChild( div ); 198 | 199 | docElem.insertBefore( body, docElem.firstChild ); 200 | 201 | ret = div.offsetWidth; 202 | 203 | if( fakeUsed ){ 204 | docElem.removeChild( body ); 205 | } 206 | else { 207 | body.removeChild( div ); 208 | } 209 | 210 | //also update eminpx before returning 211 | ret = eminpx = parseFloat(ret); 212 | 213 | return ret; 214 | }, 215 | 216 | //cached container for 1em value, populated the first time it's needed 217 | eminpx, 218 | 219 | //enable/disable styles 220 | applyMedia = function( fromResize ){ 221 | var name = "clientWidth", 222 | docElemProp = docElem[ name ], 223 | currWidth = doc.compatMode === "CSS1Compat" && docElemProp || doc.body[ name ] || docElemProp, 224 | styleBlocks = {}, 225 | lastLink = links[ links.length-1 ], 226 | now = (new Date()).getTime(); 227 | 228 | //throttle resize calls 229 | if( fromResize && lastCall && now - lastCall < resizeThrottle ){ 230 | clearTimeout( resizeDefer ); 231 | resizeDefer = setTimeout( applyMedia, resizeThrottle ); 232 | return; 233 | } 234 | else { 235 | lastCall = now; 236 | } 237 | 238 | for( var i in mediastyles ){ 239 | var thisstyle = mediastyles[ i ], 240 | min = thisstyle.minw, 241 | max = thisstyle.maxw, 242 | minnull = min === null, 243 | maxnull = max === null, 244 | em = "em"; 245 | 246 | if( !!min ){ 247 | min = parseFloat( min ) * ( min.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 248 | } 249 | if( !!max ){ 250 | max = parseFloat( max ) * ( max.indexOf( em ) > -1 ? ( eminpx || getEmValue() ) : 1 ); 251 | } 252 | 253 | // if there's no media query at all (the () part), or min or max is not null, and if either is present, they're true 254 | if( !thisstyle.hasquery || ( !minnull || !maxnull ) && ( minnull || currWidth >= min ) && ( maxnull || currWidth <= max ) ){ 255 | if( !styleBlocks[ thisstyle.media ] ){ 256 | styleBlocks[ thisstyle.media ] = []; 257 | } 258 | styleBlocks[ thisstyle.media ].push( rules[ thisstyle.rules ] ); 259 | } 260 | } 261 | 262 | //remove any existing respond style element(s) 263 | for( var i in appendedEls ){ 264 | if( appendedEls[ i ] && appendedEls[ i ].parentNode === head ){ 265 | head.removeChild( appendedEls[ i ] ); 266 | } 267 | } 268 | 269 | //inject active styles, grouped by media type 270 | for( var i in styleBlocks ){ 271 | var ss = doc.createElement( "style" ), 272 | css = styleBlocks[ i ].join( "\n" ); 273 | 274 | ss.type = "text/css"; 275 | ss.media = i; 276 | 277 | //originally, ss was appended to a documentFragment and sheets were appended in bulk. 278 | //this caused crashes in IE in a number of circumstances, such as when the HTML element had a bg image set, so appending beforehand seems best. Thanks to @dvelyk for the initial research on this one! 279 | head.insertBefore( ss, lastLink.nextSibling ); 280 | 281 | if ( ss.styleSheet ){ 282 | ss.styleSheet.cssText = css; 283 | } 284 | else { 285 | ss.appendChild( doc.createTextNode( css ) ); 286 | } 287 | 288 | //push to appendedEls to track for later removal 289 | appendedEls.push( ss ); 290 | } 291 | }, 292 | //tweaked Ajax functions from Quirksmode 293 | ajax = function( url, callback ) { 294 | var req = xmlHttp(); 295 | if (!req){ 296 | return; 297 | } 298 | req.open( "GET", url, true ); 299 | req.onreadystatechange = function () { 300 | if ( req.readyState != 4 || req.status != 200 && req.status != 304 ){ 301 | return; 302 | } 303 | callback( req.responseText ); 304 | } 305 | if ( req.readyState == 4 ){ 306 | return; 307 | } 308 | req.send( null ); 309 | }, 310 | //define ajax obj 311 | xmlHttp = (function() { 312 | var xmlhttpmethod = false; 313 | try { 314 | xmlhttpmethod = new XMLHttpRequest(); 315 | } 316 | catch( e ){ 317 | xmlhttpmethod = new ActiveXObject( "Microsoft.XMLHTTP" ); 318 | } 319 | return function(){ 320 | return xmlhttpmethod; 321 | }; 322 | })(); 323 | 324 | //translate CSS 325 | ripCSS(); 326 | 327 | //expose update for re-running respond later on 328 | respond.update = ripCSS; 329 | 330 | //adjust on resize 331 | function callMedia(){ 332 | applyMedia( true ); 333 | } 334 | if( win.addEventListener ){ 335 | win.addEventListener( "resize", callMedia, false ); 336 | } 337 | else if( win.attachEvent ){ 338 | win.attachEvent( "onresize", callMedia ); 339 | } 340 | })(this); 341 | -------------------------------------------------------------------------------- /express-demo/express-demo/public/javascripts/respond.min.js: -------------------------------------------------------------------------------- 1 | /* NUGET: BEGIN LICENSE TEXT 2 | * 3 | * Microsoft grants you the right to use these script files for the sole 4 | * purpose of either: (i) interacting through your browser with the Microsoft 5 | * website or online service, subject to the applicable licensing or use 6 | * terms; or (ii) using the files as included with a Microsoft product subject 7 | * to that product's license terms. Microsoft reserves all other rights to the 8 | * files not expressly granted by Microsoft, whether by implication, estoppel 9 | * or otherwise. Insofar as a script file is dual licensed under GPL, 10 | * Microsoft neither took the code under GPL nor distributes it thereunder but 11 | * under the terms set out in this paragraph. All notices and licenses 12 | * below are for informational purposes only. 13 | * 14 | * NUGET: END LICENSE TEXT */ 15 | /*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */ 16 | /*! NOTE: If you're already including a window.matchMedia polyfill via Modernizr or otherwise, you don't need this part */ 17 | window.matchMedia=window.matchMedia||(function(e,f){var c,a=e.documentElement,b=a.firstElementChild||a.firstChild,d=e.createElement("body"),g=e.createElement("div");g.id="mq-test-1";g.style.cssText="position:absolute;top:-100em";d.style.background="none";d.appendChild(g);return function(h){g.innerHTML='­';a.insertBefore(d,b);c=g.offsetWidth==42;a.removeChild(d);return{matches:c,media:h}}})(document); 18 | 19 | /*! Respond.js v1.2.0: min/max-width media query polyfill. (c) Scott Jehl. MIT/GPLv2 Lic. j.mp/respondjs */ 20 | (function(e){e.respond={};respond.update=function(){};respond.mediaQueriesSupported=e.matchMedia&&e.matchMedia("only all").matches;if(respond.mediaQueriesSupported){return}var w=e.document,s=w.documentElement,i=[],k=[],q=[],o={},h=30,f=w.getElementsByTagName("head")[0]||s,g=w.getElementsByTagName("base")[0],b=f.getElementsByTagName("link"),d=[],a=function(){var D=b,y=D.length,B=0,A,z,C,x;for(;B-1,minw:F.match(/\(min\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:F.match(/\(max\-width:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}}j()},l,r,v=function(){var z,A=w.createElement("div"),x=w.body,y=false;A.style.cssText="position:absolute;font-size:1em;width:1em";if(!x){x=y=w.createElement("body");x.style.background="none"}x.appendChild(A);s.insertBefore(x,s.firstChild);z=A.offsetWidth;if(y){s.removeChild(x)}else{x.removeChild(A)}z=p=parseFloat(z);return z},p,j=function(I){var x="clientWidth",B=s[x],H=w.compatMode==="CSS1Compat"&&B||w.body[x]||B,D={},G=b[b.length-1],z=(new Date()).getTime();if(I&&l&&z-l-1?(p||v()):1)}if(!!J){J=parseFloat(J)*(J.indexOf(y)>-1?(p||v()):1)}if(!K.hasquery||(!A||!L)&&(A||H>=C)&&(L||H<=J)){if(!D[K.media]){D[K.media]=[]}D[K.media].push(k[K.rules])}}for(var E in q){if(q[E]&&q[E].parentNode===f){f.removeChild(q[E])}}for(var E in D){var M=w.createElement("style"),F=D[E].join("\n");M.type="text/css";M.media=E;f.insertBefore(M,G.nextSibling);if(M.styleSheet){M.styleSheet.cssText=F}else{M.appendChild(w.createTextNode(F))}q.push(M)}},n=function(x,z){var y=c();if(!y){return}y.open("GET",x,true);y.onreadystatechange=function(){if(y.readyState!=4||y.status!=200&&y.status!=304){return}z(y.responseText)};if(y.readyState==4){return}y.send(null)},c=(function(){var x=false;try{x=new XMLHttpRequest()}catch(y){x=new ActiveXObject("Microsoft.XMLHTTP")}return function(){return x}})();a();respond.update=a;function t(){j(true)}if(e.addEventListener){e.addEventListener("resize",t,false)}else{if(e.attachEvent){e.attachEvent("onresize",t)}}})(this); -------------------------------------------------------------------------------- /express-demo/express-demo/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | /* Set padding to keep content from hitting the edges */ 6 | .body-content { 7 | padding-left: 15px; 8 | padding-right: 15px; 9 | } 10 | /* Set width on the form input elements since they're 100% wide by default */ 11 | input, 12 | select, 13 | textarea { 14 | max-width: 280px; 15 | } 16 | /* styles for validation helpers */ 17 | .field-validation-error { 18 | color: #b94a48; 19 | } 20 | .field-validation-valid { 21 | display: none; 22 | } 23 | input.input-validation-error { 24 | border: 1px solid #b94a48; 25 | } 26 | input[type="checkbox"].input-validation-error { 27 | border: 0 none; 28 | } 29 | .validation-summary-errors { 30 | color: #b94a48; 31 | } 32 | .validation-summary-valid { 33 | display: none; 34 | } 35 | -------------------------------------------------------------------------------- /express-demo/express-demo/public/stylesheets/style.styl: -------------------------------------------------------------------------------- 1 | body 2 | padding-top: 50px 3 | padding-bottom: 20px 4 | 5 | /* Set padding to keep content from hitting the edges */ 6 | .body-content 7 | padding-left: 15px 8 | padding-right: 15px 9 | 10 | /* Set width on the form input elements since they're 100% wide by default */ 11 | input, 12 | select, 13 | textarea 14 | max-width: 280px 15 | 16 | /* styles for validation helpers */ 17 | .field-validation-error 18 | color: #b94a48 19 | 20 | .field-validation-valid 21 | display: none 22 | 23 | input.input-validation-error 24 | border: 1px solid #b94a48 25 | 26 | input[type="checkbox"].input-validation-error 27 | border: 0 none 28 | 29 | .validation-summary-errors 30 | color: #b94a48 31 | 32 | .validation-summary-valid 33 | display: none 34 | -------------------------------------------------------------------------------- /express-demo/express-demo/routes/index.js: -------------------------------------------------------------------------------- 1 |  2 | /* 3 | * GET home page. 4 | */ 5 | 6 | exports.index = function (req, res) { 7 | res.render('index', { title: 'Express', year: new Date().getFullYear() }); 8 | }; 9 | 10 | exports.about = function (req, res) { 11 | res.render('about', { title: 'About', year: new Date().getFullYear(), message: 'Your application description page.' }); 12 | }; 13 | 14 | exports.contact = function (req, res) { 15 | res.render('contact', { title: 'Contact', year: new Date().getFullYear(), message: 'Your contact page.' }); 16 | }; 17 | -------------------------------------------------------------------------------- /express-demo/express-demo/views/about.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h2 #{title}. 5 | h3 #{message} 6 | p Use this area to provide additional information. 7 | -------------------------------------------------------------------------------- /express-demo/express-demo/views/contact.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h2 #{title}. 5 | h3 #{message} 6 | address 7 | | One Microsoft Way 8 | br 9 | | Redmond, WA 98052-6399 10 | br 11 | abbr(title='Phone') P: 12 | | 425.555.0100 13 | 14 | address 15 | strong Support: 16 | a(href='mailto:Support@example.com') Support@example.com 17 | br 18 | strong Marketing: 19 | a(href='mailto:Marketing@example.com') Marketing@example.com 20 | -------------------------------------------------------------------------------- /express-demo/express-demo/views/index.jade: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | .jumbotron 5 | h1 Express 6 | p.lead Express is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript. 7 | p 8 | a.btn.btn-primary.btn-large(href='http://expressjs.com/') Learn more » 9 | .row 10 | .col-md-4 11 | h2 Getting started 12 | p Express gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and gives you full control over markup for enjoyable, agile development. 13 | p 14 | a.btn.btn-default(href='http://expressjs.com/') Learn more » 15 | .col-md-4 16 | h2 Get more libraries 17 | p Node Packaged Modules is a repository of software for Node.js. 18 | p 19 | a.btn.btn-default(href='https://www.npmjs.org/') Learn more » 20 | .col-md-4 21 | h2 Microsoft Azure 22 | p You can easily publish to Microsoft Azure using Node.js Tools for Visual Studio. Find out how you can host your application using a free trial today. 23 | p 24 | a.btn.btn-default(href='http://azure.microsoft.com') Learn more » 25 | -------------------------------------------------------------------------------- /express-demo/express-demo/views/layout.jade: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | meta(charset='utf-8') 5 | meta(name='viewport', content='width=device-width, initial-scale=1.0') 6 | title #{title} - My Express Application 7 | link(rel='stylesheet', type='text/css', href='/stylesheets/bootstrap.min.css') 8 | link(rel='stylesheet', type='text/css', href='/stylesheets/style.css') 9 | script(src='/javascripts/modernizr-2.6.2.js') 10 | body 11 | .navbar.navbar-inverse.navbar-fixed-top 12 | .container 13 | .navbar-header 14 | button.navbar-toggle(type='button', data-toggle='collapse', data-target='.navbar-collapse') 15 | span.icon-bar 16 | span.icon-bar 17 | span.icon-bar 18 | a.navbar-brand(href='/') Application name 19 | .navbar-collapse.collapse 20 | ul.nav.navbar-nav 21 | li 22 | a(href='/') Home 23 | li 24 | a(href='/about') About 25 | li 26 | a(href='/contact') Contact 27 | .container.body-content 28 | block content 29 | hr 30 | footer 31 | p © #{year} - My Express Application 32 | 33 | script(src='/javascripts/jquery-1.10.2.js') 34 | script(src='/javascripts/bootstrap.js') 35 | script(src='/javascripts/respond.js') 36 | 37 | block scripts 38 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-demos", 3 | "version": "0.0.1", 4 | "description": "Intro to Node.js for .NET Devs", 5 | "main": "./express-demo/express-demo/app.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "start": "node ./express-demo/express-demo/app.js", 11 | "test": "mocha" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/reverentgeek/nodejs-demos.git" 16 | }, 17 | "author": "David Neal", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/reverentgeek/nodejs-demos/issues" 21 | }, 22 | "homepage": "https://github.com/reverentgeek/nodejs-demos", 23 | "dependencies": { 24 | "edge": "^0.9.3", 25 | "lodash": "^4.17.19" 26 | }, 27 | "devDependencies": { 28 | "eslint": "^7.3.1", 29 | "eslint-config-leankit": "^2.0.0", 30 | "mocha": "^1.21.4", 31 | "should": "^4.0.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/hello.specs.js: -------------------------------------------------------------------------------- 1 | var should = require('should'); 2 | 3 | describe('Hello Y\'all...', function() { 4 | 5 | it('should pass this test', function(done){ 6 | var i = 1 + 2; 7 | i.should.equal(3); 8 | done(); 9 | }); 10 | 11 | describe ('Bob...', function() { 12 | var bob; 13 | before(function(done){ 14 | bob = { firstName: 'Bob', lastName: 'Middleman' }; 15 | done(); 16 | }); 17 | 18 | it('should have a firstName', function(){ 19 | should.exist(bob); 20 | bob.should.have.property('firstName'); 21 | bob.firstName.should.be.instanceOf(String); 22 | bob.firstName.length.should.be.above(0); 23 | }); 24 | 25 | it('should have a lastName', function(){ 26 | should.exist(bob); 27 | bob.should.have.property('lastName'); 28 | bob.lastName.should.be.instanceOf(String); 29 | bob.lastName.length.should.be.above(0); 30 | }); 31 | 32 | }); 33 | }); 34 | --------------------------------------------------------------------------------