1

I'm am VERY inexperienced in webdev, but here i am making a website. Im using Fabric.js and a script from an answer from stackoverflow so that the user can drag an image from one div into a canvas. When i test it out i always get the error "Cannot call method 'addEventListener' of null". I guess it means that what ever the script is trying to load, it hasn't loaded thus leaving it as null. The console says its from line 77 (canvasContainer.addEventListener('dragenter'..., near the bottom) in my JS file. I've tried moving the import script code lower down (under body) so that it loads after everything else but it still doesn't work. Any ideas?

PS. the the javascript comes from natchiketa.

HTML:

<!doctype html>
<html lang="en";>
<head>
    <meta charset="utf-8" />
    <title>CustomCase</title>
    <link rel="stylesheet" href="SkapaDesign.css">
    <script src="Jquery.js"></script>
    <script src="Modernizr.js"></script>
    <script src="Fabric.js"></script>
    <script src="Canvas.js"></script>
</head>
<body>  
    <div id="Wrapper">  
        <section id="Body">
                <div id="CanvasDiv">
                    <canvas id="Canvas" width="270px" height="519px"></canvas>
                </div>

                <div id="TextureView">
                    <div id="TextureViewInside">
                        <ul class="products">
                            <img draggable="true" src="FärgadePapper.png">
                            <img draggable="true" src="Hajar.png">
                            <img draggable="true" src="Labyrint.png">
                            <img draggable="true" src="Martini.png">
                        </ul>
                    </div>
                </div>  
        </section>
    </div>
</body>
</html>

CSS:

#Body{
    height: 675px;
}
#Canvas, #TextureView{
    float: left;
}
#LeftColumn{
    float: left;
    width: 355px;
    margin: 20px 30px 0px 0px;
}
#RightColumn{
    float: left;
    width: 600px;
    margin-top: 20px;
}
#CanvasDiv{
    width: 270px;
    height: 519px;
    margin-left: 15px;
}
#Canvas{
    overflow: hidden;
}
#TextureView{
    width: 470px;
    height: 559px;
    overflow: auto;
}
#TextureViewInside{
    padding: 10px;
}
ul.products img{
    width: 97px;
    display: inline-block;
    vertical-align: top;
    padding: 4px;
}

JavaScript:

var canvas = new fabric.Canvas('Canvas');

function handleDragStart(e) {
    [].forEach.call(images, function (img) {
        img.classList.remove('img_dragging');
    });
    this.classList.add('img_dragging');
}

function handleDragOver(e) {
    if (e.preventDefault) {
        e.preventDefault(); 
    }
    e.dataTransfer.dropEffect = 'copy';
    return false;
}

function handleDragEnter(e) {
    this.classList.add('over');
}

function handleDragLeave(e) {
    this.classList.remove('over');
}

function handleDrop(e) {
    if (e.stopPropagation) {
        e.stopPropagation();
    }

    var img = document.querySelector('#images img.img_dragging');

    console.log('event: ', e);

    var newImage = new fabric.Image(img, {
        width: img.width,
        height: img.height,
        left: e.layerX,
        top: e.layerY
    });
    canvas.add(newImage);

    return false;
}

function handleDragEnd(e) {
    [].forEach.call(images, function (img) {
        img.classList.remove('img_dragging');
    });
}

if (Modernizr.draganddrop) {
    var images = document.querySelectorAll('#images img');
    [].forEach.call(images, function (img) {
        img.addEventListener('dragstart', handleDragStart, false);
        img.addEventListener('dragend', handleDragEnd, false);
    });
    var canvasContainer = document.getElementById('CanvasDiv');
    canvasContainer.addEventListener('dragenter', handleDragEnter, false);
    canvasContainer.addEventListener('dragover', handleDragOver, false);
    canvasContainer.addEventListener('dragleave', handleDragLeave, false);
    canvasContainer.addEventListener('drop', handleDrop, false);
} else {
    alert("This browser doesn't support the HTML5 Drag and Drop API.");
}
kangax
  • 37,379
  • 12
  • 94
  • 132
user2961869
  • 307
  • 2
  • 7
  • 17
  • 1
    @canon "I've tried moving the import script code lower down (under body) so that it loads after everything else but it still doesn't work." – Pedro Estrada Nov 11 '13 at 17:58

2 Answers2

1

It looks like you just need to wrap part of the code in a document.ready handler, like this...

$(function() {
    if (Modernizr.draganddrop) {
        var images = document.querySelectorAll('#images img');
        [].forEach.call(images, function (img) {
            img.addEventListener('dragstart', handleDragStart, false);
            img.addEventListener('dragend', handleDragEnd, false);
        });
        var canvasContainer = document.getElementById('CanvasDiv');
        canvasContainer.addEventListener('dragenter', handleDragEnter, false);
        canvasContainer.addEventListener('dragover', handleDragOver, false);
        canvasContainer.addEventListener('dragleave', handleDragLeave, false);
        canvasContainer.addEventListener('drop', handleDrop, false);
    } else {
        alert("This browser doesn't support the HTML5 Drag and Drop API.");
    }
});

document.getElementById("CanvasDiv") would not have returned an element as the document was not loaded at that time, but the next few lines expect there to be something there. Wrapping it in a document.ready event handler should resolve that issue as the DOM will be loaded by the time you try to reference it.

Reinstate Monica Cellio
  • 24,939
  • 6
  • 47
  • 65
  • 1
    Well perhaps, though he did say that he moved his script to the end of the `` with no improvement. – Pointy Nov 11 '13 at 17:57
  • 1
    I LOVE YOU!! I've had that frustration that i'm sure everybody writing code has felt. That solved the problem, thanks! ;) – user2961869 Nov 11 '13 at 18:03
  • 4
    @user2961869 if this solved the problem, then moving your script to the end of the body would have solved it too. – Pointy Nov 11 '13 at 18:05
  • Strange, maybe i did something wrong... Now i have a new problem, were it says "var newImage = new fabric.Image(img, { width: img.width, height: img.height, left: e.layerX, top: e.layerY });" under handeldrop(e), it says "Cannot read property 'width' of null". any clue why? – user2961869 Nov 11 '13 at 18:12
  • @user2961869 Is an element with id `images` generated by code? Otherwise your selectors are wrong... – canon Nov 11 '13 at 18:34
  • As @canon said, you're searching for image tags inside an element with an ID of `images`, yet there is no such element in the html you've shown us, so we can't help with that. – Reinstate Monica Cellio Nov 11 '13 at 18:40
0

you can't get the element until the document is loaded...

   window.addEventListener('loaded', function(){
       if (Modernizr.draganddrop) {
           var images = document.querySelectorAll('#images img');
           [].forEach.call(images, function (img) {
               img.addEventListener('dragstart', handleDragStart, false);
               img.addEventListener('dragend', handleDragEnd, false);
           });
           var canvasContainer = document.getElementById('CanvasDiv');
           canvasContainer.addEventListener('dragenter', handleDragEnter, false);
           canvasContainer.addEventListener('dragover', handleDragOver, false);
           canvasContainer.addEventListener('dragleave', handleDragLeave, false);
           canvasContainer.addEventListener('drop', handleDrop, false);
       } else {
           alert("This browser doesn't support the HTML5 Drag and Drop API.");
       }
     });
Luan Castro
  • 1,174
  • 7
  • 13