admin管理员组

文章数量:1356889

I'm writing a website with a canvas in it. The website has a script that runs successfully on every refresh except for a line at the end. When the script ends with:

document.body.onresize = function() {viewport.resizeCanvas()}

"document.body.onresize" is unchanged. (I double-checked in Chrome's javascript console: Entering "document.body.onresize" returns "undefined".)

However, when the script ends with:

document.body.onresize = function() {viewport.resizeCanvas()}
console.log(document.body.onresize)

"document.body.onresize" does change. The function works exactly as it should.

I can't explain why these two functionally identical pieces of code have different results. Can anyone help?


Edit: As far as I can tell, "document.body" is referring to the correct "document.body". When I call console.log(document.body) just before I assign document.body.onresize, the correct HTML is printed.


Edit 2: A solution (sort of)

When I substituted "window" for "document" the viewport's "resizeCanvas" function was called without fail every time I resized the window.

Why does "window" work while "document" only works if you call "console.log" first? Not a clue.

I'm writing a website with a canvas in it. The website has a script that runs successfully on every refresh except for a line at the end. When the script ends with:

document.body.onresize = function() {viewport.resizeCanvas()}

"document.body.onresize" is unchanged. (I double-checked in Chrome's javascript console: Entering "document.body.onresize" returns "undefined".)

However, when the script ends with:

document.body.onresize = function() {viewport.resizeCanvas()}
console.log(document.body.onresize)

"document.body.onresize" does change. The function works exactly as it should.

I can't explain why these two functionally identical pieces of code have different results. Can anyone help?


Edit: As far as I can tell, "document.body" is referring to the correct "document.body". When I call console.log(document.body) just before I assign document.body.onresize, the correct HTML is printed.


Edit 2: A solution (sort of)

When I substituted "window" for "document" the viewport's "resizeCanvas" function was called without fail every time I resized the window.

Why does "window" work while "document" only works if you call "console.log" first? Not a clue.

Share Improve this question edited Sep 13, 2014 at 20:55 NcAdams asked Jul 12, 2014 at 22:05 NcAdamsNcAdams 2,9095 gold badges25 silver badges34 bronze badges 7
  • 3 Is your script concatenated with something else that starts with a parenthesis? Always use semicolons. (Also, isn’t window.onresize more… mon?) – Ry- Commented Jul 12, 2014 at 22:09
  • It's not, but good suggestion. And good news is that "window.onresize" actually fixed the issue pletely :D thanks for that. But I'm still curious, this is one of the weirdest bugs I've ever had – NcAdams Commented Jul 12, 2014 at 22:20
  • There's a typo (missing on) in body.resize. Maybe your actual code has something like this as well? – Bergi Commented Jul 12, 2014 at 22:37
  • 3 document and document.body aren't resized. window is resized. So, I think what you want is window.onresize. – jfriend00 Commented Jul 12, 2014 at 22:43
  • 1 your function doesn't return a value, so it should return undefined. the value of document.body.onresize is a function, the value of document.body.onresize() is undefined since it doesn't return anything. also, I think @bergi was reffing to the fact that you wrote .resize instead of .onresize, not referring to whether or not document.body is a valid reference. – chiliNUT Commented Jul 12, 2014 at 22:44
 |  Show 2 more ments

3 Answers 3

Reset to default 3

Resize events: no go

Most browsers don't support resize events on anything other than the window object. According to this page, only Opera supported detecting resizing documents. You can use the test page to quickly test it in multiple browsers. Another source that mentions a resize event on the body element specifically also notes that it doesn't work. If we look at these bug reports for Internet Explorer, we find out that having a resize event fire on arbitrary elements was an Internet Explorer-only feature, since removed.

Object.observe: maybe in the future

A more general method of figuring out changes to properties has been proposed and will most likely be implemented cross-browser: Object.observe(). You can observe any property for changes and run a function when that happens. This way, you can observe the element and when any property changes, such as clientWidth or clientHeight, you will get notified. It currently works only in Chrome with the experimental Javascript flag turned on. Plus, it is buggy. I could only get Chrome to notify me about properties that were changed inside Javascript, not properties that were changed by the browser. Experimental stuff; may or may not work in the future.

Current solution

Currently, you will have to do dirty checking: assign the value of the property that you want to watch to a variable and then check whether it has changed every 100 ms. For example, if you have the following HTML on a page:

<span id="editableSpan" contentEditable>Change me!</span>

And this script:

window.onload = function() {

function watch(obj, prop, func) {
    var oldVal = null;
    setInterval(function() {
        var newVal = obj[prop];
        if(oldVal !=  newVal) {
            var oldValArg = oldVal;
            oldVal = newVal;
            func(newVal, oldValArg);
        }
    }, 100);
}

var span = document.querySelector('#editableSpan');

// add a watch on the offsetWidth property of the span element

watch(span, "offsetWidth", function(newVal, oldVal) {
    console.log("width changed", oldVal, newVal);
});

}

This works similarly to Object.observe and for example the watch function in the AngularJS framework. It's not perfect, because with many such checks you will have a lot of code running every 100 ms. Additionally any action will be delayed 100 ms. You could possibly improve on this by using requestAnimationFrame instead of setInterval. That way, an update will be noticed whenever the browser redraws your webpage.

What you can do is that if you know for certain what particular action triggers a resize on your element that doesn't resize the full window you can trigger a resize event so your browser recalculate all of the divs (if by the case the browser is not triggering the event correctly).

With Jquery:

$(window).trigger('resize');

In the other hand, if you have an action that resizes an element you can always hold from that action to handle other following logic.

<script>
    function body_OnResize() {
      alert('resize');
    }
</script>

<body onresize="body_OnResize()"></body>

本文标签: