66

For image upload in a cakephp project I used java-script.I added this js file in app\View\Layouts default.ctp

js code

document.querySelector('input[type=file]').addEventListener('change', function(event){

  var files = event.target.files;

  for (var i = 0; i < files.length; i++) {

    if (files[i].type.match(/image.*/)) {

        var reader = new FileReader();
        reader.onload = function (readerEvent) {
            var image = new Image();
            image.onload = function (imageEvent) {

                var imageElement = document.createElement('div');
                imageElement.classList.add('uploading');
                imageElement.innerHTML = '<span class="progress"><span></span></span>';
                var progressElement = imageElement.querySelector('span.progress span');
                progressElement.style.width = 0;
                document.querySelector('form div.photos').appendChild(imageElement);


                var canvas = document.createElement('canvas'),
                    max_size = 1200,
                    width = image.width,
                    height = image.height;
                if (width > height) {
                    if (width > max_size) {
                        height *= max_size / width;
                        width = max_size;
                    }
                } else {
                    if (height > max_size) {
                        width *= max_size / height;
                        height = max_size;
                    }
                }
                canvas.width = width;
                canvas.height = height;
                canvas.getContext('2d').drawImage(image, 0, 0, width, height);

                var xhr = new XMLHttpRequest();
                if (xhr.upload) {

                    // Update progress
                    xhr.upload.addEventListener('progress', function(event) {
                        var percent = parseInt(event.loaded / event.total * 100);
                        progressElement.style.width = percent+'%';
                    }, false);


                    xhr.onreadystatechange = function(event) {
                        if (xhr.readyState == 4) {
                            if (xhr.status == 200) {

                                imageElement.classList.remove('uploading');
                                imageElement.classList.add('uploaded');
                                imageElement.style.backgroundImage = 'url('+xhr.responseText+')';

                                console.log('Image uploaded: '+xhr.responseText);

                            } else {
                                imageElement.parentNode.removeChild(imageElement);
                            }
                        }
                    }

                    xhr.open('post', 'process.php', true);
                    xhr.send(canvas.toDataURL('image/jpeg'));

                }

            }

            image.src = readerEvent.target.result;

        }
        reader.readAsDataURL(files[i]);
    }

}

event.target.value = '';

I have checked there are no problem.

now in add.ctp file I adder

<input type="file" multiple />

In output I am seeing the file type field.Now when I clicked on this field and upload a image then mojila bug given me a error.That is

document.querySelector(...) is null error

I have no idea about this error.In here why saying queryselector is null?

Alimon Karim
  • 4,354
  • 10
  • 43
  • 68
  • 4
    It's saying it's `null` because the selector passed to `document.querySelector()` isn't returning an element/node upon which to work. Can you verify the element exists? If you can post your relevant (minimal/[SSCCE](http://sscce.org/)) HTML then we might be able to provide more specific help. – David Thomas Dec 10 '13 at 13:36
  • Do you means it not found ? – Alimon Karim Dec 10 '13 at 13:40
  • I mean it's not finding an element that's matched by the CSS selector you've passed to it. But you've called it in two separate places (`querySelector('span.progress span');` and `querySelector('form div.photos')`), neither of which is trying to find an input of *any* `type`. – David Thomas Dec 10 '13 at 13:44
  • 1
    I just edited the question for formatting. The first line was missing from the code. There's the selection you're looking for, @DavidThomas. – Andy Dec 10 '13 at 13:45
  • OP, are you sure that you have a `div.photos` within a `form` element like David asked? – Andy Dec 10 '13 at 13:49
  • 2
    Well, work out precisely *which* line is generating the error and that's (at least one of) the line(s) causing an error. If the element isn't being found it's because the selector is wrong, or the element doesn't exist at the point at which the JavaScript is run. – David Thomas Dec 10 '13 at 13:52
  • possible duplicate of [document.querySelector() returns null](http://stackoverflow.com/questions/25100883/document-queryselector-returns-null) – Mohamed Anis Dahmani Oct 19 '14 at 21:59
  • No brother see this ans have asked before 10 months, and your complain this question have asked before 2 months.Be careful before give any comment please. – Alimon Karim Oct 20 '14 at 07:02

7 Answers7

108

document.querySelector() behaves similarly to the jQuery.(document).ready() method. When the DOM is ready, the selector returns the object.

I would suggest you call all JS script bottom of the page.

Community
  • 1
  • 1
Rajinweb
  • 1,139
  • 1
  • 9
  • 9
  • 3
    The best way to do it is to put the all the script calls in the `` tag using the async or defer attributes. This downloads the script files without blocking the browser. – Rodrigo García Jun 28 '18 at 02:21
  • With the difference being that `async` merely loads the script as a non-blocking network transfer, but will _execute it immediately_ once retrieved, whereas the `defer` attribute says nothing about how to load the script, but will _not_ execute it immediately, instead executing it once the DOM has been parsed (but _before_ the DOMContentLoaded event is dispatched). In terms of cross-browser support, both have been universally supported since IE 10. – Mike 'Pomax' Kamermans Jul 18 '20 at 18:07
  • 2
    For ppl using Vue3, put it inside `onMounted()` – Artur Müller Romanov Dec 08 '21 at 16:48
30

To make sure that your DOM is ready you could add this to your JS file.

// my-script.js
document.addEventListener("DOMContentLoaded", function() { 
    // this function runs when the DOM is ready, i.e. when the document has been parsed
    document.querySelector('input[type=file]')
        .addEventListener('change', function(event){
            ...
         }
});

This way you could call your js files from wherever you like. Please take a look to this superb answer to get further insight on these matters.

Also take a look at this other Google rule.

Rodrigo García
  • 1,357
  • 15
  • 26
9

file.js

const heading1 = document.querySelector(".heading1");
console.log(heading1);

Solution 1


Use defer (best & recommended way):

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="./file.js" defer></script>
    <title>Document</title>
</head>
<body>
    <h1 class="heading1">Hello World 1</h1>
</body>
</html>

Solution 2

Place your JavaScript in bottom before closing body tag

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Document</title>
</head>
<body>
    <h1 class="heading1">Hello World 1</h1>

    <script src="./file.js"></script>
</body>
</html>
Kheersagar patel
  • 383
  • 3
  • 15
4

I suggest writing your <script type="text/javascript" src="your js file"></script> in body, before the closing tag

Picker
  • 688
  • 1
  • 7
  • 7
4

There is now another "better" way to address this issue.

put your scripts in the head tag and add the defer attribute.

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Document</title>
  <script src="main.js" defer></script>
</head>
<body>
  yoyoyo
</body>
</html>

you can read more about it here and here

TLDR (may be inaccurate and misleading so read the sources above!): the defer attribute tells the browser to load the file but hold off its execution until the dom is ready, which is close to the behavior you implicitly get when you put the script tag at the bottom of the body tag, the difference being that in the old way you have to wait for the whole body tag to be parsed until you start downloading the script tag.

Rtzoor
  • 308
  • 2
  • 11
1

Here's a quick fix. I was trying to effect some changes in my HTML page using DOM and was getting this error. The problem was I linked my Javascript file inside the head tag of the HTML page, when I changed that and linked it at the body just before the closing body tag, it worked!

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Soft dog</title>
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.4.1/dist/css/bootstrap.min.css"
        integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
    <link rel="stylesheet" href="landing.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link
        href="https://fonts.googleapis.com/css2?family=Cormorant+SC:wght@300&family=Edu+VIC+WA+NT+Beginner&display=swap"
        rel="stylesheet">
</head>

<body>
    <div class="container">
        <h2 id="newBrand">Welcome to SOFTDOG</h2>
        <p><em>property of soft 6</em></p>
        <a id="ceo" href="home.html"><img src="softdogmerch1.jpg" alt="check network"></a>
        <p id="enterstatement">Please<a href="home.html">
                <P><span>ENTER HERE</span></P>
            </a><span>to feed your eyes and fill your wardrobe</span>
        </p>

        <label for="emailinput">email:</label>
        <input id="emailinput" type="email" name="useremail" placeholder="user@email.com" required>
        <label for="passwordinput">password:</label>
        <input id="passwordinput" type="password" name="userpassword" placeholder="" required>

        <input id="clickme" type="submit" name="login" value="log in">
        <input id="clickme" type="submit" name="signup" value="sign up">
    </div>

    <script src="landing.js"></script>

</body>

</html>
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Aug 12 '22 at 08:05
0

I ran into this issue where I was trying to do (slimmed down for simplicity):

<script type="text/javascript">
    var svg = document.querySelector('svg');
    console.log(svg);
</script>

on an element in the <body>:

<svg id="svg" viewBox="0 0 120 120" width="500px" height="500px"></svg>

Once I added jQuery and moved my lines inside of a $(document).ready(), it was fine:

<script type="text/javascript" src="jquery-1.12.4.min.js"></script>
<script type="text/javascript">
    $(document).ready(function(){
        var svg = document.querySelector('svg');
        console.log(svg);
    });
</script>
vapcguy
  • 7,097
  • 1
  • 56
  • 52