diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..7e45dcf --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +github: marcj diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..4f29079 --- /dev/null +++ b/.npmignore @@ -0,0 +1,2 @@ +.idea +tests diff --git a/Gruntfile.js b/Gruntfile.js deleted file mode 100644 index 265a0de..0000000 --- a/Gruntfile.js +++ /dev/null @@ -1,16 +0,0 @@ -/* jshint node: true */ -module.exports = function(grunt) { - 'use strict'; - - grunt.loadNpmTasks('grunt-bump'); - - grunt.initConfig({ - bump: { - options: { - files: ['package.json', 'bower.json'], - commitFiles: ['package.json', 'bower.json'], - pushTo: 'origin' - } - } - }); -}; diff --git a/README.md b/README.md index 8b361f5..61c88f5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -CSS Element Queries -=================== +# CSS Element Queries + [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/marcj/css-element-queries?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) @@ -13,45 +13,61 @@ Features: - no performance issues since it listens only on size changes of elements that have element query rules defined through css. Other element query polifills only listen on `window.onresize` which causes performance issues and allows only to detect changes via window.resize event and not inside layout changes like css3 animation, :hover, DOM changes etc. - no interval/timeout detection. Truly event-based through integrated ResizeSensor class. + - automatically discovers new DOM elements. No need to call javascript manually. - no CSS modifications. Valid CSS Syntax - - all CSS selectors available. Uses regular attribute selector. No need to write rules in HTML. - - supports and tested in webkit, gecko and IE(7/8/9/10/11). + - all CSS selectors available. Uses regular attribute selector. No need to write rules in HTML/JS. + - supports and tested in webkit, gecko and IE(10+) - `min-width`, `min-height`, `max-width` and `max-height` are supported so far - works with any layout modifications: HTML (innerHTML etc), inline styles, DOM mutation, CSS3 transitions, fluid layout changes (also percent changes), pseudo classes (:hover etc.), window resizes and more - no Javascript-Framework dependency (works with jQuery, Mootools, etc.) + - Works beautiful for responsive images without FOUC More demos and information: http://marcj.github.io/css-element-queries/ -Example -------- +## Examples + +### Element Query ```css -.widget-name { - padding: 25px; +.widget-name h2 { + font-size: 12px; } -.widget-name[max-width="200px"] { - padding: 0; + +.widget-name[min-width~="400px"] h2 { + font-size: 18px; } -.widget-name[min-width="500px"] { + +.widget-name[min-width~="600px"] h2 { padding: 55px; + text-align: center; + font-size: 24px; } -/* responsive images */ -.responsive-image img { - width: 100%; +.widget-name[min-width~="700px"] h2 { + font-size: 34px; + color: red; } +``` -.responsive-image[max-width^='400px'] img { - content: url(demo/image-400px.jpg); -} +As you can see we use the `~=` [attribute selector](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors). +Since this css-element-queries polyfill adds new element attributes on the DOM element +(`
`) depending on your actual CSS and element's dimension, +you should always use this attribute selector (especially if you have several element query rules on the same element). -.responsive-image[max-width^='1000px'] img { - content: url(demo/image-1000px.jpg); -} +```html +
+

Element responsiveness FTW!

