diff --git a/.gitignore b/.gitignore index d2449be..bf68efe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules bower_components -.grunt -_SpecRunner.html +lib-instrumented +test/coverage diff --git a/.jshintrc b/.jshintrc index fa51fc3..9bc465f 100644 --- a/.jshintrc +++ b/.jshintrc @@ -1,21 +1,20 @@ { - "node": true, - "esnext": true, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "immed": true, - "indent": 4, - "latedef": true, - "newcap": true, - "noarg": true, - "quotmark": "single", - "regexp": true, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "smarttabs": true, - "white": true + "node": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "immed": false, + "indent": 2, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "single", + "regexp": true, + "undef": true, + "unused": true, + "trailing": true, + "smarttabs": true, + "browser": true, + "node": true } diff --git a/.travis.yml b/.travis.yml index b9207e5..7d999fb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,7 @@ language: node_js + node_js: - - '0.8' - - '0.10' + - "0.10" + +after_script: + - npm run coveralls diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1fe6214..285d92d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing ## Important notes -Please don't edit files in the `dist` subdirectory as they are generated via [Grunt](http://gruntjs.com/). You'll find source code in the `src` subdirectory! +Please don't edit files in the `dist` subdirectory as they are generated via [gulp](https://github.com/gulpjs/gulp). You'll find source code in the `lib` subdirectory! ### Code style Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** @@ -9,19 +9,19 @@ Regarding code style like indentation and whitespace, **follow the conventions y ## Modifying the code First, ensure that you have the latest [Node.js](http://nodejs.org/) and [npm](http://npmjs.org/) installed. -Test that Grunt's CLI is installed by running `grunt --version`. If the command isn't found, run `npm install -g grunt-cli`. For more information about installing Grunt, see the [getting started with Grunt guide](http://gruntjs.com/getting-started). +Test that gulp is installed globally by running `gulp --version` at the command-line. If gulp isn't installed globally, run `npm install -g gulp` to install the latest version. 1. Fork and clone the repo. -1. Run `npm install` to install all build dependencies (including Grunt). -1. Run `grunt` to grunt this project. +1. Run `npm install` to install all dependencies (including gulp). +1. Run `gulp` to build this project. -Assuming that you don't see any red, you're ready to go. Just be sure to run `grunt` after making any changes, to ensure that nothing is broken. +Assuming that you don't see any red, you're ready to go. Just be sure to run `gulp` after making any changes, to ensure that nothing is broken. ## Submitting pull requests 1. Create a new branch, please don't work in your `master` branch directly. -1. Add failing tests for the change you want to make. Run `grunt` to see the tests fail. +1. Add failing tests for the change you want to make. Run `gulp` to see the tests fail. 1. Fix stuff. -1. Run `grunt` to see if the tests pass. Repeat steps 2-4 until done. +1. Run `gulp` to see if the tests pass. Repeat steps 2-4 until done. 1. Update the documentation to reflect any changes. 1. Push to your fork and submit a pull request. diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index b003809..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,85 +0,0 @@ -// Generated on 2013-09-17 using generator-bespokeplugin v0.1.0 - -module.exports = function(grunt) { - - grunt.initConfig({ - pkg: grunt.file.readJSON('package.json'), - meta: { - banner: '/*!\n' + - ' * <%= pkg.title || pkg.name %> v<%= pkg.version %>\n' + - ' * <%= pkg.homepage %>\n' + - ' *\n' + - ' * Copyright <%= grunt.template.today("yyyy") %>, <%= pkg.author.name %>\n' + - ' * This content is released under the' + - ' <%= _.pluck(pkg.licenses, "type").join(", ") %> license<%= pkg.licenses.length === 1 ? "" : "s" %>\n' + - '' + - ' */\n\n', - microbanner: '/*! <%= pkg.title || pkg.name %> v<%= pkg.version %> ' + - '© <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>, ' + - 'Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n' - }, - clean: { - files: ['dist'] - }, - concat: { - options: { - banner: '<%= meta.banner %>', - stripBanners: true - }, - dist: { - src: ['src/<%= pkg.name %>.js'], - dest: 'dist/<%= pkg.name %>.js' - } - }, - uglify: { - options: { - banner: '<%= meta.microbanner %>' - }, - dist: { - src: ['<%= concat.dist.dest %>'], - dest: 'dist/<%= pkg.name %>.min.js' - } - }, - jasmine: { - src: 'src/**/*.js', - options: { - vendor: ['node_modules/bespoke/dist/bespoke.js'], - specs: 'spec/*Spec.js', - helpers: 'spec/*Helper.js' - } - }, - jshint: { - src: [ - 'Gruntfile.js', - 'src/**/*.js', - 'spec/**/*.js', - 'demo/**/*.js' - ], - options: { - jshintrc: '.jshintrc' - } - }, - micro: { - src: '<%= uglify.dist.dest %>', - options: { - limit: 1024, - gzip: true - } - }, - watch: { - files: '<%= jshint.src %>', - tasks: ['default'] - } - }); - - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-concat'); - grunt.loadNpmTasks('grunt-contrib-uglify'); - grunt.loadNpmTasks('grunt-contrib-jasmine'); - grunt.loadNpmTasks('grunt-contrib-jshint'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-micro'); - - grunt.registerTask('default', ['clean', 'jasmine', 'concat', 'uglify', 'micro']); - -}; diff --git a/LICENSE b/LICENSE index 28a353a..dcf9b32 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2013 Mark Dalgleish +Copyright 2014 Mark Dalgleish Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index f1c502f..1f89b59 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Build Status](https://secure.travis-ci.org/markdalgleish/bespoke-scale.png?branch=master)](https://travis-ci.org/markdalgleish/bespoke-scale) +[![Build Status](https://secure.travis-ci.org/markdalgleish/bespoke-scale.png?branch=master)](https://travis-ci.org/markdalgleish/bespoke-scale) [![Coverage Status](https://coveralls.io/repos/markdalgleish/bespoke-scale/badge.png)](https://coveralls.io/r/markdalgleish/bespoke-scale) # bespoke-scale @@ -13,14 +13,25 @@ Download the [production version][min] or the [development version][max], or use ## Usage -First, include both `bespoke.js` and `bespoke-scale.js` in your page. +This plugin is shipped in a [UMD format](https://github.com/umdjs/umd), meaning that it is available as a CommonJS/AMD module or browser global. -Then, simply include the plugin when instantiating your presentation. +For example, when using CommonJS modules: ```js -bespoke.from('article', { - scale: true -}); +var bespoke = require('bespoke'), + scale = require('bespoke-scale'); + +bespoke.from('article', [ + scale() +]); +``` + +When using browser globals: + +```js +bespoke.from('article', [ + bespoke.plugins.scale() +]); ``` By default, bespoke-scale detects which method to use for resizing slides. In browsers that support it, CSS `zoom` is used. In all other browsers, each slide is wrapped with an element with a `bespoke-scale-parent` class, which is resized with CSS transforms. You will need to provide styles for this element, for example: @@ -39,30 +50,23 @@ By default, bespoke-scale detects which method to use for resizing slides. In br If you'd like to specify which scaling method to use, you can pass `'zoom'` or `'transform'` as an option, for example: ```js -bespoke.from('article', { - scale: 'zoom' -}); +bespoke.from('article', [ + scale('zoom') +]); ``` ## Package managers -### Bower - -```bash -$ bower install bespoke-scale -``` - ### npm ```bash $ npm install bespoke-scale ``` -The bespoke-scale npm package is designed for use with [browserify](http://browserify.org/), e.g. +### Bower -```js -require('bespoke'); -require('bespoke-scale'); +```bash +$ bower install bespoke-scale ``` ## Credits diff --git a/bower.json b/bower.json index 1dc8f99..23092a9 100644 --- a/bower.json +++ b/bower.json @@ -1,7 +1,8 @@ { "name": "bespoke-scale", - "version": "0.2.0", + "version": "1.0.0", + "main": "./dist/bespoke-scale.js", "dependencies": { - "bespoke.js": ">=0.3.0" + "bespoke.js": "^1.0.0" } } diff --git a/demo/demo.js b/demo/demo.js index f59d9bc..afc48fc 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -1,5 +1,6 @@ -bespoke.from('article', { - keys: true, - touch: true, - scale: true -}); +bespoke.from('article', [ + bespoke.plugins.classes(), + bespoke.plugins.keys(), + bespoke.plugins.touch(), + bespoke.plugins.scale() +]); diff --git a/demo/index.html b/demo/index.html index 7e53f58..00918ee 100644 --- a/demo/index.html +++ b/demo/index.html @@ -26,9 +26,10 @@ + - + diff --git a/dist/bespoke-scale.js b/dist/bespoke-scale.js old mode 100644 new mode 100755 index 15b1702..9358fd5 --- a/dist/bespoke-scale.js +++ b/dist/bespoke-scale.js @@ -1,14 +1,14 @@ /*! - * bespoke-scale v0.2.0 - * https://github.com/markdalgleish/bespoke-scale + * bespoke-scale v1.0.0 * - * Copyright 2013, Mark Dalgleish + * Copyright 2014, Mark Dalgleish * This content is released under the MIT license + * http://mit-license.org/markdalgleish */ -(function(bespoke) { - - bespoke.plugins.scale = function(deck, options) { +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var n;"undefined"!=typeof window?n=window:"undefined"!=typeof global?n=global:"undefined"!=typeof self&&(n=self);var o=n;o=o.bespoke||(o.bespoke={}),o=o.plugins||(o.plugins={}),o.scale=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o v<%= version %>', + ' *', + ' * Copyright <%= new Date().getFullYear() %>, <%= author.name %>', + ' * This content is released under the <%= licenses[0].type %> license', + ' * <%= licenses[0].url %>', + ' */\n\n' + ].join('\n'), pkg))) + .pipe(gulp.dest('dist')) + .pipe(rename('bespoke-scale.min.js')) + .pipe(uglify()) + .pipe(header(template([ + '/*! <%= name %> v<%= version %> ', + '© <%= new Date().getFullYear() %> <%= author.name %>, ', + '<%= licenses[0].type %> License */\n' + ].join(''), pkg))) + .pipe(gulp.dest('dist')); +}); diff --git a/karma.conf.js b/karma.conf.js new file mode 100644 index 0000000..16c1a45 --- /dev/null +++ b/karma.conf.js @@ -0,0 +1,34 @@ +module.exports = function(config) { + config.set({ + basePath: '', + + frameworks: ['jasmine', 'browserify'], + + files: [ + 'test/spec/*Spec.js' + ], + + exclude: [], + + preprocessors: { + 'test/**/*.js': 'browserify' + }, + + reporters: ['progress', 'coverage'], + + coverageReporter: { + type : 'lcov', + dir : 'test/coverage' + }, + + port: 8080, + + logLevel: config.LOG_INFO, + + autoWatch: false, + + browsers: ['PhantomJS'], + + singleRun: true + }); +}; diff --git a/src/bespoke-scale.js b/lib/bespoke-scale.js similarity index 94% rename from src/bespoke-scale.js rename to lib/bespoke-scale.js index 1d054dc..ce4d832 100644 --- a/src/bespoke-scale.js +++ b/lib/bespoke-scale.js @@ -1,6 +1,5 @@ -(function(bespoke) { - - bespoke.plugins.scale = function(deck, options) { +module.exports = function(options) { + return function(deck) { var parent = deck.parent, firstSlide = deck.slides[0], slideHeight = firstSlide.offsetHeight, @@ -45,4 +44,4 @@ scaleAll(); }; -}(bespoke)); +}; diff --git a/package.json b/package.json index d11658d..403f212 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bespoke-scale", - "version": "0.2.0", + "version": "1.0.0", "description": "Responsive Slide Scaling for Bespoke.js", "homepage": "https://github.com/markdalgleish/bespoke-scale", "bugs": "https://github.com/markdalgleish/bespoke-scale/issues", @@ -8,40 +8,57 @@ "name": "Mark Dalgleish", "url": "https://github.com/markdalgleish" }, - "main": "./dist/bespoke-scale.js", + "main": "./lib/bespoke-scale.js", "repository": { "type": "git", "url": "git://github.com/markdalgleish/bespoke-scale.git" }, "scripts": { - "test": "grunt" + "test": "gulp", + "coveralls": "gulp coveralls" }, "peerDependencies": { - "bespoke": ">=0.3.0" + "bespoke": "^1.0.0" }, "devDependencies": { - "grunt-cli": "~0.1.9", - "grunt": "~0.4.1", - "grunt-contrib-jshint": "~0.6.4", - "grunt-contrib-jasmine": "~0.5.2", - "grunt-contrib-concat": "~0.3.0", - "grunt-contrib-uglify": "~0.2.4", - "grunt-contrib-clean": "~0.5.0", - "grunt-contrib-watch": "~0.5.3", - "grunt-micro": "~0.1.0", - "bespoke": "~0.4.0", - "bespoke-keys": "~0.1.0", - "bespoke-touch": "~0.1.0" + "bespoke": "^1.0.0", + "bespoke-classes": "^1.0.0", + "bespoke-keys": "^1.0.0", + "bespoke-touch": "^1.0.0", + "browserify": "^4.1.5", + "function-bind": "^0.1.0", + "gulp": "^3.5.1", + "gulp-clean": "^0.2.4", + "gulp-coveralls": "^0.1.0", + "gulp-header": "^1.0.2", + "gulp-jshint": "^1.3.4", + "gulp-karma": "0.0.2", + "gulp-rename": "^1.2.0", + "gulp-uglify": "^0.3.0", + "istanbul": "^0.2.11", + "jshint-stylish": "^0.1.5", + "karma": "^0.10.9", + "karma-browserify": "^0.2.1", + "karma-coverage": "^0.1.5", + "karma-jasmine": "^0.1.5", + "karma-phantomjs-launcher": "^0.1.4", + "karma-script-launcher": "^0.1.0", + "lodash": "^2.4.1", + "requirejs": "^2.1.10", + "vinyl-buffer": "0.0.0", + "vinyl-map": "^1.0.1", + "vinyl-source-stream": "^0.1.1" }, "engines": { - "node": ">=0.8.0" + "node": ">=0.10.0" }, "licenses": [ { - "type": "MIT" + "type": "MIT", + "url": "http://mit-license.org/markdalgleish" } ], "keywords": [ - "bespoke.js-plugin" + "bespoke-plugin" ] } diff --git a/spec/bespoke-scaleSpec.js b/spec/bespoke-scaleSpec.js deleted file mode 100644 index 7f3778d..0000000 --- a/spec/bespoke-scaleSpec.js +++ /dev/null @@ -1,120 +0,0 @@ -(function() { - 'use strict'; - - describe("bespoke-scale", function() { - - var container, deck, - - createDeck = function(width, height, pluginValue) { - var style = document.createElement('style'), - parent = document.createElement('article'); - - container = document.createElement('div'); - - style.innerText = - '.bespoke-scale-parent { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }' + - '.bespoke-parent { position: absolute; width: ' + width + 'px; height: ' + height + 'px; }' + - '.bespoke-slide { position: absolute; left: 50%; top: 50%; width: 100px; height: 100px; margin-left: -50px; margin-top: -50px; }'; - - for (var i = 0; i < 10; i++) { - parent.appendChild(document.createElement('section')); - } - - container.appendChild(style); - container.appendChild(parent); - document.body.appendChild(container); - - deck = bespoke.from(parent, { - scale: pluginValue != null ? pluginValue : true - }); - }, - - destroyDeck = function() { - document.body.removeChild(container); - }, - - resize = function(el, width, height) { - el.style.width = width + 'px'; - el.style.height = height + 'px'; - - var evt = document.createEvent('UIEvents'); - evt.initUIEvent('resize', true, false, window, 0); - window.dispatchEvent(evt); - }, - - transformProperty = (function(property) { - var prefixes = 'Moz Webkit O ms'.split(' '); - return prefixes.reduce(function(currentProperty, prefix) { - return prefix + property in document.createElement('div').style ? prefix + property : currentProperty; - }, property.toLowerCase()); - }('Transform')), - - actualSize = function(el, dimension) { - return el['offset' + (dimension === 'width' ? 'Width' : 'Height')] * - (el.style.zoom != null && el.style.zoom !== '' ? - el.style.zoom : - el.parentNode.style[transformProperty].match(/scale\(([0-9.]+)\)/)[1] - ); - }; - - [true, 'zoom', 'transform'].forEach(function(option) { - - describe("option value of '" + option + "'", function() { - - describe("loading a 4x3 pressentation", function() { - - beforeEach(createDeck.bind(null, 1024, 768, option)); - - if (option === 'transform') { - it("should wrap each of the slides in a 'bespoke-scale-parent'", function() { - deck.slides.forEach(function(slide) { - expect(slide.parentNode.className).toBe('bespoke-scale-parent'); - }); - }); - } - - it("should resize the slide to fit the height of the deck", function() { - expect(actualSize(deck.slides[0], 'height')).toBe(deck.parent.offsetHeight); - }); - - describe("resizing the window to a 3x4 ratio", function() { - - beforeEach(function() { - resize(deck.parent, 768, 1024, option) - }); - - it("should resize the slide to fit the width of the deck", function() { - expect(actualSize(deck.slides[0], 'width')).toBe(deck.parent.offsetWidth); - }); - - }); - - }); - - describe("loading a 16x9 pressentation", function() { - - beforeEach(createDeck.bind(null, 1280, 720, option)); - - it("should resize the slide to fit the height of the deck", function() { - expect(actualSize(deck.slides[0], 'height')).toBe(deck.parent.offsetHeight); - }); - - }); - - describe("loading a 3x4 pressentation", function() { - - beforeEach(createDeck.bind(null, 480, 640, option)); - - it("should resize the slide to fit the width of the deck", function() { - expect(actualSize(deck.slides[0], 'width')).toBe(deck.parent.offsetWidth); - }); - - }); - - }); - - }); - - }); - -}()); diff --git a/test/spec/bespoke-scaleSpec.js b/test/spec/bespoke-scaleSpec.js new file mode 100644 index 0000000..1bd0226 --- /dev/null +++ b/test/spec/bespoke-scaleSpec.js @@ -0,0 +1,120 @@ +Function.prototype.bind = Function.prototype.bind || require('function-bind'); + +var bespoke = require('bespoke'); +var scale = require('../../lib-instrumented/bespoke-scale.js'); + +describe("bespoke-scale", function() { + + var container, deck, + + createDeck = function(width, height, pluginValue) { + var style = document.createElement('style'), + parent = document.createElement('article'); + + container = document.createElement('div'); + + style.innerText = + '.bespoke-scale-parent { position: absolute; top: 0; left: 0; right: 0; bottom: 0; }' + + '.bespoke-parent { position: absolute; width: ' + width + 'px; height: ' + height + 'px; }' + + '.bespoke-slide { position: absolute; left: 50%; top: 50%; width: 100px; height: 100px; margin-left: -50px; margin-top: -50px; }'; + + for (var i = 0; i < 10; i++) { + parent.appendChild(document.createElement('section')); + } + + container.appendChild(style); + container.appendChild(parent); + document.body.appendChild(container); + + deck = bespoke.from(parent, [ + scale(pluginValue) + ]); + }, + + destroyDeck = function() { + document.body.removeChild(container); + }, + + resize = function(el, width, height) { + el.style.width = width + 'px'; + el.style.height = height + 'px'; + + var evt = document.createEvent('UIEvents'); + evt.initUIEvent('resize', true, false, window, 0); + window.dispatchEvent(evt); + }, + + transformProperty = (function(property) { + var prefixes = 'Moz Webkit O ms'.split(' '); + return prefixes.reduce(function(currentProperty, prefix) { + return prefix + property in document.createElement('div').style ? prefix + property : currentProperty; + }, property.toLowerCase()); + }('Transform')), + + actualSize = function(el, dimension) { + return el['offset' + (dimension === 'width' ? 'Width' : 'Height')] * + (el.style.zoom != null && el.style.zoom !== '' ? + el.style.zoom : + el.parentNode.style[transformProperty].match(/scale\(([0-9.]+)\)/)[1] + ); + }; + + [undefined, 'zoom', 'transform'].forEach(function(option) { + + describe("option value of '" + option + "'", function() { + + describe("loading a 4x3 pressentation", function() { + + beforeEach(createDeck.bind(null, 1024, 768, option)); + + if (option === 'transform') { + it("should wrap each of the slides in a 'bespoke-scale-parent'", function() { + deck.slides.forEach(function(slide) { + expect(slide.parentNode.className).toBe('bespoke-scale-parent'); + }); + }); + } + + it("should resize the slide to fit the height of the deck", function() { + expect(actualSize(deck.slides[0], 'height')).toBe(deck.parent.offsetHeight); + }); + + describe("resizing the window to a 3x4 ratio", function() { + + beforeEach(function() { + resize(deck.parent, 768, 1024, option) + }); + + it("should resize the slide to fit the width of the deck", function() { + expect(actualSize(deck.slides[0], 'width')).toBe(deck.parent.offsetWidth); + }); + + }); + + }); + + describe("loading a 16x9 pressentation", function() { + + beforeEach(createDeck.bind(null, 1280, 720, option)); + + it("should resize the slide to fit the height of the deck", function() { + expect(actualSize(deck.slides[0], 'height')).toBe(deck.parent.offsetHeight); + }); + + }); + + describe("loading a 3x4 pressentation", function() { + + beforeEach(createDeck.bind(null, 480, 640, option)); + + it("should resize the slide to fit the width of the deck", function() { + expect(actualSize(deck.slides[0], 'width')).toBe(deck.parent.offsetWidth); + }); + + }); + + }); + + }); + +});