javascript - addeventlistener drop error "Uncaught TypeError: Illegal invocation" - Stack Overflow

I create new Object by function, and i create sortable method to use, but that have an error on callbac

I create new Object by function, and i create sortable method to use, but that have an error on callback function

;"use strict";
(function(){
    function libJS(){};

    libJS.prototype = {
        loopElement : function(element, options, callback){
            var libObj = this;
            var goesCallback = function(element, options, callback){
                if (!!callback && libObj.isFunction(callback)) callback(element, options);
            };

            if (libObj.isElement(element)) goesCallback(element, options, callback);
            else if (libObj.isString(element) && /^(\.|\#)[\w\d\-_]+$/g.test(element)){
                if (/^\./g.test(element)){
                    element = document.getElementsByClassName(element.replace('.', ''));
                    var length = element.length || 0, i;
                    for(i = 0; i < length; i++) goesCallback(element[i], options, callback);
                }else{
                    element = document.getElementById(element.replace('#', ''));
                    if (!!element) goesCallback(element, options, callback);
                }
            }
        },

        isElement : function(element){
            // code check
            var f=(typeof HTMLElement === 'object' || false);
                f=(f && element instanceof HTMLElement);
                f=(f||(typeof element === 'object' && element.nodeType===1 && typeof element.nodeName === 'string'));
		    return f;
        },

        isString : function(str){
            // code check
            return true;
        },

        isObject : function(obj){
            // code check
            return true;
        },

        isFunction : function(func){
            // code check
            return true;
        },

        token : function(length){
            // create token
            return 'random_string';
        },

        sortable : function(options){
            if ('draggable' in document.createElement('span')){
                var libObj = this;
                if (libObj.isObject(options)){
                    libObj.loopElement(options.element, options, function(element, options){
                        element.style.position = 'relative';
                        var childNodes = element.childNodes,
                            length = childNodes.length || 0, x;
                        for (x = 0; x < length; x++){
                            var item = childNodes[x];
                            if (item.nodeName !== '#text'){
                                item.id = 'libJS-' + libObj.token(12);
                                item.draggable = true;
                                item.style.cursor = 'pointer';
                                item.style.transition = 'all 0.5s ease';
                                item.addEventListener('dragstart', function(event){
                                    event.preventDefault();
                                    // some code
                                });
                            }
                        }
                        element.addEventListener('dragover', function(event){
                            event.preventDefault();
                        });
                        element.addEventListener('drop', function(event){
                            event.preventDefault();
                        });
                        console.log(element.__proto__.ondrop); // View Error
                    });
                }
            }else throw 'ERROR: libJS.sortable(): this browser not support drag and drop event!';
        }
    };
    window.libJs = new libJS();
})();

libJs.sortable({
   element : '.sorter'
});
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Test</title>
        <style type="text/css">
            *{
                box-sizing: border-box;
            }
            .sorter{
                border: 1px solid green;
                padding: 10px;
            }
            .sorter:after{
                display: block;
                content: '';
                clear: both;
            }
            .sorterItem{
                display: inline-block;
                float: left;
                width: 70px;
                height: 70px;
                margin-right: 10px;
                margin-bottom: 10px;
            }
            .sorterItem img{
                display: block;
                max-width: 100%;
                max-height: 100%;
                min-width:100px;
                min-height:100px;
            }
        </style>
    </head>
    <body>
        <div class="sorter">
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
        </div>
    </body>
</html>

I create new Object by function, and i create sortable method to use, but that have an error on callback function

;"use strict";
(function(){
    function libJS(){};

    libJS.prototype = {
        loopElement : function(element, options, callback){
            var libObj = this;
            var goesCallback = function(element, options, callback){
                if (!!callback && libObj.isFunction(callback)) callback(element, options);
            };

            if (libObj.isElement(element)) goesCallback(element, options, callback);
            else if (libObj.isString(element) && /^(\.|\#)[\w\d\-_]+$/g.test(element)){
                if (/^\./g.test(element)){
                    element = document.getElementsByClassName(element.replace('.', ''));
                    var length = element.length || 0, i;
                    for(i = 0; i < length; i++) goesCallback(element[i], options, callback);
                }else{
                    element = document.getElementById(element.replace('#', ''));
                    if (!!element) goesCallback(element, options, callback);
                }
            }
        },

        isElement : function(element){
            // code check
            var f=(typeof HTMLElement === 'object' || false);
                f=(f && element instanceof HTMLElement);
                f=(f||(typeof element === 'object' && element.nodeType===1 && typeof element.nodeName === 'string'));
		    return f;
        },

        isString : function(str){
            // code check
            return true;
        },

        isObject : function(obj){
            // code check
            return true;
        },

        isFunction : function(func){
            // code check
            return true;
        },

        token : function(length){
            // create token
            return 'random_string';
        },

        sortable : function(options){
            if ('draggable' in document.createElement('span')){
                var libObj = this;
                if (libObj.isObject(options)){
                    libObj.loopElement(options.element, options, function(element, options){
                        element.style.position = 'relative';
                        var childNodes = element.childNodes,
                            length = childNodes.length || 0, x;
                        for (x = 0; x < length; x++){
                            var item = childNodes[x];
                            if (item.nodeName !== '#text'){
                                item.id = 'libJS-' + libObj.token(12);
                                item.draggable = true;
                                item.style.cursor = 'pointer';
                                item.style.transition = 'all 0.5s ease';
                                item.addEventListener('dragstart', function(event){
                                    event.preventDefault();
                                    // some code
                                });
                            }
                        }
                        element.addEventListener('dragover', function(event){
                            event.preventDefault();
                        });
                        element.addEventListener('drop', function(event){
                            event.preventDefault();
                        });
                        console.log(element.__proto__.ondrop); // View Error
                    });
                }
            }else throw 'ERROR: libJS.sortable(): this browser not support drag and drop event!';
        }
    };
    window.libJs = new libJS();
})();

libJs.sortable({
   element : '.sorter'
});
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Test</title>
        <style type="text/css">
            *{
                box-sizing: border-box;
            }
            .sorter{
                border: 1px solid green;
                padding: 10px;
            }
            .sorter:after{
                display: block;
                content: '';
                clear: both;
            }
            .sorterItem{
                display: inline-block;
                float: left;
                width: 70px;
                height: 70px;
                margin-right: 10px;
                margin-bottom: 10px;
            }
            .sorterItem img{
                display: block;
                max-width: 100%;
                max-height: 100%;
                min-width:100px;
                min-height:100px;
            }
        </style>
    </head>
    <body>
        <div class="sorter">
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
            <div class="sorterItem">
                <img src="/data/upload/noimage.jpg" />
            </div>
        </div>
    </body>
</html>

And this is an Error: Uncaught TypeError: Illegal invocation

That was in goesCallback function when I drag .sorterItem and i drop it. It can kill the browser.

So, in sortable method i have console.log(element.__proto__.ondrop) to view Error at some line.

How to fix this error?

thank everyone.

Share Improve this question edited Jun 13, 2017 at 4:32 Canh Nguyen asked Jun 5, 2017 at 5:04 Canh NguyenCanh Nguyen 3331 silver badge18 bronze badges 2
  • Not sure what you are exactly trying to achieve with the console.log. Do you want to see the function? It looks like you cannot log most functions. I ran var el = document.querySelector('.sorter'); for (let k of Object.keys(el.__proto__.__proto__)) { try { console.log(k, el.__proto__[k]); } catch (e) { } } and that prints only a handful of functions: onmouseenter, onmouseleave, click, drag and focus. It would be good if you could explain what error you get without the console.log, because I don't get one. – Just a student Commented Jun 9, 2017 at 9:29
  • @Justastudent , No, I don't want to see function. It seems that somebody has changed the content of my question, which makes it no longer what I want to ask. I'm handling the drop event but it could kill the browser, and I did the console.log () element to see but get the error. So i got console.log () to know the error at any given line – Canh Nguyen Commented Jun 13, 2017 at 4:14
Add a ment  | 

2 Answers 2

Reset to default 5

You cannot do console.log(element.__proto__.ondrop) as ondrop is an accessor-property.

Accessor Properties? With reference to this SO Answer

An accessor property is one that is defined in terms of getters and setters, not as a stored value that might be written to. The "pair of accessor functions" denotes the getter and the setter function.

Also see this answer

So basically by calling console.log(element.__proto__.ondrop) you are invoking the element's ondrop getter function without proper this context which results in Illegal Invocation error.

Code Example
A javascript code example to illustrate the point

var Person = {
  firstname: "John",
  lastname: "Doe",
  get fullname() {
    return this.firstname + " " + this.lastname
  },
  set fullname(name) {
    this.firstname = name.split(' ')[0]
    this.lastname = name.split(' ')[1]
  }
}

console.log(Person.fullname) // will trigger the getter function 'fullname'

Person.fullname = "Jane Doe" // will trigger the setter function 'fullname'

console.log(Person.fullname) // logs Jane Doe

So when you call console.log(element.__proto__.ondrop) you are essentially triggering the ondrop getter without a valid context.

Update:

I guess what you wanted to do was to inspect why the Drag-events were not firing and you ended up putting a console.log(element.__proto__.ondrop) which, as it's been already answered, caused the IllegalInvocation error, resulting in a totally different class of error then the one you were trying to debug!

The reason why your Drag events are not firing is the function call inside the handlers Event.preventDefault(), quoting from MDN

The Event interface's preventDefault() method tells the user agent that if the event goes unhandled, its default action should not be taken as it normally would be.

In your case, the default action means the Drag-related functionality, which, you are (inadvertently) preventing from execution!

I suggest you read more about HTML5 Drag and Drop API on MDN.

The error "Illegal Invocation" means you are trying to call a callable function with the wrong context, the context being the object the method is called on. Let me break down the console.log:

console.log(element.__proto__.ondrop)

Here, you're trying to log element.__proto__.ondrop. First, let me explain element.__proto__. The accessor property on every object, Object.prototype.__proto__ is an accessor property that points to the prototype of that object and is used to resolve methods in the lookup chain. For example:

function Person(name) { //This is a constructor function
  this.name = name; //Set the name to be part of the instance
} 
Person.prototype.sayName = function() { //A function on the prototype
  console.log(this.name);               //and is part of the instance
}

const bob = new Person("Bob");
console.log(bob.__proto__); //The __proto__ property refers to `Person.prototype`
                            //and will log the `Person.prototype` object

Here, __proto__ of an instance refers to the prototype of the constructor that constructed the instance. Now, in your case, the __proto__ of an element from the DOM would be something along the lines of the prototype of HTMLDivElement or something else depending on what type of element it is. For the purpose of this answer, we'll say it's a div.

Now, when you try to access the property ondrop of HTMLDivElement's prototype, you get an illegal invocation because you're trying to access ondrop statically from the HTMLDivElement prototype, not an actual div element! This leads to the "wrong context" because you're trying to call the accessor on HTMLDivElement.prototype, not a div from the DOM!

To "fix this", don't access the __proto__ key. If you want to access the element's ondrop property, just do element.ondrop.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744164164a4561228.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信