+
+``` -.responsive-image[min-width='1000px'] img { - content: url(demo/image-full.jpg); -} +### Responsive image + +```html +
+ + + +
``` Include the javascript files at the bottom and you're good to go. No custom javascript calls needed. @@ -61,13 +77,36 @@ Include the javascript files at the bottom and you're good to go. No custom java ``` -Issues ------- +## See it in action: + +Here live http://marcj.github.io/css-element-queries/. + +![Demo](http://marcj.github.io/css-element-queries/images/css-element-queries-demo.gif) + + +## Module Loader + +If you're using a module loader you need to trigger the event listening or initialization yourself: + +```javascript +var ElementQueries = require('css-element-queries/src/ElementQueries'); + + //attaches to DOMLoadContent +ElementQueries.listen(); + +//or if you want to trigger it yourself. +// Parse all available CSS and attach ResizeSensor to those elements which have rules attached +// (make sure this is called after 'load' event, because CSS files are not ready when domReady is fired. +ElementQueries.init(); +``` + +## Issues - So far does not work on `img` and other elements that can't contain other elements. Wrapping with a `div` works fine though (See demo). - Adds additional hidden elements into selected target element and forces target element to be relative or absolute. + - Local stylesheets do not work (using `file://` protocol). + - If you have rules on an element that has a css animation, also add `element-queries`. E.g. `.widget-name { animation: 2sec my-animation, 1s element-queries;}`. We use this to detect new added DOM elements automatically. +## License -License -------- -MIT license. Copyright [Marc J. Schmidt](http://marcjschmidt.de/). +MIT license. Copyright [Marc J. Schmidt](https://twitter.com/MarcJSchmidt). diff --git a/bower.json b/bower.json deleted file mode 100644 index b25b96f..0000000 --- a/bower.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "css-element-queries", - "version": "0.3.0", - "main": [ - "./src/ElementQueries.js", - "./src/ResizeSensor.js" - ], - "ignore": [ - "**/.*", - "_*", - "Gruntfile.js", - "composer.json", - "package.json", - "*.html" - ], - "dependencies": { - } -} - diff --git a/css-element-queries.d.ts b/css-element-queries.d.ts new file mode 100644 index 0000000..3fe0706 --- /dev/null +++ b/css-element-queries.d.ts @@ -0,0 +1,2 @@ +export { ResizeSensor, ResizeSensorCallback, Size } from "./src/ResizeSensor"; +export { ElementQueries } from './src/ElementQueries'; \ No newline at end of file diff --git a/index.js b/index.js index 4d7bd83..6f5145b 100644 --- a/index.js +++ b/index.js @@ -1,2 +1,4 @@ -require('./src/ResizeSensor'); -require('./src/ElementQueries'); +module.exports = { + ResizeSensor: require('./src/ResizeSensor'), + ElementQueries: require('./src/ElementQueries') +}; diff --git a/package.json b/package.json index ec54cf1..964230f 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,9 @@ { "name": "css-element-queries", - "version": "0.3.0", - "description": "CSS-Element-Queries Polyfill. proof-of-concept for high-speed element dimension/media queries in valid css.", + "version": "1.2.3", + "description": "CSS-Element-Queries Polyfill. Proof-of-concept for high-speed element dimension/media queries in valid css.", "main": "index.js", + "typings": "css-element-queries.d.ts", "directories": { "test": "test" }, diff --git a/src/ElementQueries.d.ts b/src/ElementQueries.d.ts new file mode 100644 index 0000000..00c5d93 --- /dev/null +++ b/src/ElementQueries.d.ts @@ -0,0 +1,14 @@ +export declare class ElementQueries { + /** + * Attaches to DOMLoadContent + */ + static listen(): void; + + /** + * Parses all available CSS and attach ResizeSensor to those elements which have rules attached. + * Make sure this is called after 'load' event, because CSS files are not ready when domReady is fired. + */ + static init(): void; +} + +export default ElementQueries; diff --git a/src/ElementQueries.js b/src/ElementQueries.js index 2e4b566..4fe4298 100755 --- a/src/ElementQueries.js +++ b/src/ElementQueries.js @@ -1,19 +1,35 @@ +'use strict'; + /** * Copyright Marc J. Schmidt. See the LICENSE file at the top-level * directory of this distribution and at * https://github.com/marcj/css-element-queries/blob/master/LICENSE. */ -; -(function() { +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(['./ResizeSensor.js'], factory); + } else if (typeof exports === "object") { + module.exports = factory(require('./ResizeSensor.js')); + } else { + root.ElementQueries = factory(root.ResizeSensor); + root.ElementQueries.listen(); + } +}(typeof window !== 'undefined' ? window : this, function (ResizeSensor) { + /** * * @type {Function} * @constructor */ - var ElementQueries = this.ElementQueries = function() { + var ElementQueries = function () { + // - - - Drag the gray line at the right to see it in action. -
-
-
-

Demo 1

- This is content from the first responsive demo without media queries. It uses the element queries provided by this library. -
-
-
-
-

Demo 2

-
- Box -
-
- First 1/2 box -
-
- Second 1/2 box -
-
-
-
-
-
-

Demo 3 - width

-
- This box is animated through css transitions. - We attached a resize-listener to this box. See below. -
-
- No changes. -
-
-
-
-
-

Demo 4 - height

