braid-blob 0.0.65 → 0.0.67
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.
- package/img-live-demo.html +1 -1
- package/img-live.js +46 -42
- package/package.json +1 -1
package/img-live-demo.html
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
<h1>Braid-Blob Live Image Demo</h1>
|
|
27
27
|
<p>This image updates in real-time across all connected clients.</p>
|
|
28
28
|
|
|
29
|
-
<img live droppable src="/blob.png"
|
|
29
|
+
<img live droppable src="/blob.png">
|
|
30
30
|
|
|
31
31
|
<script src="https://unpkg.com/braid-http@~1.3/braid-http-client.js"></script>
|
|
32
32
|
<script src="client.js"></script>
|
package/img-live.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// Braid-Blob Live Images
|
|
2
2
|
// requires client.js
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
;(function() {
|
|
5
|
+
|
|
6
|
+
var live_images = new Map() // img -> ac
|
|
5
7
|
|
|
6
8
|
function sync(img) {
|
|
7
9
|
var url = img.src
|
|
@@ -17,57 +19,54 @@ function sync(img) {
|
|
|
17
19
|
var blob = new Blob([body], { type: content_type || 'image/png' })
|
|
18
20
|
img.src = URL.createObjectURL(blob)
|
|
19
21
|
},
|
|
22
|
+
on_delete: () => {
|
|
23
|
+
img.src = URL.createObjectURL(new Blob([]))
|
|
24
|
+
},
|
|
20
25
|
on_error: (error) => {
|
|
21
26
|
console.error('Live image error for', url, error)
|
|
22
27
|
}
|
|
23
28
|
})
|
|
24
|
-
live_images.set(img,
|
|
25
|
-
|
|
26
|
-
if (img.hasAttribute('droppable'))
|
|
27
|
-
make_droppable(img)
|
|
28
|
-
}
|
|
29
|
+
live_images.set(img, ac)
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function make_droppable(img) {
|
|
39
|
-
img.addEventListener('dragenter', function(e) {
|
|
40
|
-
img.style.outline = '3px dashed #007bff'
|
|
41
|
-
img.style.outlineOffset = '3px'
|
|
42
|
-
})
|
|
31
|
+
if (img.hasAttribute('droppable')) {
|
|
32
|
+
img.addEventListener('dragenter', function() {
|
|
33
|
+
img.style.outline = '3px dashed #007bff'
|
|
34
|
+
img.style.outlineOffset = '3px'
|
|
35
|
+
})
|
|
43
36
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
37
|
+
img.addEventListener('dragleave', function() {
|
|
38
|
+
img.style.outline = ''
|
|
39
|
+
img.style.outlineOffset = ''
|
|
40
|
+
})
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
img.addEventListener('dragover', function(e) {
|
|
43
|
+
e.preventDefault()
|
|
44
|
+
e.dataTransfer.dropEffect = 'copy'
|
|
45
|
+
})
|
|
53
46
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
img.addEventListener('drop', function(e) {
|
|
48
|
+
e.preventDefault()
|
|
49
|
+
img.style.outline = ''
|
|
50
|
+
img.style.outlineOffset = ''
|
|
58
51
|
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
var file = e.dataTransfer.files[0]
|
|
53
|
+
if (!file || !file.type.startsWith('image/')) return
|
|
61
54
|
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
var reader = new FileReader()
|
|
56
|
+
reader.onload = function() {
|
|
57
|
+
client.update(reader.result, file.type)
|
|
58
|
+
}
|
|
59
|
+
reader.readAsArrayBuffer(file)
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
}
|
|
64
63
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
64
|
+
function unsync(img) {
|
|
65
|
+
var ac = live_images.get(img)
|
|
66
|
+
if (ac) {
|
|
67
|
+
ac.abort()
|
|
68
|
+
live_images.delete(img)
|
|
69
|
+
}
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
var observer = new MutationObserver(function(mutations) {
|
|
@@ -87,6 +86,9 @@ var observer = new MutationObserver(function(mutations) {
|
|
|
87
86
|
}
|
|
88
87
|
})
|
|
89
88
|
if (mutation.type === 'attributes' && mutation.target.tagName === 'IMG') {
|
|
89
|
+
// Ignore src changes to blob: URLs (our own updates)
|
|
90
|
+
if (mutation.attributeName === 'src' && mutation.target.src.startsWith('blob:'))
|
|
91
|
+
return
|
|
90
92
|
if (mutation.target.hasAttribute('live'))
|
|
91
93
|
sync(mutation.target)
|
|
92
94
|
else if (mutation.attributeName === 'live')
|
|
@@ -105,8 +107,10 @@ function init() {
|
|
|
105
107
|
childList: true,
|
|
106
108
|
subtree: true,
|
|
107
109
|
attributes: true,
|
|
108
|
-
attributeFilter: ['live', 'droppable']
|
|
110
|
+
attributeFilter: ['live', 'droppable', 'src']
|
|
109
111
|
})
|
|
110
112
|
|
|
111
113
|
document.querySelectorAll('img[live]').forEach(sync)
|
|
112
114
|
}
|
|
115
|
+
|
|
116
|
+
})()
|