├── .gitignore ├── .editorconfig ├── .eslintrc ├── coverage.svg ├── LICENSE ├── example ├── iframe.html ├── window.html └── index.html ├── lib ├── helpers.unit.js ├── factory.js ├── helpers.js ├── manager.js ├── postit.js └── manager.unit.js ├── docs ├── factory.md ├── helpers.md ├── postit.md └── manager.md ├── package.json ├── karma.conf.js ├── gulpfile.js ├── dist ├── postit.js └── postit.js.map ├── CONTRIBUTING.md ├── README.md └── CHANGELOG.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Numerous always-ignore extensions 2 | *.diff 3 | *.err 4 | *.orig 5 | *.log 6 | *.patch 7 | *.rej 8 | *.swo 9 | *.swp 10 | *.zip 11 | *.vi 12 | *.pid 13 | *.seed 14 | 15 | # OS or Editor 16 | .DS_Store 17 | Thumbs.db 18 | .cache 19 | .project 20 | .settings 21 | .tmproj 22 | *.esproj 23 | nbproject 24 | *.sublime-project 25 | *.sublime-workspace 26 | .idea 27 | 28 | # Directories to ignore 29 | node_modules 30 | coverage 31 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "browser": true, 4 | "node": true, 5 | "mocha": true, 6 | "jasmine": true 7 | }, 8 | "globals": { 9 | "sinon": true 10 | }, 11 | "rules": { 12 | "curly": 2, 13 | "complexity": [2, 15], 14 | "no-unused-vars": 1, 15 | "no-empty": 1, 16 | "strict": [2, "global"], 17 | "no-undef": 2, 18 | "quotes": [2, "single", "avoid-escape"], 19 | "no-loop-func": 1, 20 | "comma-dangle": [2, "never"], 21 | "semi": [2, "always"], 22 | "no-extra-semi": 1, 23 | "keyword-spacing": 1, 24 | "valid-typeof": 2 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /coverage.svg: -------------------------------------------------------------------------------- 1 | coveragecoverage99.33%99.33% -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 coopersemantics 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 | -------------------------------------------------------------------------------- /example/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PostIt 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /example/window.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PostIt 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /lib/helpers.unit.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('helpers', function() { 4 | var helpers = require('./helpers'); 5 | 6 | describe('serialize', function() { 7 | it('should serialize an object into a formatted string', function() { 8 | var object = { 9 | a: 'fooa', 10 | b: 'foob', 11 | c: 'fooc' 12 | }; 13 | 14 | expect(helpers.serialize(object)).to.equal('a=fooa, b=foob, c=fooc'); 15 | }); 16 | }); 17 | 18 | describe('shallowMerge', function() { 19 | it('should merge a shallow object', function() { 20 | var object1 = { 21 | a: 'bara', 22 | b: 'barb', 23 | c: 'barc' 24 | }; 25 | var object2 = { 26 | a: 'fooa', 27 | b: 'foob', 28 | c: 'fooc' 29 | }; 30 | var object3 = { 31 | a: 'bara', 32 | b: 'barb', 33 | c: 'barc' 34 | }; 35 | var object4 = { 36 | a: undefined, 37 | b: 'bazb', 38 | c: 'bazc' 39 | }; 40 | 41 | var merged1 = helpers.shallowMerge(object1, object2); 42 | var merged2 = helpers.shallowMerge(object3, object4); 43 | 44 | expect(merged1).to.deep.equal(object2); 45 | expect(merged2).to.deep.equal({ 46 | a: 'bara', 47 | b: 'bazb', 48 | c: 'bazc' 49 | }); 50 | }); 51 | }); 52 | }); 53 | -------------------------------------------------------------------------------- /lib/factory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var PostIt = require('./postit'); 4 | var instances = {}; 5 | 6 | /** 7 | * Factory Module. 8 | * @public 9 | */ 10 | 11 | var Factory = module.exports = {}; 12 | 13 | /** 14 | * Creates a `PostIt` factory (Singleton). 15 | * @param {string} id 16 | * @returns {object} 17 | * @public 18 | */ 19 | 20 | Factory.add = function(id) { 21 | var instance = instances[id]; 22 | 23 | // If a given `instance` is found, use it and RETURN EARLY. 24 | if (instance) { 25 | return instance; 26 | } 27 | 28 | // Otherwise, create a new `instance` and store it. 29 | return (instances[id] = new PostIt(id)); 30 | }; 31 | 32 | /** 33 | * Removes an explicit `PostIt`, factory instance. 34 | * @param {string} id 35 | * @returns {void} 36 | * @public 37 | */ 38 | 39 | Factory.remove = function(id) { 40 | delete instances[id]; 41 | }; 42 | 43 | /** 44 | * Gets an explicit `PostIt`, factory instance. 45 | * @param {string} id 46 | * @returns {object} 47 | * @public 48 | */ 49 | 50 | Factory.get = function(id) { 51 | return instances[id]; 52 | }; 53 | 54 | /** 55 | * Gets all `PostIt`, factory instances. 56 | * @returns {object} 57 | * @public 58 | */ 59 | 60 | Factory.getAll = function() { 61 | return instances; 62 | }; 63 | -------------------------------------------------------------------------------- /example/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PostIt 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /docs/factory.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Factory 4 | Factory Module. 5 | 6 | **Kind**: global variable 7 | **Access:** public 8 | 9 | * [Factory](#Factory) 10 | * [.add(id)](#Factory.add) ⇒ object 11 | * [.remove(id)](#Factory.remove) ⇒ void 12 | * [.get(id)](#Factory.get) ⇒ object 13 | * [.getAll()](#Factory.getAll) ⇒ object 14 | 15 | 16 | 17 | ### Factory.add(id) ⇒ object 18 | Creates a `PostIt` factory (Singleton). 19 | 20 | **Kind**: static method of [Factory](#Factory) 21 | **Access:** public 22 | 23 | | Param | Type | 24 | | --- | --- | 25 | | id | string | 26 | 27 | 28 | 29 | ### Factory.remove(id) ⇒ void 30 | Removes an explicit `PostIt`, factory instance. 31 | 32 | **Kind**: static method of [Factory](#Factory) 33 | **Access:** public 34 | 35 | | Param | Type | 36 | | --- | --- | 37 | | id | string | 38 | 39 | 40 | 41 | ### Factory.get(id) ⇒ object 42 | Gets an explicit `PostIt`, factory instance. 43 | 44 | **Kind**: static method of [Factory](#Factory) 45 | **Access:** public 46 | 47 | | Param | Type | 48 | | --- | --- | 49 | | id | string | 50 | 51 | 52 | 53 | ### Factory.getAll() ⇒ object 54 | Gets all `PostIt`, factory instances. 55 | 56 | **Kind**: static method of [Factory](#Factory) 57 | **Access:** public 58 | -------------------------------------------------------------------------------- /docs/helpers.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## helpers 4 | Helpers Module. 5 | 6 | **Kind**: global variable 7 | **Access:** public 8 | 9 | * [helpers](#helpers) 10 | * [.serialize(params)](#helpers.serialize) ⇒ string 11 | * [.shallowMerge(destination, source)](#helpers.shallowMerge) ⇒ object 12 | * [.openWindow(url, name, options)](#helpers.openWindow) ⇒ object 13 | 14 | 15 | 16 | ### helpers.serialize(params) ⇒ string 17 | Serializes an object into a formatted string. 18 | 19 | **Kind**: static method of [helpers](#helpers) 20 | **Access:** public 21 | 22 | | Param | Type | 23 | | --- | --- | 24 | | params | object | 25 | 26 | 27 | 28 | ### helpers.shallowMerge(destination, source) ⇒ object 29 | Merges a shallow `source` object into the `destination` object. 30 | 31 | **Kind**: static method of [helpers](#helpers) 32 | **Access:** public 33 | 34 | | Param | Type | 35 | | --- | --- | 36 | | destination | object | 37 | | source | object | 38 | 39 | 40 | 41 | ### helpers.openWindow(url, name, options) ⇒ object 42 | Loads a resource into a new browsing context (`window`). 43 | 44 | **Kind**: static method of [helpers](#helpers) 45 | **Access:** public 46 | **See**: [Window.open()](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) for more options. 47 | 48 | | Param | Type | 49 | | --- | --- | 50 | | url | string | 51 | | name | string | 52 | | options | object | 53 | | options.width | number | 54 | | options.height | number | 55 | 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "postit-js", 4 | "title": "PostIt", 5 | "description": "An elegant wrapper for postMessage.", 6 | "version": "1.1.7", 7 | "author": "coopersemantics", 8 | "license": "MIT", 9 | "repository": "outbrain/postit", 10 | "homepage": "https://github.com/outbrain/postit", 11 | "bugs": { 12 | "url": "https://github.com/outbrain/postit/issues" 13 | }, 14 | "keywords": [ 15 | "postit", 16 | "postit-js", 17 | "postMessage", 18 | "cross-window", 19 | "cross-origin", 20 | "cross-domain", 21 | "browser" 22 | ], 23 | "main": "dist/postit.js", 24 | "files": [ 25 | "lib/", 26 | "dist/" 27 | ], 28 | "scripts": { 29 | "preversion": "gulp test", 30 | "version": "gulp release && git add CHANGELOG.md -A dist docs", 31 | "prepublish": "gulp test", 32 | "test": "gulp test", 33 | "watch": "gulp" 34 | }, 35 | "devDependencies": { 36 | "browserify": "^13.0.1", 37 | "browserify-istanbul": "^2.0.0", 38 | "chai": "^3.5.0", 39 | "del": "^2.2.0", 40 | "gulp": "^3.9.1", 41 | "gulp-conventional-changelog": "^1.1.0", 42 | "gulp-eslint": "^2.0.0", 43 | "gulp-header": "^1.8.2", 44 | "gulp-jsdoc-to-markdown": "^1.2.2", 45 | "gulp-rename": "^1.2.2", 46 | "gulp-sourcemaps": "^1.6.0", 47 | "gulp-uglify": "^1.5.3", 48 | "istanbul": "^0.4.3", 49 | "karma": "^0.13.22", 50 | "karma-browserify": "^5.0.5", 51 | "karma-chai": "^0.1.0", 52 | "karma-chrome-launcher": "^1.0.1", 53 | "karma-coverage": "^1.0.0", 54 | "karma-mocha": "^1.0.1", 55 | "karma-phantomjs-launcher": "^1.0.0", 56 | "karma-sinon": "^1.0.5", 57 | "mocha": "^2.4.5", 58 | "phantomjs": "^2.1.7", 59 | "sinon": "^1.17.4", 60 | "vinyl-buffer": "^1.0.0", 61 | "vinyl-source-stream": "^1.1.0" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var istanbul = require('browserify-istanbul'); 4 | 5 | /* 6 | * Karam Config. 7 | * @see https://github.com/karma-runner/karma/blob/master/docs/config/01-configuration-file.md 8 | */ 9 | 10 | module.exports = function (config) { 11 | config.set({ 12 | // Base path that will be used to resolve all patterns. 13 | basePath: './', 14 | 15 | // Frameworks: https://npmjs.org/browse/keyword/karma-adapter 16 | frameworks: ['mocha', 'chai', 'sinon', 'browserify'], 17 | 18 | // Browserify config. 19 | browserify: { 20 | debug: true, 21 | transform: [istanbul({ 22 | ignore: ['**/*unit.js'] 23 | })] 24 | }, 25 | 26 | // Patterns to load in the browser. 27 | files: [ 28 | 'lib/**/*.js' 29 | ], 30 | 31 | // How long will Karma wait for a message from a browser before disconnecting from it (in ms). 32 | browserNoActivityTimeout: 60000, 33 | 34 | // List of files to exclude. 35 | exclude: [], 36 | 37 | // Preprocess matching files before serving them to the browser. 38 | // Available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor 39 | preprocessors: { 40 | 'lib/**/*.js': ['browserify'] 41 | }, 42 | 43 | // Available reporters: https://npmjs.org/browse/keyword/karma-reporter 44 | reporters: ['coverage', 'progress'], 45 | 46 | coverageReporter: { 47 | type: 'html', 48 | dir: 'coverage/' 49 | }, 50 | 51 | // Web server port. 52 | port: 9876, 53 | 54 | // Enable/disable colors in the output - reporters and logs. 55 | colors: true, 56 | 57 | // Logging levels: [config.LOG_DISABLE, config.LOG_ERROR, config.LOG_WARN, config.LOG_INFO, config.LOG_DEBUG] 58 | logLevel: config.LOG_INFO, 59 | 60 | // Enable/disable watching files. 61 | autoWatch: true, 62 | 63 | // Available browser launchers: https://npmjs.org/browse/keyword/karma-launcher 64 | browsers: ['PhantomJS', 'Chrome'], 65 | 66 | // Continuous Integration mode. 67 | singleRun: false 68 | }); 69 | }; 70 | -------------------------------------------------------------------------------- /docs/postit.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## PostIt 4 | **Kind**: global class 5 | **Access:** public 6 | 7 | * [PostIt](#PostIt) 8 | * [new PostIt(id)](#new_PostIt_new) 9 | * [.on(event, listener)](#PostIt+on) ⇒ object 10 | * [.off(event, [listener])](#PostIt+off) ⇒ object 11 | * [.emit(event, target, message, origin)](#PostIt+emit) ⇒ object 12 | 13 | 14 | 15 | ### new PostIt(id) 16 | PostIt Module. 17 | 18 | 19 | | Param | Type | 20 | | --- | --- | 21 | | id | string | 22 | 23 | 24 | 25 | ### postIt.on(event, listener) ⇒ object 26 | Registers a `listener` to a `PostIt` instance (`id`), for a given `event`. 27 | 28 | **Kind**: instance method of [PostIt](#PostIt) 29 | **Access:** public 30 | 31 | | Param | Type | 32 | | --- | --- | 33 | | event | string | 34 | | listener | function | 35 | 36 | 37 | 38 | ### postIt.off(event, [listener]) ⇒ object 39 | - If a `listener` is not provided, then unregister all listeners from a `PostIt` instance (`id`), for a given `event`. 40 | - If a `listener` is provided, then unregister a `listener` from a `PostIt` instance (`id`), for a given `event`. 41 | 42 | **Kind**: instance method of [PostIt](#PostIt) 43 | **Access:** public 44 | 45 | | Param | Type | 46 | | --- | --- | 47 | | event | string | 48 | | [listener] | function | 49 | 50 | 51 | 52 | ### postIt.emit(event, target, message, origin) ⇒ object 53 | - If `event` is an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for all given `event`s. 54 | - If `event` is not an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for a given `event`. 55 | 56 | **Kind**: instance method of [PostIt](#PostIt) 57 | **Access:** public 58 | 59 | | Param | Type | 60 | | --- | --- | 61 | | event | string | 62 | | target | object | 63 | | message | string | array | object | 64 | | origin | string | 65 | 66 | -------------------------------------------------------------------------------- /lib/helpers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Helpers Module. 5 | * @public 6 | */ 7 | 8 | var helpers = module.exports = {}; 9 | 10 | /** 11 | * Serializes an object into a formatted string. 12 | * @param {object} params 13 | * @returns {string} 14 | * @public 15 | */ 16 | 17 | helpers.serialize = function(params) { 18 | var _params = []; 19 | 20 | for (var param in params) { 21 | _params.push(param + '=' + params[param]); 22 | } 23 | 24 | return _params.join(', '); 25 | }; 26 | 27 | /** 28 | * Merges a shallow `source` object into the `destination` object. 29 | * @param {object} destination 30 | * @param {object} source 31 | * @returns {object} 32 | * @public 33 | */ 34 | 35 | helpers.shallowMerge = function(destination, source) { 36 | for (var prop in source) { 37 | if (null != source[prop]) { 38 | destination[prop] = source[prop]; 39 | } 40 | } 41 | 42 | return destination; 43 | }; 44 | 45 | /** 46 | * Loads a resource into a new browsing context (`window`). 47 | * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open|Window.open()} for more options. 48 | * @param {string} url 49 | * @param {string} name 50 | * @param {object} options 51 | * @param {number} options.width 52 | * @param {number} options.height 53 | * @returns {object} 54 | * @public 55 | */ 56 | 57 | /* istanbul ignore next */ 58 | helpers.openWindow = function(url, name, options) { 59 | options = options || {}; 60 | 61 | var that = this; 62 | var nativeScreen = screen || {}; 63 | var nativeWindow = window; 64 | var nativeDocument = document; 65 | var nativeDocumentElement = nativeDocument.documentElement || {}; 66 | var dualScreenLeft = nativeWindow.screenLeft || nativeScreen.left || 0; 67 | var dualScreenTop = nativeWindow.screenTop || nativeScreen.top || 0; 68 | var width = nativeWindow.innerWidth || nativeDocumentElement.clientWidth || nativeScreen.width || 0; 69 | var height = nativeWindow.innerHeight || nativeDocumentElement.clientHeight || nativeScreen.height || 0; 70 | var left = ((width / 2) - (options.width / 2)) + dualScreenLeft; 71 | var top = ((height / 2) - (options.height / 2)) + dualScreenTop; 72 | var features = that.serialize(that.shallowMerge({ 73 | top: top, 74 | left: left 75 | }, options)); 76 | var newWindow = nativeWindow.open(url, name, features); 77 | 78 | if (nativeWindow.focus) { 79 | newWindow.focus(); 80 | } 81 | 82 | return newWindow; 83 | }; 84 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var path = require('path'); 4 | var gulp = require('gulp'); 5 | var rename = require('gulp-rename'); 6 | var uglify = require('gulp-uglify'); 7 | var sourcemaps = require('gulp-sourcemaps'); 8 | var header = require('gulp-header'); 9 | var eslint = require('gulp-eslint'); 10 | var gulpJsdoc2md = require('gulp-jsdoc-to-markdown'); 11 | var conventionalChangelog = require('gulp-conventional-changelog'); 12 | var browserify = require('browserify'); 13 | var source = require('vinyl-source-stream'); 14 | var buffer = require('vinyl-buffer'); 15 | var Server = require('karma').Server; 16 | var del = require('del'); 17 | var version = require('./package').version; 18 | 19 | var basePath = path.resolve(__dirname, '.'); 20 | var libPath = path.join(basePath, 'lib'); 21 | 22 | var glob = { 23 | all: ['*.js', path.join(libPath, '**', '*.js')], 24 | lib: [path.join(libPath, '**', '*.js')], 25 | docs: [path.join(libPath, '**', '!(*.unit).js')], 26 | app: [path.join(libPath, 'manager.js')] 27 | }; 28 | 29 | var banner = ['/*', 30 | ' * PostIt v<%= version %>', 31 | ' * Copyright 2016 coopersemantics', 32 | ' * Available under MIT license ', 33 | ' * @Date <%= date %>', 34 | ' */', 35 | ''].join('\n'); 36 | 37 | // Linting. 38 | gulp.task('lint', function () { 39 | return gulp.src(glob.all) 40 | .pipe(eslint()) 41 | .pipe(eslint.format()); 42 | }); 43 | 44 | // Functional tests (unit). 45 | gulp.task('unit', function (done) { 46 | del.sync('./coverage/**'); 47 | 48 | return new Server({ 49 | configFile: path.join(basePath, 'karma.conf.js'), 50 | singleRun: true 51 | }, done).start(); 52 | }); 53 | 54 | // Build `dist` dir/files. 55 | gulp.task('build', function () { 56 | del.sync('./dist/**'); 57 | 58 | return browserify({ 59 | entries: glob.app, 60 | standalone: 'PostIt', 61 | debug: true 62 | }) 63 | .bundle() 64 | .on('error', console.error.bind(console)) 65 | .pipe(source('postit.js')) 66 | .pipe(buffer()) 67 | .pipe(sourcemaps.init({ loadMaps: true })) 68 | .pipe(uglify()) 69 | .pipe(header(banner, { 70 | version: version, 71 | date: new Date() 72 | })) 73 | .pipe(rename('postit.js')) 74 | .pipe(sourcemaps.write('./')) 75 | .pipe(gulp.dest('./dist')) 76 | .on('finish', console.log.bind(console, '`build` task complete')); 77 | }); 78 | 79 | // `CHANGELOG.md` creation. 80 | gulp.task('changelog', function () { 81 | return gulp.src('CHANGELOG.md', { 82 | buffer: false 83 | }) 84 | .pipe(conventionalChangelog({ 85 | preset: 'eslint' 86 | })) 87 | .pipe(gulp.dest('./')); 88 | }); 89 | 90 | // Documentation creation. 91 | gulp.task('docs', function () { 92 | del.sync('./docs/**'); 93 | 94 | return gulp.src(glob.docs) 95 | .pipe(gulpJsdoc2md()) 96 | .on('error', function (err) { 97 | throw new Error(err); 98 | }) 99 | .pipe(rename(function (path) { 100 | path.extname = '.md'; 101 | })) 102 | .pipe(gulp.dest('./docs')); 103 | }); 104 | 105 | // Run the `test` task, when a file changes. 106 | gulp.task('watch', function() { 107 | return gulp.watch(glob.lib, ['test']); 108 | }); 109 | 110 | gulp.task('test', ['lint', 'unit']); 111 | gulp.task('release', ['build', 'changelog', 'docs']); 112 | gulp.task('default', ['watch']); 113 | -------------------------------------------------------------------------------- /dist/postit.js: -------------------------------------------------------------------------------- 1 | /* 2 | * PostIt v1.1.7 3 | * Copyright 2016 coopersemantics 4 | * Available under MIT license 5 | * @Date Wed Jul 13 2016 16:25:23 GMT-0400 (EDT) 6 | */ 7 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;t="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,t.PostIt=e()}}(function(){return function e(t,n,r){function i(s,u){if(!n[s]){if(!t[s]){var f="function"==typeof require&&require;if(!u&&f)return f(s,!0);if(o)return o(s,!0);var a=new Error("Cannot find module '"+s+"'");throw a.code="MODULE_NOT_FOUND",a}var c=n[s]={exports:{}};t[s][0].call(c.exports,function(e){var n=t[s][1][e];return i(n?n:e)},c,c.exports,e,t,n,r)}return n[s].exports}for(var o="function"==typeof require&&require,s=0;s.. 75 | ``` 76 | 77 | And constructed with the following guidelines: 78 | 79 | - Breaking backward compatibility **bumps the major** while resetting minor and patch. 80 | - New additions without breaking backward compatibility **bumps the minor** while resetting the patch. 81 | - Bug fixes and misc. changes **bumps only the patch**. 82 | 83 | For more information on SemVer, please visit . 84 | 85 | ## Browser Support 86 | 87 | | Browser | Version | 88 | |:-----------------:|:-------:| 89 | | Chrome | Latest | 90 | | Firefox | Latest | 91 | | Safari | Latest | 92 | | Internet Explorer | 9+ * | 93 | 94 | *= `PostIt.openWindow` does not work in IE (cross-domain), whilst using `.postMessage`; however, `iframe` support is available. 95 | 96 | ## Coding Guidelines 97 | 98 | Please adhere to the current style conventions. `ESLint` will catch most of the problematic issues that could occur, syntactically. In addition, when adding new features and/or updating existing code, please update/add unit tests, accordingly. 99 | 100 | ### Contributor API Docs 101 | 102 | [Contributor API Docs](docs) 103 | -------------------------------------------------------------------------------- /lib/manager.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Factory = require('./factory'); 4 | var helpers = require('./helpers'); 5 | 6 | /** 7 | * Manager Module. 8 | * @public 9 | */ 10 | 11 | var Manager = module.exports = {}; 12 | 13 | /** 14 | * Creates and manages a `PostIt` instance (`id`). 15 | * @param {string} id 16 | * @returns {object} 17 | * @public 18 | */ 19 | 20 | Manager.add = function(id) { 21 | var that = this; 22 | 23 | if ('string' !== typeof id) { 24 | console.warn(id + ' should be a `String`.'); 25 | 26 | return that; 27 | } 28 | 29 | // Create a memoized factory. 30 | Factory.add(id); 31 | 32 | return that; 33 | }; 34 | 35 | /** 36 | * Removes a `PostIt` instance (`id`). 37 | * @param {string} id 38 | * @returns {object} 39 | * @public 40 | */ 41 | 42 | Manager.remove = function(id) { 43 | var that = this; 44 | var record = that.get(id); 45 | 46 | if (!record) { 47 | return that; 48 | } 49 | 50 | // Remove listeners to avoid memory leaks. 51 | for (var event in record.listeners) { 52 | record.off(event); 53 | } 54 | 55 | Factory.remove(id); 56 | 57 | return that; 58 | }; 59 | 60 | /** 61 | * Removes all `PostIt` instances. 62 | * @return {object} 63 | * @public 64 | */ 65 | 66 | Manager.removeAll = function() { 67 | var that = this; 68 | var records = that.getAll(); 69 | 70 | for (var record in records) { 71 | that.remove(record); 72 | } 73 | 74 | return that; 75 | }; 76 | 77 | /** 78 | * Returns the length of all `PostIt` instances. 79 | * @return {number} 80 | * @public 81 | */ 82 | 83 | Manager.size = function() { 84 | var size = 0; 85 | var records = this.getAll(); 86 | 87 | for (var record in records) { 88 | size++; 89 | } 90 | 91 | return size; 92 | }; 93 | 94 | /** 95 | * Gets a `PostIt` instance (`id`). 96 | * @param {string} id 97 | * @returns {object|void} 98 | */ 99 | 100 | Manager.get = function(id) { 101 | return Factory.get(id) || console.warn(id + ' does not match any `PostIt` instances.'); 102 | }; 103 | 104 | /** 105 | * Gets all `PostIt` instances. 106 | * @returns {object} 107 | */ 108 | 109 | Manager.getAll = function() { 110 | return Factory.getAll(); 111 | }; 112 | 113 | /** 114 | * @see {@link postit.md#PostIt+on} for further information. 115 | * @param {string} id 116 | * @param {string} event 117 | * @param {function} listener 118 | * @returns {object} 119 | * @public 120 | */ 121 | 122 | Manager.on = function(id, event, listener) { 123 | var that = this; 124 | var record = that.get(id); 125 | 126 | if (!record) { 127 | return that; 128 | } 129 | 130 | record.on(event, listener); 131 | 132 | return that; 133 | }; 134 | 135 | /** 136 | * @see {@link postit.md#PostIt+off} for further information. 137 | * @param {string} id 138 | * @param {string} event 139 | * @param {function=} listener 140 | * @returns {object} 141 | * @public 142 | */ 143 | 144 | Manager.off = function(id, event, listener) { 145 | var that = this; 146 | var record = that.get(id); 147 | 148 | if (!record) { 149 | return that; 150 | } 151 | 152 | record.off(event, listener); 153 | 154 | return that; 155 | }; 156 | 157 | /** 158 | * @see {@link postit.md#PostIt+emit} for further information. 159 | * @param {string} id 160 | * @param {string} event 161 | * @param {object} target 162 | * @param {string|array|object} message 163 | * @param {string} origin 164 | * @returns {object} 165 | * @public 166 | */ 167 | 168 | Manager.emit = function(id, event, target, message, origin) { 169 | var that = this; 170 | var record = that.get(id); 171 | 172 | if (!record) { 173 | return that; 174 | } 175 | 176 | record.emit(event, target, message, origin); 177 | 178 | return that; 179 | }; 180 | 181 | /** 182 | * @see {@link helpers.md#helpers.openWindow} for further information. 183 | * @param {string} url 184 | * @param {string} name 185 | * @param {object} options 186 | * @param {number} options.width 187 | * @param {number} options.height 188 | * @public 189 | */ 190 | 191 | Manager.openWindow = function(url, name, options) { 192 | return helpers.openWindow(url, name, options); 193 | }; 194 | -------------------------------------------------------------------------------- /lib/postit.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * PostIt Module. 5 | * @constructor 6 | * @param {string} id 7 | * @public 8 | */ 9 | 10 | var PostIt = module.exports = function(id) { 11 | this.id = id; 12 | this.nextGuid = 0; 13 | this.listeners = {}; 14 | }; 15 | 16 | /** 17 | * Registers a `listener` to a `PostIt` instance (`id`), for a given `event`. 18 | * @param {string} event 19 | * @param {function} listener 20 | * @returns {object} 21 | * @public 22 | */ 23 | 24 | PostIt.prototype.on = function(event, listener) { 25 | var that = this; 26 | 27 | var listeners = that.listeners[event] = that.listeners[event] || []; 28 | listener.guid = that.nextGuid++; 29 | listeners.dispatcher = dispatcher; 30 | 31 | listeners.push(listener); 32 | 33 | function dispatcher(evt) { 34 | var data = null; 35 | 36 | if (/__postit\s?"/.test(evt.data)) { 37 | try { 38 | data = evt.dataParsed = JSON.parse(evt.data); 39 | } catch (err) { 40 | console.error(err); 41 | } 42 | } 43 | 44 | if (!data || // The preferred symbol (`__postit`) is not present, or an 'Uncaught SyntaxError' occurs, whilst parsing `evt.data` => RETURN EARLY, 45 | that.id !== data.__id || // or an instance identifier does not match => RETURN EARLY, 46 | (event !== data.__event && '*' !== event) || // or an event does not match, and an asterisk (*) is not the event => RETURN EARLY 47 | ('null' !== evt.origin && -1 === data.__origin.indexOf(evt.origin)) // or `'null'` is not the `evt.origin`, and the origins do not match. => RETURN EARLY 48 | ) { 49 | return; 50 | } 51 | 52 | for (var i = 0; i < listeners.length; ++i) { 53 | listeners[i].call(this, evt); 54 | } 55 | } 56 | 57 | // Only attach one dispatcher per `event`. 58 | if (listeners.length === 1) { 59 | window.addEventListener('message', dispatcher, false); 60 | } 61 | 62 | return that; 63 | }; 64 | 65 | /** 66 | * - If a `listener` is not provided, then unregister all listeners from a `PostIt` instance (`id`), for a given `event`. 67 | * - If a `listener` is provided, then unregister a `listener` from a `PostIt` instance (`id`), for a given `event`. 68 | * @param {string} event 69 | * @param {function=} listener 70 | * @returns {object} 71 | * @public 72 | */ 73 | 74 | PostIt.prototype.off = function(event, listener) { 75 | var that = this; 76 | var listeners = that.listeners[event] || []; 77 | 78 | for (var i = 0; i < listeners.length; ++i) { 79 | if (!listener || listener.guid === listeners[i].guid) { 80 | listeners.splice(i--, 1); 81 | } 82 | } 83 | 84 | if (!listeners.length) { 85 | window.removeEventListener('message', listeners.dispatcher, false); 86 | 87 | delete that.listeners[event]; 88 | } 89 | 90 | return that; 91 | }; 92 | 93 | /** 94 | * - If `event` is an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for all given `event`s. 95 | * - If `event` is not an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for a given `event`. 96 | * @param {string} event 97 | * @param {object} target 98 | * @param {string|array|object} message 99 | * @param {string} origin 100 | * @returns {object} 101 | * @public 102 | */ 103 | 104 | PostIt.prototype.emit = function(event, target, message, origin) { 105 | var that = this; 106 | var eventOrigin = window.location.href; 107 | var symbol = 'postit'; 108 | 109 | switch (Object.prototype.toString.call(message)) { 110 | case '[object Function]': 111 | console.warn(message + ' should either be an `Object`, `Array` or `String`.'); 112 | 113 | return that; 114 | 115 | case '[object Object]': 116 | message.__postit = symbol; 117 | message.__id = that.id; 118 | message.__event = event; 119 | message.__origin = eventOrigin; 120 | message = JSON.stringify(message); 121 | 122 | break; 123 | 124 | default: 125 | message = JSON.stringify({ 126 | __postit: symbol, 127 | __value: message, 128 | __id: that.id, 129 | __event: event, 130 | __origin: eventOrigin 131 | }); 132 | } 133 | 134 | target.postMessage(message, origin); 135 | 136 | return that; 137 | }; 138 | -------------------------------------------------------------------------------- /docs/manager.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Manager 4 | Manager Module. 5 | 6 | **Kind**: global variable 7 | **Access:** public 8 | 9 | * [Manager](#Manager) 10 | * [.add(id)](#Manager.add) ⇒ object 11 | * [.remove(id)](#Manager.remove) ⇒ object 12 | * [.removeAll()](#Manager.removeAll) ⇒ object 13 | * [.size()](#Manager.size) ⇒ number 14 | * [.get(id)](#Manager.get) ⇒ object | void 15 | * [.getAll()](#Manager.getAll) ⇒ object 16 | * [.on(id, event, listener)](#Manager.on) ⇒ object 17 | * [.off(id, event, [listener])](#Manager.off) ⇒ object 18 | * [.emit(id, event, target, message, origin)](#Manager.emit) ⇒ object 19 | * [.openWindow(url, name, options)](#Manager.openWindow) 20 | 21 | 22 | 23 | ### Manager.add(id) ⇒ object 24 | Creates and manages a `PostIt` instance (`id`). 25 | 26 | **Kind**: static method of [Manager](#Manager) 27 | **Access:** public 28 | 29 | | Param | Type | 30 | | --- | --- | 31 | | id | string | 32 | 33 | 34 | 35 | ### Manager.remove(id) ⇒ object 36 | Removes a `PostIt` instance (`id`). 37 | 38 | **Kind**: static method of [Manager](#Manager) 39 | **Access:** public 40 | 41 | | Param | Type | 42 | | --- | --- | 43 | | id | string | 44 | 45 | 46 | 47 | ### Manager.removeAll() ⇒ object 48 | Removes all `PostIt` instances. 49 | 50 | **Kind**: static method of [Manager](#Manager) 51 | **Access:** public 52 | 53 | 54 | ### Manager.size() ⇒ number 55 | Returns the length of all `PostIt` instances. 56 | 57 | **Kind**: static method of [Manager](#Manager) 58 | **Access:** public 59 | 60 | 61 | ### Manager.get(id) ⇒ object | void 62 | Gets a `PostIt` instance (`id`). 63 | 64 | **Kind**: static method of [Manager](#Manager) 65 | 66 | | Param | Type | 67 | | --- | --- | 68 | | id | string | 69 | 70 | 71 | 72 | ### Manager.getAll() ⇒ object 73 | Gets all `PostIt` instances. 74 | 75 | **Kind**: static method of [Manager](#Manager) 76 | 77 | 78 | ### Manager.on(id, event, listener) ⇒ object 79 | **Kind**: static method of [Manager](#Manager) 80 | **Access:** public 81 | **See**: [postit.md#PostIt+on](postit.md#PostIt+on) for further information. 82 | 83 | | Param | Type | 84 | | --- | --- | 85 | | id | string | 86 | | event | string | 87 | | listener | function | 88 | 89 | 90 | 91 | ### Manager.off(id, event, [listener]) ⇒ object 92 | **Kind**: static method of [Manager](#Manager) 93 | **Access:** public 94 | **See**: [postit.md#PostIt+off](postit.md#PostIt+off) for further information. 95 | 96 | | Param | Type | 97 | | --- | --- | 98 | | id | string | 99 | | event | string | 100 | | [listener] | function | 101 | 102 | 103 | 104 | ### Manager.emit(id, event, target, message, origin) ⇒ object 105 | **Kind**: static method of [Manager](#Manager) 106 | **Access:** public 107 | **See**: [postit.md#PostIt+emit](postit.md#PostIt+emit) for further information. 108 | 109 | | Param | Type | 110 | | --- | --- | 111 | | id | string | 112 | | event | string | 113 | | target | object | 114 | | message | string | array | object | 115 | | origin | string | 116 | 117 | 118 | 119 | ### Manager.openWindow(url, name, options) 120 | **Kind**: static method of [Manager](#Manager) 121 | **Access:** public 122 | **See**: [helpers.md#helpers.openWindow](helpers.md#helpers.openWindow) for further information. 123 | 124 | | Param | Type | 125 | | --- | --- | 126 | | url | string | 127 | | name | string | 128 | | options | object | 129 | | options.width | number | 130 | | options.height | number | 131 | 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostIt 2 | 3 | An elegant wrapper for [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage). 4 | 5 | ![Unit Test Coverage](https://cdn.rawgit.com/outbrain/postit/master/coverage.svg) 6 | [![Known Vulnerabilities](https://snyk.io/test/npm/postit-js/badge.svg)](https://snyk.io/test/npm/postit-js) 7 | 8 | ## Installation 9 | 10 | Install `postit-js` as a dependency. 11 | 12 | ```bash 13 | $ npm install --save postit-js 14 | ``` 15 | 16 | ## Run PostIt in a Browser 17 | 18 | ### HTML Script Element 19 | 20 | ```html 21 | 22 | ``` 23 | 24 | ### CommonJS Browser Shimming (Browserify and Other Flavors) 25 | 26 | ```js 27 | var PostIt = require('postit'); 28 | ``` 29 | 30 | ## API Documentation 31 | 32 | ### .add(id) => `object` 33 | 34 | Creates and manages a `PostIt` instance (`id`). 35 | 36 | | Param | Type | 37 | |:-----:|:--------:| 38 | | id | `string` | 39 | 40 | ```javascript 41 | PostIt.add('baz'); 42 | ``` 43 | 44 | ### .remove(id) => `object` 45 | 46 | Removes a `PostIt` instance (`id`). 47 | 48 | | Param | Type | 49 | |:-----:|:--------:| 50 | | id | `string` | 51 | 52 | ```javascript 53 | PostIt.remove('baz'); 54 | ``` 55 | 56 | ### .removeAll() => `object` 57 | 58 | Removes all `PostIt` instances. 59 | 60 | ```javascript 61 | PostIt.removeAll(); 62 | ``` 63 | 64 | ### .size() => `number` 65 | 66 | Returns the length of all `PostIt` instances. 67 | 68 | ```javascript 69 | PostIt.size(); 70 | ``` 71 | 72 | ### .get(id) => `object` | `void` 73 | 74 | Gets a `PostIt` instance (`id`). 75 | 76 | | Param | Type | 77 | |:-----:|:--------:| 78 | | id | `string` | 79 | 80 | ```javascript 81 | PostIt.get('baz'); 82 | ``` 83 | 84 | ### .getAll() => `object` 85 | 86 | Gets all `PostIt` instances. 87 | 88 | ```javascript 89 | PostIt.getAll(); 90 | ``` 91 | 92 | ### .on(id, event, listener) => `object` 93 | 94 | Registers a `listener` to a `PostIt` instance (`id`), for a given `event`. 95 | 96 | | Param | Type | 97 | |:--------:|:----------:| 98 | | id | `string` | 99 | | event | `string` | 100 | | listener | `function` | 101 | 102 | ```javascript 103 | PostIt.on('baz', 'bar', function(event) { 104 | // ... 105 | }); 106 | ``` 107 | 108 | ### .off(id, event[, listener]) => `object` 109 | 110 | - If a `listener` is not provided, then unregister all listeners from a `PostIt` instance (`id`), for a given `event`. 111 | - If a `listener` is provided, then unregister a `listener` from a `PostIt` instance (`id`), for a given `event`. 112 | 113 | | Param | Type | 114 | |:----------:|:----------:| 115 | | id | `string` | 116 | | event | `string` | 117 | | [listener] | `function` | 118 | 119 | ```javascript 120 | PostIt.off('baz', 'bar'); 121 | 122 | function bazBar() {} 123 | 124 | PostIt.off('baz', 'bar', bazBar); 125 | ``` 126 | 127 | ### .emit(id, event, target, message, origin) => `object` 128 | 129 | - If `event` is an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for all given `event`s. 130 | - If `event` is not an asterisk (\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for a given `event`. 131 | 132 | | Param | Type | 133 | |:-------:|:-------------------------:| 134 | | id | `string` | 135 | | event | `string` | 136 | | target | `object` | 137 | | message | `string` `array` `object` | 138 | | origin | `string` | 139 | 140 | ```javascript 141 | PostIt.emit('baz', 'bar', window.parent.opener, { baz: 'bar' }, 'http://www.baz.com'); 142 | ``` 143 | 144 | ### .openWindow(url, name, options) => `object` 145 | 146 | Loads a resource into a new browsing context (`window`). 147 | 148 | | Param | Type | 149 | |:--------------:|:--------:| 150 | | url | `string` | 151 | | name | `string` | 152 | | options | `object` | 153 | | options.width | `number` | 154 | | options.height | `number` | 155 | 156 | See: [window.open](https://developer.mozilla.org/en-US/docs/Web/API/Window/open) for more options. 157 | 158 | ```javascript 159 | PostIt.openWindow('http://www.foo.com', 'foo', { 160 | width: 700, 161 | height: 500 162 | }); 163 | ``` 164 | 165 | ## Example 166 | 167 | [Example](example) 168 | 169 | ## Contributing 170 | 171 | [Contributing](CONTRIBUTING.md) 172 | 173 | ## Changelog 174 | 175 | [Changelog](CHANGELOG.md) 176 | 177 | ## License 178 | 179 | [MIT License](LICENSE) 180 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [1.1.7](https://github.com/outbrain/postit/compare/v1.1.6...v1.1.7) (2016-07-13) 3 | 4 | 5 | ### Docs 6 | 7 | * Update `README` documentation to display the `coverage` badge. ([47d5ba6f51e80c9ec61f520526b09c30ab5fd59d](https://github.com/outbrain/postit/commit/47d5ba6f51e80c9ec61f520526b09c30ab5fd59d)) 8 | 9 | 10 | 11 | 12 | ## [1.1.6](https://github.com/outbrain/postit/compare/v1.1.5...v1.1.6) (2016-05-25) 13 | 14 | 15 | ### Docs 16 | 17 | * Update `/example/*.html` and `README` documentation. ([44a2fbaab42082728ff12ff6ca4d0aee2dda53c2](https://github.com/outbrain/postit/commit/44a2fbaab42082728ff12ff6ca4d0aee2dda53c2)) 18 | 19 | 20 | 21 | 22 | ## [1.1.5](https://github.com/outbrain/postit/compare/v1.1.4...v1.1.5) (2016-05-13) 23 | 24 | 25 | ### Docs 26 | 27 | * Update `README` documentation. ([072520acd3690b356abb50c0b1af62f8b206cab9](https://github.com/outbrain/postit/commit/072520acd3690b356abb50c0b1af62f8b206cab9)) 28 | 29 | ### Upgrade 30 | 31 | * Update `package` dependencies. ([0080460365ff6054db0910ce1e58dd567c2ef902](https://github.com/outbrain/postit/commit/0080460365ff6054db0910ce1e58dd567c2ef902)) 32 | 33 | 34 | 35 | 36 | ## [1.1.4](https://github.com/outbrain/postit/compare/v1.1.3...v1.1.4) (2016-04-28) 37 | 38 | 39 | ### Build 40 | 41 | * Fix unit test spacing. ([7c00353921d57de02f6aa2d089a3aa4c8c5f4269](https://github.com/outbrain/postit/commit/7c00353921d57de02f6aa2d089a3aa4c8c5f4269)) 42 | 43 | ### Docs 44 | 45 | * Update `CONTRIBUTING` documentation. ([9cba3ef6d054e2b8118ca387fe25a0ffb11f41f0](https://github.com/outbrain/postit/commit/9cba3ef6d054e2b8118ca387fe25a0ffb11f41f0)) 46 | 47 | ### Upgrade 48 | 49 | * Update `package` dependencies. ([74eeac68564203ed0594316ab2026b43dd08d9d6](https://github.com/outbrain/postit/commit/74eeac68564203ed0594316ab2026b43dd08d9d6)) 50 | 51 | 52 | 53 | 54 | ## [1.1.3](https://github.com/outbrain/postit/compare/v1.1.2...v1.1.3) (2016-04-19) 55 | 56 | 57 | ### Docs 58 | 59 | * Update `CONTRIBUTOR` documentation. ([cc2af21dd01baffce768b33853a3a1ff09147eeb](https://github.com/outbrain/postit/commit/cc2af21dd01baffce768b33853a3a1ff09147eeb)) 60 | 61 | 62 | 63 | 64 | ## [1.1.2](https://github.com/outbrain/postit/compare/v1.1.1...v1.1.2) (2016-03-30) 65 | 66 | 67 | ### Docs 68 | 69 | * Update `README` and `/example/index.html` documentation. ([fb091c987df3c7686efd8e854358f0dd7ab3a1ea](https://github.com/outbrain/postit/commit/fb091c987df3c7686efd8e854358f0dd7ab3a1ea)) 70 | 71 | ### Upgrade 72 | 73 | * Update `package` dependencies. ([89b1bf5fe291aaaf71a91795b14ecab1f21ab04f](https://github.com/outbrain/postit/commit/89b1bf5fe291aaaf71a91795b14ecab1f21ab04f)) 74 | 75 | 76 | 77 | 78 | ## [1.1.1](https://github.com/outbrain/postit/compare/v1.1.0...v1.1.1) (2016-03-26) 79 | 80 | 81 | ### Docs 82 | 83 | * Update `postit`, `/example/*.html` and `README` documentation. ([88f580adaefe920dc3cbbcd696297c3a20ce72de](https://github.com/outbrain/postit/commit/88f580adaefe920dc3cbbcd696297c3a20ce72de)) 84 | 85 | 86 | 87 | 88 | # [1.1.0](https://github.com/outbrain/postit/compare/v1.0.1...v1.1.0) (2016-03-26) 89 | 90 | 91 | ### Docs 92 | 93 | * Update `manager`, `/example/*.html` and `README` documentation. ([fdf39ce29fbf3267ed45fe09997cb7d576ecf3da](https://github.com/outbrain/postit/commit/fdf39ce29fbf3267ed45fe09997cb7d576ecf3da)) 94 | 95 | ### Update 96 | 97 | * Remove a hidden feature that enables asterisk (*) events, to listen to all registered events of any instance (`id`). ([22474ef21a8f3e04c9e4bfa4638cadd4e80f3607](https://github.com/outbrain/postit/commit/22474ef21a8f3e04c9e4bfa4638cadd4e80f3607)) 98 | 99 | 100 | 101 | 102 | ## [1.0.1](https://github.com/outbrain/postit/compare/v1.0.0...v1.0.1) (2016-03-21) 103 | 104 | 105 | ### Build 106 | 107 | * Add `prepublish` task. ([3a9f02d25a42228845dcb0b7aa0494e10f52a3f4](https://github.com/outbrain/postit/commit/3a9f02d25a42228845dcb0b7aa0494e10f52a3f4)) 108 | 109 | ### Docs 110 | 111 | * Update `manager`, `postit` and `README` documentation. ([41bf6fe26e920ab21834dc5765021640b7375116](https://github.com/outbrain/postit/commit/41bf6fe26e920ab21834dc5765021640b7375116)) 112 | 113 | 114 | 115 | 116 | # [1.0.0](https://github.com/outbrain/postit/compare/v1.0.0-rc.1...v1.0.0) (2016-03-15) 117 | 118 | 119 | 120 | 121 | 122 | # [1.0.0-rc.1](https://github.com/outbrain/postit/compare/v0.4.3...v1.0.0-rc.1) (2016-03-05) 123 | 124 | 125 | ### Breaking 126 | 127 | * `.openWindow` signature has changed, to read: `.openWindow(url, name, options)`. ([23ad25ab8c9c028de5bd7f6a5fd6c0b3a028ee76](https://github.com/outbrain/postit/commit/23ad25ab8c9c028de5bd7f6a5fd6c0b3a028ee76)) 128 | 129 | ### Build 130 | 131 | * Enable watching files, in `Karma`. ([7d9a6114f6e8018190a68e634be043f0d4aefc46](https://github.com/outbrain/postit/commit/7d9a6114f6e8018190a68e634be043f0d4aefc46)) 132 | * Remove unused packages; namely, `mkdir` and `mkdirp`. ([fe3840bd2ff306e819fe0a1b87ea825c4d4dca94](https://github.com/outbrain/postit/commit/fe3840bd2ff306e819fe0a1b87ea825c4d4dca94)) 133 | 134 | ### Upgrade 135 | 136 | * Update `package` dependencies, add ESLint rules and modify the 'Copyright' date. ([ea9d8349be729fa0352417120531e995eb4c2bf9](https://github.com/outbrain/postit/commit/ea9d8349be729fa0352417120531e995eb4c2bf9)) 137 | * Update `package` dependencies. ([82bef9b1ca992eea216d0f01113f2afbba0c2c02](https://github.com/outbrain/postit/commit/82bef9b1ca992eea216d0f01113f2afbba0c2c02)) 138 | 139 | 140 | 141 | 142 | ## [0.4.3](https://github.com/outbrain/postit/compare/v0.4.2...v0.4.3) (2015-12-07) 143 | 144 | 145 | ### Build 146 | 147 | * Add `watch` task, which will run the `test` task, upon file change, and additionally, minor, `gulpfile.js` cleanup. ([72607e88f837e0f791180d5a9313cb7a6190ef81](https://github.com/outbrain/postit/commit/72607e88f837e0f791180d5a9313cb7a6190ef81)) 148 | * Remove `postversion` command in `package.json`. ([de99dda9e732df6fc2558603dd1fe30759b3b25c](https://github.com/outbrain/postit/commit/de99dda9e732df6fc2558603dd1fe30759b3b25c)) 149 | * Update `version` command in `package.json`. ([97c34dd666f662049060ea7500f668f4e21baaef](https://github.com/outbrain/postit/commit/97c34dd666f662049060ea7500f668f4e21baaef)) 150 | 151 | ### Docs 152 | 153 | * Add 'commit message guidelines' and fix spacing. ([f189b1dd5e1c2ff1d79201c73131db07fd67b99c](https://github.com/outbrain/postit/commit/f189b1dd5e1c2ff1d79201c73131db07fd67b99c)) 154 | * Add 'Versioning' to `README` and minor document updates. ([fe214b4f5aaaf86d7142ccacc37c9fb224a61855](https://github.com/outbrain/postit/commit/fe214b4f5aaaf86d7142ccacc37c9fb224a61855)) 155 | * Update `CONTRIBUTOR` documentation. ([60404f492d5cd41cce4e7ee1660fbecc8548c512](https://github.com/outbrain/postit/commit/60404f492d5cd41cce4e7ee1660fbecc8548c512)) 156 | 157 | 158 | 159 | 160 | ## [0.4.2](https://github.com/outbrain/postit/compare/v0.4.1...v0.4.2) (2015-11-24) 161 | 162 | 163 | ### Build 164 | 165 | * Add `CHANGELOG` to the `release` task. ([e5a7a91325f938f5e1116f99cc3bbb5155030d9f](https://github.com/outbrain/postit/commit/e5a7a91325f938f5e1116f99cc3bbb5155030d9f)) 166 | 167 | --- 168 | * Add `npm-version` for releases. 169 | * Remove extra semicolon, and add a `ESLint` rule, to check for such. 170 | * Add additional `ESLint` rules, replace `console.error` with `console.warn`, where appropriate, and refactor `.on`. 171 | * Update filename case for `CHANGELOG`. 172 | 173 | 174 | ## [0.4.1](https://github.com/outbrain/postit/compare/v0.4.0...v0.4.1) (2015-11-17) 175 | 176 | * Remove `gulp-browserify`, given that it is no longer maintained, and replace with a recommended recipe. In addition, restructure `/docs`. 177 | * Update `README`/`contributor` documentation. 178 | * Update `devDependencies` and remove unused, example code. 179 | * Update `/example/*.html` and `README` documentation. 180 | 181 | 182 | ## [0.4.0](https://github.com/outbrain/postit/compare/v0.3.2...v0.4.0) (2015-11-6) 183 | 184 | * Update `/example/*.html` to be more succinct, and additionally, ensure that `.on` fails gracefully, for a thrown `syntaxError` exception. 185 | * Add external source map. 186 | * Refactor `.on` to leverage parsed data, and additionally, fix event origin. 187 | * Add `origin` checking in `.on`, to avoid manual checking. 188 | * Update `README`/`contributor` documentation. 189 | 190 | 191 | ## [0.3.2](https://github.com/outbrain/postit/compare/v0.3.1...v0.3.2) (2015-10-21) 192 | 193 | * Add `browserify-istanbul` in replacement of `sourceStore`. 194 | * Add `sourceStore` fix for `karma-coverage`. 195 | * Remove `bootstrap.js` and add new `ESLint` rules. 196 | * Add `karma-browserify` in replacement of `karma-commonjs`. 197 | * Add `ESLint` in replacement of `JSHint`. 198 | * Add `files` property in `package.json` for `npm` installs. 199 | 200 | 201 | ## [0.3.1](https://github.com/outbrain/postit/compare/v0.3.0...v0.3.1) (2015-09-24) 202 | 203 | * Add a pre-commit hook, for `Git`. 204 | * Update `README` documentation. 205 | * Add `CommonJS` browser shimming support. 206 | * Update `README`/`contributor' documentation, add source maps, and rename `gulp` tasks. 207 | 208 | 209 | ## [0.3.0](https://github.com/outbrain/postit/compare/v0.2.0...v0.3.0) (2015-08-12) 210 | 211 | * Additional tweaks to `.off`'s functionality. 212 | * Modify `.off`'s functionality. 213 | * Modify incoming `event` filtering and add a format fix for `contributor` doc. 214 | * Update `contributor` browser support. 215 | * Fix minor typos, fix regex in `.on`, and update docs. 216 | * Add additional test coverage for `manager` and update docs. 217 | * Fix `.emit` documentation. 218 | * Refactor `manager` to leverage `factory`, as it should, and additionally, update unit tests and docs. 219 | 220 | 221 | ## [0.2.0](https://github.com/outbrain/postit/compare/v0.1.0...v0.2.0) (2015-07-07) 222 | 223 | * Update docs and increase unit test coverage. 224 | * Deprecate `PostIt.__records`. 225 | * Fix a factory memoization bug. 226 | * Add `PostIt.get` and `PostIt.getAll` methods to the API. 227 | * Add `Factory.destroy` internal method. 228 | * Add error handling for unknown/non-string `id`s. 229 | * Fix `Contributor API Docs` linkable source. 230 | * Update Contributor docs. 231 | * Add `Changelog` and contributing documentation. 232 | * Minor documentation corrections. 233 | 234 | 235 | ## [0.1.0]() (2015-06-24) 236 | 237 | * Initial release. 238 | -------------------------------------------------------------------------------- /lib/manager.unit.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | describe('Manager', function() { 4 | var noop = function noop() {}; 5 | var Manager = require('./manager'); 6 | 7 | afterEach(function() { 8 | Manager.removeAll(); 9 | }); 10 | 11 | describe('add', function() { 12 | it('should create an instance', function() { 13 | Manager.add('foo'); 14 | Manager.add('bar'); 15 | 16 | expect(Manager.getAll()).to.contain.all.keys(['foo', 'bar']); 17 | }); 18 | 19 | it('should memoize an existing instance', function() { 20 | var foo1 = Manager.add('foo'); 21 | var foo2 = Manager.add('foo'); 22 | 23 | var bar1 = Manager.add('bar'); 24 | var bar2 = Manager.add('bar'); 25 | 26 | expect(foo1).to.equal(foo2); 27 | expect(bar1).to.equal(bar2); 28 | }); 29 | 30 | it('should not create an instance if an `id` is not a `String`', function() { 31 | Manager.add({ foo: 'bar' }); 32 | Manager.add(noop); 33 | Manager.add(['foo', 'bar']); 34 | Manager.add(9); 35 | 36 | expect(Manager.getAll()).to.be.empty; 37 | }); 38 | }); 39 | 40 | describe('remove', function() { 41 | it('should remove an instance', function() { 42 | Manager.add('foo') 43 | .on('foo', 'foo.bar', noop) 44 | .on('foo', 'foo.baz', noop); 45 | 46 | Manager.add('bar') 47 | .on('bar', 'bar.bar', noop) 48 | .on('bar', 'bar.baz', noop); 49 | 50 | Manager.remove('foo'); 51 | Manager.remove('bar'); 52 | 53 | expect(Manager.getAll()).to.be.empty; 54 | }); 55 | 56 | it('should not remove an instance with an unknown `id`', function() { 57 | Manager.add('foo'); 58 | Manager.add('bar'); 59 | 60 | Manager.remove('abar'); 61 | Manager.remove('afoo'); 62 | 63 | expect(Manager.getAll()).to.include.all.keys(['foo', 'bar']); 64 | }); 65 | }); 66 | 67 | describe('removeAll', function() { 68 | it('should remove all instances', function() { 69 | Manager.add('foo') 70 | .on('foo', 'foo.bar', noop) 71 | .on('foo', 'foo.baz', noop); 72 | 73 | Manager.add('bar') 74 | .on('bar', 'bar.bar', noop) 75 | .on('bar', 'bar.baz', noop); 76 | 77 | Manager.removeAll(); 78 | 79 | expect(Manager.getAll()).to.be.empty; 80 | }); 81 | }); 82 | 83 | describe('size', function() { 84 | it('should return the length of all instances', function() { 85 | Manager.add('foo') 86 | .on('foo', 'foo.bar', noop) 87 | .on('foo', 'foo.baz', noop); 88 | 89 | Manager.add('bar') 90 | .on('bar', 'bar.bar', noop) 91 | .on('bar', 'bar.baz', noop); 92 | 93 | expect(Manager.size()).to.equal(2); 94 | }); 95 | }); 96 | 97 | describe('get', function() { 98 | it('should get an instance', function() { 99 | Manager.add('foo'); 100 | Manager.add('bar'); 101 | 102 | expect(Manager.get('foo')).to.contain.all.keys(['id', 'nextGuid', 'listeners']); 103 | expect(Manager.get('bar')).to.contain.all.keys(['id', 'nextGuid', 'listeners']); 104 | }); 105 | 106 | it('should not get an instance with an unknown `id`', function() { 107 | expect(Manager.get('foo')).to.be.undefined; 108 | }); 109 | }); 110 | 111 | describe('getAll', function() { 112 | it('should get all instances', function() { 113 | Manager.add('foo'); 114 | Manager.add('bar'); 115 | 116 | expect(Manager.getAll()).to.contain.all.keys(['foo', 'bar']); 117 | }); 118 | 119 | it('should return an empty object when no instances are present', function() { 120 | expect(Manager.getAll()).to.be.empty; 121 | }); 122 | }); 123 | 124 | describe('on', function() { 125 | it('should register an event listener', function() { 126 | Manager.add('foo') 127 | .on('foo', 'foo.bar', noop) 128 | .on('foo', 'foo.bar', noop) 129 | .on('foo', 'foo.baz', noop); 130 | 131 | Manager.add('bar') 132 | .on('bar', 'bar.bar', noop) 133 | .on('bar', 'bar.baz', noop) 134 | .on('bar', 'bar.baz', noop); 135 | 136 | expect(Manager.get('foo').listeners['foo.bar']).to.have.length(2); 137 | expect(Manager.get('foo').listeners['foo.bar'].dispatcher).to.be.a('function'); 138 | expect(Manager.get('foo').listeners['foo.baz']).to.have.length(1); 139 | expect(Manager.get('foo').listeners['foo.baz'].dispatcher).to.be.a('function'); 140 | expect(Manager.get('foo').listeners['foo.boo']).to.not.exist; 141 | 142 | expect(Manager.get('bar').listeners['bar.bar']).to.have.length(1); 143 | expect(Manager.get('bar').listeners['bar.baz'].dispatcher).to.be.a('function'); 144 | expect(Manager.get('bar').listeners['bar.baz']).to.have.length(2); 145 | expect(Manager.get('bar').listeners['bar.baz'].dispatcher).to.be.a('function'); 146 | }); 147 | 148 | it('should not register an event listener with an unknown `id`', function() { 149 | Manager.add('foo') 150 | .on('foobar', 'foobar.foo', noop); 151 | 152 | Manager.add('bar') 153 | .on('barfoo', 'barfoo.bar', noop); 154 | 155 | expect(Manager.get('foo').listeners).to.be.empty; 156 | expect(Manager.get('bar').listeners).to.be.empty; 157 | }); 158 | }); 159 | 160 | describe('off', function() { 161 | it('should unregister all event listeners', function() { 162 | Manager.add('foo') 163 | .on('foo', 'foo.bar', noop) 164 | .on('foo', 'foo.bar', noop) 165 | .on('foo', 'foo.bar', noop); 166 | 167 | Manager.add('bar') 168 | .on('bar', 'bar.bar', noop) 169 | .on('bar', 'bar.bar', noop) 170 | .on('bar', 'bar.bar', noop); 171 | 172 | Manager.off('foo', 'foo.bar'); 173 | Manager.off('bar', 'bar.bar'); 174 | 175 | expect(Manager.get('foo').listeners['foo.bar']).to.be.undefined; 176 | expect(Manager.get('foo').listeners['foo.bar']).to.be.undefined; 177 | 178 | expect(Manager.get('bar').listeners['bar.bar']).to.be.undefined; 179 | expect(Manager.get('bar').listeners['bar.bar']).to.be.undefined; 180 | }); 181 | 182 | it('should unregister an event listener', function() { 183 | var listener1 = function listener1() {}; 184 | var listener2 = function listener2() {}; 185 | 186 | Manager.add('foo') 187 | .on('foo', 'foo.bar', noop) 188 | .on('foo', 'foo.bar', listener1) 189 | .on('foo', 'foo.bar', noop); 190 | 191 | Manager.add('bar') 192 | .on('bar', 'bar.bar', noop) 193 | .on('bar', 'bar.bar', listener2) 194 | .on('bar', 'bar.bar', noop); 195 | 196 | Manager.off('foo', 'foo.bar', listener1); 197 | Manager.off('bar', 'bar.bar', listener2); 198 | 199 | expect(Manager.get('foo').listeners['foo.bar']).to.have.length(2); 200 | expect(Manager.get('foo').listeners['foo.bar'][1].guid).to.not.equal(listener1.guid); 201 | expect(Manager.get('foo').listeners['foo.bar'].dispatcher).to.be.a('function'); 202 | 203 | expect(Manager.get('bar').listeners['bar.bar']).to.have.length(2); 204 | expect(Manager.get('bar').listeners['bar.bar'][1].guid).to.not.equal(listener2.guid); 205 | expect(Manager.get('bar').listeners['bar.bar'].dispatcher).to.be.a('function'); 206 | }); 207 | 208 | it('should not unregister an event listener with an unknown `id`', function() { 209 | Manager.add('foo') 210 | .on('foo', 'foo.bar', noop); 211 | 212 | Manager.add('bar') 213 | .on('bar', 'bar.bar', noop); 214 | 215 | Manager.off('foobar', 'foo.bar'); 216 | Manager.off('barbar', 'bar.bar'); 217 | 218 | expect(Manager.get('foo').listeners['foo.bar']).to.have.length(1); 219 | expect(Manager.get('bar').listeners['bar.bar']).to.have.length(1); 220 | }); 221 | }); 222 | 223 | describe('emit', function() { 224 | it('should emit an event to listeners', function(done) { 225 | var listener1 = sinon.spy(); 226 | var listener2 = sinon.spy(); 227 | var listener3 = sinon.spy(); 228 | var listener4 = sinon.spy(); 229 | 230 | var eventOrigin = window.location.href; 231 | var symbol = 'postit'; 232 | 233 | var fooEvent = { 234 | dataParsed: { 235 | foo: 'bar', 236 | __postit: symbol, 237 | __event: 'foo.bar', 238 | __id: 'foo', 239 | __origin: eventOrigin 240 | } 241 | }; 242 | 243 | var barEvent = { 244 | dataParsed: { 245 | bar: 'bar', 246 | __postit: symbol, 247 | __event: 'bar.bar', 248 | __id: 'bar', 249 | __origin: eventOrigin 250 | } 251 | }; 252 | 253 | Manager.add('foo') 254 | .on('foo', 'foo.bar', listener1) 255 | .on('foo', 'foo.bar', listener2); 256 | 257 | Manager.add('bar') 258 | .on('bar', 'bar.bar', listener3) 259 | .on('bar', 'bar.bar', listener4); 260 | 261 | Manager.emit('foo', 'foo.bar', window.self, { foo: 'bar' }, '*'); 262 | Manager.emit('bar', 'bar.bar', window.self, { bar: 'bar' }, '*'); 263 | window.self.postMessage('foo', '*'); 264 | 265 | setTimeout(function() { 266 | var listener1Args = listener1.args[0][0]; 267 | var listener2Args = listener2.args[0][0]; 268 | var listener3Args = listener3.args[0][0]; 269 | var listener4Args = listener4.args[0][0]; 270 | 271 | expect(listener1.calledOnce).to.be.true; 272 | expect(listener1Args.dataParsed).to.deep.equal(fooEvent.dataParsed); 273 | 274 | expect(listener2.calledOnce).to.be.true; 275 | expect(listener2Args.dataParsed).to.deep.equal(fooEvent.dataParsed); 276 | 277 | expect(listener3.calledOnce).to.be.true; 278 | expect(listener3Args.dataParsed).to.deep.equal(barEvent.dataParsed); 279 | 280 | expect(listener4.calledOnce).to.be.true; 281 | expect(listener4Args.dataParsed).to.deep.equal(barEvent.dataParsed); 282 | 283 | listener1.reset(); 284 | listener2.reset(); 285 | listener3.reset(); 286 | listener4.reset(); 287 | done(); 288 | }, 1); 289 | }); 290 | 291 | it('should emit an event to all listeners', function(done) { 292 | var listener1 = sinon.spy(); 293 | var listener2 = sinon.spy(); 294 | 295 | Manager.add('foo') 296 | .on('foo', 'foo.bar', noop) 297 | .on('foo', 'foo.baz', noop) 298 | .on('foo', '*', listener1); 299 | 300 | Manager.add('bar') 301 | .on('bar', 'bar.bar', noop) 302 | .on('bar', 'bar.baz', noop) 303 | .on('bar', '*', listener2); 304 | 305 | Manager.emit('foo', 'foo.bar', window.self, { foo: 'bar' }, '*'); 306 | Manager.emit('foo', 'foo.baz', window.self, { foo: 'baz' }, '*'); 307 | 308 | Manager.emit('bar', 'bar.bar', window.self, { bar: 'bar' }, '*'); 309 | Manager.emit('bar', 'bar.baz', window.self, { bar: 'baz' }, '*'); 310 | window.self.postMessage('foo', '*'); 311 | 312 | setTimeout(function() { 313 | var listener1Args1 = listener1.args[0][0]; 314 | var listener1Args2 = listener1.args[1][0]; 315 | 316 | var listener2Args1 = listener2.args[0][0]; 317 | var listener2Args2 = listener2.args[1][0]; 318 | 319 | expect(listener1Args1.dataParsed.foo).to.equal('bar'); 320 | expect(listener1Args2.dataParsed.foo).to.equal('baz'); 321 | expect(listener1.callCount).to.equal(2); 322 | 323 | expect(listener2Args1.dataParsed.bar).to.equal('bar'); 324 | expect(listener2Args2.dataParsed.bar).to.equal('baz'); 325 | expect(listener2.callCount).to.equal(2); 326 | 327 | listener1.reset(); 328 | listener2.reset(); 329 | done(); 330 | }, 1); 331 | }); 332 | 333 | it('should not emit an event to removed listeners', function(done) { 334 | var listener1 = sinon.spy(); 335 | var listener2 = sinon.spy(); 336 | 337 | Manager.add('foo') 338 | .on('foo', 'foo.bar', listener1) 339 | .off('foo', 'foo.bar'); 340 | 341 | Manager.add('bar') 342 | .on('bar', 'bar.bar', listener2) 343 | .off('bar', 'bar.bar'); 344 | 345 | Manager.emit('foo', 'foo.bar', window.self, { foo: 'bar' }, '*'); 346 | Manager.emit('bar', 'bar.bar', window.self, { bar: 'bar' }, '*'); 347 | 348 | setTimeout(function() { 349 | expect(listener1.calledOnce).to.be.false; 350 | expect(listener2.calledOnce).to.be.false; 351 | expect(Manager.get('foo').listeners['foo.bar']).to.be.undefined; 352 | 353 | listener1.reset(); 354 | listener2.reset(); 355 | done(); 356 | }, 1); 357 | }); 358 | 359 | it('should normalize the `message` sent message', function(done) { 360 | var listener1 = sinon.spy(); 361 | var listener2 = sinon.spy(); 362 | var listener3 = sinon.spy(); 363 | var listener4 = sinon.spy(); 364 | var listener5 = sinon.spy(); 365 | var listener6 = sinon.spy(); 366 | 367 | Manager.add('foo') 368 | .on('foo', 'foo.bar', listener1) 369 | .on('foo', 'foo.baz', listener2) 370 | .on('foo', 'foo.boo', listener3); 371 | 372 | Manager.add('bar') 373 | .on('bar', 'bar.bar', listener4) 374 | .on('bar', 'bar.baz', listener5) 375 | .on('bar', 'bar.boo', listener6); 376 | 377 | Manager.emit('foo', 'foo.bar', window.self, { foo: 'bar' }, '*'); 378 | Manager.emit('foo', 'foo.baz', window.self, 'foobar', '*'); 379 | Manager.emit('foo', 'foo.boo', window.self, [0, 1, 2], '*'); 380 | 381 | Manager.emit('bar', 'bar.bar', window.self, { bar: 'bar' }, '*'); 382 | Manager.emit('bar', 'bar.baz', window.self, 'barbar', '*'); 383 | Manager.emit('bar', 'bar.boo', window.self, [0, 1, 2], '*'); 384 | 385 | setTimeout(function() { 386 | var listener1Args = listener1.args[0][0]; 387 | var listener2Args = listener2.args[0][0]; 388 | var listener3Args = listener3.args[0][0]; 389 | var listener4Args = listener4.args[0][0]; 390 | var listener5Args = listener5.args[0][0]; 391 | var listener6Args = listener6.args[0][0]; 392 | 393 | expect(listener1Args.dataParsed.foo).to.equal('bar'); 394 | expect(listener2Args.dataParsed.__value).to.equal('foobar'); 395 | expect(listener3Args.dataParsed.__value).to.have.members([0, 1, 2]); 396 | 397 | expect(listener4Args.dataParsed.bar).to.equal('bar'); 398 | expect(listener5Args.dataParsed.__value).to.equal('barbar'); 399 | expect(listener6Args.dataParsed.__value).to.have.members([0, 1, 2]); 400 | 401 | listener1.reset(); 402 | listener2.reset(); 403 | listener3.reset(); 404 | listener4.reset(); 405 | listener5.reset(); 406 | listener6.reset(); 407 | done(); 408 | }, 1); 409 | }); 410 | 411 | it('should not emit an event that has a `message` type of `Function`', function(done) { 412 | var listener1 = sinon.spy(); 413 | var listener2 = sinon.spy(); 414 | 415 | Manager.add('foo') 416 | .on('foo', 'foo.bar', listener1); 417 | 418 | Manager.add('bar') 419 | .on('bar', 'bar.bar', listener2); 420 | 421 | Manager.emit('foo', 'foo.bar', window.self, noop, '*'); 422 | Manager.emit('bar', 'bar.bar', window.self, noop, '*'); 423 | 424 | setTimeout(function() { 425 | expect(listener1.calledOnce).to.be.false; 426 | expect(listener2.calledOnce).to.be.false; 427 | 428 | listener1.reset(); 429 | listener2.reset(); 430 | done(); 431 | }, 1); 432 | }); 433 | 434 | it('should not emit an event with an unknown `id`', function(done) { 435 | var listener1 = sinon.spy(); 436 | var listener2 = sinon.spy(); 437 | 438 | Manager.add('foo') 439 | .on('foo', 'foo.bar', listener1); 440 | 441 | Manager.add('bar') 442 | .on('bar', 'bar.bar', listener2); 443 | 444 | Manager.emit('foobar', 'foo.bar', window.self, { foo: 'bar' }, '*'); 445 | Manager.emit('barbar', 'bar.bar', window.self, { bar: 'bar' }, '*'); 446 | 447 | setTimeout(function() { 448 | expect(listener1.calledOnce).to.be.false; 449 | expect(listener2.calledOnce).to.be.false; 450 | 451 | listener1.reset(); 452 | listener2.reset(); 453 | done(); 454 | }, 1); 455 | }); 456 | 457 | it('should not emit an event to an origin that does not match', function(done) { 458 | var listener1 = sinon.spy(); 459 | var listener2 = sinon.spy(); 460 | 461 | Manager.add('foo') 462 | .on('foo', 'foo.bar', listener1); 463 | 464 | Manager.add('bar') 465 | .on('bar', 'bar.bar', listener2); 466 | 467 | Manager.emit('foo', 'foo.bar', window.self, { foo: 'bar' }, 'http://www.foobarbaz.com'); 468 | Manager.emit('bar', 'bar.bar', window.self, { bar: 'bar' }, 'http://www.foobarbaz.com'); 469 | 470 | setTimeout(function() { 471 | expect(listener1.calledOnce).to.be.false; 472 | expect(listener2.calledOnce).to.be.false; 473 | 474 | listener1.reset(); 475 | listener2.reset(); 476 | done(); 477 | }, 1); 478 | }); 479 | }); 480 | 481 | describe('openWindow', function() { 482 | it('should open a new `window`', function() { 483 | var openWindow = Manager.openWindow('http://www.foo.com', 'foo', { 484 | width: 700, 485 | height: 700 486 | }); 487 | 488 | expect(openWindow).not.to.be.null; 489 | }); 490 | }); 491 | }); 492 | -------------------------------------------------------------------------------- /dist/postit.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["node_modules/browserify/node_modules/browser-pack/_prelude.js","lib/factory.js","postit.js","lib/helpers.js","lib/manager.js","lib/postit.js"],"names":["f","exports","module","define","amd","g","window","global","self","this","PostIt","e","t","n","r","s","o","u","a","require","i","Error","code","l","call","length","1","instances","Factory","add","id","instance","remove","get","getAll","./postit","2","helpers","serialize","params","_params","param","push","join","shallowMerge","destination","source","prop","openWindow","url","name","options","that","nativeScreen","screen","nativeWindow","nativeDocument","document","nativeDocumentElement","documentElement","dualScreenLeft","screenLeft","left","dualScreenTop","screenTop","top","width","innerWidth","clientWidth","height","innerHeight","clientHeight","features","newWindow","open","focus","3","Manager","console","warn","record","event","listeners","off","removeAll","records","size","on","listener","emit","target","message","origin","./factory","./helpers","4","nextGuid","prototype","dispatcher","evt","data","test","dataParsed","JSON","parse","err","error","__id","__event","__origin","indexOf","guid","addEventListener","splice","removeEventListener","eventOrigin","location","href","symbol","Object","toString","__postit","stringify","__value","postMessage"],"mappings":"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","file":"postit.js","sourcesContent":["(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);var f=new Error(\"Cannot find module '\"+o+\"'\");throw f.code=\"MODULE_NOT_FOUND\",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require==\"function\"&&require;for(var o=0;o RETURN EARLY,\n\t\t\tthat.id !== data.__id || // or an instance identifier does not match => RETURN EARLY,\n\t\t\t(event !== data.__event && '*' !== event) || // or an event does not match, and an asterisk (*) is not the event => RETURN EARLY\n\t\t\t('null' !== evt.origin && -1 === data.__origin.indexOf(evt.origin)) // or `'null'` is not the `evt.origin`, and the origins do not match. => RETURN EARLY\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var i = 0; i < listeners.length; ++i) {\n\t\t\tlisteners[i].call(this, evt);\n\t\t}\n\t}\n\n\t// Only attach one dispatcher per `event`.\n\tif (listeners.length === 1) {\n\t\twindow.addEventListener('message', dispatcher, false);\n\t}\n\n\treturn that;\n};\n\n/**\n * - If a `listener` is not provided, then unregister all listeners from a `PostIt` instance (`id`), for a given `event`.\n * - If a `listener` is provided, then unregister a `listener` from a `PostIt` instance (`id`), for a given `event`.\n * @param {string} event\n * @param {function=} listener\n * @returns {object}\n * @public\n */\n\nPostIt.prototype.off = function(event, listener) {\n\tvar that = this;\n\tvar listeners = that.listeners[event] || [];\n\n\tfor (var i = 0; i < listeners.length; ++i) {\n\t\tif (!listener || listener.guid === listeners[i].guid) {\n\t\t\tlisteners.splice(i--, 1);\n\t\t}\n\t}\n\n\tif (!listeners.length) {\n\t\twindow.removeEventListener('message', listeners.dispatcher, false);\n\n\t\tdelete that.listeners[event];\n\t}\n\n\treturn that;\n};\n\n/**\n * - If `event` is an asterisk (\\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for all given `event`s.\n * - If `event` is not an asterisk (\\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for a given `event`.\n * @param {string} event\n * @param {object} target\n * @param {string|array|object} message\n * @param {string} origin\n * @returns {object}\n * @public\n */\n\nPostIt.prototype.emit = function(event, target, message, origin) {\n\tvar that = this;\n\tvar eventOrigin = window.location.href;\n\tvar symbol = 'postit';\n\n\tswitch (Object.prototype.toString.call(message)) {\n\t\tcase '[object Function]':\n\t\t\tconsole.warn(message + ' should either be an `Object`, `Array` or `String`.');\n\n\t\t\treturn that;\n\n\t\tcase '[object Object]':\n\t\t\tmessage.__postit = symbol;\n\t\t\tmessage.__id = that.id;\n\t\t\tmessage.__event = event;\n\t\t\tmessage.__origin = eventOrigin;\n\t\t\tmessage = JSON.stringify(message);\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tmessage = JSON.stringify({\n\t\t\t\t__postit: symbol,\n\t\t\t\t__value: message,\n\t\t\t\t__id: that.id,\n\t\t\t\t__event: event,\n\t\t\t\t__origin: eventOrigin\n\t\t\t});\n\t}\n\n\ttarget.postMessage(message, origin);\n\n\treturn that;\n};\n\n},{}]},{},[3])(3)\n});\n\n","'use strict';\n\n/**\n * Helpers Module.\n * @public\n */\n\nvar helpers = module.exports = {};\n\n/**\n * Serializes an object into a formatted string.\n * @param {object} params\n * @returns {string}\n * @public\n */\n\nhelpers.serialize = function(params) {\n\tvar _params = [];\n\n\tfor (var param in params) {\n\t\t_params.push(param + '=' + params[param]);\n\t}\n\n\treturn _params.join(', ');\n};\n\n/**\n * Merges a shallow `source` object into the `destination` object.\n * @param {object} destination\n * @param {object} source\n * @returns {object}\n * @public\n */\n\nhelpers.shallowMerge = function(destination, source) {\n\tfor (var prop in source) {\n\t\tif (null != source[prop]) {\n\t\t\tdestination[prop] = source[prop];\n\t\t}\n\t}\n\n\treturn destination;\n};\n\n/**\n * Loads a resource into a new browsing context (`window`).\n * @see {@link https://developer.mozilla.org/en-US/docs/Web/API/Window/open|Window.open()} for more options.\n * @param {string} url\n * @param {string} name\n * @param {object} options\n * @param {number} options.width\n * @param {number} options.height\n * @returns {object}\n * @public\n */\n\n/* istanbul ignore next */\nhelpers.openWindow = function(url, name, options) {\n\toptions = options || {};\n\n\tvar that = this;\n\tvar nativeScreen = screen || {};\n\tvar nativeWindow = window;\n\tvar nativeDocument = document;\n\tvar nativeDocumentElement = nativeDocument.documentElement || {};\n\tvar dualScreenLeft = nativeWindow.screenLeft || nativeScreen.left || 0;\n\tvar dualScreenTop = nativeWindow.screenTop || nativeScreen.top || 0;\n\tvar width = nativeWindow.innerWidth || nativeDocumentElement.clientWidth || nativeScreen.width || 0;\n\tvar height = nativeWindow.innerHeight || nativeDocumentElement.clientHeight || nativeScreen.height || 0;\n\tvar left = ((width / 2) - (options.width / 2)) + dualScreenLeft;\n\tvar top = ((height / 2) - (options.height / 2)) + dualScreenTop;\n\tvar features = that.serialize(that.shallowMerge({\n\t\ttop: top,\n\t\tleft: left\n\t}, options));\n\tvar newWindow = nativeWindow.open(url, name, features);\n\n\tif (nativeWindow.focus) {\n\t\tnewWindow.focus();\n\t}\n\n\treturn newWindow;\n};\n","'use strict';\n\nvar Factory = require('./factory');\nvar helpers = require('./helpers');\n\n/**\n * Manager Module.\n * @public\n */\n\nvar Manager = module.exports = {};\n\n/**\n * Creates and manages a `PostIt` instance (`id`).\n * @param {string} id\n * @returns {object}\n * @public\n */\n\nManager.add = function(id) {\n\tvar that = this;\n\n\tif ('string' !== typeof id) {\n\t\tconsole.warn(id + ' should be a `String`.');\n\n\t\treturn that;\n\t}\n\n\t// Create a memoized factory.\n\tFactory.add(id);\n\n\treturn that;\n};\n\n/**\n * Removes a `PostIt` instance (`id`).\n * @param {string} id\n * @returns {object}\n * @public\n */\n\nManager.remove = function(id) {\n\tvar that = this;\n\tvar record = that.get(id);\n\n\tif (!record) {\n\t\treturn that;\n\t}\n\n\t// Remove listeners to avoid memory leaks.\n\tfor (var event in record.listeners) {\n\t\trecord.off(event);\n\t}\n\n\tFactory.remove(id);\n\n\treturn that;\n};\n\n/**\n * Removes all `PostIt` instances.\n * @return {object}\n * @public\n */\n\nManager.removeAll = function() {\n\tvar that = this;\n\tvar records = that.getAll();\n\n\tfor (var record in records) {\n\t\tthat.remove(record);\n\t}\n\n\treturn that;\n};\n\n/**\n * Returns the length of all `PostIt` instances.\n * @return {number}\n * @public\n */\n\nManager.size = function() {\n\tvar size = 0;\n\tvar records = this.getAll();\n\n\tfor (var record in records) {\n\t\tsize++;\n\t}\n\n\treturn size;\n};\n\n/**\n * Gets a `PostIt` instance (`id`).\n * @param {string} id\n * @returns {object|void}\n */\n\nManager.get = function(id) {\n\treturn Factory.get(id) || console.warn(id + ' does not match any `PostIt` instances.');\n};\n\n/**\n * Gets all `PostIt` instances.\n * @returns {object}\n */\n\nManager.getAll = function() {\n\treturn Factory.getAll();\n};\n\n/**\n * @see {@link postit.md#PostIt+on} for further information.\n * @param {string} id\n * @param {string} event\n * @param {function} listener\n * @returns {object}\n * @public\n */\n\nManager.on = function(id, event, listener) {\n\tvar that = this;\n\tvar record = that.get(id);\n\n\tif (!record) {\n\t\treturn that;\n\t}\n\n\trecord.on(event, listener);\n\n\treturn that;\n};\n\n/**\n * @see {@link postit.md#PostIt+off} for further information.\n * @param {string} id\n * @param {string} event\n * @param {function=} listener\n * @returns {object}\n * @public\n */\n\nManager.off = function(id, event, listener) {\n\tvar that = this;\n\tvar record = that.get(id);\n\n\tif (!record) {\n\t\treturn that;\n\t}\n\n\trecord.off(event, listener);\n\n\treturn that;\n};\n\n/**\n * @see {@link postit.md#PostIt+emit} for further information.\n * @param {string} id\n * @param {string} event\n * @param {object} target\n * @param {string|array|object} message\n * @param {string} origin\n * @returns {object}\n * @public\n */\n\nManager.emit = function(id, event, target, message, origin) {\n\tvar that = this;\n\tvar record = that.get(id);\n\n\tif (!record) {\n\t\treturn that;\n\t}\n\n\trecord.emit(event, target, message, origin);\n\n\treturn that;\n};\n\n/**\n * @see {@link helpers.md#helpers.openWindow} for further information.\n * @param {string} url\n * @param {string} name\n * @param {object} options\n * @param {number} options.width\n * @param {number} options.height\n * @public\n */\n\nManager.openWindow = function(url, name, options) {\n\treturn helpers.openWindow(url, name, options);\n};\n","'use strict';\n\n/**\n * PostIt Module.\n * @constructor\n * @param {string} id\n * @public\n */\n\nvar PostIt = module.exports = function(id) {\n\tthis.id = id;\n\tthis.nextGuid = 0;\n\tthis.listeners = {};\n};\n\n/**\n * Registers a `listener` to a `PostIt` instance (`id`), for a given `event`.\n * @param {string} event\n * @param {function} listener\n * @returns {object}\n * @public\n */\n\nPostIt.prototype.on = function(event, listener) {\n\tvar that = this;\n\n\tvar listeners = that.listeners[event] = that.listeners[event] || [];\n\tlistener.guid = that.nextGuid++;\n\tlisteners.dispatcher = dispatcher;\n\n\tlisteners.push(listener);\n\n\tfunction dispatcher(evt) {\n\t\tvar data = null;\n\n\t\tif (/__postit\\s?\"/.test(evt.data)) {\n\t\t\ttry {\n\t\t\t\tdata = evt.dataParsed = JSON.parse(evt.data);\n\t\t\t} catch (err) {\n\t\t\t\tconsole.error(err);\n\t\t\t}\n\t\t}\n\n\t\tif (!data || // The preferred symbol (`__postit`) is not present, or an 'Uncaught SyntaxError' occurs, whilst parsing `evt.data` => RETURN EARLY,\n\t\t\tthat.id !== data.__id || // or an instance identifier does not match => RETURN EARLY,\n\t\t\t(event !== data.__event && '*' !== event) || // or an event does not match, and an asterisk (*) is not the event => RETURN EARLY\n\t\t\t('null' !== evt.origin && -1 === data.__origin.indexOf(evt.origin)) // or `'null'` is not the `evt.origin`, and the origins do not match. => RETURN EARLY\n\t\t) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (var i = 0; i < listeners.length; ++i) {\n\t\t\tlisteners[i].call(this, evt);\n\t\t}\n\t}\n\n\t// Only attach one dispatcher per `event`.\n\tif (listeners.length === 1) {\n\t\twindow.addEventListener('message', dispatcher, false);\n\t}\n\n\treturn that;\n};\n\n/**\n * - If a `listener` is not provided, then unregister all listeners from a `PostIt` instance (`id`), for a given `event`.\n * - If a `listener` is provided, then unregister a `listener` from a `PostIt` instance (`id`), for a given `event`.\n * @param {string} event\n * @param {function=} listener\n * @returns {object}\n * @public\n */\n\nPostIt.prototype.off = function(event, listener) {\n\tvar that = this;\n\tvar listeners = that.listeners[event] || [];\n\n\tfor (var i = 0; i < listeners.length; ++i) {\n\t\tif (!listener || listener.guid === listeners[i].guid) {\n\t\t\tlisteners.splice(i--, 1);\n\t\t}\n\t}\n\n\tif (!listeners.length) {\n\t\twindow.removeEventListener('message', listeners.dispatcher, false);\n\n\t\tdelete that.listeners[event];\n\t}\n\n\treturn that;\n};\n\n/**\n * - If `event` is an asterisk (\\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for all given `event`s.\n * - If `event` is not an asterisk (\\*), then emit an `event` to all listeners registered to a `PostIt` instance (`id`), for a given `event`.\n * @param {string} event\n * @param {object} target\n * @param {string|array|object} message\n * @param {string} origin\n * @returns {object}\n * @public\n */\n\nPostIt.prototype.emit = function(event, target, message, origin) {\n\tvar that = this;\n\tvar eventOrigin = window.location.href;\n\tvar symbol = 'postit';\n\n\tswitch (Object.prototype.toString.call(message)) {\n\t\tcase '[object Function]':\n\t\t\tconsole.warn(message + ' should either be an `Object`, `Array` or `String`.');\n\n\t\t\treturn that;\n\n\t\tcase '[object Object]':\n\t\t\tmessage.__postit = symbol;\n\t\t\tmessage.__id = that.id;\n\t\t\tmessage.__event = event;\n\t\t\tmessage.__origin = eventOrigin;\n\t\t\tmessage = JSON.stringify(message);\n\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\tmessage = JSON.stringify({\n\t\t\t\t__postit: symbol,\n\t\t\t\t__value: message,\n\t\t\t\t__id: that.id,\n\t\t\t\t__event: event,\n\t\t\t\t__origin: eventOrigin\n\t\t\t});\n\t}\n\n\ttarget.postMessage(message, origin);\n\n\treturn that;\n};\n"],"sourceRoot":"/source/"} --------------------------------------------------------------------------------