0

I have an inner function named highchartCheck which does not appear to be executing and I do not know why. The print media query check executes and I get that logged but not the highchartCheck even though I call it at the end of the if block.

if (window.matchMedia) {
    var mq = window.matchMedia('print');

        if (mq.matches) {
            console.log("Print JS Executed");

            function highchartCheck() {
                console.log("check func exec");

                if (document.getElementById('highcharts-0') && document.getElementById("highcharts-2") && document.getElementById("highcharts-4")) {
                    document.getElementById("highcharts-0").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
                    document.getElementById("highcharts-2").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
                    document.getElementById("highcharts-4").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
                    console.log("if exec");
                } else {
                    setTimeout(highchartCheck, 250);
                }
            }

            //Print Styling
            $('#one').find("rect").css({"width": "3.6in !important";});
            $('#two').find("rect").css({"width": "3.6in !important";});
            $('#three').find("rect").css({"width": "3.6in !important";});

            highchartCheck();


        }

}
Michael Paccione
  • 2,467
  • 6
  • 39
  • 74
  • 4
    why are you declaring a function inside of two `if` statements? – Barry_D_Dale Mar 03 '16 at 19:24
  • Hi @Michael, try some logging before and after, one, two and three and the call to highchartCheck and share what you get. If nothing, then try moving the function out of the if blocks. – Vivek Jain Mar 03 '16 at 19:25
  • 2
    See [Conditionally defining a function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Conditionally_defining_a_function) – Teemu Mar 03 '16 at 19:25
  • 1
    I don't think you can declare a function inside an IF statement like that. That whole function should be outside on its own. – durbnpoisn Mar 03 '16 at 19:27
  • 1
    Do not use function declarations inside a block. Even if some implementations allow it, it's not standard, and is unreliable. "*Several widely used implementations of ECMAScript are known to support the use of FunctionDeclaration as a Statement. However there are significant and irreconcilable variations among the implementations in the semantics applied to such FunctionDeclarations. Because of these irreconcilable differences, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations.*" – Oriol Mar 03 '16 at 19:28
  • Yes, you can: https://plnkr.co/edit/6AnYhFrmueIolStaXYIv?p=info – lux Mar 03 '16 at 19:29
  • 1
    @lux No you can't. It's a (bydesign) bug in your implementation. – Oriol Mar 03 '16 at 19:30
  • Wow.. I did not know that. Unfortunately, upon moving the function outside of the media query I still get the same result :( Rather confusing as to why...I still don't know. – Michael Paccione Mar 03 '16 at 19:30
  • 1
    @Oriol Did you care to check the plunkr I posted? Not recommended, but it compiles and runs. You can absolutely declare functions within an IF block. Can != should. – lux Mar 03 '16 at 19:31
  • @lux Yes, I cared to see your demo, and explained why it seems to work. Did you care to read the spec? I even posted the relevant quote in a comment. – Oriol Mar 03 '16 at 19:32
  • Try just using `var highchartCheck = function() { ... };`, as indicated in the link provided by @Teemu. – Heretic Monkey Mar 03 '16 at 19:34
  • 1
    @lux, Run [this fiddle](https://jsfiddle.net/37ky9ttc/) in FF and Chrome, Do you see any difference? – Teemu Mar 03 '16 at 19:36
  • @Teemu. You accessed `doStuff()` outside of the scope if the IF, where the function was defined - of course it will be undefined when accessed in that manner... – lux Mar 03 '16 at 19:37
  • Listen, I'm not saying this is recommended or a proper pattern, but it is possible, hence why the spec says "should" and not "cannot". – lux Mar 03 '16 at 19:39
  • @MikeMcCaughan I changed it to that (functional expression?) and I still don't get a log out. I also took the function out of the if blocks into global scope and I didn't get a log out then either. This is making me crazy! – Michael Paccione Mar 03 '16 at 19:39
  • @lux Block scope is declared with `let` ... The difference is, that Chrome runs the function, FF says it's not defined. You really can't declare functions in blocks, since you can't rely on them belonging to a particular scope in different browsers. – Teemu Mar 03 '16 at 19:40
  • 1
    `$('#one').find("rect").css({"width": "3.6in !important";});` that extra semi-colon looks a bit weird, and throws an error in my console. and would certainly prevent `highchartCheck` from being called. – Kevin B Mar 03 '16 at 22:25
  • 1
    @Oriol, Teemu, lux: Have a look at [What are the precise semantics of block-level functions in ES6?](http://stackoverflow.com/a/31461615/1048572). OP is not using the function outside of the block it's declared in, so it usually works. – Bergi Mar 03 '16 at 22:26
  • 1
    @Bergi Fair enough, I was referring to ES5. I haven't read this part of ES6 yet. Thanks. – Oriol Mar 03 '16 at 22:41

1 Answers1

-1

You should only need to check that the DOM is fully loaded before running your function.

function doStuff() {
    // Set Attributes
    document.getElementById("highcharts-0").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
    document.getElementById("highcharts-2").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
    document.getElementById("highcharts-4").querySelectorAll("svg")[0].setAttribute("viewBox", "0 0 5.5in 3.6in");
    //Print Styling
    $('#one').find("rect").css({"width": "3.6in !important"});
    $('#two').find("rect").css({"width": "3.6in !important"});
    $('#three').find("rect").css({"width": "3.6in !important"});
}

if (window.matchMedia) {
    var mq = window.matchMedia('print');
    if (mq.matches) {
        // Call the function until true
        if (document.readyState == "complete" || document.readyState == "loaded") {
            // document is already ready to go - do what you want
            doStuff();
        }
    }
}
aphextwix
  • 1,838
  • 3
  • 21
  • 27
  • Because if those elements havent loaded yet (lot of math to them) then I need the function to run the check again to be sure it executes when they have been loaded. That was the thinking behind it since I believe the prrint media query is executing before the charts have loaded. – Michael Paccione Mar 03 '16 at 19:49
  • @MichaelPaccione - not the best way to do that. You need to monitor the event for them loading THEN execute when that is triggered. – Mark Schultheiss Mar 03 '16 at 19:52
  • 1
    @MichaelPaccione I would think a promise that resolves after all the dependents have loaded that then executes the function would be better - otherwise you just end up with another timer to re-execute/check the boolean. Here is the jQuery promise if you wan to use it; https://api.jquery.com/deferred.promise/ – Mark Schultheiss Mar 03 '16 at 20:06
  • @aphextwix Thank you for your code. It turned out I was loading/saving the js int he wrong directory. The files use php and so I had to make a copy into my htdocs and it turned out that was the problem. I do like your solution however and from what ive read in the comments about functions in if blocks I am going to mark this as the answer. Thanks. – Michael Paccione Mar 03 '16 at 21:13
  • @MichaelPaccione - I have to add that I haven't tested this against your data, so I can't be sure that the code will work exactly as expected. – aphextwix Mar 03 '16 at 21:16
  • @aphextwix Yes. I have tried it and I do in fact get in error on the while else....I know java has while else loops but I am not so sure Javascript does. What do you think? – Michael Paccione Mar 03 '16 at 21:26
  • @MichaelPaccione - I've had a think about and changed my answer – aphextwix Mar 04 '16 at 09:24