-
- This box is animated through css transitions. - We attached a resize-listener to this box. See below. -
-
- No changes. -
-
-
- -
-
-
- 0 changes -
-
-
- - - -
- - - - -
-
-
- -
- diff --git a/tests/demo.css b/tests/demo.css new file mode 100644 index 0000000..73ba7f3 --- /dev/null +++ b/tests/demo.css @@ -0,0 +1,425 @@ +@import url(https://fonts.googleapis.com/css?family=Lato:400,700,300); + + +* { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; +} + +html, body { + background-color: #f9f9f9; + padding: 0; + margin: 0; + text-align: center; + -webkit-font-smoothing: antialiased; + text-rendering: geometricPrecision; + font-family: 'Lato', sans-serif; + font-weight: 400; + font-size: 18px; + line-height: 26px; + color: #444; +} + +textarea { + width: 100%; + height: 80px; +} + +.wrapper { + background-color: #ffffff; + max-width: 1000px; + margin: auto; + text-align: left; + padding: 30px 20px; + box-shadow: 0px 0px 10px #c8cac5; +} + +.download-buttons { + padding-top: 20px; + padding-bottom: 20px; + text-align: right; +} + +.wrapper h1:first-child { + margin-top: 0; +} + +footer { + padding: 25px 0; +} + +h1 { + font-weight: 300; + padding-bottom: 25px; +} + +h1.sub, h2.sub { + padding-top: 10px; + font-size: 22px; + color: #888; +} + +h2 { + padding-bottom: 20px; + font-weight: 300; +} + +p.seperator { + padding-top: 30px; + border-bottom: 1px solid #e6e6e6; + margin-bottom: 30px; +} + +.text-panel { + margin: auto; + text-align: left; + max-width: 780px; + + font-size: 16px; + color: #444; + line-height: 26px; +} + +.text-panel:first-child { + padding-top: 30px; + } + + +.text-panel p.seperator { + padding-top: 30px; + border-bottom: 1px solid #e6e6e6; + margin-bottom: 30px; +} + +.code { + width: 50%; + float: left; + text-align: left; + margin: auto; + font-size: 13px; + line-height: 15px; + position: relative; + margin-top: 20px; + padding: 0 25px; + margin-bottom: 15px; +} + +.code .CodeMirror { + border: 1px solid #e8e8e8; + border-radius: 5px; + height: auto; +} + +.code-full { + float: none; + width: 80%; + margin-left: auto; + margin-right: auto; + padding: 0; +} + +.example-desc { + text-align: center; +} + +.example { + text-align: center; + margin: 100px auto; + + padding-bottom: 100px; + border-bottom: 1px solid #e6e6e6; +} + +.examplesResizerDemos, +.examplesResizerDemosXY { + background-color: #dae3e8; + width: 550px; + margin: 15px auto; + padding: 15px 0; + border-radius: 5px; + position: relative; +} + +.examplesResizerDemosXY { + height: 150px; +} + +.examplesResizerDemos h2 { + font-size: 20px; +} + +.resizerDemo-info { + position: absolute; + right: 23px; + top: 0; + color: #333; + font-size: 13px; + line-height: 15px; + font-family: monospace; +} + +.bash { + border-radius: 3px; + border: 1px solid #eee; + margin: 15px; + padding: 5px; + font-size: 14px; + width: 80%; + margin-left: auto; + margin-right: auto; + font-family: monospace; +} + + +.resizerDemo-handler { + position: absolute; + right: 0; + top: 0; + bottom: 0; + width: 20px; + padding: 0 1px; + background-color: gray; + cursor: ew-resize; + line-height: 5px; + font-size: 14px; +} + +.resizerDemo-handler:before { + content: '• • •'; + color: white; + width: 10px; + position: absolute; + top: 50%; + left: 5px; + font-weight: 300; + line-height: 6px; + font-size: 11px; + text-align: center; + margin-top: -15px; +} + +.breaker { + clear: both; +} + +.example-2 { + border: 1px solid silver; + background-color: #eee; +} + +.example-2-first, +.example-2-second { + background-color: black; + color: white; + padding: 2px; + width: 50%; + float: left; + border: 5px solid #eee; +} + +.example-2-second { + float: right; +} + +.example-2-box { + color: white; + margin: 5px; + padding: 2px; +} + +.example-3, +.example-4 { + border: 1px solid silver; + margin: 25px; + background-color: #eee; +} + +#example-5 { + overflow: visible; + position: relative; + text-align: center; +} + +#example-3-box, +#example-4-box { + background-color: gray; + color: white; + margin: auto; + width: 50%; + padding: 50px; +} + +.example-3-box-start, +.example-4-box-start { + animation-duration: 3s; + -moz-animation-duration: 3s; + -webkit-animation-duration: 3s; + -moz-animation-name: anim; + animation-name: anim; + -webkit-animation-name: anim; + animation-iteration-count: infinite; + -webkit-animation-iteration-count: infinite; +} + +.example-4-box-start { + -moz-animation-name: animHeight; + animation-name: animHeight; + -webkit-animation-name: animHeight; +} + +#example-3-log, +#example-4-log { + background-color: white; + padding: 2px; + margin: 5px; +} + +@keyframes anim { + 0% { + padding: 50px; + width: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + width: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + width: 50%; + background-color: gray; + } +} + +@-webkit-keyframes anim { + 0% { + padding: 50px; + width: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + width: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + width: 50%; + background-color: gray; + } +} + +@-moz-keyframes anim { + 0% { + padding: 50px; + width: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + width: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + width: 50%; + background-color: gray; + } +} + +@keyframes animHeight { + 0% { + padding: 50px; + height: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + height: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + height: 50%; + background-color: gray; + } +} + +@-webkit-keyframes animHeight { + 0% { + padding: 50px; + height: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + height: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + height: 50%; + background-color: gray; + } +} + +@-moz-keyframes animHeight { + 0% { + padding: 50px; + height: 50%; + background-color: gray; + } + + 50% { + padding: 10px; + height: 40%; + background-color: #806522; + } + + 100% { + padding: 50px; + height: 50%; + background-color: gray; + } +} + +.dynamicElement { + margin: 50px; + width: 50px; + + -moz-animation-name: animHeight; + animation-name: animHeight; + -webkit-animation-name: animHeight; + + animation-duration: 3s; + -moz-animation-duration: 3s; + -webkit-animation-duration: 3s; + animation-iteration-count: infinite; + -webkit-animation-iteration-count: infinite; + + display: inline-block; + border: 1px solid #eee; + background-color: #f9f9f9; +} + +.dynamic { + margin: 15px; + text-align: center; +} + +.dynamic .input-group { + width: 500px; + margin: auto; +} \ No newline at end of file diff --git a/tests/demo.html b/tests/demo.html new file mode 100644 index 0000000..22968f0 --- /dev/null +++ b/tests/demo.html @@ -0,0 +1,425 @@ + + + + + + + + Css-element-queries Demo + + + + + + + + + + + + + + + + + +
+

+

Examples +
+ Drag the gray line at the right to see it in action. +
+

+
+
+
+

Responsive Text

+
+
+
+

Element responsiveness FTW!

+
+ + + + +
+

Element detachable

+
+ + + +
+

Dynamic element {{id}}

+
+ + +
+
+
+ +
+
+ +
+
+
+
+

Responsive Image

+
+
+
+ + + +
+ + The image above has a default of 700px. Shrink or expend the container too see responsive image + working. + Thanks @placehold.it +
+
+
+ +
+
+
+
+

Responsive Widget

+
+
+

Demo 1

+ This is content from the first responsive demo without media queries. It uses the element + queries + provided by this library. +
+
+ +
+ +
+
+ +
+
+
+ +
+

Responsive Layout

+
+
+

Demo 2

+
+ Box +
+
+ First 1/2 box +
+
+ Second 1/2 box +
+
+
+
+
+ +
+
+ +
+
+
+
+

Responsive Animation

+
+
+

Demo 3 - width + +

+
+ This box is animated through css transitions. + We attached a resize-listener to this box. See below. +
+
+ No changes. +
+
+
+
+
+

Demo 4 - height + +

+
+ This box is animated through css transitions. + We attached a resize-listener to this box. See below. +
+
+ No changes. +
+
+
+
+ +
+

ResizeSensor Demo

+
+
+
+ 0 changes +
+
+
+
+ CSS-Element-Queries comes with a Javascript ResizeSensor class you can use in Javascript directly. +
+ +
+
+
+ +
+

Invisible Demo

+
+
+ Press button to show. +
+ This should be red. +
+
+
+
+ + +
+
+ +
+

Performance Demo

+
+
+ Performance Test: + + + + + + + +
+
+
+
+
+
+
+
+ diff --git a/tests/demo.js b/tests/demo.js new file mode 100644 index 0000000..e4899a1 --- /dev/null +++ b/tests/demo.js @@ -0,0 +1,135 @@ +$(document).ready(function () { + console.log('ready'); + + // $("textarea.html").each(function(idx, textarea) { + // CodeMirror.fromTextArea(textarea, { + // lineNumbers: true, + // mode: "htmlmixed", + // readOnly: true + // }); + // }); + // + // $("textarea.css").each(function(idx, textarea) { + // CodeMirror.fromTextArea(textarea, { + // lineNumbers: true, + // mode: "css", + // readOnly: true + // }); + // }); + // + // $("textarea.javascript").each(function(idx, textarea) { + // CodeMirror.fromTextArea(textarea, { + // lineNumbers: true, + // mode: "javascript", + // readOnly: true + // }); + // }); +}); + +function ResizerDemo(element) { + element = $(element); + var handler = $('
'); + var info = $('
'); + + element.append(handler); + element.append(info); + + var hammer = new Hammer(element[0], {recognizers: [ + [Hammer.Pan, { threshold: 0}] + ]}); + + var startWidth; + element.on('mousedown', function(e){ + e.preventDefault(); + }); + hammer.on('panstart', function(e) { + startWidth = element[0].clientWidth; + }); + + hammer.on('panmove', function(e) { + element[0].style.width = (startWidth + e.deltaX) + 'px'; + info.html(element[0].clientWidth + 'px x ' + element[0].clientHeight + 'px'); + }) +} + +$( document ).ready(function(){ + $('.examplesResizerDemos').each(function(idx, element){ + new ResizerDemo(element); + }); + + perfTest(); + example3(); + example4(); + example5(); +}); + +function perfTest(){ + var container = $('#dynamicContainer'); + var dynamicCount = $('#dynamicCount'); + var dynamicCounter = $('#dynamicCounter'); + + window.detachDynamic = function() { + container.children().each(function(idx, element) { + ResizeSensor.detach(element); + }); + }; + + window.removeDynamic = function() { + container.html(''); + }; + + window.addDynamic = function() { + container.html(''); + var i = 0, to = dynamicCount.val(), div, counter = 0; + for (; i < to; i++) { + div = $('
#'+i+'
'); + container.append(div); + + new ResizeSensor(div, function(){ + counter++; + dynamicCounter.html(counter + ' changes.'); + }); + } + } +} + +function example3(){ + var logger = $('#example-3-log'); + var box = $('#example-3-box'); + + $('#startStop3').on('click', function(){ + if (box.hasClass('example-3-box-start')) { + box.removeClass('example-3-box-start'); + } else { + box.addClass('example-3-box-start'); + } + }); + new ResizeSensor(box, function(el){ + logger.html('Changed to ' + box[0].clientWidth+'px width.'); + }); + +} + +function example4(){ + var logger = $('#example-4-log'); + var box = $('#example-4-box'); + + $('#startStop4').on('click', function(){ + if (box.hasClass('example-4-box-start')) { + box.removeClass('example-4-box-start'); + } else { + box.addClass('example-4-box-start'); + } + }); + new ResizeSensor(box, function(){ + logger.html('Changed to ' + box[0].clientHeight+'px height.'); + }); +} + +function example5(){ + var box = $('#example-5'); + var changed = 0; + new ResizeSensor(box.parent(), function(){ + box[0].innerHTML = (++changed) + ' changes. ' + box.parent()[0].clientWidth+'px/'+box.parent()[0].clientHeight+'px'; + }); +} \ No newline at end of file diff --git a/tests/late-trigger.html b/tests/late-trigger.html new file mode 100644 index 0000000..71a2b17 --- /dev/null +++ b/tests/late-trigger.html @@ -0,0 +1,48 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/tests/mutation/app.js b/tests/mutation/app.js new file mode 100644 index 0000000..2100612 --- /dev/null +++ b/tests/mutation/app.js @@ -0,0 +1,75 @@ +var __values = (this && this.__values) || function (o) { + var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; + if (m) return m.call(o); + return { + next: function () { + if (o && i >= o.length) o = void 0; + return { value: o && o[i++], done: !o }; + } + }; +}; +var e_1, _a, e_2, _b; +var state = { + dragged: null +}; +var i = 0; +try { + for (var _c = __values(document.getElementsByClassName('drag')), _d = _c.next(); !_d.done; _d = _c.next()) { + var item = _d.value; + i++; + item.setAttribute('draggable', 'true'); + item.setAttribute('id', 'drag-' + i); + (function (element) { + var title = 'Drag me #' + i; + element.setAttribute('data-label', title); + new ResizeSensor(element, function (size) { + element.setAttribute('data-label', title + " (" + size.width + "x" + size.height + ")"); + }); + })(item); + item.addEventListener('dragstart', function (event) { + state.dragged = event.target; + event.dataTransfer.setData('text', 'thanks firefox'); + event.dataTransfer.dropEffect = 'move'; + }); + } +} +catch (e_1_1) { e_1 = { error: e_1_1 }; } +finally { + try { + if (_d && !_d.done && (_a = _c.return)) _a.call(_c); + } + finally { if (e_1) throw e_1.error; } +} +var _loop_1 = function (item) { + (function (element) { + item.addEventListener('drop', function (event) { + event.preventDefault(); + item.classList.remove('drag-hover'); + state.dragged.parentNode.removeChild(state.dragged); + element.appendChild(state.dragged); + state.dragged = null; + }); + })(item); + item.addEventListener('dragleave', function (event) { + item.classList.remove('drag-hover'); + }); + item.addEventListener('dragover', function (event) { + item.classList.add('drag-hover'); + }); + item.addEventListener('dragover', function (event) { + event.preventDefault(); + }); +}; +try { + for (var _e = __values(document.getElementsByClassName('container')), _f = _e.next(); !_f.done; _f = _e.next()) { + var item = _f.value; + _loop_1(item); + } +} +catch (e_2_1) { e_2 = { error: e_2_1 }; } +finally { + try { + if (_f && !_f.done && (_b = _e.return)) _b.call(_e); + } + finally { if (e_2) throw e_2.error; } +} diff --git a/tests/mutation/app.ts b/tests/mutation/app.ts new file mode 100644 index 0000000..15974f7 --- /dev/null +++ b/tests/mutation/app.ts @@ -0,0 +1,56 @@ +declare const ResizeSensor; + +const state: { + dragged: Element +} = { + dragged: null +}; + +let i = 0; + +for (const item of document.getElementsByClassName('drag')) { + i++; + item.setAttribute('draggable', 'true'); + item.setAttribute('id', 'drag-' + i); + + (element => { + const title = 'Drag me #' + i; + element.setAttribute('data-label', title); + + new ResizeSensor(element, (size) => { + element.setAttribute('data-label', `${title} (${size.width}x${size.height})`); + }); + })(item); + + item.addEventListener('dragstart', (event: DragEvent) => { + state.dragged = event.target; + event.dataTransfer.setData('text', 'thanks firefox'); + event.dataTransfer.dropEffect = 'move'; + }); +} + +for (const item of document.getElementsByClassName('container')) { + (element => { + item.addEventListener('drop', (event) => { + event.preventDefault(); + item.classList.remove('drag-hover'); + + state.dragged.parentNode.removeChild(state.dragged); + element.appendChild(state.dragged); + + state.dragged = null; + }); + })(item); + + item.addEventListener('dragleave', (event) => { + item.classList.remove('drag-hover'); + }); + + item.addEventListener('dragover', (event) => { + item.classList.add('drag-hover'); + }); + + item.addEventListener('dragover', (event) => { + event.preventDefault(); + }); +} diff --git a/tests/mutation/index.html b/tests/mutation/index.html new file mode 100644 index 0000000..6d2ddce --- /dev/null +++ b/tests/mutation/index.html @@ -0,0 +1,76 @@ + + + + + + + + +
+
+
+
+ +
+
+
+
+ + + \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..7b56f0e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "compilerOptions": { + "target": "es5", + "downlevelIteration": true, + "lib" : ["dom","es6","dom.iterable","scripthost", "es2015.iterable", "es2015.collection"] + } +} \ No newline at end of file