blissful-rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: df8565fa42b627dc8e0d6d66ed7f87488cdbc7b4
4
+ data.tar.gz: 9336ccff34e99cf23227600a474c31ffe057f3d3
5
+ SHA512:
6
+ metadata.gz: d21fdbd67a22cd1e723f0d6c3bfe43adbde3d4ee82b33cf9b8ff0ee04c105214ff2382e945c0608d4ddfcaf97dad2a0a28accdd42f3734a5fa97a4bf9fb7d052
7
+ data.tar.gz: fa24cd7f09667f29f3d6b3c2012720cba17a803265ba378f389d5b2cfc543dc71a46a198c262bcfbc83e76f4822c564ef0178abcee0995cdf40b7737938525dd
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.11.2
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Spicy Magpie
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
13
+ all 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
21
+ THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ # Bliss.js for Rails
2
+
3
+ This gem wraps the [Bliss.js](https://blissfuljs.com) library written by
4
+ [Lea Verou](http://lea.verou.me) and makes it available to the Rails Asset
5
+ Pipeline.
6
+
7
+ ## Installation
8
+
9
+ Add the gem to the `Gemfile` in your Rails project:
10
+
11
+ ```ruby
12
+ gem 'blissful-rails'
13
+ ```
14
+
15
+ Then execute:
16
+
17
+ ```sh
18
+ $ bundle install
19
+ ```
20
+
21
+ And add your favourite flavour to your `application.js` file:
22
+
23
+ ```javascript
24
+ //= require bliss
25
+ ```
26
+
27
+ If you want to go with the shy version (it doesn't touch the host environment,
28
+ except by adding a global variable named `Bliss`), you might do want to add
29
+ this instead:
30
+
31
+ ```javascript
32
+ //= require bliss.shy
33
+ ```
34
+
35
+
36
+ You might also be interested in the `blissful-ujs` gem if you are looking to
37
+ replace `jquery-ujs`. Read more about it
38
+ [here](https://github.com/spicymagpie/blissful-ujs).
39
+
40
+ ## Usage
41
+
42
+ If you installed this library, then you might want to visit the
43
+ [documentation](http://blissfuljs.com). Basically, I might give you a tip:
44
+
45
+ ```javascript
46
+
47
+ $.ready().then(function () {
48
+ console.log('Ok, you\'ve loaded Bliss.js successfully!')
49
+ })
50
+
51
+ ```
52
+
53
+ Blissful documentation mentions which jQuery methods are similar. The difference
54
+ between those is the implementation: Bliss is only 3kb and might probably not
55
+ work well in older browsers without polyfills.
56
+
57
+ [See this](http://blissfuljs.com/#browser-support) if you have issues.
58
+
59
+ ## Development
60
+
61
+ This gem is updated once a week. Basically, if we find changes in the JavaScript
62
+ library, we will put the new JavaScript files and upload a new gem. However, the
63
+ library was written for little to no maintenance, hence even if you do not see
64
+ activity in a month or so, it's safe to use.
65
+
66
+ ## Contributing
67
+
68
+ Bug reports and pull requests are welcome on GitHub at
69
+ https://github.com/spicymagpie/blissful-rails.
70
+
71
+ ## License
72
+
73
+ The gem is available as open source under the terms of the
74
+ [MIT License](http://opensource.org/licenses/MIT).
75
+
76
+ ## Thanks
77
+
78
+ Thanks to [Lea Verou](http://lea.verou.me/) for writing the library, and to
79
+ [Hendrik Kleinwächter](http://zeit.io/) for letting me experiment a little with
80
+ other things.
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList['test/**/*_test.rb']
8
+ end
9
+
10
+ task :default => :spec
@@ -0,0 +1,21 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'blissful/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "blissful-rails"
8
+ spec.version = Blissful::Rails::VERSION
9
+ spec.authors = ["Spicy Magpie"]
10
+ spec.email = ["spicy.magpie@gmail.com"]
11
+ spec.summary = %q{A wrapper gem for Bliss.js}
12
+ spec.homepage = "https://github.com/spicymagpie/blissful-rails"
13
+ spec.license = "MIT"
14
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_dependency "railties", "~> 4.0"
18
+ spec.add_development_dependency "bundler", "~> 1.11"
19
+ spec.add_development_dependency "rake", "~> 10.0"
20
+ spec.add_development_dependency "minitest", "~> 5.0"
21
+ end
@@ -0,0 +1,4 @@
1
+ require "blissful/rails"
2
+
3
+ module Blissful
4
+ end
@@ -0,0 +1,50 @@
1
+ require "blissful/rails/version"
2
+
3
+ module Blissful
4
+ module Rails
5
+ class << self
6
+ # Loading the heavenly library
7
+ def load!
8
+ if rails?
9
+ loader_for_rails
10
+ elsif sprockets?
11
+ loader_for_sprockets
12
+ end
13
+ end
14
+
15
+ # Paths
16
+ def gem_path
17
+ @gem_path ||= File.expand_path '..', File.dirname(__FILE__)
18
+ end
19
+
20
+ def assets_path
21
+ @assets_path ||= File.join gem_path, 'assets'
22
+ end
23
+
24
+ def javascripts_path
25
+ File.join assets_path, 'javascripts'
26
+ end
27
+
28
+ # Environment detection helpers
29
+ def rails?
30
+ defined?(::Rails)
31
+ end
32
+
33
+ def sprockets?
34
+ defined?(::Sprockets)
35
+ end
36
+
37
+ # Loader for Rails
38
+ def loader_for_rails
39
+ require 'blissful/rails/engine'
40
+ end
41
+
42
+ # Loader for Sprockets
43
+ def loader_for_sprockets
44
+ Sprockets.append_path(javascripts_path)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ Blissful::Rails.load!
@@ -0,0 +1,6 @@
1
+ module Blissful
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Blissful
2
+ module Rails
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,722 @@
1
+ (function() {
2
+ "use strict";
3
+
4
+ function overload(callback, start, end) {
5
+ start = start === undefined ? 1 : start;
6
+ end = end || start + 1;
7
+
8
+ if (end - start <= 1) {
9
+ return function() {
10
+ if ($.type(arguments[start]) === 'string') {
11
+ return callback.apply(this, arguments);
12
+ }
13
+
14
+ var obj = arguments[start], ret;
15
+
16
+ for (var key in obj) {
17
+ var args = Array.from(arguments);
18
+ args.splice(start, 1, key, obj[key]);
19
+ ret = callback.apply(this, args);
20
+ }
21
+
22
+ return ret;
23
+ };
24
+ }
25
+
26
+ return overload(overload(callback, start + 1, end), start, end - 1);
27
+ }
28
+
29
+ // Copy properties from one object to another. Overwrites allowed.
30
+ function extend(to, from, whitelist) {
31
+ for (var property in from) {
32
+ if (whitelist) {
33
+ var type = $.type(whitelist);
34
+
35
+ if (whitelist === "own" && !from.hasOwnProperty(property) ||
36
+ type === "array" && whitelist.indexOf(property) === -1 ||
37
+ type === "regexp" && !whitelist.test(property) ||
38
+ type === "function" && !whitelist.call(from, property)) {
39
+ continue;
40
+ }
41
+ }
42
+
43
+ // To copy gettters/setters, preserve flags etc
44
+ var descriptor = Object.getOwnPropertyDescriptor(from, property);
45
+
46
+ if (descriptor && (!descriptor.writable || !descriptor.configurable || !descriptor.enumerable || descriptor.get || descriptor.set)) {
47
+ delete to[property];
48
+ Object.defineProperty(to, property, descriptor);
49
+ }
50
+ else {
51
+ to[property] = from[property];
52
+ }
53
+ }
54
+
55
+ return to;
56
+ }
57
+
58
+ var $ = self.Bliss = extend(function(expr, context) {
59
+ return $.type(expr) === "string"? (context || document).querySelector(expr) : expr || null;
60
+ }, self.Bliss);
61
+
62
+ extend($, {
63
+ extend: extend,
64
+
65
+ overload: overload,
66
+
67
+ property: $.property || "_",
68
+
69
+ sources: {},
70
+
71
+ noop: function(){},
72
+
73
+ $: function(expr, context) {
74
+ if (expr instanceof Node || expr instanceof Window) {
75
+ return [expr];
76
+ }
77
+
78
+ return Array.from(typeof expr == "string"? (context || document).querySelectorAll(expr) : expr || []);
79
+ },
80
+
81
+ /**
82
+ * Returns the [[Class]] of an object in lowercase (eg. array, date, regexp, string etc)
83
+ */
84
+ type: function(obj) {
85
+ if (obj === null) { return 'null'; }
86
+
87
+ if (obj === undefined) { return 'undefined'; }
88
+
89
+ var ret = (Object.prototype.toString.call(obj).match(/^\[object\s+(.*?)\]$/)[1] || "").toLowerCase();
90
+
91
+ if(ret == 'number' && isNaN(obj)) {
92
+ return 'nan';
93
+ }
94
+
95
+ return ret;
96
+ },
97
+
98
+ /*
99
+ * Return first non-undefined value. Mainly used internally.
100
+ */
101
+ defined: function () {
102
+ for (var i=0; i<arguments.length; i++) {
103
+ if (arguments[i] !== undefined) {
104
+ return arguments[i];
105
+ }
106
+ }
107
+ },
108
+
109
+ create: function (tag, o) {
110
+ // 4 signatures: (tag, o), (tag), (o), ()
111
+ if (arguments.length === 1) {
112
+ if ($.type(tag) === "string") {
113
+ o = {};
114
+ }
115
+ else {
116
+ o = tag;
117
+ tag = o.tag;
118
+ delete o.tag;
119
+ }
120
+ }
121
+
122
+ return $.set(document.createElement(tag || "div"), o);
123
+ },
124
+
125
+ each: function(obj, callback, ret) {
126
+ ret = ret || {};
127
+
128
+ for (var property in obj) {
129
+ ret[property] = callback.call(obj, property, obj[property]);
130
+ }
131
+
132
+ return ret;
133
+ },
134
+
135
+ ready: function(context) {
136
+ context = context || document;
137
+
138
+ return new Promise(function(resolve, reject){
139
+ if (context.readyState !== "loading") {
140
+ resolve();
141
+ }
142
+ else {
143
+ context.addEventListener("DOMContentLoaded", function(){
144
+ resolve();
145
+ });
146
+ }
147
+ });
148
+ },
149
+
150
+ // Helper for defining OOP-like “classes”
151
+ Class: function(o) {
152
+ var init = $.noop;
153
+
154
+ if (o.hasOwnProperty("constructor")) {
155
+ init = o.constructor;
156
+ delete o.constructor;
157
+ }
158
+
159
+ var abstract = o.abstract;
160
+ delete o.abstract;
161
+
162
+ var ret = function() {
163
+ if (abstract && this.constructor === ret) {
164
+ throw new Error("Abstract classes cannot be directly instantiated.");
165
+ }
166
+
167
+ if (this.constructor.super && this.constructor.super != ret) {
168
+ // FIXME This should never happen, but for some reason it does if ret.super is null
169
+ // Debugging revealed that somehow this.constructor !== ret, wtf. Must look more into this
170
+ this.constructor.super.apply(this, arguments);
171
+ }
172
+
173
+ return init.apply(this, arguments);
174
+ };
175
+
176
+ ret.super = o.extends || null;
177
+ delete o.extends;
178
+
179
+ ret.prototype = $.extend(Object.create(ret.super? ret.super.prototype : Object), {
180
+ constructor: ret
181
+ });
182
+
183
+ $.extend(ret, o.static);
184
+ delete o.static;
185
+
186
+ for (var property in o) {
187
+ if (property in $.classProps) {
188
+ $.classProps[property].call(ret, ret.prototype, o[property]);
189
+ delete o[property];
190
+ }
191
+ }
192
+
193
+ // Anything that remains is an instance method/property or ret.prototype.constructor
194
+ $.extend(ret.prototype, o);
195
+
196
+ // For easier calling of super methods
197
+ // This doesn't save us from having to use .call(this) though
198
+ ret.prototype.super = ret.super? ret.super.prototype : null;
199
+
200
+ return ret;
201
+ },
202
+
203
+ // Properties with special handling in classes
204
+ classProps: {
205
+ // Lazily evaluated properties
206
+ lazy: overload(function(obj, property, getter) {
207
+ Object.defineProperty(obj, property, {
208
+ get: function() {
209
+ // FIXME this does not work for instances if property is defined on the prototype
210
+ delete this[property];
211
+ return this[property] = getter.call(this);
212
+ },
213
+ configurable: true,
214
+ enumerable: true
215
+ });
216
+ return obj;
217
+ }),
218
+
219
+ // Properties that behave like normal properties but also execute code upon getting/setting
220
+ live: overload(function(obj, property, descriptor) {
221
+ if ($.type(descriptor) === "function") {
222
+ descriptor = {set: descriptor};
223
+ }
224
+
225
+ Object.defineProperty(obj, property, {
226
+ get: function() {
227
+ var value = this["_" + property];
228
+ var ret = descriptor.get && descriptor.get.call(this, value);
229
+ return ret !== undefined? ret : value;
230
+ },
231
+ set: function(v) {
232
+ var value = this["_" + property];
233
+ var ret = descriptor.set && descriptor.set.call(this, v, value);
234
+ this["_" + property] = ret !== undefined? ret : v;
235
+ },
236
+ configurable: descriptor.configurable,
237
+ enumerable: descriptor.enumerable
238
+ });
239
+
240
+ return obj;
241
+ })
242
+
243
+ },
244
+
245
+ // Includes a script, returns a promise
246
+ include: function() {
247
+ var url = arguments[arguments.length - 1];
248
+ var loaded = arguments.length === 2? arguments[0] : false;
249
+
250
+ var script = document.createElement("script");
251
+
252
+ return loaded? Promise.resolve() : new Promise(function(resolve, reject){
253
+ $.set(script, {
254
+ async: true,
255
+ onload: function() {
256
+ resolve();
257
+ $.remove(script);
258
+ },
259
+ onerror: function() {
260
+ reject();
261
+ },
262
+ src: url,
263
+ inside: document.head
264
+ });
265
+ });
266
+
267
+ },
268
+
269
+ /*
270
+ * Fetch API inspired XHR wrapper. Returns promise.
271
+ */
272
+ fetch: function(url, o) {
273
+ if (!url) {
274
+ throw new TypeError("URL parameter is mandatory and cannot be " + url);
275
+ }
276
+
277
+ // Set defaults & fixup arguments
278
+ var env = extend({
279
+ url: new URL(url, location),
280
+ data: "",
281
+ method: "GET",
282
+ headers: {},
283
+ xhr: new XMLHttpRequest()
284
+ }, o);
285
+
286
+ env.method = env.method.toUpperCase();
287
+
288
+ $.hooks.run("fetch-args", env);
289
+
290
+ // Start sending the request
291
+
292
+ if (env.method === "GET" && env.data) {
293
+ env.url.search += env.data;
294
+ }
295
+
296
+ document.body.setAttribute('data-loading', env.url);
297
+
298
+ env.xhr.open(env.method, env.url.href, env.async !== false, env.user, env.password);
299
+
300
+ for (var property in o) {
301
+ if (property in env.xhr) {
302
+ try {
303
+ env.xhr[property] = o[property];
304
+ }
305
+ catch (e) {
306
+ self.console && console.error(e);
307
+ }
308
+ }
309
+ }
310
+
311
+ if (env.method !== 'GET' && !env.headers['Content-type'] && !env.headers['Content-Type']) {
312
+ env.xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
313
+ }
314
+
315
+ for (var header in env.headers) {
316
+ env.xhr.setRequestHeader(header, env.headers[header]);
317
+ }
318
+
319
+ return new Promise(function(resolve, reject){
320
+ env.xhr.onload = function(){
321
+ document.body.removeAttribute('data-loading');
322
+
323
+ if (env.xhr.status === 0 || env.xhr.status >= 200 && env.xhr.status < 300 || env.xhr.status === 304) {
324
+ // Success!
325
+ resolve(env.xhr);
326
+ }
327
+ else {
328
+ reject(Error(env.xhr.statusText));
329
+ }
330
+
331
+ };
332
+
333
+ env.xhr.onerror = function() {
334
+ document.body.removeAttribute('data-loading');
335
+ reject(Error("Network Error"));
336
+ };
337
+
338
+ env.xhr.send(env.method === 'GET'? null : env.data);
339
+ });
340
+ },
341
+
342
+ value: function(obj) {
343
+ var hasRoot = $.type(obj) !== "string";
344
+
345
+ return $$(arguments).slice(+hasRoot).reduce(function(obj, property) {
346
+ return obj && obj[property];
347
+ }, hasRoot? obj : self);
348
+ }
349
+ });
350
+
351
+ $.Hooks = new $.Class({
352
+ add: function (name, callback) {
353
+ this[name] = this[name] || [];
354
+ this[name].push(callback);
355
+ },
356
+
357
+ run: function (name, env) {
358
+ (this[name] || []).forEach(function(callback) {
359
+ callback(env);
360
+ });
361
+ }
362
+ });
363
+
364
+ $.hooks = new $.Hooks();
365
+
366
+ var _ = $.property;
367
+
368
+ $.Element = function (subject) {
369
+ this.subject = subject;
370
+
371
+ // Author-defined element-related data
372
+ this.data = {};
373
+
374
+ // Internal Bliss element-related data
375
+ this.bliss = {};
376
+ };
377
+
378
+ $.Element.prototype = {
379
+ set: overload(function(property, value) {
380
+
381
+ if (property in $.setProps) {
382
+ $.setProps[property].call(this, value);
383
+ }
384
+ else if (property in this) {
385
+ this[property] = value;
386
+ }
387
+ else {
388
+ this.setAttribute(property, value);
389
+ }
390
+
391
+ }, 0),
392
+
393
+ // Run a CSS transition, return promise
394
+ transition: function(props, duration) {
395
+ duration = +duration || 400;
396
+
397
+ return new Promise(function(resolve, reject){
398
+ if ("transition" in this.style) {
399
+ // Get existing style
400
+ var previous = $.extend({}, this.style, /^transition(Duration|Property)$/);
401
+
402
+ $.style(this, {
403
+ transitionDuration: (duration || 400) + "ms",
404
+ transitionProperty: Object.keys(props).join(", ")
405
+ });
406
+
407
+ $.once(this, "transitionend", function(){
408
+ clearTimeout(i);
409
+ $.style(this, previous);
410
+ resolve(this);
411
+ });
412
+
413
+ // Failsafe, in case transitionend doesn’t fire
414
+ var i = setTimeout(resolve, duration+50, this);
415
+
416
+ $.style(this, props);
417
+ }
418
+ else {
419
+ $.style(this, props);
420
+ resolve(this);
421
+ }
422
+ }.bind(this));
423
+ },
424
+
425
+ // Fire a synthesized event on the element
426
+ fire: function (type, properties) {
427
+ var evt = document.createEvent("HTMLEvents");
428
+
429
+ evt.initEvent(type, true, true );
430
+
431
+ this.dispatchEvent($.extend(evt, properties));
432
+ }
433
+ };
434
+
435
+ /*
436
+ * Properties with custom handling in $.set()
437
+ * Also available as functions directly on element._ and on $
438
+ */
439
+ $.setProps = {
440
+ // Set a bunch of inline CSS styles
441
+ style: function (val) {
442
+ $.extend(this.style, val);
443
+ },
444
+
445
+ // Set a bunch of attributes
446
+ attributes: function (o) {
447
+ for (var attribute in o) {
448
+ this.setAttribute(attribute, o[attribute]);
449
+ }
450
+ },
451
+
452
+ // Set a bunch of properties on the element
453
+ properties: function (val) {
454
+ $.extend(this, val);
455
+ },
456
+
457
+ // Bind one or more events to the element
458
+ events: function (val) {
459
+ if (val && val.addEventListener) {
460
+ // Copy events from other element (requires Bliss Full)
461
+ var me = this;
462
+
463
+ // Copy listeners
464
+ if (val[_] && val[_].bliss) {
465
+ var listeners = val[_].bliss.listeners;
466
+
467
+ for (var type in listeners) {
468
+ listeners[type].forEach(function(l){
469
+ me.addEventListener(type, l.callback, l.capture);
470
+ });
471
+ }
472
+ }
473
+
474
+ // Copy inline events
475
+ for (var onevent in val) {
476
+ if (onevent.indexOf("on") === 0) {
477
+ this[onevent] = val[onevent];
478
+ }
479
+ }
480
+ }
481
+ else {
482
+ for (var events in val) {
483
+ events.split(/\s+/).forEach(function (event) {
484
+ this.addEventListener(event, val[events]);
485
+ }, this);
486
+ }
487
+ }
488
+ },
489
+
490
+ once: overload(function(events, callback){
491
+ events = events.split(/\s+/);
492
+ var me = this;
493
+ var once = function() {
494
+ events.forEach(function(event){
495
+ me.removeEventListener(event, once);
496
+ });
497
+
498
+ return callback.apply(me, arguments);
499
+ };
500
+
501
+ events.forEach(function (event) {
502
+ me.addEventListener(event, once);
503
+ });
504
+ }, 0),
505
+
506
+ // Event delegation
507
+ delegate: overload(function (type, selector, callback) {
508
+ this.addEventListener(type, function(evt) {
509
+ if (evt.target.closest(selector)) {
510
+ callback.call(this, evt);
511
+ }
512
+ });
513
+ }, 0, 2),
514
+
515
+ // Set the contents as a string, an element, an object to create an element or an array of these
516
+ contents: function (val) {
517
+ if (val || val === 0) {
518
+ (Array.isArray(val)? val : [val]).forEach(function (child) {
519
+ var type = $.type(child);
520
+
521
+ if (/^(string|number)$/.test(type)) {
522
+ child = document.createTextNode(child + "");
523
+ }
524
+ else if (type === "object") {
525
+ child = $.create(child);
526
+ }
527
+
528
+ if (child instanceof Node) {
529
+ this.appendChild(child);
530
+ }
531
+ }, this);
532
+ }
533
+ },
534
+
535
+ // Append the element inside another element
536
+ inside: function (element) {
537
+ element.appendChild(this);
538
+ },
539
+
540
+ // Insert the element before another element
541
+ before: function (element) {
542
+ element.parentNode.insertBefore(this, element);
543
+ },
544
+
545
+ // Insert the element after another element
546
+ after: function (element) {
547
+ element.parentNode.insertBefore(this, element.nextSibling);
548
+ },
549
+
550
+ // Insert the element before another element's contents
551
+ start: function (element) {
552
+ element.insertBefore(this, element.firstChild);
553
+ },
554
+
555
+ // Wrap the element around another element
556
+ around: function (element) {
557
+ if (element.parentNode) {
558
+ $.before(this, element);
559
+ }
560
+
561
+ (/^template$/i.test(this.nodeName)? this.content || this : this).appendChild(element);
562
+ }
563
+ };
564
+
565
+ $.Array = function (subject) {
566
+ this.subject = subject;
567
+ };
568
+
569
+ $.Array.prototype = {
570
+ all: function(method) {
571
+ var args = $$(arguments).slice(1);
572
+
573
+ return this[method].apply(this, args);
574
+ }
575
+ };
576
+
577
+ // Extends Bliss with more methods
578
+ $.add = overload(function(method, callback, on, noOverwrite) {
579
+ on = $.extend({$: true, element: true, array: true}, on);
580
+
581
+ if ($.type(callback) == "function") {
582
+ if (on.element && (!(method in $.Element.prototype) || !noOverwrite)) {
583
+ $.Element.prototype[method] = function () {
584
+ return this.subject && $.defined(callback.apply(this.subject, arguments), this.subject);
585
+ };
586
+ }
587
+
588
+ if (on.array && (!(method in $.Array.prototype) || !noOverwrite)) {
589
+ $.Array.prototype[method] = function() {
590
+ var args = arguments;
591
+ return this.subject.map(function(element) {
592
+ return element && $.defined(callback.apply(element, args), element);
593
+ });
594
+ };
595
+ }
596
+
597
+ if (on.$) {
598
+ $.sources[method] = $[method] = callback;
599
+
600
+ if (on.array || on.element) {
601
+ $[method] = function () {
602
+ var args = [].slice.apply(arguments);
603
+ var subject = args.shift();
604
+ var Type = on.array && Array.isArray(subject)? "Array" : "Element";
605
+
606
+ return $[Type].prototype[method].apply({subject: subject}, args);
607
+ };
608
+ }
609
+ }
610
+ }
611
+ }, 0);
612
+
613
+ $.add($.Array.prototype, {element: false});
614
+ $.add($.Element.prototype);
615
+ $.add($.setProps);
616
+ $.add($.classProps, {element: false, array: false});
617
+
618
+ // Add native methods on $ and _
619
+ var dummy = document.createElement("_");
620
+ $.add($.extend({}, HTMLElement.prototype, function(method){
621
+ return $.type(dummy[method]) === "function";
622
+ }), null, true);
623
+
624
+
625
+ })();
626
+
627
+ (function($) {
628
+ "use strict";
629
+
630
+ if (!Bliss || Bliss.shy) {
631
+ return;
632
+ }
633
+
634
+ var _ = Bliss.property;
635
+
636
+ // Methods requiring Bliss Full
637
+ $.add({
638
+ // Clone elements, with events
639
+ clone: function () {
640
+ var clone = this.cloneNode(true);
641
+ var descendants = $.$("*", clone).concat(clone);
642
+
643
+ $.$("*", this).concat(this).forEach(function(element, i, arr) {
644
+ $.events(descendants[i], element);
645
+ });
646
+
647
+ return clone;
648
+ }
649
+ }, {array: false});
650
+
651
+ // Define the _ property on arrays and elements
652
+
653
+ Object.defineProperty(Node.prototype, _, {
654
+ // Written for IE compatability (see #49)
655
+ get: function getter () {
656
+ Object.defineProperty(Node.prototype, _, {
657
+ get: undefined
658
+ });
659
+ Object.defineProperty(this, _, {
660
+ value: new $.Element(this)
661
+ });
662
+ Object.defineProperty(Node.prototype, _, {
663
+ get: getter
664
+ });
665
+ return this[_];
666
+ },
667
+ configurable: true
668
+ });
669
+
670
+ Object.defineProperty(Array.prototype, _, {
671
+ get: function () {
672
+ Object.defineProperty(this, _, {
673
+ value: new $.Array(this)
674
+ });
675
+
676
+ return this[_];
677
+ },
678
+ configurable: true
679
+ });
680
+
681
+ // Hijack addEventListener and removeEventListener to store callbacks
682
+
683
+ if (self.EventTarget && "addEventListener" in EventTarget.prototype) {
684
+ var addEventListener = EventTarget.prototype.addEventListener,
685
+ removeEventListener = EventTarget.prototype.removeEventListener,
686
+ equal = function(callback, capture, l){
687
+ return l.callback === callback && l.capture == capture;
688
+ },
689
+ notEqual = function() { return !equal.apply(this, arguments); };
690
+
691
+ EventTarget.prototype.addEventListener = function(type, callback, capture) {
692
+ if (this[_] && callback) {
693
+ var listeners = this[_].bliss.listeners = this[_].bliss.listeners || {};
694
+
695
+ listeners[type] = listeners[type] || [];
696
+
697
+ if (listeners[type].filter(equal.bind(null, callback, capture)).length === 0) {
698
+ listeners[type].push({callback: callback, capture: capture});
699
+ }
700
+ }
701
+
702
+ return addEventListener.call(this, type, callback, capture);
703
+ };
704
+
705
+ EventTarget.prototype.removeEventListener = function(type, callback, capture) {
706
+ if (this[_] && callback) {
707
+ var listeners = this[_].bliss.listeners = this[_].bliss.listeners || {};
708
+
709
+ if (listeners[type]) {
710
+ listeners[type] = listeners[type].filter(notEqual.bind(null, callback, capture));
711
+ }
712
+ }
713
+
714
+ return removeEventListener.call(this, type, callback, capture);
715
+ };
716
+ }
717
+
718
+ // Set $ and $$ convenience methods, if not taken
719
+ self.$ = self.$ || $;
720
+ self.$$ = self.$$ || $.$;
721
+
722
+ })(Bliss);