{"id":17181518,"url":"https://github.com/dimitarchristoff/primish","last_synced_at":"2025-04-13T17:50:19.040Z","repository":{"id":9532402,"uuid":"11434280","full_name":"DimitarChristoff/primish","owner":"DimitarChristoff","description":"Tiny OOP JavaScript Class constructor sugar in the style of MooTools","archived":false,"fork":false,"pushed_at":"2014-11-10T12:10:34.000Z","size":1678,"stargazers_count":19,"open_issues_count":0,"forks_count":2,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-10T18:56:35.626Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://dimitarchristoff.github.io/primish/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/DimitarChristoff.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-15T21:29:42.000Z","updated_at":"2021-09-12T04:50:59.000Z","dependencies_parsed_at":"2022-08-31T00:01:12.283Z","dependency_job_id":null,"html_url":"https://github.com/DimitarChristoff/primish","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DimitarChristoff%2Fprimish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DimitarChristoff%2Fprimish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DimitarChristoff%2Fprimish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/DimitarChristoff%2Fprimish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/DimitarChristoff","download_url":"https://codeload.github.com/DimitarChristoff/primish/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248757984,"owners_count":21156954,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-15T00:34:33.433Z","updated_at":"2025-04-13T17:50:19.001Z","avatar_url":"https://github.com/DimitarChristoff.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"primish\n=======\n\nA prime derivative that went beyond repair. Initially a fork of [MooTools prime](https://github.com/mootools/prime/), now with a lot of sugar. \n\nWhy fork prime in the first place? Although prime is very good, it has been two years in the making and is not officially released yet. It's also written for CommonJS and it needs a fair amount of packaging, bundling of plugins and behaviours in order to make it work in a browser (via `browserify` or `wrapup`). It also tries to provide its own utilities methods and helpers, something that a lot of people have solved via `lodash` or `underscore`. It also does not try to keep the MooTools Class API / features. Primish does not only fix the module packaging (UMD!), there are considerable changes in code to make it more Classy and it is `bower`-ready and available on `cdnjs.com` for immediate use. At little over 4K in size, you get a lot of mileage for your money if you like classic OOP style code in your JavaScript.\n\n[![NPM version](https://badge.fury.io/js/primish.png)](http://badge.fury.io/js/primish)\n\n## Differences\n\n### prime changes\n\n- forked from before the new prime [types and object mixins](https://github.com/mootools/prime/blob/master/index.js#L6-L11).\n- `.parent()`\n- `.implement()` and `implement` mutator, like mootools. not `mixin`\n- `extend`, not `inherits`\n- `prime.merge()` shallow Object merging\n- object keys of constructor object are NOT de-referenced / cloned\n- only `options` objects are automatically de-referenced like in MooTools, other objects will point to prototype and will be mutable\n- extras from prime like utils, shell, type, etc have all been removed, recommended util library is `lodash`.\n- primish classes can have IDs for reflection like in AMD.\n\n### emitter changes\n\n- `.emit` is actually `.trigger`, so it's not an `emitter` as such :)\n- no support for defered async events (see [this](https://github.com/mootools/prime/blob/master/emitter.js#L50-L65))\n- support for event stacking like `.on('foo bar baz', function(){});`\n- support for event pseudos like `.on('foo:once', function(){});`\n- `emitter.definePseudo()` to allow custom pseudo events\n\n### options\n\n- `.setOptions()` - shallow merging of object with `this.options`\n- support for emitter events via `onEventname` -\u003e `this.on('eventname')` like in MooTools 1.x\n\n### Browser support\n\nThe main driving force behind primish is to change prime to work in a browser out of the box as well as under nodejs.\nThis fork changes the code to work via an UMD wrap w/o any dependencies, so it supports AMD (eg. RequireJS, Almond) as\nwell as simple browser exports to globals. If you don't have an AMD loader and not under NodeJS / browserify, it will\nexport `window.primish`, `window.emitter` and `window.options`, so be careful. Another goal has been to bring as much\nMooTools 1.x sugar into classes as possible.\n\n### Size and download\n\nThe minified packaged version weighs just 4.2K without gzipping, so a tiny footprint in any codebase.\n\n\u003ca class=\"btn btn-large btn-primary\" rel=\"download\" target=\"_blank\" href=\"./js/primish/primish-min.js\"\u003eprimish-min.js (4.2k)\u003c/a\u003e\n\n### Changelog\n\n- 0.3.9 safer hasOwnProperty checks\n- 0.3.8 performance optimisations for primish/emitter\n- 0.3.7 tweaks for bower consumption\n- 0.3.6 perf fixes for emitter.trigger, tiny doc changes, jsdoc notation\n- 0.3.5 dereferencing `this.options` from protos, export of `primish.clone`\n- 0.3.4 fixed AMD module IDs for build to work better with bundles\n- 0.3.3 requirejs 2.1.10 compatible bundles support via module ids\n- 0.3.2 requirejs uglify2 build\n\n## Testimonials\n\n[kentaromiura](https://github.com/kentaromiura), mootools-core and mootools-prime developer said:\n\n\u003e _I guess that when you said I'll go and make my own version of prime with, blackjack and hookers you really meant it_\n\n![our own](http://cdn.meme.li/instances/300x300/39768609.jpg)\n\n## Creating a Class\n\nTo create a new Class, you simply need to do:\n\n```ace\n// under AMD\nrequire(['primish/primish'], function(primish){\n\n\tvar Human = primish({\n\t\tsetName: function(name){\n\t\t\tthis.name = name;\n\t\t},\n\t\tgetName: function(){\n\t\t\treturn this.name;\n\t\t}\n\t});\n\n\tvar Bob = new Human();\n\tBob.setName('Bob');\n\tconsole.log(Bob.getName()); // 'Bob'\n\n});\n```\n\nYou can also add a constructor method on your config object to run automatically:\n\n```ace\nrequire(['primish/primish'], function(primish){\n\n\tvar Human = primish({\n\t\tconstructor: function(name){\n\t\t\tname \u0026\u0026 this.setName(name);\n\t\t},\n\t\tsetName: function(name){\n\t\t\tthis.name = name;\n\t\t},\n\t\tgetName: function(){\n\t\t\treturn this.name;\n\t\t}\n\t});\n\n\tvar Bob = new Human('Bob');\n\tconsole.log(Bob.getName()); // 'Bob'\n\n});\n```\n\nFor node / CommonJS:\n```javascript\nvar primish = require('primish'),\n\toptions = require('primish/options');\n\nvar Human = primish({\n\timplement: [options],\n\tconstructor: function(options){\n\t\tthis.setOptions(options);\n\t}\n});\n\nvar Bob = new Human({name: 'Bob'});\nconsole.log(Bob.options.name); // 'Bob'\n```\n\nHere is an example that will make the name property `readonly` and  example private variables\n\n```ace\nrequire(['primish/primish'], function(primish){\n\n    var Human = (function(){\n        var storage = {},\n            hid = 0;\n\n        var Human = primish({\n            constructor: function(name){\n                this.$hid = hid++;\n                storage[this.$hid] = {};\n                // disallow changes to human id\n                primish.define(this, '$hid', {\n                    writable: false,\n                    enumerable: false\n                });\n\n                primish.define(this, 'name', {\n                    configurable: false,\n                    get: function(){\n                        return this.getName();\n                    }\n                });\n\n                name \u0026\u0026 this.setName(name);\n            },\n            setName: function(name){\n                storage[this.$hid].name = name;\n            },\n            getName: function(){\n                return storage[this.$hid].name;\n            }\n        });\n\n        return Human;\n    }());\n\n    var Bob = new Human('Bob'),\n        Greg = new Human('Greg');\n\n    console.log(Bob);\n    console.log(Bob.getName()); // 'Bob'\n    console.log(Bob.name); // 'Bob'\n    Bob.name = 'Robert'; // nope, should not change.\n    console.log(Bob.name); // 'Bob'\n    Bob.$uid = Greg.$uid; // try to puncture Greg's storage\n    console.log(Bob.name); // 'Bob'\n\n});\n```\n\nWhat happens behind the scenes? `prime` accepts a single argument as a config object. The object is a simple JavaScript\nObject - with special keys (also referred to `mutator keys`).\n\nA `mutator key` is a key:value pair that has a special meaning and is used differently by the Class constructor. The\nfollowing keys in your config object are considered `mutator`:\n\n### constructor\n\nThe `constructor` method in your config object is what becomes the prime constructor. It runs automatically when you\ninstantiate and can accept any number of arguments, named or otherwise.\n\n```ace\nrequire(['primish/primish'], function(primish){\n\t// have an element\n\tvar div = document.createElement('div');\n\tdiv.setAttribute('id', 'myWidget');\n\tdocument.body.appendChild(div);\n\n\tvar Widget = primish({\n\t\toptions: {\n\t\t\ttitle: 'My Widget'\n\t\t},\n\t\tconstructor: function(el, options){\n\t\t\tthis.element = document.getElementById(el);\n\t\t\tif (options \u0026\u0026 Object(options) === options){\n\t\t\t\tthis.options = options;\n\t\t\t}\n\t\t\tthis.element.innerHTML = this.options.title;\n\t\t}\n\t});\n\n\tvar instance = new Widget('myWidget', {\n\t\ttitle: 'Cool Widget',\n\t\theight: 300\n\t});\n\n\tconsole.log(instance.options.title); // 'Cool Widget'\n\tconsole.log(instance.element.innerHTML); // 'Cool Widget'\n});\n```\n\n#### class IDs\n\nPrimish also supports Class IDs (for 'reflection') - similar to AMD's module IDs. The first argument can be an optional\nstring ID, which can then be accessed via `instance._id`. When possible, these are added via `Object.defineProperty` and\nare not enumerable.\n\n```ace\nrequire(['primish/primish'], function(primish){\n\n\tvar User = primish('Admin.User', {\n\t\tconstructor: function(){\n\t\t\tconsole.log(this._id);\n\t\t}\n\t});\n\n\tvar instance = new User();\n\tconsole.log('It looks like the instance is ' + instance._id);\n});\n```\n\nCaveat: if your super Class has an ID but your subclass does not, it will still resolve this via the prototype chain\nand may incorrectly identify your instance as the parent. Make sure you use IDs recursively if you need them.\n\n### extend\n\nThe special key `extend` defines what SuperClass your new Class will inherit from. It only accepts a single argument,\npointing to another Class. The resulting new Class definition will have its prototype set to the SuperClass and inherit\nany of its static properties and methods via the scope chain.\n\nThis allows you to abstract differences between Classes without having to repeat a lot of code.\n\n```ace\nrequire(['primish/primish'], function(primish){\n\tvar Rectangle = primish({\n\n\t\tconstructor: function(width, height){\n\t\t\treturn this.setWidth(width).setHeight(height);\n\t\t},\n\n\t\tsetWidth: function(width){\n\t\t\tthis.width = width;\n\t\t\treturn this; // allow chaining\n\t\t},\n\n\t\tsetHeight: function(height){\n\t\t\tthis.height = height;\n\t\t\treturn this;\n\t\t},\n\n\t\tsquareRoot: function(){\n\t\t\treturn this.height * this.width;\n\t\t}\n\n\t});\n\n\tvar Square = primish({\n\n\t\t// subclass of Rectangle\n\t\textend: Rectangle,\n\n\t\tconstructor: function(side){\n\t\t\treturn this.setSide(side);\n\t\t},\n\n\t\tsetSide: function(side){\n\t\t\t// both sides are the same\n\t\t\tthis.width = this.height = side;\n\t\t\treturn this;\n\t\t},\n\n\t\tsetWidth: function(width){\n\t\t\treturn this.setSide(width);\n\t\t},\n\n\t\tsetHeight: function(height){\n\t\t\treturn this.setSide(height);\n\t\t}\n\n\t});\n\n\tvar square = new Square(30);\n\tsquare.setWidth(5); // local\n\tconsole.log(square.height); // 5\n\tconsole.log(square.squareRoot()); // from parent proto of Rectangle, 25\n});\n```\nChanges to the parent Class are also reflected in the child Class by inheritance (unless the child has a local\nimplementation). This differs from when you use the [implement](#creating-a-class/implement) directives, which copies instead.\n\n```javascript\n// continued from above\nRectangle.prototype.shrink = function(){\n\tthis.width--;\n\tthis.height--;\n\treturn this;\n};\n\n// square can also now call .shrink:\nsquare.setSide(5).shrink();\nsquare.width; // 4;\nsquare.height; // 4\n```\n\n**Warning**: when creating a new sub class, if you have an `options` object in the constructor and the super class also has it,\nit will automatically merge them for you. This is really helpful when using the [options](#plugins/options) mixin:\n\n```javascript\nrequire(['primish/primish'], function(primish){\n\tvar a = primish({\n\t\toptions: {\n\t\t\tx: 1,\n\t\t\ty: 1\n\t\t}\n\t});\n\n\tvar b = primish({\n\t\textend: a,\n\t\toptions: {\n\t\t\tz: 1\n\t\t}\n\t});\n\n\tconsole.log(new b().options);  // {x:1, y:1, z:1}\n});\n```\n\n### implement\n\nThe special key `implement` is used to tell prime which other Objects' properties are to be `copied` into your own Class\ndefinition. Mixins do not work via inheritance, they create a local instance of the properties.\n\nWhen used as a property, `implement` accepts either a single Class or an array of Classes to implement.\n\n```ace\nrequire(['primish/primish'], function(primish){\n\t// example using a small event emitter as a mixin\n\tvar EID = 0;\n\n\tvar Emitter = primish({\n\n\t\ton: function(event, fn){\n\t\t\tvar listeners = this._listeners || (this._listeners = {}),\n\t\t\t\tevents = listeners[event] || (listeners[event] = {});\n\n\t\t\t\tfor (var k in events) if (events[k] === fn) return this;\n\n\t\t\t\tevents[(EID++).toString(36)] = fn;\n\t\t\treturn this;\n\t\t},\n\n\t\ttrigger: function(event){\n\t\t\tvar listeners = this._listeners, events, k, args;\n\t\t\tif (listeners \u0026\u0026 (events = listeners[event])){\n\t\t\t\targs = (arguments.length \u003e 1) ? slice.call(arguments, 1) : [];\n\t\t\t\tfor (k in events) events[k].apply(this, args);\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\n\t});\n\n\tvar myClass = primish({\n\n\t\t// implement the emitter:\n\t\timplement: [Emitter],\n\n\t\tdoSomethingImportant: function(){\n\t\t\tthis.trigger('important');\n\t\t}\n\n\t});\n\n\tvar instance = new myClass();\n\n\t// bind some event, .on is available\n\tinstance.on('important', function(){\n\t\tconsole.log('important is done');\n\t});\n\n\t// call the method that will fire the event.\n\tinstance.doSomethingImportant();\n});\n```\n\nThere is an alternative syntax to allow `late implementation` via the `.mixin` method:\n\n```javascript\nmyClass.implement(new OtherClass());\n// or chaining on an instance\ninstanceofMyClass.implement(new OtherClass2()).implement(new OtherClass3());\n\n// late binding at proto definition also works\nvar myClass = primish({}).implement(new OtherClass);\n```\n\n\u003cdiv class=\"alert\"\u003eNote: When a mixin is implemented, the mixin Class is instantiated (via `new`) and the methods are copied from\nthe instance, not the prototype. Changing the mixin prototype afterwards will not automatically make the changes available\nin your Class instances (unlike when using [extend](#creating-a-class/extend))\n\n\n### parent\n\nWhen [extending a Class](#extend), you can access methods from the super via the `.parent()` method. It expects at least\n1 argument - the method name as `String`. This is synthactic sugar for saying:\n\n`this.constructor.prototype.methodname.apply(this, [arguments])`, where methodname is the method passed as string.\n\nThe parent method is borrowed from Arian's prime-util repo.\n\nHere is a more comprehensive example:\n\n```ace\nrequire(['primish/primish'], function(primish){\n\t// this example won't work w/o jQuery and ECMA5\n\t// assume this.$element is a jquery wrapped el.\n\n\tvar Widget = primish({\n\n\t\tattachEvents: function(){\n\t\t\tthis.$element.on('click', this.handleclick.bind(this));\n\t\t},\n\t\thandleClick: function(){\n\n\t\t},\n\t\tsetTitle: function(title){\n\t\t\tthis.$element.find('.title').text(title);\n\t\t}\n\n\t});\n\n\tvar WeatherWidget = primish({\n\n\t\textend: Widget,\n\n\t\tattachEvents: function(){\n\t\t\tthis.parent('attachEvents'); // call it on super Widget\n\t\t\t// do more.\n\t\t\tthis.$element.find('input').on('blur', this.validateInput.bind(this));\n\t\t},\n\t\tvalidateInput: function(event){\n\n\t\t}\n\n\t});\n\n\t// example with shifting arguments\n\tvar NewsWidget = primish({\n\n\t\textend: Widget,\n\n\t\tsetTitle: function(text){\n\t\t\tthis.$element.find('.sub-heading').addClass('active');\n\t\t\tthis.parent('setTitle', text); // passes original arg to parent.\n\t\t}\n\n\t});\n});\n```\n\n## Define\n\nDefine is a micro polyfill to `Object.defineProperty` - see [MDN](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty). It works in conjunction with `Object.getOwnPropertyDescriptor`, which is also shimmed for older browsers.\n\nThis allows you to have read-only properties of objects, or private getters/setters. Example use\n\n```ace\nrequire(['primish/primish'], function(primish){\n\tvar Human = primish({\n\n\t\tconstructor: function(name){\n\t\t\tthis.name = name;\n\n\t\t\t// make name readonly\n\t\t\tprimish.define(this, 'name', {\n\t\t\t\twritable: false,\n\t\t\t\tenumerable: true\n\t\t\t});\n\t\t},\n\n\t\tsetName: function(name){\n\t\t\tthis.name = name; // won't work in modern browsers\n\t\t}\n\n\t});\n\n\tvar Bob = new Human('Bob');\n\n\tBob.setName('Robert');\n\n\tBob.name = 'Rob';\n\n\t// should be fine.\n\tconsole.info(Bob.name);\n\tconsole.assert(Bob.name === 'Bob');\n\n});\n```\n\n## Plugins\n\n### emitter\n\nThe Emitter class can work either as a [mixin](#creating-a-class/implement) or as a standalone Class instance. It provides any Class that uses it with 3 methods it can call:\n\n- `.on(event, callback)` - subscribes to `String(event)` and runs `callback` when fired.\n- `.off(event, callback)` - removes specific subscription to `String(event)` by exact reference to `callback`. Removing events requires you to be able to pass on the original bound callback.\n- `.trigger(event, [Optional arguments])` - fires `String(event)` and optionally passes arguments to the callback\n\nBy default, the scope of `this` in any event callback function will be the object that fired it, not the subscriber. If you want to keep scope bound to your local instance, you need to use `Function.prototype.bind` (if ES5Shim is being used) or `_.bind` (lodash or underscore), which is probably safer.\n\n#### Using events\n\n```ace\nrequire(['primish/primish', 'primish/emitter'], function(primish, emitter){\n\t// this example won't run w/o ECMA5 Function.prototype.bind\n\n\tvar someController = new (primish({\n\t\timplement: [emitter]\n\t}))();\n\n\tvar Human = primish({\n\t\timplement: [Emitter],\n\t\tconstructor: function(){\n\t\t\tthis.attachEvents();\n\t\t},\n\t\teat: function(energy){\n\t\t\tthis.energy += energy;\n\t\t\t// fire an event, passing how much and new energy level\n\t\t\tthis.trigger('eat', [energy, this.energy]);\n\t\t},\n\t\tattachEvents: function(){\n\t\t\t// subscribe to another instance's init event\n\t\t\tsomeController.on('init', this.initialize.bind(this));\n\n\t\t\t// example of an event that gets removed after a single run\n\t\t\tthis.boundFetch = this.dataFetched.bind(this);\n\t\t\tsomeController.on('fetch', this.boundFetch);\n\t\t},\n\t\tinitialize: function(){\n\t\t\t// this will only run after the controller fires init, this = self.\n\t\t\tconsole.log('ready to do stuff');\n\t\t},\n\t\tdataFetched: function(){\n\t\t\t// should only run once and unsubscribe\n\t\t\t// do stuff\n\t\t\tconsole.log('we have data');\n\n\t\t\t// remove the event by passing reference to the saved bound function\n\t\t\tthis.off('fetch', this.boundFetch);\n\t\t\tdelete this.boundFetch;\n\t\t}\n\t});\n\n\tvar Bob = new Human();\n\tsomeController.trigger('init');\n\tsetTimeout(function(){\n\t\tsomeController.trigger('fetch');\n\t}, 1000);\n});\n```\n\nYou can also use **named anonymous functions** to remove your own event in a hurry:\n\n```ace\nrequire(['primish/primish', 'primish/emitter'], function(primish, emitter){\n\tvar Human = primish({\n\t\timplement: [emitter],\n\t\tconstructor: function(){\n\t\t\tthis.on('hi', function hiEvent(){\n\t\t\t\tconsole.log('running callback');\n\t\t\t\tthis.off('hi', hiEvent);\n\t\t\t});\n\t\t}\n\t});\n\n\tvar h = new Human();\n\th.trigger('hi').trigger('hi'); // should only console.log once\n\n\t// or simply use the :once pseudo\n\th.on('bye:once', function(){\n\t\tconsole.log('bye');\n\t});\n\n\th.trigger('bye');\n\th.trigger('bye'); // won't do anything\n});\n\n```\n\nThere is also syntactic sugar available for adding more than one event to the same callback:\n\n```javascript\nvar cb = function(){\n};\n\nmodel.on('change fetch create', cb); // any of change, fetch or create events fire the same handler\n```\n\n#### definePseudo\n\nEmitter supports `pseudo events`, similar in style to CSS pseudos. For instance: `load:once` is a `load` event with a `once` pseudo.\n\nBy default, emitter ships with `once` pre-defined - which will run an event callback once only, then unbind itself.\n\nIt exposes an API to define custom pseudos on the emitter object.\n\n```ace\nrequire(['primish/primish', 'primish/emitter'], function(primish, emitter){\n\n    var user = {\n        role: 'tester'\n    };\n\n    // definePseudo takes 2 arguments - base event name and fn callback\n    emitter.definePseudo('admin', function(eventName, fn){\n        // need to return a function\n        return function(){\n            // eg, check if user.role is admin\n            if (user.role === 'admin'){\n                fn.apply(this, arguments);\n            }\n        };\n    });\n\n    var e = new emitter();\n\n    e.on('load:once', function(){\n        console.log('loaded, should see this once');\n    });\n\n    e.on('test:admin', function(){\n        console.log('this should only run when user.role === \"admin\"');\n    });\n\n    // once\n    e.trigger('load');\n    e.trigger('load');\n\n    // at the moment, role is wrong, so this won't fire\n    e.trigger('test');\n\n    user.role = 'admin';\n    e.trigger('test'); // test:admin cb will now run\n});\n```\n\n### options\n\nA small utility mixin from Arian's prime-util that allows easy object merge of an Object into `this.object` from right to left. If emitter is also mixed-in, it will automatically add events prefixed by `on` and camelcased, eg, `onReady: function(){}`.\n\n```ace\nrequire(['primish/primish', 'primish/emitter', 'primish/options'], function(primish, emitter, options){\n\tvar Human = primish({\n\t\toptions: {\n\t\t\tname: 'unknown'\n\t\t},\n\t\timplement: [options, emitter],\n\t\tconstructor: function(options){\n\t\t\tthis.setOptions(options);\n\t\t\tthis.trigger('ready');\n\t\t}\n\t});\n\n\tvar bob = new Human({\n\t\tname: 'Bob',\n\t\tsurname: 'Roberts',\n\t\tonReady: function(){\n\t\t\tconsole.log(this.options.name, this.options.surname);\n\t\t\t// this.options.onReady won't be added.\n\t\t}\n\t});\n});\n```\n\n## contributing\n\nTo install locally, clone the repo and setup:\n\n```sh\n$ git clone https://github.com/dimitarchristoff/primish.git\n$ cd primish/\n\n# pull the deps\n$ npm install\n\n# run the tests\n$ npm test\n\n# generate docs and make a new build\n$ npm install -g grunt-cli\n$ grunt\n$ cd dist\n$ python -m SimpleHTTPServer\n$ open http://localhost:8000\n\n# just generate a new build\n$ grunt requirejs:build\n```\n\n## npm usage\n\nYou can install it via npm by simply doing:\n\n```sh\n$ npm install primish --save\n```\n\nThen to access it in a nodejs script:\n\n```javascript\nvar prime = require('primish'),\n\temitter = require('primish/emitter');\n\nvar foo = primish({\n\n\timplement: emitter\n\n}); // etc.\n```\n\n## bower usage\n\nTo install it as a bower component, simply do:\n\n```sh\n$ bower install primish --save\n```\n\n## RequireJS usage\n\nPrimish is compatible with RequireJS 2.1.10 bundles. Here's an example require config that lets you use the minified primish\nfile and require all sub modules later:\n\n```javascript\nrequire.config({\n\tbundles: {\n\t\t'bower_components/primish/primish-min': [\n\t\t\t'primish/primish',\n\t\t\t'primish/emitter',\n\t\t\t'primish/options'\n\t\t]\n\t}\n});\n\nrequire([\n\t'primish/primish',\n\t'primish/options',\n\t'primish/emitter'\n], function(primish, options, emitter){\n\t// should see one HTTP request for primish-min only for either of\n\t// the 3 files requested for the first time.\n\tvar Person = primish({\n\t\timplement: [options, emitter],\n\t\tconstructor: function(options){\n\t\t\tthis.setOptions(options);\n\t\t}\n\t});\n});\n```\n\nHave fun, examples in `./examples/` and also look at the `spec` folder (jasmine-node test runner).\nMost examples in the docs are runnable, just edit the code and press `run`, then look at your console.\n\nA more complex example can be seen in [Epik](http://dimitarchristoff.github.io/epik/), a fully fledged MVC framework\nbuilt on top of primish and lodash.\n\n## License\n\nUse as you deem fit under the original [MIT license](https://github.com/mootools/prime/blob/master/package.json#L23) for prime. Primish brings little on top of the work of the MooTools team. The documentation and examples are not covered by the license and may need to be changed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimitarchristoff%2Fprimish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimitarchristoff%2Fprimish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimitarchristoff%2Fprimish/lists"}