├── .gitignore
├── .npmignore
├── README.md
├── build
└── index.coffee
├── karma.conf.coffee
├── package.json
├── src
├── _throttledListener.coffee
├── class.coffee
├── dynamicCss.coffee
├── fragToString.coffee
├── getDocumentHeight.coffee
├── getViewportOffset.coffee
├── getViewportSize.coffee
├── getVue.coffee
├── isOpened.coffee
├── isOpened2.coffee
├── onClick.coffee
├── onClickStack.coffee
├── onClickStore.coffee
├── onDocument.coffee
├── onElementResize.coffee
├── onMouseMove.coffee
├── onResize.coffee
├── onWindowResize.coffee
├── onWindowScroll.coffee
├── onceDocument.coffee
├── parentListener.coffee
├── parentListener2.coffee
├── setCss.coffee
├── style.coffee
├── transition.coffee
├── transition2.coffee
└── vue.coffee
├── test
├── class.coffee
├── dynamicCss.coffee
├── fragToString.coffee
├── getViewportOffset.coffee
├── getViewportSize.coffee
├── getVue.coffee
├── onClick.coffee
├── onClickStack.coffee
├── onClickStore.coffee
├── onDocument.coffee
├── onElementResize.coffee
├── onMouseMove.coffee
├── onWindowResize.coffee
├── onceDocument.coffee
├── setCss.coffee
├── style.coffee
└── vue.coffee
└── webpack.config.coffee
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.sublime-project
3 | *.sublime-workspace
4 | npm-debug.log
5 | build/*.js
6 | *.js
7 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | *.sublime-project
3 | *.sublime-workspace
4 | npm-debug.log
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-mixins
2 |
3 | A collection of mixins in vue.
4 | Heavily used in [**vue-comps**](https://github.com/vue-comps).
5 |
6 | ## Policy
7 |
8 | all sorts of mixins can be submitted. There will be no removes because of deprecation. If the API of a mixin changes the name has to change, for example `onResize` -> `onResize2`
9 |
10 | ## Install
11 |
12 | ```sh
13 | npm install --save-dev vue-mixins
14 | ```
15 | or include `bundle.js`
16 | ## Usage
17 | ```coffee
18 | ## whithin your module
19 | components:
20 | mixins:[
21 | require("vue-mixins/onClick")
22 | ]
23 | # if you have used the bundle.js
24 | components:
25 | mixins:[
26 | window.vueMixins.onClick
27 | ]
28 | ```
29 | ## List of mixins
30 | Name | src| description
31 | ---: | ---| -------
32 | [getViewportSize](https://github.com/paulpflug/vue-mixins#getviewportsize) | [src](src/getViewportSize.coffee) | adds a method `getViewportSize` which returns an object containing the `width` and `height` of the viewport
33 | [getDocumentHeight](https://github.com/paulpflug/vue-mixins#getdocumentheight) | [src](src/getDocumentHeight.coffee) | adds a method `getDocumentHeight` which returns the `height` of the document
34 | [onceDocument](https://github.com/paulpflug/vue-mixins#oncedocument) | [src](src/onceDocument.coffee) | adds a eventListener to the document which removes itself after first successful call|
35 | |[onClick](https://github.com/paulpflug/vue-mixins#onclick) | [src](src/onClick.coffee) | adds a method `click` which will call the function `onClick` if set
36 | [onClickStack](https://github.com/paulpflug/vue-mixins#onclickstack) | [src](src/onClickStack.coffee) | adds two methods: `click` and `addToClickStack`
37 | [onClickStore](https://github.com/paulpflug/vue-mixins#onclickstore) | [src](src/onClickStore.coffee) | adds two methods: `click` and `onClick` (see below)
38 | [onDocument](https://github.com/paulpflug/vue-mixins#ondocument) | [src](src/onDocument.coffee) | like `onceDocument` but doesn't removes itself
39 | onResize | [src](src/onResize.coffee) | deprecated
40 | [onWindowResize](https://github.com/paulpflug/vue-mixins#onwindowresize) | [src](src/onWindowResize.coffee) | fires on resize of window (throttled and bundled)
41 | [onElementResize](https://github.com/paulpflug/vue-mixins#onelementresize) | [src](src/onElementResize.coffee) | fires on resize of window or element, but only if the dimensions of the element changed
42 | [onWindowScroll](https://github.com/paulpflug/vue-mixins#onwindowscroll) | [src](src/onWindowScroll.coffee) | fires on scroll on window (throttled and bundled)
43 | [setCss](https://github.com/paulpflug/vue-mixins#setcss) | [src](src/setCss.coffee) | set Css of another element
44 | [dynamicCss](https://github.com/paulpflug/vue-mixins#dynamiccss) | [src](src/dynamicCss.coffee) | dynamically manipulate css stylesheet
45 | getVue | [src](src/getVue.coffee) | deprecated, use `vue` instead
46 | [vue](https://github.com/paulpflug/vue-mixins#vue) | [src](src/vue.coffee) | adds a computed property `Vue` with the current instance of `Vue`
47 | [isOpened](https://github.com/paulpflug/vue-mixins#isopened) | [src](src/isOpened.coffee) | adds everything for opened state management (two-way)
48 | [isOpened2](https://github.com/paulpflug/vue-mixins#isopened) | [src](src/isOpened2.coffee) | same as isOpened but for vue 2.0 (one-way)
49 | [parentListener](https://github.com/paulpflug/vue-mixins#parentlistener) | [src](src/parentListener.coffee) | hooks a function upon parent click
50 | [parentListener2](https://github.com/paulpflug/vue-mixins#parentlistener) | [src](src/parentListener2.coffee) | same as parentListener but for vue 2.0
51 | [fragToString](https://github.com/paulpflug/vue-mixins#fragtostring) | [src](src/fragToString.coffee) | converts a `documentFragment` to `String`
52 | [class](https://github.com/paulpflug/vue-mixins#class) | [src](src/class.coffee) | used to create a properly merged vue class object/array from a given prop and another vue class object/array
53 | [style](https://github.com/paulpflug/vue-mixins#style) | [src](src/style.coffee) | used to create a properly merged vue style object/array from a given prop and another vue style object/array
54 | [transition](https://github.com/paulpflug/vue-mixins#transition) | [src](src/transition.coffee) | used to manage user provided transition in a reusable component
55 | [transition2](https://github.com/paulpflug/vue-mixins#transition) | [src](src/transition2.coffee) | same as transition but for vue 2.0
56 | [onMouseMove](https://github.com/paulpflug/vue-mixins#onmousemove) | [src](src/onMouseMove.coffee) | fires on move of the mouse (throttled and bundled)
57 |
58 | ## Detailed usage
59 | ### getViewportSize
60 | ```js
61 | // adds a method:
62 | // getViewportSize()
63 | //
64 | // usage:
65 | vs = this.getViewportSize()
66 | vs.width
67 | vs.height
68 | ```
69 | ### getDocumentHeight
70 | ```js
71 | // adds a method:
72 | // getDocumentHeight()
73 | //
74 | // usage:
75 | height = this.getDocumentHeight()
76 | ```
77 | ### onceDocument
78 | ```js
79 | // adds a method:
80 | // onceDocument(event, cb, useCapture)
81 | //
82 | // usage:
83 | dispose = this.onceDocument('click',function(e){
84 | doSomething()
85 | // return true will remove the listener
86 | // return false will not remove the listener
87 | },false)
88 | dispose() // will remove the listener
89 | ```
90 | ### onClick
91 | ```js
92 | // adds a method:
93 | // click(event) which will call this.onClick(e) if available
94 | //
95 | // usage:
96 | this.onClick = function(e) {doSomething()}
97 | ```
98 | ```html
99 |
100 |
101 | ```
102 |
103 | ### onClickStack
104 | ```js
105 | // adds two methods:
106 | // - click(event) will call the last function in this.onClickStack if available
107 | // - addToClickStack(fn) will add a function to this.onClickStack and return a function to dispose it
108 | //
109 | // usage:
110 | var dispose = null
111 | var cb = function(e) {
112 | doSomething()
113 | dispose() // to remove from stack
114 | }
115 | dispose = this.addToClickStack(cb)
116 | ```
117 | ```html
118 |
119 |
120 | ```
121 |
122 | ### onClickStore
123 | ```js
124 | // adds two methods:
125 | // - click(event) will call all functions in this.onClickStore
126 | // - onClick(fn) will add a function to this.onClickStore and return a function to dispose it
127 | //
128 | // usage:
129 | var dispose = null
130 | var cb = function(e) {
131 | doSomething()
132 | dispose() // to remove from store
133 | }
134 | dispose = this.onClickStore(cb)
135 | ```
136 | ```html
137 |
138 |
139 | ```
140 | ### onDocument
141 | like `onceDocument`, but doesn't remove itself on first successful invokation.
142 |
143 | ### onWindowResize
144 | ```js
145 | // adds a method: onWindowResize(cb) which will return a function to dispose it
146 | //
147 | // usage:
148 | dispose = this.onWindowResize(function(){/*doSomethingOnWindowResize*/})
149 | // remove your cb
150 | dispose()
151 | // all events will be automatically disposed on `beforeDestroy`
152 | ```
153 |
154 | ### onElementResize
155 | ```js
156 | // adds a method: onElementResize(el, cb) which will return a function to dispose it
157 | //
158 | // usage:
159 | dispose = this.onElementResize(el, function(){/*doSomethingOnElementResize*/})
160 | // remove your cb
161 | dispose()
162 | // all events will be automatically disposed on `beforeDestroy`
163 | ```
164 |
165 | ### onWindowScroll
166 | ```js
167 | // adds a method: onWindowScroll(cb) which will return a function to dispose it
168 | //
169 | // usage:
170 | dispose = this.onWindowScroll(function(){/*doSomethingOnWindowScroll*/})
171 | // remove your cb
172 | dispose()
173 | // all events will be automatically disposed on `beforeDestroy`
174 | ```
175 |
176 | ### setCss
177 | ```js
178 | // adds a method:
179 | // setCss(element,cssProperty, cssValue)
180 | //
181 | // usage:
182 | this.setCss(document.body,"overflow","hidden")
183 |
184 | // remove overflow from style attribute
185 | this.setCss(document.body,"overflow")
186 | // or
187 | this.setCss(document.body,"overflow", "")
188 | ```
189 |
190 | ### dynamicCss
191 | ```js
192 | // used to create a stylesheet and set rules in it.
193 | // adds a method:
194 | // setCssRules(newRules)
195 | //
196 | // usage:
197 | this.setCssRules({body: {overflow: "hidden"}})
198 | // to remove a rule:
199 | this.setCssRules({body: {overflow: null}})
200 | // nesting:
201 | this.setCssRules({body: {"& div": {width: "10px"},overflow:"hidden"}})
202 | // is short for: (& will be replaced by the parent selector)
203 | // deeper nesting is allowed
204 | this.setCssRules({body: {overflow:"hidden"},"body div": {width: "10px"}})
205 | ```
206 |
207 | ### vue
208 | ```js
209 | // adds a computed property:
210 | // Vue
211 | //
212 | // usage:
213 | Vue = this.Vue
214 | ```
215 |
216 | ### isOpened
217 | ```js
218 | // adds a boolean prop "isOpened" which will call "this.toggle()" on change
219 | // the state is saved on "opened"
220 | //
221 | // adds two methods:
222 | // setOpened(), setClosed() which will set "this.isOpened" without triggering
223 | // the toggle
224 | // and emit a event "toggled(opened)"
225 | //
226 | // usage:
227 | methods:
228 | toggle: function(){
229 | if (this.opened) {
230 | this.close()
231 | } else {
232 | this.open()
233 | }
234 | }
235 | open: function() {
236 | this.setOpened()
237 | }
238 | close: function() {
239 | this.setClosed()
240 | }
241 | ```
242 | ### parentListener
243 | ```js
244 | // adds two props: "ignoreParent" and "parent", which
245 | // defaults to "this.$el.parentElement"
246 | //
247 | // usage:
248 | methods:
249 | onParentClick: function() {
250 | // will be called when "ignoreParent" is false on click on parent
251 | }
252 | ```
253 | ### fragToString
254 | ```js
255 | // adds a method: "fragToString"
256 | // usage:
257 | str = this.fragToString(someFrag)
258 | // str contains outerHTML of someFrag
259 | ```
260 | ### class
261 | ```js
262 | // adds a computed property: "computedClass"
263 | // which merges a "mergeClass" data object/array and a "class" prop.
264 | // usage:
265 | template: "",
266 | props: {
267 | class: {
268 | default: function() {
269 | return ["someClass"]
270 | }
271 | }
272 | },
273 | data: function() {
274 | return {
275 | mergeClass: ["anotherClass"]
276 | }
277 | }
278 | // computedClass will be ["anotherClass","someClass"] when no prop is given
279 | // if the component is used like this
280 | // computedClass will be ["anotherClass","yetAnotherClass"]
281 | // works also with object notation and a mixture of both
282 | ```
283 | ### style
284 | ```js
285 | // adds a computed property: "computedStyle"
286 | // which merges a "mergeStyle" data object and a "style" prop.
287 | // usage:
288 | template: "",
289 | props: {
290 | style: {
291 | default: function() {
292 | return {color:"red"}
293 | }
294 | }
295 | },
296 | data: function() {
297 | return {
298 | mergeStyle: {color:"blue"}
299 | }
300 | }
301 | // computedStyle will be [{color:"blue"},{color:"red"}] when no prop is given
302 | // if the component is used like this
303 | // computedStyle will be [{color:"blue"},{color:"white"}]
304 | // works also with array notation and a mixture of both
305 | ```
306 |
307 | ### transition
308 | used to manage user provided transition in a reusable component
309 | ```js
310 | // adds a method: "processTransition" and a computed value "cTransition"
311 | // usage:
312 | template: "",
313 | props: {
314 | transition: {
315 | type: String,
316 | default: "someDefaultTransition"
317 | }
318 | },
319 | ready: function() {
320 | this.$on("before-enter",function(){
321 | // will be called after element is inserted in dom but before transition starts
322 | // regardless of a optional provided transition
323 | })
324 | }
325 | ```
326 | `processTransition(name,parent = this.$parent)` resolves `name` to the actual transition on
327 | `parent` vm or global Vue. Adds `before-enter`, `after-enter`, `before-leave`, `after-leave`, `enterCancelled` and `leaveCancelled` emit hooks on the instance and inserts the modified transition into `this.$options.transitions[name]`
328 | `cTransition` lazily calls `processTransition` on the first transition and every time `transition` changes.
329 |
330 | You can disable transition by setting `this.disableTransition = true`.
331 |
332 | ### onMouseMove
333 | ```js
334 | // adds a method: onMouseMove(cb) which will return a function to dispose it
335 | //
336 | // usage:
337 | dispose = this.onMouseMove(function(){/*doSomethingOnMouseMove*/})
338 | // remove your cb
339 | dispose()
340 | // all events will be automatically disposed on `beforeDestroy`
341 | ```
342 |
343 | ## Develop
344 | Clone rep
345 | ```
346 | npm install
347 | ```
348 | Available scripts:
349 | ```
350 | npm run build # compiles coffee-script in src/
351 | npm run test # runs a single-run karma in chrome and firefox
352 | npm run watch # runs karma in chrome (uses src/*.coffee files direclty, no need for build)
353 |
354 | # to run only single tests:
355 | karma start --browsers Chrome --auto-watch --reporters spec --files ['test/onClick.coffee']
356 | ```
357 |
358 | ## License
359 | Copyright (c) 2015 Paul Pflugradt
360 | Licensed under the MIT license.
361 |
--------------------------------------------------------------------------------
/build/index.coffee:
--------------------------------------------------------------------------------
1 | # out: ./index.js
2 | mixins = {}
3 | req = require.context("..",false,/.js$/)
4 | for name in [
5 | "class"
6 | "dynamicCss"
7 | "fragToString"
8 | "getDocumentHeight"
9 | "getViewportOffset"
10 | "getViewportSize"
11 | "isOpened"
12 | "isOpened2"
13 | "onceDocument"
14 | "onClick"
15 | "onClickStack"
16 | "onClickStore"
17 | "onDocument"
18 | "onElementResize"
19 | "onMouseMove"
20 | "onWindowResize"
21 | "onWindowScroll"
22 | "parentListener"
23 | "setCss"
24 | "style"
25 | "transition"
26 | "vue"
27 | ]
28 | mixins[name] = req("./#{name}.js")
29 | if module.exports != null
30 | module.exports = mixins
31 | else
32 | window.vueMixins = mixins
33 |
--------------------------------------------------------------------------------
/karma.conf.coffee:
--------------------------------------------------------------------------------
1 | module.exports = (config) ->
2 | config.set
3 | preprocessors: "**/*.coffee": ["webpack",'sourcemap']
4 | webpack:
5 | devtool: 'inline-source-map'
6 | resolve:
7 | extensions: [".js",".coffee"]
8 | module:
9 | loaders: [
10 | { test: /\.coffee$/, loader: "coffee-loader" }
11 | ]
12 | webpackMiddleware:
13 | noInfo: true
14 | files: ["test/*.coffee"]
15 | frameworks: ["mocha","chai-dom","chai-spies","chai","vue-component"]
16 | plugins: [
17 | require("karma-chai")
18 | require("karma-chai-dom")
19 | require("karma-chrome-launcher")
20 | require("karma-firefox-launcher")
21 | require("karma-mocha")
22 | require("karma-webpack")
23 | require("karma-sourcemap-loader")
24 | require("karma-spec-reporter")
25 | require("karma-chai-spies")
26 | require("karma-vue-component")
27 | ]
28 | browsers: ["Chromium","Firefox"]
29 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "vue-mixins",
3 | "description": "collection of mixins in vue",
4 | "version": "0.3.6",
5 | "homepage": "https://github.com/paulpflug/",
6 | "author": {
7 | "name": "Paul Pflugradt",
8 | "email": "paul.pflugradt@gmail.com"
9 | },
10 | "license": "MIT",
11 | "main": "build/bundle.js",
12 | "repository": {
13 | "type": "git",
14 | "url": "git://github.com/paulpflug/vue-mixins"
15 | },
16 | "engines": {
17 | "node": "*"
18 | },
19 | "dependencies": {
20 | "lodash": "^4.16.1",
21 | "javascript-detect-element-resize": "^0.5.3"
22 | },
23 | "devDependencies": {
24 | "chai": "^3.5.0",
25 | "chai-spies": "^0.7.1",
26 | "coffee-loader": "^0.7.2",
27 | "coffee-script": "^1.11.1",
28 | "karma": "^1.3.0",
29 | "karma-chai": "^0.1.0",
30 | "karma-chai-dom": "^1.1.0",
31 | "karma-chai-spies": "^0.1.4",
32 | "karma-chrome-launcher": "^2.0.0",
33 | "karma-firefox-launcher": "^1.0.0",
34 | "karma-mocha": "^1.1.1",
35 | "karma-sourcemap-loader": "^0.3.7",
36 | "karma-spec-reporter": "0.0.26",
37 | "karma-vue-component": "^0.1.0",
38 | "karma-webpack": "^1.8.0",
39 | "lodash": "^4.16.1",
40 | "mocha": "^3.0.2",
41 | "script-runner": "^0.1.5",
42 | "vue": "^1.0.26",
43 | "webpack": "^2.1.0-beta.25"
44 | },
45 | "keywords": [],
46 | "readmeFilename": "README.md",
47 | "scripts": {
48 | "build:coffee": "coffee --no-header --compile --output . src/*.coffee",
49 | "build:webpack": "webpack",
50 | "build": "run-npm build:*",
51 | "watch": "karma start --browsers Chromium --auto-watch --reporters spec",
52 | "watch:coffee": "coffee --no-header --watch --output . src/*.coffee",
53 | "test": "karma start --single-run",
54 | "preversion": "npm test && npm run build",
55 | "version": "git add .",
56 | "postversion": "git push && git push --tags && npm publish"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/_throttledListener.coffee:
--------------------------------------------------------------------------------
1 | # out: ../_throttledListener.js
2 | called = []
3 | fn = () -> called.push arguments
4 | if document? and window?
5 | document.addEventListener "DOMContentLoaded", ->
6 | rAF = window.requestAnimationFrame ||
7 | window.mozRequestAnimationFrame ||
8 | window.webkitRequestAnimationFrame ||
9 | window.msRequestAnimationFrame
10 |
11 | cAF = window.cancelAnimationFrame ||
12 | window.mozCancelAnimationFrame
13 | if rAF
14 | fn = (event, cb) ->
15 | lastRequest = null
16 | window.addEventListener event, ->
17 | args = arguments
18 | cAF(lastRequest)
19 | lastRequest = rAF -> cb.apply(null, args)
20 | else
21 | throttle = require("lodash/throttle")
22 | fn = (event, cb) ->
23 | window.addEventListener event, throttle(cb, 66)
24 | for args in called
25 | fn.apply(null, args)
26 | module.exports = fn
27 |
--------------------------------------------------------------------------------
/src/class.coffee:
--------------------------------------------------------------------------------
1 | # out: ../class.js
2 | isString = (str) -> typeof str == 'string' or str instanceof String
3 | processInput = (obj) ->
4 | isArray = Array.isArray(obj)
5 | if isString(obj) and not isArray
6 | obj = obj.split(" ")
7 | isArray = true
8 | return isArray:isArray, obj:obj
9 | module.exports =
10 | computed:
11 | computedClass: ->
12 | { isArray: isArray1, obj: obj1 } = processInput(@class)
13 | return obj1 unless @mergeClass?
14 | { isArray: isArray2, obj: obj2 } = processInput(@mergeClass)
15 | if isArray1 and isArray2
16 | return obj2.concat obj1
17 | else
18 | result = {}
19 | if isArray2
20 | for item in obj2
21 | if isString(item)
22 | result[item] = true
23 | else
24 | for key,val of item
25 | result[key] = val
26 | else
27 | for key,val of obj2
28 | result[key] = val
29 | if isArray1
30 | for item in obj1
31 | if isString(item)
32 | result[item] = true
33 | else
34 | for key,val of item
35 | result[key] = val
36 | else
37 | for key,val of obj1
38 | result[key] = val
39 | return result
40 |
--------------------------------------------------------------------------------
/src/dynamicCss.coffee:
--------------------------------------------------------------------------------
1 | # out: ../dynamicCss.js
2 | if document?
3 | styletag = document.createElement('style')
4 | styletag.setAttribute 'id', 'vm-dynamic-css'
5 | styletag.setAttribute "type","text/css"
6 | document.head.appendChild styletag
7 | stylesheet = if styletag.sheet then styletag.sheet else styletag.styleSheet
8 |
9 | flatten = (obj,base="") ->
10 | tmp = {}
11 | for key,val of obj
12 | if val instanceof Object
13 | props = {}
14 | for key2,val2 of val
15 | if key2.indexOf("&") > -1
16 | tmp2 = {}
17 | tmp2[key2.replace("&","")] = val2
18 | tmp2 = flatten(tmp2,base+key)
19 | for key3, val3 of tmp2
20 | tmp[key3] = val3
21 | else
22 | props[key2] = val2
23 | tmp[base+key] = props
24 | else
25 | tmp[base+key] = val
26 | return tmp
27 |
28 | setRules = (newRules) ->
29 | newRules = flatten(newRules)
30 | for selector,css of newRules
31 | str = ""
32 | {cssRule,index} = getRule(selector)
33 | if cssRule?
34 | if css?
35 | for singleRule,singleValue of css
36 | if singleValue?
37 | cssRule.style.setProperty singleRule, singleValue
38 | else
39 | cssRule.style.removeProperty singleRule
40 | else
41 | removeRule(index)
42 | else
43 | if css?
44 | for singleRule,singleValue of css
45 | if singleValue?
46 | str += singleRule+":"+singleValue+";"
47 | insertRule(selector,str)
48 |
49 | getRule = (selector) ->
50 | cssRules = stylesheet.cssRules or stylesheet.rules or []
51 | for cssRule,index in cssRules
52 | if cssRule.selectorText == selector
53 | return {cssRule:cssRule,index:index}
54 | return {cssRule:null,index:null}
55 |
56 | insertRule = (selector,str) ->
57 | selector = selector.toLowerCase()
58 | str = str.toLowerCase()
59 | if stylesheet.insertRule
60 | stylesheet.insertRule selector + ' { ' + str + ' } ', stylesheet.cssRules.length
61 | else if stylesheet.addRule
62 | stylesheet.addRule selector, str
63 |
64 | removeRule = (index) ->
65 | if stylesheet.removeRule
66 | stylesheet.removeRule(index)
67 | else
68 | stylesheet.deleteRule(index)
69 |
70 | module.exports =
71 | methods:
72 | 'setCssRules': setRules
73 |
--------------------------------------------------------------------------------
/src/fragToString.coffee:
--------------------------------------------------------------------------------
1 | # out: ../fragToString.js
2 | module.exports =
3 | methods:
4 | fragToString: (frag) ->
5 | div = document.createElement "div"
6 | div.appendChild frag.cloneNode(true)
7 | return div.innerHTML
8 |
--------------------------------------------------------------------------------
/src/getDocumentHeight.coffee:
--------------------------------------------------------------------------------
1 | # out: ../getDocumentHeight.js
2 |
3 | getDocumentHeight = ->
4 | body = document.body
5 | html = document.documentElement
6 | return document.height or Math.max(body.scrollHeight,
7 | body.offsetHeight,
8 | html.clientHeight,
9 | html.scrollHeight,
10 | html.offsetHeight)
11 |
12 | module.exports =
13 | methods:
14 | getDocumentHeight: getDocumentHeight
15 |
--------------------------------------------------------------------------------
/src/getViewportOffset.coffee:
--------------------------------------------------------------------------------
1 | # out: ../getViewportOffset.js
2 | # https://gist.github.com/jlong/eff01958791d3e0bf10c
3 | obj = require "./getViewportSize"
4 | getViewportSize = obj.methods.getViewportSize
5 | getViewportOffset = (element = @$el) ->
6 | left = element.offsetLeft
7 | top = element.offsetTop
8 | el = element.parentElement
9 | while el
10 | styles = getComputedStyle el
11 | if styles
12 | position = styles.getPropertyValue 'position'
13 | left -= el.scrollLeft
14 | top -= el.scrollTop
15 | if /relative|absolute|fixed/.test(position)
16 | left += parseInt(styles.getPropertyValue('border-left-width'), 10)
17 | top += parseInt(styles.getPropertyValue('border-top-width'), 10)
18 | left += el.offsetLeft
19 | top += el.offsetTop
20 | break if position == 'fixed'
21 | el = el.parentElement
22 | viewportSize = getViewportSize()
23 | return {
24 | top: top
25 | bottom: viewportSize.height-element.offsetHeight-top
26 | left: left
27 | right: viewportSize.width-element.offsetWidth-left
28 | }
29 |
30 | module.exports =
31 | methods:
32 | getViewportOffset: getViewportOffset
33 |
--------------------------------------------------------------------------------
/src/getViewportSize.coffee:
--------------------------------------------------------------------------------
1 | # out: ../getViewportSize.js
2 | # http://andylangton.co.uk/blog/development/get-viewport-size-width-and-height-javascript
3 | getViewportSize = ->
4 | if window.innerWidth?
5 | e = window
6 | a = 'inner'
7 | else
8 | a = 'client'
9 | e = document.documentElement || document.body
10 | return { width : e[ a+'Width' ] , height : e[ a+'Height' ] }
11 |
12 | module.exports =
13 | methods:
14 | getViewportSize: getViewportSize
15 |
--------------------------------------------------------------------------------
/src/getVue.coffee:
--------------------------------------------------------------------------------
1 | # out: ../getVue.js
2 | module.exports =
3 | methods:
4 | 'getVue': ->
5 | return Object.getPrototypeOf(Object.getPrototypeOf(@)).constructor
6 |
--------------------------------------------------------------------------------
/src/isOpened.coffee:
--------------------------------------------------------------------------------
1 | # out: ../isOpened.js
2 | module.exports =
3 | props:
4 | "isOpened":
5 | type: Boolean
6 | default: false
7 | data: ->
8 | opened: null
9 | methods:
10 | setOpened: ->
11 | @opened = true
12 | @isOpened = true
13 | @$emit "toggled", true
14 | setClosed: ->
15 | @opened = false
16 | @isOpened = false
17 | @$emit "toggled", false
18 | watch:
19 | "isOpened": (val) ->
20 | if val != @opened
21 | @toggle()
22 | ready: ->
23 | if @isOpened
24 | @disableTransition = true
25 | @toggle()
26 | @disableTransition = false
27 |
--------------------------------------------------------------------------------
/src/isOpened2.coffee:
--------------------------------------------------------------------------------
1 | # out: ../isOpened.js
2 | module.exports =
3 | props:
4 | "isOpened":
5 | type: Boolean
6 | default: false
7 | data: ->
8 | opened: null
9 | methods:
10 | setOpened: ->
11 | @opened = true
12 | @$emit "toggled", true
13 | setClosed: ->
14 | @opened = false
15 | @$emit "toggled", false
16 | watch:
17 | "isOpened": (val) ->
18 | if val != @opened
19 | @toggle()
20 | mounted: -> @$nextTick ->
21 | if @isOpened
22 | @toggle()
23 |
--------------------------------------------------------------------------------
/src/onClick.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onClick.js
2 | module.exports =
3 | data: ->
4 | onClick: null
5 | methods:
6 | click: (e) ->
7 | if @onClick?
8 | @onClick(e)
9 |
--------------------------------------------------------------------------------
/src/onClickStack.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onClickStack.js
2 | module.exports =
3 | data: ->
4 | onClickStack: []
5 | methods:
6 | addToClickStack: (cb) ->
7 | @onClickStack.push(cb) unless @onClickStack.indexOf(cb) > -1
8 | return =>
9 | index = @onClickStack.indexOf cb
10 | if index > -1
11 | @onClickStack.splice index,1
12 | click: (e) ->
13 | if @onClickStack.length > 0
14 | @onClickStack[@onClickStack.length-1](e)
15 |
--------------------------------------------------------------------------------
/src/onClickStore.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onClickStore.js
2 | module.exports =
3 | data: ->
4 | onClickStore: []
5 | methods:
6 | onClick: (cb) ->
7 | unless @onClickStore.indexOf(cb) > -1
8 | @onClickStore.push cb
9 | return =>
10 | index = @onClickStore.indexOf cb
11 | if index > -1
12 | @onClickStore.splice index,1
13 | click: (e) ->
14 | for fn in @onClickStore
15 | fn(e)
16 |
--------------------------------------------------------------------------------
/src/onDocument.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onDocument.js
2 | onDocument = (event, cb, useCapture) ->
3 | document.documentElement.addEventListener event, cb, useCapture
4 | remover = ->
5 | document.documentElement.removeEventListener event, cb
6 | remover = null
7 | return remover
8 | module.exports =
9 | methods:
10 | onDocument: onDocument
11 |
--------------------------------------------------------------------------------
/src/onElementResize.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onElementResize.js
2 | called = []
3 | disposes = []
4 | fn = () ->
5 | args = arguments
6 | called.push args
7 | return ->
8 | i = called.indexOf args
9 | if i > -1
10 | called.splice i,1
11 | if disposes[i]?
12 | disposes[i]()
13 | disposes.splice i,1
14 |
15 |
16 | if document? and window?
17 | document.addEventListener "DOMContentLoaded", ->
18 | if window.MutationObserver?
19 | allResizeCbs = []
20 | fn = (el, cb) ->
21 | elheight = el.offsetHeight
22 | elwidth = el.offsetWidth
23 | cbwrapper = ->
24 | if elheight != el.offsetHeight or elwidth != el.offsetWidth
25 | elheight = el.offsetHeight
26 | elwidth = el.offsetWidth
27 | cb.apply(null,arguments)
28 | allResizeCbs.push cbwrapper
29 | return ->
30 | index = allResizeCbs.indexOf cbwrapper
31 | if index > -1
32 | allResizeCbs.splice index,1
33 | callResizeCbs = ->
34 | for cb in allResizeCbs
35 | cb.apply(null,arguments)
36 | require("./_throttledListener")("resize",callResizeCbs)
37 | throttle = require("lodash/throttle")
38 | observer = new MutationObserver throttle(callResizeCbs,66)
39 | observer.observe document.body,
40 | attributes: true
41 | childList: true
42 | characterData: true
43 | subtree: true
44 | else
45 | require "javascript-detect-element-resize"
46 | fn = (el, cb) ->
47 | window.addResizeListener(el,cb)
48 | return -> window.removeResizeListener(el,cb)
49 | for args,i in called
50 | disposes[i] = fn.apply(null, args)
51 | module.exports =
52 | data: ->
53 | resizeCbDisposables: []
54 | methods:
55 | onElementResize: (el,cb) ->
56 | return unless cb?
57 | dispose = fn(el,cb)
58 | @resizeCbDisposables.push dispose
59 | return =>
60 | index = @resizeCbDisposables.indexOf dispose
61 | if index > -1
62 | @resizeCbDisposables.splice index,1
63 | dispose()
64 |
65 | beforeDestroy: ->
66 | for resizeCbDisposable in @resizeCbDisposables
67 | resizeCbDisposable()
68 |
--------------------------------------------------------------------------------
/src/onMouseMove.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onMouseMove.js
2 | allMouseMoveCbs = []
3 | callMouseMoveCbs = ->
4 | for cb in allMouseMoveCbs
5 | cb.apply(null,arguments)
6 | require("./_throttledListener")("mousemove",callMouseMoveCbs)
7 | module.exports =
8 | data: ->
9 | mouseMoveCbDisposables: []
10 | methods:
11 | onMouseMove: (cb) ->
12 | allMouseMoveCbs.push cb
13 | dispose = ->
14 | index = allMouseMoveCbs.indexOf cb
15 | if index > -1
16 | allMouseMoveCbs.splice index,1
17 | @mouseMoveCbDisposables.push dispose
18 | return =>
19 | dispose()
20 | index = @mouseMoveCbDisposables.indexOf dispose
21 | if index > -1
22 | @mouseMoveCbDisposables.splice index,1
23 |
24 | beforeDestroy: ->
25 | for mouseMoveCbDisposable in @mouseMoveCbDisposables
26 | mouseMoveCbDisposable()
27 |
--------------------------------------------------------------------------------
/src/onResize.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onResize.js
2 | if window
3 | resizeRunning = false
4 | allResizeCbs = []
5 | resizeHandler = ->
6 | unless resizeRunning
7 | resizeRunning = true
8 | if window.requestAnimationFrame
9 | window.requestAnimationFrame callResizeCbs
10 | else
11 | setTimeout callResizeCbs, 66
12 | callResizeCbs = (e) ->
13 | for cb in allResizeCbs
14 | cb(e)
15 | resizeRunning = false
16 | window.addEventListener "resize", resizeHandler
17 | observer = new MutationObserver resizeHandler
18 | observer.observe document.body,
19 | attributes: true
20 | childList: true
21 | characterData: true
22 | subtree: true
23 |
24 | module.exports =
25 | data: ->
26 | resizeCbDisposables: []
27 | methods:
28 | addResizeCb: (cb) ->
29 | allResizeCbs.push cb
30 | dispose = ->
31 | index = allResizeCbs.indexOf cb
32 | if index > -1
33 | allResizeCbs.splice index,1
34 | @resizeCbDisposables.push dispose
35 | return =>
36 | dispose()
37 | index = @resizeCbDisposables.indexOf dispose
38 | if index > -1
39 | @resizeCbDisposables.splice index,1
40 |
41 | beforeDestroy: ->
42 | for resizeCbDisposable in @resizeCbDisposables
43 | resizeCbDisposable()
44 |
--------------------------------------------------------------------------------
/src/onWindowResize.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onWindowResize.js
2 | allResizeCbs = []
3 | callResizeCbs = ->
4 | for cb in allResizeCbs
5 | cb.apply(null,arguments)
6 | resizeRunning = false
7 | require("./_throttledListener")("resize",callResizeCbs)
8 |
9 | module.exports =
10 | data: ->
11 | resizeCbDisposables: []
12 | methods:
13 | onWindowResize: (cb) ->
14 | allResizeCbs.push cb
15 | dispose = ->
16 | index = allResizeCbs.indexOf cb
17 | if index > -1
18 | allResizeCbs.splice index,1
19 | @resizeCbDisposables.push dispose
20 | return =>
21 | dispose()
22 | index = @resizeCbDisposables.indexOf dispose
23 | if index > -1
24 | @resizeCbDisposables.splice index,1
25 |
26 | beforeDestroy: ->
27 | for resizeCbDisposable in @resizeCbDisposables
28 | resizeCbDisposable()
29 |
--------------------------------------------------------------------------------
/src/onWindowScroll.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onWindowScroll.js
2 | allScrollCbs = []
3 | callScrollCbs = ->
4 | for cb in allScrollCbs
5 | cb.apply(null,arguments)
6 | require("./_throttledListener")("scroll",callScrollCbs)
7 |
8 |
9 | module.exports =
10 | data: ->
11 | scrollCbDisposables: []
12 | methods:
13 | onWindowScroll: (cb) ->
14 | allScrollCbs.push cb
15 | dispose = ->
16 | index = allScrollCbs.indexOf cb
17 | if index > -1
18 | allScrollCbs.splice index,1
19 | @scrollCbDisposables.push dispose
20 | return =>
21 | dispose()
22 | index = @scrollCbDisposables.indexOf dispose
23 | if index > -1
24 | @scrollCbDisposables.splice index,1
25 |
26 | beforeDestroy: ->
27 | for scrollCbDisposable in @scrollCbDisposables
28 | scrollCbDisposable()
29 |
--------------------------------------------------------------------------------
/src/onceDocument.coffee:
--------------------------------------------------------------------------------
1 | # out: ../onceDocument.js
2 | onceDocument = (event, cb, useCapture) ->
3 | remover = null
4 | wrapper = (e) ->
5 | if cb(e)
6 | remover() if remover?
7 | document.documentElement.addEventListener event, wrapper, useCapture
8 | remover = ->
9 | document.documentElement.removeEventListener event, wrapper
10 | remover = null
11 | return remover
12 | module.exports =
13 | methods:
14 | onceDocument: onceDocument
15 |
--------------------------------------------------------------------------------
/src/parentListener.coffee:
--------------------------------------------------------------------------------
1 | # out: ../parentListener.js
2 | module.exports =
3 | props:
4 | "ignoreParent":
5 | type: Boolean
6 | default: false
7 | "parent":
8 | type: Object
9 | data: ->
10 | removeParentClickListener: null
11 | methods:
12 | setupParent: (parent = @parent) ->
13 | unless @ignoreParent
14 | @removeParentClickListener?()
15 | parent.addEventListener "click", @onParentClick
16 | @removeParentClickListener = =>
17 | parent.removeEventListener "click", @onParentClick
18 | watch:
19 | "parent": "setupParent"
20 | attached: ->
21 | unless @parent?
22 | @parent = @$el.parentElement
23 | else
24 | @setupParent()
25 |
26 | dettached: ->
27 | @removeParentClickListener?()
28 |
--------------------------------------------------------------------------------
/src/parentListener2.coffee:
--------------------------------------------------------------------------------
1 | # out: ../parentListener.js
2 | module.exports =
3 | props:
4 | "ignoreParent":
5 | type: Boolean
6 | default: false
7 | "parent":
8 | type: Object
9 | data: ->
10 | removeParentClickListener: null
11 | methods:
12 | setupParent: (parent = @parent) ->
13 | unless @ignoreParent
14 | @removeParentClickListener?()
15 | parent.addEventListener "click", @onParentClick
16 | @removeParentClickListener = =>
17 | parent.removeEventListener "click", @onParentClick
18 | watch:
19 | "parent": "setupParent"
20 | mounted: -> @$nextTick ->
21 | unless @parent?
22 | @parent = @$el.parentElement
23 | else
24 | @setupParent()
25 |
26 | beforeDestroy: ->
27 | @removeParentClickListener?()
28 |
--------------------------------------------------------------------------------
/src/setCss.coffee:
--------------------------------------------------------------------------------
1 | # out: ../setCss.js
2 | setCss = (el, name, value) ->
3 | return unless el? and name?
4 | style = el.getAttribute("style")
5 | css = null
6 | if style?
7 | splitted = style.split(";")
8 | css = {}
9 | for str in splitted
10 | if str
11 | [cssname,cssvalue] = str.split(":")
12 | cssname = cssname.slice(1) if cssname[0] == ' '
13 | css[cssname] = cssvalue
14 | if value? and value != ""
15 | css[name] = value
16 | else if css[name]?
17 | delete css[name]
18 | else if value? and value != ""
19 | css = {}
20 | css[name] = value
21 | cssString = ""
22 | if css?
23 | for name,value of css
24 | cssString += "#{name}:#{value};"
25 | if cssString
26 | el.setAttribute("style", cssString)
27 | else
28 | el.removeAttribute("style")
29 | module.exports =
30 | methods:
31 | setCss: setCss
32 |
--------------------------------------------------------------------------------
/src/style.coffee:
--------------------------------------------------------------------------------
1 | # out: ../style.js
2 | isString = (str) -> typeof str == 'string' or str instanceof String
3 | trim = (str) -> return str.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '')
4 | arrayize = (arr) ->
5 | if Array.isArray(arr)
6 | return arr
7 | else if isString(arr)
8 | obj = {}
9 | for opt in arr.split(";")
10 | kv = opt.split(":")
11 | obj[trim(kv[0])] = trim(kv[1])
12 | return [obj]
13 | else
14 | return [arr]
15 | module.exports =
16 | computed:
17 | computedStyle: ->
18 | style = arrayize(@style)
19 | return style unless @mergeStyle?
20 | return arrayize(@mergeStyle).concat style
21 |
--------------------------------------------------------------------------------
/src/transition.coffee:
--------------------------------------------------------------------------------
1 | # out: ../transition.js
2 | module.exports =
3 | mixins: [
4 | require("./vue")
5 | ]
6 | computed:
7 | cTransition: ->
8 | if @disableTransition
9 | name = "empty"
10 | else
11 | name = @transition
12 | @processTransition(name)
13 | return name
14 | methods:
15 | processTransition: (value, parent = @$parent) ->
16 | unless value == "empty"
17 | hooks = @Vue.util.resolveAsset(parent.$options,'transitions',value)
18 | unless hooks?
19 | hooks ?= @$options.transitions[value]
20 | return if hooks?.modified
21 | if hooks?
22 | newHooks =
23 | enterClass: hooks.enterClass
24 | leaveClass: hooks.leaveClass
25 | leave: hooks.leave
26 | beforeEnter: hooks.beforeEnter
27 | else
28 | newHooks = {}
29 | newHooks.modified = true
30 | addHook = (name) =>
31 | eventName = @Vue.util.hyphenate(name)
32 | if hooks?[name]?
33 | hook = hooks[name]
34 | fn = (el) =>
35 | @$emit eventName
36 | hook.bind(@)(el)
37 | else
38 | fn = (el) =>
39 | @$emit eventName
40 | newHooks[name] = fn
41 | for hook in ["afterEnter","beforeLeave","afterLeave","enterCancelled","leaveCancelled"]
42 | addHook(hook)
43 | if hooks?.enter? and hooks.enter.length == 2
44 | hook = hooks.enter
45 | newHooks.enter = (el,cb) =>
46 | @$emit "before-enter"
47 | hook.bind(@)(el,cb)
48 | else if hooks?.enter?
49 | hook = hooks.enter
50 | newHooks.enter = (el) =>
51 | @$emit "before-enter"
52 | hook.bind(@)(el)
53 | else
54 | newHooks.enter = (el) => @$emit "before-enter"
55 | @$options.transitions[value] = newHooks
56 |
--------------------------------------------------------------------------------
/src/transition2.coffee:
--------------------------------------------------------------------------------
1 | # out: ../transition.js
2 | module.exports =
3 | mixins: [
4 | require("./vue")
5 | ]
6 | computed:
7 | cTransition: ->
8 | return @processTransition(@transition)
9 | cTransitionGroup: ->
10 | return @processTransitionGroup(@transition)
11 | methods:
12 | processTransitionGroup: (name, options = {}) ->
13 | options.defaultName ?= "transition-group"
14 | @processTransition name, options
15 | processTransition: (name, options = {}) ->
16 | {parent=@$parent, defaultName="transition"} = options
17 | parent ?= @
18 | comp = @Vue.util.resolveAsset(parent.$options,'components',name)
19 | if parent != @ and not comp?
20 | comp = @Vue.util.resolveAsset(@$options,'components',name)
21 | if comp?
22 | @$options.components[name] = comp
23 | else
24 | name = defaultName
25 | return name
26 |
--------------------------------------------------------------------------------
/src/vue.coffee:
--------------------------------------------------------------------------------
1 | # out: ../vue.js
2 | module.exports =
3 | computed:
4 | Vue: ->
5 | return Object.getPrototypeOf(Object.getPrototypeOf(@)).constructor
6 |
--------------------------------------------------------------------------------
/test/class.coffee:
--------------------------------------------------------------------------------
1 | comp =
2 | el: -> document.createElement "div"
3 | template: ""
4 | mixins: [require "../src/class.coffee"]
5 | data: ->
6 | mergeClass: []
7 | props:
8 | class:
9 | default: -> []
10 |
11 | comp = Vue.extend(comp)
12 | comp = new comp()
13 |
14 | describe "class", ->
15 | it 'should have class', ->
16 | should.exist comp.class
17 | comp.class.length.should.equal 0
18 | it 'should have mergeClass', ->
19 | should.exist comp.mergeClass
20 | comp.mergeClass.length.should.equal 0
21 | it 'should have computedClass', ->
22 | should.exist comp.computedClass
23 | comp.computedClass.length.should.equal 0
24 | it 'should merge arrays', ->
25 | comp.class = ["a"]
26 | comp.mergeClass = ["b"]
27 | comp.computedClass[0].should.equal "b"
28 | comp.computedClass[1].should.equal "a"
29 | it "should convert to object, when one isn't a array", ->
30 | comp.class = a:true
31 | comp.mergeClass = ["b"]
32 | comp.computedClass.a.should.be.true
33 | comp.computedClass.b.should.be.true
34 | comp.class = ["c"]
35 | comp.mergeClass = d:true
36 | comp.computedClass.c.should.be.true
37 | comp.computedClass.d.should.be.true
38 | should.not.exist comp.computedClass.a
39 | should.not.exist comp.computedClass.b
40 | it "should merge objects", ->
41 | comp.class = a:true,b:true
42 | comp.mergeClass = b:false,c:true
43 | comp.computedClass.a.should.be.true
44 | comp.computedClass.b.should.be.true
45 | comp.computedClass.c.should.be.true
46 | it "should support objects in arrays", ->
47 | comp.class = ["a", b:false]
48 | comp.mergeClass = b:true,c:true
49 | comp.computedClass.a.should.be.true
50 | comp.computedClass.b.should.be.false
51 | comp.computedClass.c.should.be.true
52 | it "should support plain class strings", ->
53 | comp.class = "a b"
54 | comp.mergeClass = "c d e"
55 | comp.computedClass.length.should.equal 5
56 | comp.computedClass[0].should.equal "c"
57 | comp.computedClass[1].should.equal "d"
58 | comp.computedClass[2].should.equal "e"
59 | comp.computedClass[3].should.equal "a"
60 | comp.computedClass[4].should.equal "b"
61 |
--------------------------------------------------------------------------------
/test/dynamicCss.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/dynamicCss.coffee"]
2 | styletag = document.getElementById("vm-dynamic-css")
3 | stylesheet = if styletag.sheet then styletag.sheet else styletag.styleSheet
4 | cssRules = stylesheet.cssRules or stylesheet.rules or []
5 | describe "dynamicCss", ->
6 | it 'should add a rule', ->
7 | comp.setCssRules "p":"font-size": "12px"
8 | cssRules[0].cssText.should.equal "p { font-size: 12px; }"
9 | it 'should add another property', ->
10 | comp.setCssRules "p":"height": "12px"
11 | cssRules[0].cssText.should.equal "p { font-size: 12px; height: 12px; }"
12 | it 'should remove a property', ->
13 | comp.setCssRules "p":"height": null
14 | cssRules[0].cssText.should.equal "p { font-size: 12px; }"
15 | it 'should remove a rule', ->
16 | comp.setCssRules "p":null
17 | should.not.exist(cssRules[0])
18 | it 'should flatten', ->
19 | comp.setCssRules "p": {"& p" :{"font-size": "12px"},"height":"12px"}
20 | cssRules[0].cssText.should.equal "p p { font-size: 12px; }"
21 | cssRules[1].cssText.should.equal "p { height: 12px; }"
22 | it 'should remove flattened', ->
23 | comp.setCssRules "p": "& p": null
24 | comp.setCssRules "p": null
25 | should.not.exist(cssRules[0])
26 | should.not.exist(cssRules[1])
27 | it 'should flatten deep', ->
28 | comp.setCssRules "p": {"& p" :{"& p" :{"font-size": "12px"}}}
29 | cssRules = stylesheet.cssRules or stylesheet.rules or []
30 | cssRules[0].cssText.should.equal "p p p { font-size: 12px; }"
31 |
--------------------------------------------------------------------------------
/test/fragToString.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/fragToString.coffee"]
2 | describe "fragToString", ->
3 | it "should resolve a frag to string", ->
4 | frag = document.createDocumentFragment()
5 | p = document.createElement('p')
6 | p.textContent = 'test'
7 | frag.appendChild p
8 | comp.fragToString(frag).should.equal("test
")
9 |
--------------------------------------------------------------------------------
/test/getViewportOffset.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp {
2 | template: ""
3 | mixins: [require "../src/getViewportOffset.coffee"]
4 | }
5 | describe "getViewportOffset", ->
6 | it 'should return a object with top and left', ->
7 | obj = comp.getViewportOffset()
8 | should.exist(obj.top)
9 | should.exist(obj.left)
10 |
--------------------------------------------------------------------------------
/test/getViewportSize.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/getViewportSize.coffee"]
2 | describe "getViewportSize", ->
3 | it 'should return a object with width and height', ->
4 | obj = comp.getViewportSize()
5 | should.exist(obj.width)
6 | should.exist(obj.height)
7 |
--------------------------------------------------------------------------------
/test/getVue.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/getVue.coffee"]
2 | describe "getVue", ->
3 | it 'should get Vue', ->
4 | name = comp.getVue().toString()
5 | name = name.substr('function '.length);
6 | name = name.substr(0, name.indexOf('('));
7 | name.should.equal "Vue"
8 |
--------------------------------------------------------------------------------
/test/onClick.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onClick.coffee"]
2 | describe "onClick", ->
3 | it 'should be called on click', ->
4 | spy = chai.spy()
5 | comp.onClick = spy
6 | comp.click()
7 | spy.should.have.been.called.once
8 |
--------------------------------------------------------------------------------
/test/onClickStack.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onClickStack.coffee"]
2 | describe "onClickStack", ->
3 | disposes = []
4 | spies = [chai.spy(),chai.spy(),chai.spy()]
5 | it 'should call last cb on click', ->
6 | for spy in spies
7 | disposes.push comp.addToClickStack spy
8 | comp.click()
9 | spies[0].should.not.have.been.called
10 | spies[1].should.not.have.been.called
11 | spies[2].should.have.been.called.once
12 | it 'should properly dispose', ->
13 | disposes[2]()
14 | comp.click()
15 | spies[0].should.not.have.been.called
16 | spies[1].should.have.been.called.once
17 | disposes[1]()
18 | comp.click()
19 | spies[0].should.have.been.called.once
20 |
--------------------------------------------------------------------------------
/test/onClickStore.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onClickStore.coffee"]
2 | describe "onClickStore", ->
3 | disposes = []
4 | spies = [chai.spy(),chai.spy(),chai.spy()]
5 | it 'should call all cbs on click', ->
6 | for spy in spies
7 | disposes.push comp.onClick spy
8 | comp.click()
9 | spies[0].should.have.been.called.once
10 | spies[1].should.have.been.called.once
11 | spies[2].should.have.been.called.once
12 | it 'should properly dispose', ->
13 | disposes[2]()
14 | comp.click()
15 | spies[0].should.have.been.called.twice
16 | spies[1].should.have.been.called.twice
17 | spies[2].should.have.been.called.once
18 | disposes[1]()
19 | comp.click()
20 | spies[0].should.have.been.called.exactly(3)
21 | spies[1].should.have.been.called.twice
22 | spies[2].should.have.been.called.once
23 |
--------------------------------------------------------------------------------
/test/onDocument.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onDocument.coffee"]
2 | describe "onDocument", ->
3 | dispose = null
4 | it 'should call cb on event', ->
5 | spy = chai.spy()
6 | dispose = comp.onDocument "click", spy
7 | document.documentElement.dispatchEvent(new Event("click"))
8 | spy.should.have.been.called.once
9 | it 'should properly dispose cb', ->
10 | spy = chai.spy()
11 | dispose()
12 | document.documentElement.dispatchEvent(new Event("click"))
13 | spy.should.not.have.been.called
14 |
--------------------------------------------------------------------------------
/test/onElementResize.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onElementResize.coffee"]
2 | cel = comp.$el
3 | describe "onElementResize", ->
4 | it "should not call cb on window resize "+
5 | " when element doesn't change", (done) ->
6 | spy = chai.spy()
7 | comp.onElementResize cel, spy
8 | document.dispatchEvent(
9 | new Event 'resize',
10 | 'view': window
11 | 'bubbles': true
12 | 'cancelable': true
13 | )
14 | window.requestAnimationFrame ->
15 | spy.should.not.have.been.called()
16 | done()
17 |
18 | it "should call cb on element width change", (done) ->
19 | spy = chai.spy()
20 | comp.onElementResize cel, spy
21 | cel.setAttribute("style", "width:200px")
22 | setTimeout (->
23 | spy.should.have.been.called.once
24 | cel.removeAttribute("style")
25 | setTimeout (->
26 | spy.should.have.been.called.twice
27 | done()
28 | ),100
29 | ),100
30 | it "should call cb on element height change", (done) ->
31 | spy = chai.spy()
32 | comp.onElementResize cel, spy
33 | cel.setAttribute("style", "height:200px")
34 | setTimeout (->
35 | spy.should.have.been.called.once
36 | cel.removeAttribute("style")
37 | setTimeout (->
38 | spy.should.have.been.called.twice
39 | done()
40 | ),100
41 | ),100
42 | it "should call cb on element when an "+
43 | "larger inner element is added", (done) ->
44 | spy = chai.spy()
45 | comp.onElementResize cel, spy
46 | el = document.createElement "div"
47 | el.setAttribute "style", "height:200px"
48 | cel.appendChild el
49 | setTimeout (->
50 | spy.should.have.been.called.once
51 | cel.removeChild el
52 | setTimeout (->
53 | spy.should.have.been.called.twice
54 | done()
55 | ),100
56 | ),100
57 |
--------------------------------------------------------------------------------
/test/onMouseMove.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onMouseMove.coffee"]
2 | describe "onMouseMove", ->
3 | it 'should call cb on mouse move', (done) ->
4 | spy = chai.spy()
5 | comp.onMouseMove spy
6 | document.dispatchEvent(
7 | new Event 'mousemove',
8 | 'view': window
9 | 'bubbles': true
10 | 'cancelable': true
11 | )
12 | window.requestAnimationFrame ->
13 | spy.should.have.been.called.once
14 | done()
15 |
--------------------------------------------------------------------------------
/test/onWindowResize.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onWindowResize.coffee"]
2 | describe "onWindowResize", ->
3 | it 'should call cb on window resize', (done) ->
4 | spy = chai.spy()
5 | comp.onWindowResize spy
6 | document.dispatchEvent(
7 | new Event 'resize',
8 | 'view': window
9 | 'bubbles': true
10 | 'cancelable': true
11 | )
12 | window.requestAnimationFrame ->
13 | spy.should.have.been.called.once
14 | done()
15 |
--------------------------------------------------------------------------------
/test/onceDocument.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/onceDocument.coffee"]
2 | describe "onceDocument", ->
3 | dispose = null
4 | it 'should call cb on event and remove on success', ->
5 | spy = chai.spy()
6 | comp.onceDocument "click", -> spy(); return true
7 | document.documentElement.dispatchEvent(new Event("click"))
8 | spy.should.have.been.called.once
9 | document.documentElement.dispatchEvent(new Event("click"))
10 | spy.should.have.been.called.once
11 | it 'should call cb on event and not remove on failure', ->
12 | spy = chai.spy()
13 | dispose = comp.onceDocument "click", -> spy(); return false
14 | document.documentElement.dispatchEvent(new Event("click"))
15 | spy.should.have.been.called.once
16 | document.documentElement.dispatchEvent(new Event("click"))
17 | spy.should.have.been.called.twice
18 | it 'should properly dispose cb', ->
19 | spy = chai.spy()
20 | dispose()
21 | document.documentElement.dispatchEvent(new Event("click"))
22 | spy.should.not.have.been.called
23 |
--------------------------------------------------------------------------------
/test/setCss.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/setCss.coffee"]
2 | describe "setCss", ->
3 | it 'should add a style prop', ->
4 | comp.setCss document.body, "width", "100%"
5 | document.body.should.have.attr("style","width:100%;")
6 | it 'should add another style prop', ->
7 | comp.setCss document.body, "height", "100%"
8 | document.body.should.have.attr("style","width:100%;height:100%;")
9 | it 'should remove a style prop', ->
10 | comp.setCss document.body, "width"
11 | document.body.should.have.attr("style","height:100%;")
12 | it 'should remove another style prop', ->
13 | comp.setCss document.body, "height"
14 | document.body.should.not.have.attr("style")
15 |
--------------------------------------------------------------------------------
/test/style.coffee:
--------------------------------------------------------------------------------
1 | comp =
2 | el: -> document.createElement "div"
3 | template: ""
4 | mixins: [require "../src/style.coffee"]
5 | data: ->
6 | mergeStyle: []
7 | props:
8 | style:
9 | default: -> []
10 |
11 | comp = Vue.extend(comp)
12 | comp = new comp()
13 |
14 | describe "style", ->
15 | it 'should have style', ->
16 | should.exist comp.style
17 | comp.style.length.should.equal 0
18 | it 'should have mergeStyle', ->
19 | should.exist comp.mergeStyle
20 | comp.mergeStyle.length.should.equal 0
21 | it 'should have computedStyle', ->
22 | should.exist comp.computedStyle
23 | comp.computedStyle.length.should.equal 0
24 | it 'should merge arrays', ->
25 | comp.style = ["a"]
26 | comp.mergeStyle = ["b"]
27 | comp.computedStyle[0].should.equal "b"
28 | comp.computedStyle[1].should.equal "a"
29 | it "should convert to array, when one isn't a array", ->
30 | comp.style = a:true
31 | comp.mergeStyle = ["b"]
32 | comp.computedStyle.length.should.equal 2
33 | comp.computedStyle[0].should.equal "b"
34 | comp.computedStyle[1].a.should.be.true
35 | comp.style = ["c"]
36 | comp.mergeStyle = d:true
37 | comp.computedStyle.length.should.equal 2
38 | comp.computedStyle[0].d.should.be.true
39 | comp.computedStyle[1].should.equal "c"
40 | it "should support plain style strings", ->
41 | comp.style = "color:red"
42 | comp.mergeStyle = "color:blue;font-size:10px"
43 | comp.computedStyle.length.should.equal 2
44 | comp.computedStyle[0].color.should.equal "blue"
45 | comp.computedStyle[0]["font-size"].should.equal "10px"
46 | comp.computedStyle[1].color.should.equal "red"
47 |
--------------------------------------------------------------------------------
/test/vue.coffee:
--------------------------------------------------------------------------------
1 | comp = loadComp mixins: [require "../src/vue.coffee"]
2 | describe "vue", ->
3 | it 'should get Vue', ->
4 | name = comp.Vue.toString()
5 | name = name.substr('function '.length);
6 | name = name.substr(0, name.indexOf('('));
7 | name.should.equal "Vue"
8 |
--------------------------------------------------------------------------------
/webpack.config.coffee:
--------------------------------------------------------------------------------
1 | webpack = require('webpack')
2 |
3 | module.exports = {
4 | entry: "./build/index.js"
5 | output:
6 | filename: "./build/bundle.js"
7 | plugins: [
8 | new webpack.optimize.UglifyJsPlugin compress: warnings: false
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------