diff --git a/.gitignore b/.gitignore index 5fdf453..42e2c62 100644 --- a/.gitignore +++ b/.gitignore @@ -22,4 +22,10 @@ Desktop.ini $RECYCLE.BIN/ # SublimeText project files -*.sublime-workspace \ No newline at end of file +*.sublime-workspace + +# build script dependencies +node_modules/ + +# production folder +production/ \ No newline at end of file diff --git a/README.md b/README.md index ec604b7..51e1905 100644 --- a/README.md +++ b/README.md @@ -9,19 +9,23 @@ this is an experiment for the web browser. it corrupts jpg images so that they a this experiment is very much based on the [smack my glitch up js](https://github.com/Hugosslade/smackmyglitchupjs) script. -minification / build +build script --- -the [requirejs optimizer](http://requirejs.org/docs/optimization.html) is used to minify both javascript and css files. -to minify javascript, run ```r.js -o name=main out=main.min.js``` in the terminal from the ```scripts``` folder. +the build script takes care of concatenating and minifying all scripts and styles. it uses [gruntjs](http://gruntjs.com/). -to minify css, run ```r.js -o cssIn=global.css out=global.min.css optimizeCss=default``` from the ```styles``` folder. +please make sure that both [nodejs](http://nodejs.org/) and grunt-cli are [set up properly](http://gruntjs.com/getting-started) on your machine. + +run ```npm install``` from within the ```build/``` folder to install the dependencies of the build script. + +to build, run ```grunt production``` from within the ```build/``` folder. the optimized files will get copied to the ```production/``` folder. third party code used in this experiment --- * [html5slider](http://frankyan.com/labs/html5slider/) by [fryn](https://github.com/fryn), MIT license * [js signals](http://millermedeiros.github.io/js-signals/) by [millermedeiros](https://github.com/millermedeiros), MIT license * [require js](http://requirejs.org/), by [jrburke](jrburke), BSD & MIT license +* [require js](https://github.com/jrburke/almond), by [jrburke](jrburke), BSD & MIT license * [raf js](https://gist.github.com/paulirish/1579671), by [paulirish](https://github.com/paulirish), MIT license license diff --git a/build/Gruntfile.js b/build/Gruntfile.js new file mode 100644 index 0000000..97bccc8 --- /dev/null +++ b/build/Gruntfile.js @@ -0,0 +1,74 @@ +// http://gruntjs.com/configuring-tasks +module.exports = function( grunt ) +{ + var grunt_configuration = { + pkg: grunt.file.readJSON( 'package.json' ), + requirejs: { + index: { + options: { + name: 'lib/almond-0.2.6', + include: 'main', + baseUrl: '../scripts/', + mainConfigFile: '../scripts/main.js', + out: '../production/scripts/main.min.js', + wrap: true + } + } + }, + cssmin: { + inline_import: { + files: { + '../production/styles/main.min.css': [ '../styles/main.css' ] + } + } + }, + copy: { + copy_html: { + options: { processContent: updateHTML }, + files: [ + { src: [ '../index.html' ], dest: '../production/index.html' } + ] + } + }, + imagemin: { + jpg: { + options: { progressive: true }, + files: [ + { + expand: true, + cwd: '../', + src: [ '**/*.jpg', '!**/production/**', '!**/node_modules/**' ], + dest: '../production/', + ext: '.jpg' + } + ] + } + } + }; + + function updateHTML( content, path ) + { + if ( path === '../index.html' ) + { + content = content + .replace( 'href="styles/main.css"', 'href="styles/main.min.css"' ) + .replace( 'src="scripts/lib/require-2.1.4.js"', 'src="scripts/main.min.js"' ) + .replace( ' data-main="scripts/main"', '' ); + } + + return content; + } + + grunt.initConfig( grunt_configuration ); + grunt.loadNpmTasks( 'grunt-contrib-requirejs' ); + grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); + grunt.loadNpmTasks( 'grunt-contrib-copy' ); + grunt.loadNpmTasks( 'grunt-contrib-imagemin' ); + + grunt.registerTask( 'default', [ 'requirejs', 'cssmin', 'copy', 'imagemin' ] ); + grunt.registerTask( 'production', [ 'requirejs', 'cssmin', 'copy', 'imagemin' ] ); + grunt.registerTask( 'js', [ 'requirejs' ] ); + grunt.registerTask( 'css', [ 'cssmin' ] ); + grunt.registerTask( 'cp', [ 'copy' ] ); + grunt.registerTask( 'img', [ 'imagemin' ] ); +}; \ No newline at end of file diff --git a/build/package.json b/build/package.json new file mode 100644 index 0000000..4d5c530 --- /dev/null +++ b/build/package.json @@ -0,0 +1,11 @@ +{ + "name": "jpg-glitch-build", + "version": "0.0.1", + "devDependencies": { + "grunt": "~0.4.1", + "grunt-contrib-requirejs": "~0.4.1", + "grunt-contrib-cssmin": "~0.6.1", + "grunt-contrib-copy": "~0.4.1", + "grunt-contrib-imagemin": "~0.3.0" + } +} diff --git a/index.html b/index.html index c024148..5bcdbc4 100644 --- a/index.html +++ b/index.html @@ -3,7 +3,7 @@ image glitch experiment - +
diff --git a/scripts/lib/almond-0.2.6.js b/scripts/lib/almond-0.2.6.js new file mode 100644 index 0000000..807815c --- /dev/null +++ b/scripts/lib/almond-0.2.6.js @@ -0,0 +1,410 @@ +/** + * almond 0.2.6 Copyright (c) 2011-2012, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*jslint sloppy: true */ +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, + foundI, foundStarMap, starI, i, j, part, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name && name.charAt(0) === ".") { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + //Convert baseName to array, and lop off the last part, + //so that . matches that "directory" and not name of the baseName's + //module. For instance, baseName of "one/two/three", maps to + //"one/two/three.js", but we want the directory, "one/two" for + //this normalization. + baseParts = baseParts.slice(0, baseParts.length - 1); + + name = baseParts.concat(name.split("/")); + + //start trimDots + for (i = 0; i < name.length; i += 1) { + part = name[i]; + if (part === ".") { + name.splice(i, 1); + i -= 1; + } else if (part === "..") { + if (i === 1 && (name[2] === '..' || name[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join("/"); + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relName) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relName)); + } else { + name = normalize(name, relName); + } + } else { + name = normalize(name, relName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, + args = [], + usingExports; + + //Use name if no relName + relName = relName || name; + + //Call the callback to define the module, if necessary. + if (typeof callback === 'function') { + + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relName); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback.apply(defined[name], args); + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, callback).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + config = cfg; + if (config.deps) { + req(config.deps, config.callback); + } + return req; + }; + + /** + * Expose module registry for debugging and tooling + */ + requirejs._defined = defined; + + define = function (name, deps, callback) { + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); diff --git a/styles/global.css b/styles/main.css similarity index 100% rename from styles/global.css rename to styles/main.css