Skip to content

Commit

Permalink
Merge pull request #3927 from MattiasBuelens/video-bindings
Browse files Browse the repository at this point in the history
Add bindings for HTMLVideoElement.videoWidth and videoHeight
  • Loading branch information
Rich-Harris committed Nov 15, 2019
2 parents 05cf649 + 51c1ade commit 927fcbf
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 8 deletions.
4 changes: 3 additions & 1 deletion src/compiler/compile/nodes/Binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ const read_only_media_attributes = new Set([
'seekable',
'played',
'seeking',
'ended'
'ended',
'videoHeight',
'videoWidth'
]);

export default class Binding extends Node {
Expand Down
10 changes: 10 additions & 0 deletions src/compiler/compile/nodes/Element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,16 @@ export default class Element extends Node {
message: `'${name}' binding can only be used with <audio> or <video>`
});
}
} else if (
name === 'videoHeight' ||
name === 'videoWidth'
) {
if (this.name !== 'video') {
component.error(binding, {
code: `invalid-binding`,
message: `'${name}' binding can only be used with <video>`
});
}
} else if (dimensions.test(name)) {
if (this.name === 'svg' && (name === 'offsetWidth' || name === 'offsetHeight')) {
component.error(binding, {
Expand Down
12 changes: 9 additions & 3 deletions src/compiler/compile/render_dom/wrappers/Element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const events = [
},

{
event_names: ['resize'],
event_names: ['elementresize'],
filter: (_node: Element, name: string) =>
dimensions.test(name)
},
Expand Down Expand Up @@ -112,6 +112,12 @@ const events = [
node.is_media_node() &&
name === 'ended'
},
{
event_names: ['resize'],
filter: (node: Element, name: string) =>
node.is_media_node() &&
(name === 'videoHeight' || name === 'videoWidth')
},

// details event
{
Expand Down Expand Up @@ -536,7 +542,7 @@ export default class ElementWrapper extends Wrapper {
`);

group.events.forEach(name => {
if (name === 'resize') {
if (name === 'elementresize') {
// special case
const resize_listener = block.get_unique_name(`${this.var.name}_resize_listener`);
block.add_variable(resize_listener);
Expand Down Expand Up @@ -578,7 +584,7 @@ export default class ElementWrapper extends Wrapper {
);
}

if (group.events[0] === 'resize') {
if (group.events[0] === 'elementresize') {
block.chunks.hydrate.push(
b`@add_render_callback(() => ${callee}.call(${this.var}));`
);
Expand Down
8 changes: 4 additions & 4 deletions test/js/samples/bind-width-height/expected.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ function create_fragment(ctx) {
c() {
div = element("div");
div.textContent = "some content";
add_render_callback(() => ctx.div_resize_handler.call(div));
add_render_callback(() => ctx.div_elementresize_handler.call(div));
},
m(target, anchor) {
insert(target, div, anchor);
div_resize_listener = add_resize_listener(div, ctx.div_resize_handler.bind(div));
div_resize_listener = add_resize_listener(div, ctx.div_elementresize_handler.bind(div));
},
p: noop,
i: noop,
Expand All @@ -39,7 +39,7 @@ function instance($$self, $$props, $$invalidate) {
let { w } = $$props;
let { h } = $$props;

function div_resize_handler() {
function div_elementresize_handler() {
w = this.offsetWidth;
h = this.offsetHeight;
$$invalidate("w", w);
Expand All @@ -51,7 +51,7 @@ function instance($$self, $$props, $$invalidate) {
if ("h" in $$props) $$invalidate("h", h = $$props.h);
};

return { w, h, div_resize_handler };
return { w, h, div_elementresize_handler };
}

class Component extends SvelteComponent {
Expand Down
121 changes: 121 additions & 0 deletions test/js/samples/video-bindings/expected.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* generated by Svelte vX.Y.Z */
import {
SvelteComponent,
add_render_callback,
add_resize_listener,
detach,
element,
init,
insert,
listen,
noop,
raf,
run_all,
safe_not_equal
} from "svelte/internal";

function create_fragment(ctx) {
let video;
let video_updating = false;
let video_resize_listener;
let video_animationframe;
let dispose;

function video_timeupdate_handler() {
cancelAnimationFrame(video_animationframe);

if (!video.paused) {
video_animationframe = raf(video_timeupdate_handler);
video_updating = true;
}

ctx.video_timeupdate_handler.call(video);
}

return {
c() {
video = element("video");
add_render_callback(() => ctx.video_elementresize_handler.call(video));
if (ctx.videoHeight === void 0 || ctx.videoWidth === void 0) add_render_callback(() => ctx.video_resize_handler.call(video));

dispose = [
listen(video, "timeupdate", video_timeupdate_handler),
listen(video, "resize", ctx.video_resize_handler)
];
},
m(target, anchor) {
insert(target, video, anchor);
video_resize_listener = add_resize_listener(video, ctx.video_elementresize_handler.bind(video));
},
p(changed, ctx) {
if (!video_updating && changed.currentTime && !isNaN(ctx.currentTime)) {
video.currentTime = ctx.currentTime;
}

video_updating = false;
},
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(video);
video_resize_listener.cancel();
run_all(dispose);
}
};
}

function instance($$self, $$props, $$invalidate) {
let { currentTime } = $$props;
let { videoHeight } = $$props;
let { videoWidth } = $$props;
let { offsetWidth } = $$props;

function video_elementresize_handler() {
offsetWidth = this.offsetWidth;
$$invalidate("offsetWidth", offsetWidth);
}

function video_timeupdate_handler() {
currentTime = this.currentTime;
$$invalidate("currentTime", currentTime);
}

function video_resize_handler() {
videoHeight = this.videoHeight;
videoWidth = this.videoWidth;
$$invalidate("videoHeight", videoHeight);
$$invalidate("videoWidth", videoWidth);
}

$$self.$set = $$props => {
if ("currentTime" in $$props) $$invalidate("currentTime", currentTime = $$props.currentTime);
if ("videoHeight" in $$props) $$invalidate("videoHeight", videoHeight = $$props.videoHeight);
if ("videoWidth" in $$props) $$invalidate("videoWidth", videoWidth = $$props.videoWidth);
if ("offsetWidth" in $$props) $$invalidate("offsetWidth", offsetWidth = $$props.offsetWidth);
};

return {
currentTime,
videoHeight,
videoWidth,
offsetWidth,
video_elementresize_handler,
video_timeupdate_handler,
video_resize_handler
};
}

class Component extends SvelteComponent {
constructor(options) {
super();

init(this, options, instance, create_fragment, safe_not_equal, {
currentTime: 0,
videoHeight: 0,
videoWidth: 0,
offsetWidth: 0
});
}
}

export default Component;
8 changes: 8 additions & 0 deletions test/js/samples/video-bindings/input.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<script>
export let currentTime;
export let videoHeight;
export let videoWidth;
export let offsetWidth;
</script>

<video bind:currentTime bind:videoHeight bind:videoWidth bind:offsetWidth/>

0 comments on commit 927fcbf

Please sign in to comment.