├── .gitignore
├── .meteor
├── .finished-upgraders
├── .gitignore
├── .id
├── packages
├── platforms
├── release
└── versions
├── README.md
├── client
├── compatibility
│ └── tether.js
├── imports
│ └── my.css
├── main.css
├── main.html
├── main.js
└── my2.import.css
├── package.json
├── public
├── arch.jpg
├── nature.jpg
└── people.jpg
└── server
└── main.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/.meteor/.finished-upgraders:
--------------------------------------------------------------------------------
1 | # This file contains information which helps Meteor properly upgrade your
2 | # app when you run 'meteor update'. You should check it into version control
3 | # with your project.
4 |
5 | notices-for-0.9.0
6 | notices-for-0.9.1
7 | 0.9.4-platform-file
8 | notices-for-facebook-graph-api-2
9 | 1.2.0-standard-minifiers-package
10 | 1.2.0-meteor-platform-split
11 | 1.2.0-cordova-changes
12 | 1.2.0-breaking-changes
13 | 1.3.0-split-minifiers-package
14 |
--------------------------------------------------------------------------------
/.meteor/.gitignore:
--------------------------------------------------------------------------------
1 | local
2 |
--------------------------------------------------------------------------------
/.meteor/.id:
--------------------------------------------------------------------------------
1 | # This file contains a token that is unique to your project.
2 | # Check it into your repository along with the rest of this directory.
3 | # It can be used for purposes such as:
4 | # - ensuring you don't accidentally deploy one app on top of another
5 | # - providing package authors with aggregated statistics
6 |
7 | ykqrrvdl2h3s145oxrp
8 |
--------------------------------------------------------------------------------
/.meteor/packages:
--------------------------------------------------------------------------------
1 | # Meteor packages used by this project, one per line.
2 | # Check this file (and the other files in this directory) into your repository.
3 | #
4 | # 'meteor add' and 'meteor remove' will edit this file for you,
5 | # but you can also edit it by hand.
6 |
7 | meteor-base # Packages every Meteor app needs to have
8 | mobile-experience # Packages for a great mobile UX
9 | mongo # The database Meteor supports right now
10 | blaze-html-templates # Compile .html files into Meteor Blaze views
11 | reactive-var # Reactive variable for tracker
12 | jquery # Helpful client-side library
13 | tracker # Meteor's client-side reactive programming library
14 |
15 | standard-minifier-js # JS minifier run for production mode
16 | es5-shim # ECMAScript 5 compatibility for older browsers.
17 | ecmascript # Enable ECMAScript2015+ syntax in app code
18 |
19 | autopublish # Publish all data to the clients (for prototyping)
20 | insecure # Allow all DB writes from clients (for prototyping)
21 | juliancwirko:postcss@1.0.0-rc.12
22 |
--------------------------------------------------------------------------------
/.meteor/platforms:
--------------------------------------------------------------------------------
1 | server
2 | browser
3 |
--------------------------------------------------------------------------------
/.meteor/release:
--------------------------------------------------------------------------------
1 | METEOR@1.3-rc.12
2 |
--------------------------------------------------------------------------------
/.meteor/versions:
--------------------------------------------------------------------------------
1 | allow-deny@1.0.2-rc.12
2 | autopublish@1.0.5-rc.12
3 | autoupdate@1.2.6-rc.12
4 | babel-compiler@6.5.2-rc.12
5 | babel-runtime@0.1.6-rc.12
6 | base64@1.0.6-rc.12
7 | binary-heap@1.0.6-rc.12
8 | blaze@2.1.5-rc.12
9 | blaze-html-templates@1.0.2-rc.12
10 | blaze-tools@1.0.6-rc.12
11 | boilerplate-generator@1.0.6-rc.12
12 | caching-compiler@1.0.2-rc.12
13 | caching-html-compiler@1.0.4-rc.12
14 | callback-hook@1.0.6-rc.12
15 | check@1.1.2-rc.12
16 | ddp@1.2.3-rc.12
17 | ddp-client@1.2.3-rc.12
18 | ddp-common@1.2.3-rc.12
19 | ddp-server@1.2.4-rc.12
20 | deps@1.0.10-rc.12
21 | diff-sequence@1.0.3-rc.12
22 | ecmascript@0.4.1-rc.12
23 | ecmascript-runtime@0.2.8-rc.12
24 | ejson@1.0.9-rc.12
25 | es5-shim@4.5.8-rc.12
26 | fastclick@1.0.9-rc.12
27 | geojson-utils@1.0.6-rc.12
28 | hot-code-push@1.0.2-rc.12
29 | html-tools@1.0.7-rc.12
30 | htmljs@1.0.7-rc.12
31 | http@1.1.3-rc.12
32 | id-map@1.0.5-rc.12
33 | insecure@1.0.5-rc.12
34 | jquery@1.11.6-rc.12
35 | juliancwirko:postcss@1.0.0-rc.12
36 | launch-screen@1.0.8-rc.12
37 | livedata@1.0.16-rc.12
38 | logging@1.0.10-rc.12
39 | meteor@1.1.12-rc.12
40 | meteor-base@1.0.2-rc.12
41 | minifier-css@1.1.9-rc.12
42 | minifier-js@1.1.9-rc.12
43 | minimongo@1.0.12-rc.12
44 | mobile-experience@1.0.2-rc.12
45 | mobile-status-bar@1.0.10-rc.12
46 | modules@0.5.1-rc.12
47 | modules-runtime@0.6.1-rc.12
48 | mongo@1.1.5-rc.12
49 | mongo-id@1.0.2-rc.12
50 | npm-mongo@1.4.41-rc.12
51 | observe-sequence@1.0.9-rc.12
52 | ordered-dict@1.0.5-rc.12
53 | promise@0.6.5-rc.12
54 | random@1.0.7-rc.12
55 | reactive-var@1.0.7-rc.12
56 | reload@1.1.6-rc.12
57 | retry@1.0.5-rc.12
58 | routepolicy@1.0.8-rc.12
59 | spacebars@1.0.9-rc.12
60 | spacebars-compiler@1.0.9-rc.12
61 | standard-minifier-js@1.0.4-rc.12
62 | templating@1.1.7-rc.12
63 | templating-tools@1.0.2-rc.12
64 | tracker@1.0.11-rc.12
65 | ui@1.0.9-rc.12
66 | underscore@1.0.6-rc.12
67 | url@1.0.7-rc.12
68 | webapp@1.2.6-rc.12
69 | webapp-hashing@1.0.7-rc.12
70 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Meteor Bootstrap 4 Scss from Npm with PostCSS - playground
2 |
3 | This is just a quick test and demo project which uses [PostCSS package](https://github.com/juliancwirko/meteor-postcss/tree/meteor-1.3-in-progress) and some PostCSS plugins to compile Scss provided by Bootstrap 4 from Npm package.
4 |
5 | **For now with Meteor 1.3 you are not able to import and compile .scss files from `node_modules`. Here we use PostCSS and couple of its plugins to be able to install bootstrap from Npm and then import its .scss files from `node_modules` folder.**
6 |
7 | ### Run it locally
8 |
9 | ```bash
10 | $ git clone https://github.com/juliancwirko/meteor-bootstrap-postcss-test.git
11 | $ cd meteor-bootstrap-postcss-test
12 | $ npm install
13 | $ meteor
14 | ```
15 |
16 | ### What I've done here:
17 |
18 | 1. I use [juliancwirko:postcss](https://github.com/juliancwirko/meteor-postcss/tree/meteor-1.3-in-progress) PostCSS integration package for Meteor (in version 1.0.0-rc.12)
19 | 2. I use some PostCSS plugins. Take a look at `package.json` file at 'postcss' key. Here is the list: ["autoprefixer": "^6.3.4", "postcss-easy-import": "^1.0.1", "postcss-nested": "^1.0.0", "postcss-sassy-mixins": "^2.0.0", "postcss-simple-vars": "^1.2.0"]
20 | 3. I import all bootstrap .scss files in `client/main.css` file - yes it should be .css file not .scss
21 | 4. I import all Bootstrap javascript in `client/main.js` file (ES6 modules).
22 | 5. All is installed by `npm install bootstrap@4.0.0-alpha.2 --save`
23 | 6. We don't need `fourseven:scss` here!
24 |
25 | ### Benefits
26 |
27 | Scss imports and compilation from `node_modules` without any additional work. (You can't do this now with Meteor 1.3) Bootstrap here is just a working example, there can be more other libs with styles attached.
28 |
29 | This could be also a very good transition from projects based on Scss to full PostCSS stack without preprocessors. I think that Bootstrap will be written in PostCSS in the future too.
30 |
31 | Besides Scss and Bootstrap you can use plenty other [PostCSS plugins](http://postcss.parts/).
32 |
33 | ### What doesn't work
34 |
35 | I've tried it with Foundation 6 too. Unfortunatelly because Foundation 6 uses complicated mixins structures the PostCSS plugin responsible for [sassy mixins](https://github.com/andyjansson/postcss-sassy-mixins) can't manage it. We don't use a standard Scss compiler here, so it could be problematic in complicated structures. We use basic stuff like Sass-like variables, nesting, mixins, imports.
36 |
37 | **This solution will not work in complicated use cases. But I'm sure it could be worked out somehow.**
38 |
39 | ### Please play with it
40 |
41 | Let me know if you'll find something interesting. You can also comment here in the GitHub issues.
42 | I'll try to do some more research too. I'll try to run Foundation 6 from Npm.
43 |
44 | ### ...
45 |
46 |
47 |
--------------------------------------------------------------------------------
/client/compatibility/tether.js:
--------------------------------------------------------------------------------
1 | /*! tether 1.2.0 */
2 |
3 | (function(root, factory) {
4 | if (typeof define === 'function' && define.amd) {
5 | define(factory);
6 | } else if (typeof exports === 'object') {
7 | module.exports = factory(require, exports, module);
8 | } else {
9 | root.Tether = factory();
10 | }
11 | }(this, function(require, exports, module) {
12 |
13 | 'use strict';
14 |
15 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
16 |
17 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
18 |
19 | var TetherBase = undefined;
20 | if (typeof TetherBase === 'undefined') {
21 | TetherBase = { modules: [] };
22 | }
23 |
24 | function getScrollParent(el) {
25 | // In firefox if the el is inside an iframe with display: none; window.getComputedStyle() will return null;
26 | // https://bugzilla.mozilla.org/show_bug.cgi?id=548397
27 | var computedStyle = getComputedStyle(el) || {};
28 | var position = computedStyle.position;
29 |
30 | if (position === 'fixed') {
31 | return el;
32 | }
33 |
34 | var parent = el;
35 | while (parent = parent.parentNode) {
36 | var style = undefined;
37 | try {
38 | style = getComputedStyle(parent);
39 | } catch (err) {}
40 |
41 | if (typeof style === 'undefined' || style === null) {
42 | return parent;
43 | }
44 |
45 | var _style = style;
46 | var overflow = _style.overflow;
47 | var overflowX = _style.overflowX;
48 | var overflowY = _style.overflowY;
49 |
50 | if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
51 | if (position !== 'absolute' || ['relative', 'absolute', 'fixed'].indexOf(style.position) >= 0) {
52 | return parent;
53 | }
54 | }
55 | }
56 |
57 | return document.body;
58 | }
59 |
60 | var uniqueId = (function () {
61 | var id = 0;
62 | return function () {
63 | return ++id;
64 | };
65 | })();
66 |
67 | var zeroPosCache = {};
68 | var getOrigin = function getOrigin(doc) {
69 | // getBoundingClientRect is unfortunately too accurate. It introduces a pixel or two of
70 | // jitter as the user scrolls that messes with our ability to detect if two positions
71 | // are equivilant or not. We place an element at the top left of the page that will
72 | // get the same jitter, so we can cancel the two out.
73 | var node = doc._tetherZeroElement;
74 | if (typeof node === 'undefined') {
75 | node = doc.createElement('div');
76 | node.setAttribute('data-tether-id', uniqueId());
77 | extend(node.style, {
78 | top: 0,
79 | left: 0,
80 | position: 'absolute'
81 | });
82 |
83 | doc.body.appendChild(node);
84 |
85 | doc._tetherZeroElement = node;
86 | }
87 |
88 | var id = node.getAttribute('data-tether-id');
89 | if (typeof zeroPosCache[id] === 'undefined') {
90 | zeroPosCache[id] = {};
91 |
92 | var rect = node.getBoundingClientRect();
93 | for (var k in rect) {
94 | // Can't use extend, as on IE9, elements don't resolve to be hasOwnProperty
95 | zeroPosCache[id][k] = rect[k];
96 | }
97 |
98 | // Clear the cache when this position call is done
99 | defer(function () {
100 | delete zeroPosCache[id];
101 | });
102 | }
103 |
104 | return zeroPosCache[id];
105 | };
106 |
107 | function getBounds(el) {
108 | var doc = undefined;
109 | if (el === document) {
110 | doc = document;
111 | el = document.documentElement;
112 | } else {
113 | doc = el.ownerDocument;
114 | }
115 |
116 | var docEl = doc.documentElement;
117 |
118 | var box = {};
119 | // The original object returned by getBoundingClientRect is immutable, so we clone it
120 | // We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9
121 | var rect = el.getBoundingClientRect();
122 | for (var k in rect) {
123 | box[k] = rect[k];
124 | }
125 |
126 | var origin = getOrigin(doc);
127 |
128 | box.top -= origin.top;
129 | box.left -= origin.left;
130 |
131 | if (typeof box.width === 'undefined') {
132 | box.width = document.body.scrollWidth - box.left - box.right;
133 | }
134 | if (typeof box.height === 'undefined') {
135 | box.height = document.body.scrollHeight - box.top - box.bottom;
136 | }
137 |
138 | box.top = box.top - docEl.clientTop;
139 | box.left = box.left - docEl.clientLeft;
140 | box.right = doc.body.clientWidth - box.width - box.left;
141 | box.bottom = doc.body.clientHeight - box.height - box.top;
142 |
143 | return box;
144 | }
145 |
146 | function getOffsetParent(el) {
147 | return el.offsetParent || document.documentElement;
148 | }
149 |
150 | function getScrollBarSize() {
151 | var inner = document.createElement('div');
152 | inner.style.width = '100%';
153 | inner.style.height = '200px';
154 |
155 | var outer = document.createElement('div');
156 | extend(outer.style, {
157 | position: 'absolute',
158 | top: 0,
159 | left: 0,
160 | pointerEvents: 'none',
161 | visibility: 'hidden',
162 | width: '200px',
163 | height: '150px',
164 | overflow: 'hidden'
165 | });
166 |
167 | outer.appendChild(inner);
168 |
169 | document.body.appendChild(outer);
170 |
171 | var widthContained = inner.offsetWidth;
172 | outer.style.overflow = 'scroll';
173 | var widthScroll = inner.offsetWidth;
174 |
175 | if (widthContained === widthScroll) {
176 | widthScroll = outer.clientWidth;
177 | }
178 |
179 | document.body.removeChild(outer);
180 |
181 | var width = widthContained - widthScroll;
182 |
183 | return { width: width, height: width };
184 | }
185 |
186 | function extend() {
187 | var out = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
188 |
189 | var args = [];
190 |
191 | Array.prototype.push.apply(args, arguments);
192 |
193 | args.slice(1).forEach(function (obj) {
194 | if (obj) {
195 | for (var key in obj) {
196 | if (({}).hasOwnProperty.call(obj, key)) {
197 | out[key] = obj[key];
198 | }
199 | }
200 | }
201 | });
202 |
203 | return out;
204 | }
205 |
206 | function removeClass(el, name) {
207 | if (typeof el.classList !== 'undefined') {
208 | name.split(' ').forEach(function (cls) {
209 | if (cls.trim()) {
210 | el.classList.remove(cls);
211 | }
212 | });
213 | } else {
214 | var regex = new RegExp('(^| )' + name.split(' ').join('|') + '( |$)', 'gi');
215 | var className = getClassName(el).replace(regex, ' ');
216 | setClassName(el, className);
217 | }
218 | }
219 |
220 | function addClass(el, name) {
221 | if (typeof el.classList !== 'undefined') {
222 | name.split(' ').forEach(function (cls) {
223 | if (cls.trim()) {
224 | el.classList.add(cls);
225 | }
226 | });
227 | } else {
228 | removeClass(el, name);
229 | var cls = getClassName(el) + (' ' + name);
230 | setClassName(el, cls);
231 | }
232 | }
233 |
234 | function hasClass(el, name) {
235 | if (typeof el.classList !== 'undefined') {
236 | return el.classList.contains(name);
237 | }
238 | var className = getClassName(el);
239 | return new RegExp('(^| )' + name + '( |$)', 'gi').test(className);
240 | }
241 |
242 | function getClassName(el) {
243 | if (el.className instanceof SVGAnimatedString) {
244 | return el.className.baseVal;
245 | }
246 | return el.className;
247 | }
248 |
249 | function setClassName(el, className) {
250 | el.setAttribute('class', className);
251 | }
252 |
253 | function updateClasses(el, add, all) {
254 | // Of the set of 'all' classes, we need the 'add' classes, and only the
255 | // 'add' classes to be set.
256 | all.forEach(function (cls) {
257 | if (add.indexOf(cls) === -1 && hasClass(el, cls)) {
258 | removeClass(el, cls);
259 | }
260 | });
261 |
262 | add.forEach(function (cls) {
263 | if (!hasClass(el, cls)) {
264 | addClass(el, cls);
265 | }
266 | });
267 | }
268 |
269 | var deferred = [];
270 |
271 | var defer = function defer(fn) {
272 | deferred.push(fn);
273 | };
274 |
275 | var flush = function flush() {
276 | var fn = undefined;
277 | while (fn = deferred.pop()) {
278 | fn();
279 | }
280 | };
281 |
282 | var Evented = (function () {
283 | function Evented() {
284 | _classCallCheck(this, Evented);
285 | }
286 |
287 | _createClass(Evented, [{
288 | key: 'on',
289 | value: function on(event, handler, ctx) {
290 | var once = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
291 |
292 | if (typeof this.bindings === 'undefined') {
293 | this.bindings = {};
294 | }
295 | if (typeof this.bindings[event] === 'undefined') {
296 | this.bindings[event] = [];
297 | }
298 | this.bindings[event].push({ handler: handler, ctx: ctx, once: once });
299 | }
300 | }, {
301 | key: 'once',
302 | value: function once(event, handler, ctx) {
303 | this.on(event, handler, ctx, true);
304 | }
305 | }, {
306 | key: 'off',
307 | value: function off(event, handler) {
308 | if (typeof this.bindings !== 'undefined' && typeof this.bindings[event] !== 'undefined') {
309 | return;
310 | }
311 |
312 | if (typeof handler === 'undefined') {
313 | delete this.bindings[event];
314 | } else {
315 | var i = 0;
316 | while (i < this.bindings[event].length) {
317 | if (this.bindings[event][i].handler === handler) {
318 | this.bindings[event].splice(i, 1);
319 | } else {
320 | ++i;
321 | }
322 | }
323 | }
324 | }
325 | }, {
326 | key: 'trigger',
327 | value: function trigger(event) {
328 | if (typeof this.bindings !== 'undefined' && this.bindings[event]) {
329 | var i = 0;
330 |
331 | for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
332 | args[_key - 1] = arguments[_key];
333 | }
334 |
335 | while (i < this.bindings[event].length) {
336 | var _bindings$event$i = this.bindings[event][i];
337 | var handler = _bindings$event$i.handler;
338 | var ctx = _bindings$event$i.ctx;
339 | var once = _bindings$event$i.once;
340 |
341 | var context = ctx;
342 | if (typeof context === 'undefined') {
343 | context = this;
344 | }
345 |
346 | handler.apply(context, args);
347 |
348 | if (once) {
349 | this.bindings[event].splice(i, 1);
350 | } else {
351 | ++i;
352 | }
353 | }
354 | }
355 | }
356 | }]);
357 |
358 | return Evented;
359 | })();
360 |
361 | TetherBase.Utils = {
362 | getScrollParent: getScrollParent,
363 | getBounds: getBounds,
364 | getOffsetParent: getOffsetParent,
365 | extend: extend,
366 | addClass: addClass,
367 | removeClass: removeClass,
368 | hasClass: hasClass,
369 | updateClasses: updateClasses,
370 | defer: defer,
371 | flush: flush,
372 | uniqueId: uniqueId,
373 | Evented: Evented,
374 | getScrollBarSize: getScrollBarSize
375 | };
376 | /* globals TetherBase, performance */
377 |
378 | 'use strict';
379 |
380 | var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
381 |
382 | var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
383 |
384 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
385 |
386 | if (typeof TetherBase === 'undefined') {
387 | throw new Error('You must include the utils.js file before tether.js');
388 | }
389 |
390 | var _TetherBase$Utils = TetherBase.Utils;
391 | var getScrollParent = _TetherBase$Utils.getScrollParent;
392 | var getBounds = _TetherBase$Utils.getBounds;
393 | var getOffsetParent = _TetherBase$Utils.getOffsetParent;
394 | var extend = _TetherBase$Utils.extend;
395 | var addClass = _TetherBase$Utils.addClass;
396 | var removeClass = _TetherBase$Utils.removeClass;
397 | var updateClasses = _TetherBase$Utils.updateClasses;
398 | var defer = _TetherBase$Utils.defer;
399 | var flush = _TetherBase$Utils.flush;
400 | var getScrollBarSize = _TetherBase$Utils.getScrollBarSize;
401 |
402 | function within(a, b) {
403 | var diff = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
404 |
405 | return a + diff >= b && b >= a - diff;
406 | }
407 |
408 | var transformKey = (function () {
409 | if (typeof document === 'undefined') {
410 | return '';
411 | }
412 | var el = document.createElement('div');
413 |
414 | var transforms = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
415 | for (var i = 0; i < transforms.length; ++i) {
416 | var key = transforms[i];
417 | if (el.style[key] !== undefined) {
418 | return key;
419 | }
420 | }
421 | })();
422 |
423 | var tethers = [];
424 |
425 | var position = function position() {
426 | tethers.forEach(function (tether) {
427 | tether.position(false);
428 | });
429 | flush();
430 | };
431 |
432 | function now() {
433 | if (typeof performance !== 'undefined' && typeof performance.now !== 'undefined') {
434 | return performance.now();
435 | }
436 | return +new Date();
437 | }
438 |
439 | (function () {
440 | var lastCall = null;
441 | var lastDuration = null;
442 | var pendingTimeout = null;
443 |
444 | var tick = function tick() {
445 | if (typeof lastDuration !== 'undefined' && lastDuration > 16) {
446 | // We voluntarily throttle ourselves if we can't manage 60fps
447 | lastDuration = Math.min(lastDuration - 16, 250);
448 |
449 | // Just in case this is the last event, remember to position just once more
450 | pendingTimeout = setTimeout(tick, 250);
451 | return;
452 | }
453 |
454 | if (typeof lastCall !== 'undefined' && now() - lastCall < 10) {
455 | // Some browsers call events a little too frequently, refuse to run more than is reasonable
456 | return;
457 | }
458 |
459 | if (typeof pendingTimeout !== 'undefined') {
460 | clearTimeout(pendingTimeout);
461 | pendingTimeout = null;
462 | }
463 |
464 | lastCall = now();
465 | position();
466 | lastDuration = now() - lastCall;
467 | };
468 |
469 | if (typeof window !== 'undefined') {
470 | ['resize', 'scroll', 'touchmove'].forEach(function (event) {
471 | window.addEventListener(event, tick);
472 | });
473 | }
474 | })();
475 |
476 | var MIRROR_LR = {
477 | center: 'center',
478 | left: 'right',
479 | right: 'left'
480 | };
481 |
482 | var MIRROR_TB = {
483 | middle: 'middle',
484 | top: 'bottom',
485 | bottom: 'top'
486 | };
487 |
488 | var OFFSET_MAP = {
489 | top: 0,
490 | left: 0,
491 | middle: '50%',
492 | center: '50%',
493 | bottom: '100%',
494 | right: '100%'
495 | };
496 |
497 | var autoToFixedAttachment = function autoToFixedAttachment(attachment, relativeToAttachment) {
498 | var left = attachment.left;
499 | var top = attachment.top;
500 |
501 | if (left === 'auto') {
502 | left = MIRROR_LR[relativeToAttachment.left];
503 | }
504 |
505 | if (top === 'auto') {
506 | top = MIRROR_TB[relativeToAttachment.top];
507 | }
508 |
509 | return { left: left, top: top };
510 | };
511 |
512 | var attachmentToOffset = function attachmentToOffset(attachment) {
513 | var left = attachment.left;
514 | var top = attachment.top;
515 |
516 | if (typeof OFFSET_MAP[attachment.left] !== 'undefined') {
517 | left = OFFSET_MAP[attachment.left];
518 | }
519 |
520 | if (typeof OFFSET_MAP[attachment.top] !== 'undefined') {
521 | top = OFFSET_MAP[attachment.top];
522 | }
523 |
524 | return { left: left, top: top };
525 | };
526 |
527 | function addOffset() {
528 | var out = { top: 0, left: 0 };
529 |
530 | for (var _len = arguments.length, offsets = Array(_len), _key = 0; _key < _len; _key++) {
531 | offsets[_key] = arguments[_key];
532 | }
533 |
534 | offsets.forEach(function (_ref) {
535 | var top = _ref.top;
536 | var left = _ref.left;
537 |
538 | if (typeof top === 'string') {
539 | top = parseFloat(top, 10);
540 | }
541 | if (typeof left === 'string') {
542 | left = parseFloat(left, 10);
543 | }
544 |
545 | out.top += top;
546 | out.left += left;
547 | });
548 |
549 | return out;
550 | }
551 |
552 | function offsetToPx(offset, size) {
553 | if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
554 | offset.left = parseFloat(offset.left, 10) / 100 * size.width;
555 | }
556 | if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
557 | offset.top = parseFloat(offset.top, 10) / 100 * size.height;
558 | }
559 |
560 | return offset;
561 | }
562 |
563 | var parseOffset = function parseOffset(value) {
564 | var _value$split = value.split(' ');
565 |
566 | var _value$split2 = _slicedToArray(_value$split, 2);
567 |
568 | var top = _value$split2[0];
569 | var left = _value$split2[1];
570 |
571 | return { top: top, left: left };
572 | };
573 | var parseAttachment = parseOffset;
574 |
575 | var TetherClass = (function () {
576 | function TetherClass(options) {
577 | var _this = this;
578 |
579 | _classCallCheck(this, TetherClass);
580 |
581 | this.position = this.position.bind(this);
582 |
583 | tethers.push(this);
584 |
585 | this.history = [];
586 |
587 | this.setOptions(options, false);
588 |
589 | TetherBase.modules.forEach(function (module) {
590 | if (typeof module.initialize !== 'undefined') {
591 | module.initialize.call(_this);
592 | }
593 | });
594 |
595 | this.position();
596 | }
597 |
598 | _createClass(TetherClass, [{
599 | key: 'getClass',
600 | value: function getClass() {
601 | var key = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
602 | var classes = this.options.classes;
603 |
604 | if (typeof classes !== 'undefined' && classes[key]) {
605 | return this.options.classes[key];
606 | } else if (this.options.classPrefix) {
607 | return this.options.classPrefix + '-' + key;
608 | } else {
609 | return key;
610 | }
611 | }
612 | }, {
613 | key: 'setOptions',
614 | value: function setOptions(options) {
615 | var _this2 = this;
616 |
617 | var pos = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1];
618 |
619 | var defaults = {
620 | offset: '0 0',
621 | targetOffset: '0 0',
622 | targetAttachment: 'auto auto',
623 | classPrefix: 'tether'
624 | };
625 |
626 | this.options = extend(defaults, options);
627 |
628 | var _options = this.options;
629 | var element = _options.element;
630 | var target = _options.target;
631 | var targetModifier = _options.targetModifier;
632 |
633 | this.element = element;
634 | this.target = target;
635 | this.targetModifier = targetModifier;
636 |
637 | if (this.target === 'viewport') {
638 | this.target = document.body;
639 | this.targetModifier = 'visible';
640 | } else if (this.target === 'scroll-handle') {
641 | this.target = document.body;
642 | this.targetModifier = 'scroll-handle';
643 | }
644 |
645 | ['element', 'target'].forEach(function (key) {
646 | if (typeof _this2[key] === 'undefined') {
647 | throw new Error('Tether Error: Both element and target must be defined');
648 | }
649 |
650 | if (typeof _this2[key].jquery !== 'undefined') {
651 | _this2[key] = _this2[key][0];
652 | } else if (typeof _this2[key] === 'string') {
653 | _this2[key] = document.querySelector(_this2[key]);
654 | }
655 | });
656 |
657 | addClass(this.element, this.getClass('element'));
658 | if (!(this.options.addTargetClasses === false)) {
659 | addClass(this.target, this.getClass('target'));
660 | }
661 |
662 | if (!this.options.attachment) {
663 | throw new Error('Tether Error: You must provide an attachment');
664 | }
665 |
666 | this.targetAttachment = parseAttachment(this.options.targetAttachment);
667 | this.attachment = parseAttachment(this.options.attachment);
668 | this.offset = parseOffset(this.options.offset);
669 | this.targetOffset = parseOffset(this.options.targetOffset);
670 |
671 | if (typeof this.scrollParent !== 'undefined') {
672 | this.disable();
673 | }
674 |
675 | if (this.targetModifier === 'scroll-handle') {
676 | this.scrollParent = this.target;
677 | } else {
678 | this.scrollParent = getScrollParent(this.target);
679 | }
680 |
681 | if (!(this.options.enabled === false)) {
682 | this.enable(pos);
683 | }
684 | }
685 | }, {
686 | key: 'getTargetBounds',
687 | value: function getTargetBounds() {
688 | if (typeof this.targetModifier !== 'undefined') {
689 | if (this.targetModifier === 'visible') {
690 | if (this.target === document.body) {
691 | return { top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth };
692 | } else {
693 | var bounds = getBounds(this.target);
694 |
695 | var out = {
696 | height: bounds.height,
697 | width: bounds.width,
698 | top: bounds.top,
699 | left: bounds.left
700 | };
701 |
702 | out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
703 | out.height = Math.min(out.height, bounds.height - (bounds.top + bounds.height - (pageYOffset + innerHeight)));
704 | out.height = Math.min(innerHeight, out.height);
705 | out.height -= 2;
706 |
707 | out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
708 | out.width = Math.min(out.width, bounds.width - (bounds.left + bounds.width - (pageXOffset + innerWidth)));
709 | out.width = Math.min(innerWidth, out.width);
710 | out.width -= 2;
711 |
712 | if (out.top < pageYOffset) {
713 | out.top = pageYOffset;
714 | }
715 | if (out.left < pageXOffset) {
716 | out.left = pageXOffset;
717 | }
718 |
719 | return out;
720 | }
721 | } else if (this.targetModifier === 'scroll-handle') {
722 | var bounds = undefined;
723 | var target = this.target;
724 | if (target === document.body) {
725 | target = document.documentElement;
726 |
727 | bounds = {
728 | left: pageXOffset,
729 | top: pageYOffset,
730 | height: innerHeight,
731 | width: innerWidth
732 | };
733 | } else {
734 | bounds = getBounds(target);
735 | }
736 |
737 | var style = getComputedStyle(target);
738 |
739 | var hasBottomScroll = target.scrollWidth > target.clientWidth || [style.overflow, style.overflowX].indexOf('scroll') >= 0 || this.target !== document.body;
740 |
741 | var scrollBottom = 0;
742 | if (hasBottomScroll) {
743 | scrollBottom = 15;
744 | }
745 |
746 | var height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
747 |
748 | var out = {
749 | width: 15,
750 | height: height * 0.975 * (height / target.scrollHeight),
751 | left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
752 | };
753 |
754 | var fitAdj = 0;
755 | if (height < 408 && this.target === document.body) {
756 | fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
757 | }
758 |
759 | if (this.target !== document.body) {
760 | out.height = Math.max(out.height, 24);
761 | }
762 |
763 | var scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
764 | out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
765 |
766 | if (this.target === document.body) {
767 | out.height = Math.max(out.height, 24);
768 | }
769 |
770 | return out;
771 | }
772 | } else {
773 | return getBounds(this.target);
774 | }
775 | }
776 | }, {
777 | key: 'clearCache',
778 | value: function clearCache() {
779 | this._cache = {};
780 | }
781 | }, {
782 | key: 'cache',
783 | value: function cache(k, getter) {
784 | // More than one module will often need the same DOM info, so
785 | // we keep a cache which is cleared on each position call
786 | if (typeof this._cache === 'undefined') {
787 | this._cache = {};
788 | }
789 |
790 | if (typeof this._cache[k] === 'undefined') {
791 | this._cache[k] = getter.call(this);
792 | }
793 |
794 | return this._cache[k];
795 | }
796 | }, {
797 | key: 'enable',
798 | value: function enable() {
799 | var pos = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
800 |
801 | if (!(this.options.addTargetClasses === false)) {
802 | addClass(this.target, this.getClass('enabled'));
803 | }
804 | addClass(this.element, this.getClass('enabled'));
805 | this.enabled = true;
806 |
807 | if (this.scrollParent !== document) {
808 | this.scrollParent.addEventListener('scroll', this.position);
809 | }
810 |
811 | if (pos) {
812 | this.position();
813 | }
814 | }
815 | }, {
816 | key: 'disable',
817 | value: function disable() {
818 | removeClass(this.target, this.getClass('enabled'));
819 | removeClass(this.element, this.getClass('enabled'));
820 | this.enabled = false;
821 |
822 | if (typeof this.scrollParent !== 'undefined') {
823 | this.scrollParent.removeEventListener('scroll', this.position);
824 | }
825 | }
826 | }, {
827 | key: 'destroy',
828 | value: function destroy() {
829 | var _this3 = this;
830 |
831 | this.disable();
832 |
833 | tethers.forEach(function (tether, i) {
834 | if (tether === _this3) {
835 | tethers.splice(i, 1);
836 | return;
837 | }
838 | });
839 | }
840 | }, {
841 | key: 'updateAttachClasses',
842 | value: function updateAttachClasses(elementAttach, targetAttach) {
843 | var _this4 = this;
844 |
845 | elementAttach = elementAttach || this.attachment;
846 | targetAttach = targetAttach || this.targetAttachment;
847 | var sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
848 |
849 | if (typeof this._addAttachClasses !== 'undefined' && this._addAttachClasses.length) {
850 | // updateAttachClasses can be called more than once in a position call, so
851 | // we need to clean up after ourselves such that when the last defer gets
852 | // ran it doesn't add any extra classes from previous calls.
853 | this._addAttachClasses.splice(0, this._addAttachClasses.length);
854 | }
855 |
856 | if (typeof this._addAttachClasses === 'undefined') {
857 | this._addAttachClasses = [];
858 | }
859 | var add = this._addAttachClasses;
860 |
861 | if (elementAttach.top) {
862 | add.push(this.getClass('element-attached') + '-' + elementAttach.top);
863 | }
864 | if (elementAttach.left) {
865 | add.push(this.getClass('element-attached') + '-' + elementAttach.left);
866 | }
867 | if (targetAttach.top) {
868 | add.push(this.getClass('target-attached') + '-' + targetAttach.top);
869 | }
870 | if (targetAttach.left) {
871 | add.push(this.getClass('target-attached') + '-' + targetAttach.left);
872 | }
873 |
874 | var all = [];
875 | sides.forEach(function (side) {
876 | all.push(_this4.getClass('element-attached') + '-' + side);
877 | all.push(_this4.getClass('target-attached') + '-' + side);
878 | });
879 |
880 | defer(function () {
881 | if (!(typeof _this4._addAttachClasses !== 'undefined')) {
882 | return;
883 | }
884 |
885 | updateClasses(_this4.element, _this4._addAttachClasses, all);
886 | if (!(_this4.options.addTargetClasses === false)) {
887 | updateClasses(_this4.target, _this4._addAttachClasses, all);
888 | }
889 |
890 | delete _this4._addAttachClasses;
891 | });
892 | }
893 | }, {
894 | key: 'position',
895 | value: function position() {
896 | var _this5 = this;
897 |
898 | var flushChanges = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
899 |
900 | // flushChanges commits the changes immediately, leave true unless you are positioning multiple
901 | // tethers (in which case call Tether.Utils.flush yourself when you're done)
902 |
903 | if (!this.enabled) {
904 | return;
905 | }
906 |
907 | this.clearCache();
908 |
909 | // Turn 'auto' attachments into the appropriate corner or edge
910 | var targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
911 |
912 | this.updateAttachClasses(this.attachment, targetAttachment);
913 |
914 | var elementPos = this.cache('element-bounds', function () {
915 | return getBounds(_this5.element);
916 | });
917 |
918 | var width = elementPos.width;
919 | var height = elementPos.height;
920 |
921 | if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
922 | var _lastSize = this.lastSize;
923 |
924 | // We cache the height and width to make it possible to position elements that are
925 | // getting hidden.
926 | width = _lastSize.width;
927 | height = _lastSize.height;
928 | } else {
929 | this.lastSize = { width: width, height: height };
930 | }
931 |
932 | var targetPos = this.cache('target-bounds', function () {
933 | return _this5.getTargetBounds();
934 | });
935 | var targetSize = targetPos;
936 |
937 | // Get an actual px offset from the attachment
938 | var offset = offsetToPx(attachmentToOffset(this.attachment), { width: width, height: height });
939 | var targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
940 |
941 | var manualOffset = offsetToPx(this.offset, { width: width, height: height });
942 | var manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
943 |
944 | // Add the manually provided offset
945 | offset = addOffset(offset, manualOffset);
946 | targetOffset = addOffset(targetOffset, manualTargetOffset);
947 |
948 | // It's now our goal to make (element position + offset) == (target position + target offset)
949 | var left = targetPos.left + targetOffset.left - offset.left;
950 | var top = targetPos.top + targetOffset.top - offset.top;
951 |
952 | for (var i = 0; i < TetherBase.modules.length; ++i) {
953 | var _module2 = TetherBase.modules[i];
954 | var ret = _module2.position.call(this, {
955 | left: left,
956 | top: top,
957 | targetAttachment: targetAttachment,
958 | targetPos: targetPos,
959 | elementPos: elementPos,
960 | offset: offset,
961 | targetOffset: targetOffset,
962 | manualOffset: manualOffset,
963 | manualTargetOffset: manualTargetOffset,
964 | scrollbarSize: scrollbarSize,
965 | attachment: this.attachment
966 | });
967 |
968 | if (ret === false) {
969 | return false;
970 | } else if (typeof ret === 'undefined' || typeof ret !== 'object') {
971 | continue;
972 | } else {
973 | top = ret.top;
974 | left = ret.left;
975 | }
976 | }
977 |
978 | // We describe the position three different ways to give the optimizer
979 | // a chance to decide the best possible way to position the element
980 | // with the fewest repaints.
981 | var next = {
982 | // It's position relative to the page (absolute positioning when
983 | // the element is a child of the body)
984 | page: {
985 | top: top,
986 | left: left
987 | },
988 |
989 | // It's position relative to the viewport (fixed positioning)
990 | viewport: {
991 | top: top - pageYOffset,
992 | bottom: pageYOffset - top - height + innerHeight,
993 | left: left - pageXOffset,
994 | right: pageXOffset - left - width + innerWidth
995 | }
996 | };
997 |
998 | var scrollbarSize = undefined;
999 | if (document.body.scrollWidth > window.innerWidth) {
1000 | scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
1001 | next.viewport.bottom -= scrollbarSize.height;
1002 | }
1003 |
1004 | if (document.body.scrollHeight > window.innerHeight) {
1005 | scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
1006 | next.viewport.right -= scrollbarSize.width;
1007 | }
1008 |
1009 | if (['', 'static'].indexOf(document.body.style.position) === -1 || ['', 'static'].indexOf(document.body.parentElement.style.position) === -1) {
1010 | // Absolute positioning in the body will be relative to the page, not the 'initial containing block'
1011 | next.page.bottom = document.body.scrollHeight - top - height;
1012 | next.page.right = document.body.scrollWidth - left - width;
1013 | }
1014 |
1015 | if (typeof this.options.optimizations !== 'undefined' && this.options.optimizations.moveElement !== false && !(typeof this.targetModifier !== 'undefined')) {
1016 | (function () {
1017 | var offsetParent = _this5.cache('target-offsetparent', function () {
1018 | return getOffsetParent(_this5.target);
1019 | });
1020 | var offsetPosition = _this5.cache('target-offsetparent-bounds', function () {
1021 | return getBounds(offsetParent);
1022 | });
1023 | var offsetParentStyle = getComputedStyle(offsetParent);
1024 | var offsetParentSize = offsetPosition;
1025 |
1026 | var offsetBorder = {};
1027 | ['Top', 'Left', 'Bottom', 'Right'].forEach(function (side) {
1028 | offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle['border' + side + 'Width']);
1029 | });
1030 |
1031 | offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
1032 | offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
1033 |
1034 | if (next.page.top >= offsetPosition.top + offsetBorder.top && next.page.bottom >= offsetPosition.bottom) {
1035 | if (next.page.left >= offsetPosition.left + offsetBorder.left && next.page.right >= offsetPosition.right) {
1036 | // We're within the visible part of the target's scroll parent
1037 | var scrollTop = offsetParent.scrollTop;
1038 | var scrollLeft = offsetParent.scrollLeft;
1039 |
1040 | // It's position relative to the target's offset parent (absolute positioning when
1041 | // the element is moved to be a child of the target's offset parent).
1042 | next.offset = {
1043 | top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
1044 | left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
1045 | };
1046 | }
1047 | }
1048 | })();
1049 | }
1050 |
1051 | // We could also travel up the DOM and try each containing context, rather than only
1052 | // looking at the body, but we're gonna get diminishing returns.
1053 |
1054 | this.move(next);
1055 |
1056 | this.history.unshift(next);
1057 |
1058 | if (this.history.length > 3) {
1059 | this.history.pop();
1060 | }
1061 |
1062 | if (flushChanges) {
1063 | flush();
1064 | }
1065 |
1066 | return true;
1067 | }
1068 |
1069 | // THE ISSUE
1070 | }, {
1071 | key: 'move',
1072 | value: function move(pos) {
1073 | var _this6 = this;
1074 |
1075 | if (!(typeof this.element.parentNode !== 'undefined')) {
1076 | return;
1077 | }
1078 |
1079 | var same = {};
1080 |
1081 | for (var type in pos) {
1082 | same[type] = {};
1083 |
1084 | for (var key in pos[type]) {
1085 | var found = false;
1086 |
1087 | for (var i = 0; i < this.history.length; ++i) {
1088 | var point = this.history[i];
1089 | if (typeof point[type] !== 'undefined' && !within(point[type][key], pos[type][key])) {
1090 | found = true;
1091 | break;
1092 | }
1093 | }
1094 |
1095 | if (!found) {
1096 | same[type][key] = true;
1097 | }
1098 | }
1099 | }
1100 |
1101 | var css = { top: '', left: '', right: '', bottom: '' };
1102 |
1103 | var transcribe = function transcribe(_same, _pos) {
1104 | var hasOptimizations = typeof _this6.options.optimizations !== 'undefined';
1105 | var gpu = hasOptimizations ? _this6.options.optimizations.gpu : null;
1106 | if (gpu !== false) {
1107 | var yPos = undefined,
1108 | xPos = undefined;
1109 | if (_same.top) {
1110 | css.top = 0;
1111 | yPos = _pos.top;
1112 | } else {
1113 | css.bottom = 0;
1114 | yPos = -_pos.bottom;
1115 | }
1116 |
1117 | if (_same.left) {
1118 | css.left = 0;
1119 | xPos = _pos.left;
1120 | } else {
1121 | css.right = 0;
1122 | xPos = -_pos.right;
1123 | }
1124 |
1125 | css[transformKey] = 'translateX(' + Math.round(xPos) + 'px) translateY(' + Math.round(yPos) + 'px)';
1126 |
1127 | if (transformKey !== 'msTransform') {
1128 | // The Z transform will keep this in the GPU (faster, and prevents artifacts),
1129 | // but IE9 doesn't support 3d transforms and will choke.
1130 | css[transformKey] += " translateZ(0)";
1131 | }
1132 | } else {
1133 | if (_same.top) {
1134 | css.top = _pos.top + 'px';
1135 | } else {
1136 | css.bottom = _pos.bottom + 'px';
1137 | }
1138 |
1139 | if (_same.left) {
1140 | css.left = _pos.left + 'px';
1141 | } else {
1142 | css.right = _pos.right + 'px';
1143 | }
1144 | }
1145 | };
1146 |
1147 | var moved = false;
1148 | if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
1149 | css.position = 'absolute';
1150 | transcribe(same.page, pos.page);
1151 | } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
1152 | css.position = 'fixed';
1153 | transcribe(same.viewport, pos.viewport);
1154 | } else if (typeof same.offset !== 'undefined' && same.offset.top && same.offset.left) {
1155 | (function () {
1156 | css.position = 'absolute';
1157 | var offsetParent = _this6.cache('target-offsetparent', function () {
1158 | return getOffsetParent(_this6.target);
1159 | });
1160 |
1161 | if (getOffsetParent(_this6.element) !== offsetParent) {
1162 | defer(function () {
1163 | _this6.element.parentNode.removeChild(_this6.element);
1164 | offsetParent.appendChild(_this6.element);
1165 | });
1166 | }
1167 |
1168 | transcribe(same.offset, pos.offset);
1169 | moved = true;
1170 | })();
1171 | } else {
1172 | css.position = 'absolute';
1173 | transcribe({ top: true, left: true }, pos.page);
1174 | }
1175 |
1176 | if (!moved) {
1177 | var offsetParentIsBody = true;
1178 | var currentNode = this.element.parentNode;
1179 | while (currentNode && currentNode.tagName !== 'BODY') {
1180 | if (getComputedStyle(currentNode).position !== 'static') {
1181 | offsetParentIsBody = false;
1182 | break;
1183 | }
1184 |
1185 | currentNode = currentNode.parentNode;
1186 | }
1187 |
1188 | if (!offsetParentIsBody) {
1189 | this.element.parentNode.removeChild(this.element);
1190 | document.body.appendChild(this.element);
1191 | }
1192 | }
1193 |
1194 | // Any css change will trigger a repaint, so let's avoid one if nothing changed
1195 | var writeCSS = {};
1196 | var write = false;
1197 | for (var key in css) {
1198 | var val = css[key];
1199 | var elVal = this.element.style[key];
1200 |
1201 | if (elVal !== '' && val !== '' && ['top', 'left', 'bottom', 'right'].indexOf(key) >= 0) {
1202 | elVal = parseFloat(elVal);
1203 | val = parseFloat(val);
1204 | }
1205 |
1206 | if (elVal !== val) {
1207 | write = true;
1208 | writeCSS[key] = val;
1209 | }
1210 | }
1211 |
1212 | if (write) {
1213 | defer(function () {
1214 | extend(_this6.element.style, writeCSS);
1215 | });
1216 | }
1217 | }
1218 | }]);
1219 |
1220 | return TetherClass;
1221 | })();
1222 |
1223 | TetherClass.modules = [];
1224 |
1225 | TetherBase.position = position;
1226 |
1227 | var Tether = extend(TetherClass, TetherBase);
1228 | /* globals TetherBase */
1229 |
1230 | 'use strict';
1231 |
1232 | var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
1233 |
1234 | var _TetherBase$Utils = TetherBase.Utils;
1235 | var getBounds = _TetherBase$Utils.getBounds;
1236 | var extend = _TetherBase$Utils.extend;
1237 | var updateClasses = _TetherBase$Utils.updateClasses;
1238 | var defer = _TetherBase$Utils.defer;
1239 |
1240 | var BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
1241 |
1242 | function getBoundingRect(tether, to) {
1243 | if (to === 'scrollParent') {
1244 | to = tether.scrollParent;
1245 | } else if (to === 'window') {
1246 | to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
1247 | }
1248 |
1249 | if (to === document) {
1250 | to = to.documentElement;
1251 | }
1252 |
1253 | if (typeof to.nodeType !== 'undefined') {
1254 | (function () {
1255 | var size = getBounds(to);
1256 | var pos = size;
1257 | var style = getComputedStyle(to);
1258 |
1259 | to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
1260 |
1261 | BOUNDS_FORMAT.forEach(function (side, i) {
1262 | side = side[0].toUpperCase() + side.substr(1);
1263 | if (side === 'Top' || side === 'Left') {
1264 | to[i] += parseFloat(style['border' + side + 'Width']);
1265 | } else {
1266 | to[i] -= parseFloat(style['border' + side + 'Width']);
1267 | }
1268 | });
1269 | })();
1270 | }
1271 |
1272 | return to;
1273 | }
1274 |
1275 | TetherBase.modules.push({
1276 | position: function position(_ref) {
1277 | var _this = this;
1278 |
1279 | var top = _ref.top;
1280 | var left = _ref.left;
1281 | var targetAttachment = _ref.targetAttachment;
1282 |
1283 | if (!this.options.constraints) {
1284 | return true;
1285 | }
1286 |
1287 | var _cache = this.cache('element-bounds', function () {
1288 | return getBounds(_this.element);
1289 | });
1290 |
1291 | var height = _cache.height;
1292 | var width = _cache.width;
1293 |
1294 | if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
1295 | var _lastSize = this.lastSize;
1296 |
1297 | // Handle the item getting hidden as a result of our positioning without glitching
1298 | // the classes in and out
1299 | width = _lastSize.width;
1300 | height = _lastSize.height;
1301 | }
1302 |
1303 | var targetSize = this.cache('target-bounds', function () {
1304 | return _this.getTargetBounds();
1305 | });
1306 |
1307 | var targetHeight = targetSize.height;
1308 | var targetWidth = targetSize.width;
1309 |
1310 | var allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
1311 |
1312 | this.options.constraints.forEach(function (constraint) {
1313 | var outOfBoundsClass = constraint.outOfBoundsClass;
1314 | var pinnedClass = constraint.pinnedClass;
1315 |
1316 | if (outOfBoundsClass) {
1317 | allClasses.push(outOfBoundsClass);
1318 | }
1319 | if (pinnedClass) {
1320 | allClasses.push(pinnedClass);
1321 | }
1322 | });
1323 |
1324 | allClasses.forEach(function (cls) {
1325 | ['left', 'top', 'right', 'bottom'].forEach(function (side) {
1326 | allClasses.push(cls + '-' + side);
1327 | });
1328 | });
1329 |
1330 | var addClasses = [];
1331 |
1332 | var tAttachment = extend({}, targetAttachment);
1333 | var eAttachment = extend({}, this.attachment);
1334 |
1335 | this.options.constraints.forEach(function (constraint) {
1336 | var to = constraint.to;
1337 | var attachment = constraint.attachment;
1338 | var pin = constraint.pin;
1339 |
1340 | if (typeof attachment === 'undefined') {
1341 | attachment = '';
1342 | }
1343 |
1344 | var changeAttachX = undefined,
1345 | changeAttachY = undefined;
1346 | if (attachment.indexOf(' ') >= 0) {
1347 | var _attachment$split = attachment.split(' ');
1348 |
1349 | var _attachment$split2 = _slicedToArray(_attachment$split, 2);
1350 |
1351 | changeAttachY = _attachment$split2[0];
1352 | changeAttachX = _attachment$split2[1];
1353 | } else {
1354 | changeAttachX = changeAttachY = attachment;
1355 | }
1356 |
1357 | var bounds = getBoundingRect(_this, to);
1358 |
1359 | if (changeAttachY === 'target' || changeAttachY === 'both') {
1360 | if (top < bounds[1] && tAttachment.top === 'top') {
1361 | top += targetHeight;
1362 | tAttachment.top = 'bottom';
1363 | }
1364 |
1365 | if (top + height > bounds[3] && tAttachment.top === 'bottom') {
1366 | top -= targetHeight;
1367 | tAttachment.top = 'top';
1368 | }
1369 | }
1370 |
1371 | if (changeAttachY === 'together') {
1372 | if (top < bounds[1] && tAttachment.top === 'top') {
1373 | if (eAttachment.top === 'bottom') {
1374 | top += targetHeight;
1375 | tAttachment.top = 'bottom';
1376 |
1377 | top += height;
1378 | eAttachment.top = 'top';
1379 | } else if (eAttachment.top === 'top') {
1380 | top += targetHeight;
1381 | tAttachment.top = 'bottom';
1382 |
1383 | top -= height;
1384 | eAttachment.top = 'bottom';
1385 | }
1386 | }
1387 |
1388 | if (top + height > bounds[3] && tAttachment.top === 'bottom') {
1389 | if (eAttachment.top === 'top') {
1390 | top -= targetHeight;
1391 | tAttachment.top = 'top';
1392 |
1393 | top -= height;
1394 | eAttachment.top = 'bottom';
1395 | } else if (eAttachment.top === 'bottom') {
1396 | top -= targetHeight;
1397 | tAttachment.top = 'top';
1398 |
1399 | top += height;
1400 | eAttachment.top = 'top';
1401 | }
1402 | }
1403 |
1404 | if (tAttachment.top === 'middle') {
1405 | if (top + height > bounds[3] && eAttachment.top === 'top') {
1406 | top -= height;
1407 | eAttachment.top = 'bottom';
1408 | } else if (top < bounds[1] && eAttachment.top === 'bottom') {
1409 | top += height;
1410 | eAttachment.top = 'top';
1411 | }
1412 | }
1413 | }
1414 |
1415 | if (changeAttachX === 'target' || changeAttachX === 'both') {
1416 | if (left < bounds[0] && tAttachment.left === 'left') {
1417 | left += targetWidth;
1418 | tAttachment.left = 'right';
1419 | }
1420 |
1421 | if (left + width > bounds[2] && tAttachment.left === 'right') {
1422 | left -= targetWidth;
1423 | tAttachment.left = 'left';
1424 | }
1425 | }
1426 |
1427 | if (changeAttachX === 'together') {
1428 | if (left < bounds[0] && tAttachment.left === 'left') {
1429 | if (eAttachment.left === 'right') {
1430 | left += targetWidth;
1431 | tAttachment.left = 'right';
1432 |
1433 | left += width;
1434 | eAttachment.left = 'left';
1435 | } else if (eAttachment.left === 'left') {
1436 | left += targetWidth;
1437 | tAttachment.left = 'right';
1438 |
1439 | left -= width;
1440 | eAttachment.left = 'right';
1441 | }
1442 | } else if (left + width > bounds[2] && tAttachment.left === 'right') {
1443 | if (eAttachment.left === 'left') {
1444 | left -= targetWidth;
1445 | tAttachment.left = 'left';
1446 |
1447 | left -= width;
1448 | eAttachment.left = 'right';
1449 | } else if (eAttachment.left === 'right') {
1450 | left -= targetWidth;
1451 | tAttachment.left = 'left';
1452 |
1453 | left += width;
1454 | eAttachment.left = 'left';
1455 | }
1456 | } else if (tAttachment.left === 'center') {
1457 | if (left + width > bounds[2] && eAttachment.left === 'left') {
1458 | left -= width;
1459 | eAttachment.left = 'right';
1460 | } else if (left < bounds[0] && eAttachment.left === 'right') {
1461 | left += width;
1462 | eAttachment.left = 'left';
1463 | }
1464 | }
1465 | }
1466 |
1467 | if (changeAttachY === 'element' || changeAttachY === 'both') {
1468 | if (top < bounds[1] && eAttachment.top === 'bottom') {
1469 | top += height;
1470 | eAttachment.top = 'top';
1471 | }
1472 |
1473 | if (top + height > bounds[3] && eAttachment.top === 'top') {
1474 | top -= height;
1475 | eAttachment.top = 'bottom';
1476 | }
1477 | }
1478 |
1479 | if (changeAttachX === 'element' || changeAttachX === 'both') {
1480 | if (left < bounds[0]) {
1481 | if (eAttachment.left === 'right') {
1482 | left += width;
1483 | eAttachment.left = 'left';
1484 | } else if (eAttachment.left === 'center') {
1485 | left += width / 2;
1486 | eAttachment.left = 'left';
1487 | }
1488 | }
1489 |
1490 | if (left + width > bounds[2]) {
1491 | if (eAttachment.left === 'left') {
1492 | left -= width;
1493 | eAttachment.left = 'right';
1494 | } else if (eAttachment.left === 'center') {
1495 | left -= width / 2;
1496 | eAttachment.left = 'right';
1497 | }
1498 | }
1499 | }
1500 |
1501 | if (typeof pin === 'string') {
1502 | pin = pin.split(',').map(function (p) {
1503 | return p.trim();
1504 | });
1505 | } else if (pin === true) {
1506 | pin = ['top', 'left', 'right', 'bottom'];
1507 | }
1508 |
1509 | pin = pin || [];
1510 |
1511 | var pinned = [];
1512 | var oob = [];
1513 |
1514 | if (top < bounds[1]) {
1515 | if (pin.indexOf('top') >= 0) {
1516 | top = bounds[1];
1517 | pinned.push('top');
1518 | } else {
1519 | oob.push('top');
1520 | }
1521 | }
1522 |
1523 | if (top + height > bounds[3]) {
1524 | if (pin.indexOf('bottom') >= 0) {
1525 | top = bounds[3] - height;
1526 | pinned.push('bottom');
1527 | } else {
1528 | oob.push('bottom');
1529 | }
1530 | }
1531 |
1532 | if (left < bounds[0]) {
1533 | if (pin.indexOf('left') >= 0) {
1534 | left = bounds[0];
1535 | pinned.push('left');
1536 | } else {
1537 | oob.push('left');
1538 | }
1539 | }
1540 |
1541 | if (left + width > bounds[2]) {
1542 | if (pin.indexOf('right') >= 0) {
1543 | left = bounds[2] - width;
1544 | pinned.push('right');
1545 | } else {
1546 | oob.push('right');
1547 | }
1548 | }
1549 |
1550 | if (pinned.length) {
1551 | (function () {
1552 | var pinnedClass = undefined;
1553 | if (typeof _this.options.pinnedClass !== 'undefined') {
1554 | pinnedClass = _this.options.pinnedClass;
1555 | } else {
1556 | pinnedClass = _this.getClass('pinned');
1557 | }
1558 |
1559 | addClasses.push(pinnedClass);
1560 | pinned.forEach(function (side) {
1561 | addClasses.push(pinnedClass + '-' + side);
1562 | });
1563 | })();
1564 | }
1565 |
1566 | if (oob.length) {
1567 | (function () {
1568 | var oobClass = undefined;
1569 | if (typeof _this.options.outOfBoundsClass !== 'undefined') {
1570 | oobClass = _this.options.outOfBoundsClass;
1571 | } else {
1572 | oobClass = _this.getClass('out-of-bounds');
1573 | }
1574 |
1575 | addClasses.push(oobClass);
1576 | oob.forEach(function (side) {
1577 | addClasses.push(oobClass + '-' + side);
1578 | });
1579 | })();
1580 | }
1581 |
1582 | if (pinned.indexOf('left') >= 0 || pinned.indexOf('right') >= 0) {
1583 | eAttachment.left = tAttachment.left = false;
1584 | }
1585 | if (pinned.indexOf('top') >= 0 || pinned.indexOf('bottom') >= 0) {
1586 | eAttachment.top = tAttachment.top = false;
1587 | }
1588 |
1589 | if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== _this.attachment.top || eAttachment.left !== _this.attachment.left) {
1590 | _this.updateAttachClasses(eAttachment, tAttachment);
1591 | }
1592 | });
1593 |
1594 | defer(function () {
1595 | if (!(_this.options.addTargetClasses === false)) {
1596 | updateClasses(_this.target, addClasses, allClasses);
1597 | }
1598 | updateClasses(_this.element, addClasses, allClasses);
1599 | });
1600 |
1601 | return { top: top, left: left };
1602 | }
1603 | });
1604 | /* globals TetherBase */
1605 |
1606 | 'use strict';
1607 |
1608 | var _TetherBase$Utils = TetherBase.Utils;
1609 | var getBounds = _TetherBase$Utils.getBounds;
1610 | var updateClasses = _TetherBase$Utils.updateClasses;
1611 | var defer = _TetherBase$Utils.defer;
1612 |
1613 | TetherBase.modules.push({
1614 | position: function position(_ref) {
1615 | var _this = this;
1616 |
1617 | var top = _ref.top;
1618 | var left = _ref.left;
1619 |
1620 | var _cache = this.cache('element-bounds', function () {
1621 | return getBounds(_this.element);
1622 | });
1623 |
1624 | var height = _cache.height;
1625 | var width = _cache.width;
1626 |
1627 | var targetPos = this.getTargetBounds();
1628 |
1629 | var bottom = top + height;
1630 | var right = left + width;
1631 |
1632 | var abutted = [];
1633 | if (top <= targetPos.bottom && bottom >= targetPos.top) {
1634 | ['left', 'right'].forEach(function (side) {
1635 | var targetPosSide = targetPos[side];
1636 | if (targetPosSide === left || targetPosSide === right) {
1637 | abutted.push(side);
1638 | }
1639 | });
1640 | }
1641 |
1642 | if (left <= targetPos.right && right >= targetPos.left) {
1643 | ['top', 'bottom'].forEach(function (side) {
1644 | var targetPosSide = targetPos[side];
1645 | if (targetPosSide === top || targetPosSide === bottom) {
1646 | abutted.push(side);
1647 | }
1648 | });
1649 | }
1650 |
1651 | var allClasses = [];
1652 | var addClasses = [];
1653 |
1654 | var sides = ['left', 'top', 'right', 'bottom'];
1655 | allClasses.push(this.getClass('abutted'));
1656 | sides.forEach(function (side) {
1657 | allClasses.push(_this.getClass('abutted') + '-' + side);
1658 | });
1659 |
1660 | if (abutted.length) {
1661 | addClasses.push(this.getClass('abutted'));
1662 | }
1663 |
1664 | abutted.forEach(function (side) {
1665 | addClasses.push(_this.getClass('abutted') + '-' + side);
1666 | });
1667 |
1668 | defer(function () {
1669 | if (!(_this.options.addTargetClasses === false)) {
1670 | updateClasses(_this.target, addClasses, allClasses);
1671 | }
1672 | updateClasses(_this.element, addClasses, allClasses);
1673 | });
1674 |
1675 | return true;
1676 | }
1677 | });
1678 | /* globals TetherBase */
1679 |
1680 | 'use strict';
1681 |
1682 | var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } }; })();
1683 |
1684 | TetherBase.modules.push({
1685 | position: function position(_ref) {
1686 | var top = _ref.top;
1687 | var left = _ref.left;
1688 |
1689 | if (!this.options.shift) {
1690 | return;
1691 | }
1692 |
1693 | var shift = this.options.shift;
1694 | if (typeof this.options.shift === 'function') {
1695 | shift = this.options.shift.call(this, { top: top, left: left });
1696 | }
1697 |
1698 | var shiftTop = undefined,
1699 | shiftLeft = undefined;
1700 | if (typeof shift === 'string') {
1701 | shift = shift.split(' ');
1702 | shift[1] = shift[1] || shift[0];
1703 |
1704 | var _shift = shift;
1705 |
1706 | var _shift2 = _slicedToArray(_shift, 2);
1707 |
1708 | shiftTop = _shift2[0];
1709 | shiftLeft = _shift2[1];
1710 |
1711 | shiftTop = parseFloat(shiftTop, 10);
1712 | shiftLeft = parseFloat(shiftLeft, 10);
1713 | } else {
1714 | shiftTop = shift.top;
1715 | shiftLeft = shift.left;
1716 | }
1717 |
1718 | top += shiftTop;
1719 | left += shiftLeft;
1720 |
1721 | return { top: top, left: left };
1722 | }
1723 | });
1724 | return Tether;
1725 |
1726 | }));
1727 |
--------------------------------------------------------------------------------
/client/imports/my.css:
--------------------------------------------------------------------------------
1 | .my-import-test {
2 | color: red;
3 | }
--------------------------------------------------------------------------------
/client/main.css:
--------------------------------------------------------------------------------
1 | // here we import bootstrap.scss from node_modules/bootstrap/scss
2 | // we can ommit .scss extension because of postcss-easy-import extensions option
3 | // see package.json file for details
4 | @import 'bootstrap';
5 |
6 | // you can still import standard css files
7 | // just add .import.css extension or place it in 'imports' directory
8 | @import './imports/my';
9 | @import './my2';
10 |
11 | // test of a scss-like comment
12 | // this is possible because of postcss-scss parser
13 | .carousel {
14 | max-width: 640px;
15 | margin: 0 auto;
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/client/main.html:
--------------------------------------------------------------------------------
1 |
You've pressed the button {{counter}} times.
16 |