MouseEvents

class webix.MouseEvents()

Mouseevents mixin

External references

Official documentation page.

Code

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
webix.MouseEvents={
    $init: function(config){
        config = config || {};

        this._clickstamp = 0;
        this._dbl_sensetive = 300;
        this._item_clicked = null;

        this._mouse_action_extend(config.onClick, "on_click");
        this._mouse_action_extend(config.onContext, "on_context");
        this._mouse_action_extend(config.onDblClick, "on_dblclick");
        this._mouse_action_extend(config.onMouseMove, "on_mouse_move");

        //attach dom events if related collection is defined
        if (this.on_click){
            webix._event(this._contentobj,"click",this._onClick,{bind:this});
            if (webix.env.isIE8 && this.on_dblclick)
                webix._event(this._contentobj, "dblclick", this._onDblClick, {bind:this});
        }
        if (this.on_context)
            webix._event(this._contentobj,"contextmenu",this._onContext,{bind:this});

        if (this.on_mouse_move)
            this._enable_mouse_move();
    },

    _enable_mouse_move:function(){
        if (!this._mouse_move_enabled){
            this.on_mouse_move = this.on_mouse_move || {};
            webix._event(this._contentobj,"mousemove",this._onMouse,{bind:this});
            webix._event(this._contentobj,(webix.env.isIE?"mouseleave":"mouseout"),this._onMouse,{bind:this});
            this._mouse_move_enabled = 1;
            this.attachEvent("onDestruct", function(){
                if (this._mouse_move_timer)
                    window.clearTimeout(this._mouse_move_timer);
            });
        }

    },

    _mouse_action_extend:function(config, key){
        if (config){
            var now = this[key];
            var step = now ? webix.extend({}, now) : {};
            this[key] = webix.extend(step, config);
        }
    },

    //inner onclick object handler
    _onClick: function(e){
        if(!this.isEnabled())
            return false;

        webix.UIManager._focus_action(this);
        if(this.on_dblclick){
            // emulates double click
            var stamp = (new Date()).valueOf();

            if (stamp - this._clickstamp <= this._dbl_sensetive && this.locate){
                var item = this.locate(e);
                if (""+item == ""+this._item_clicked) {
                    this._clickstamp = 0;
                    return this._onDblClick(e);
                }
            }
            this._clickstamp = stamp;
        }

        var result = this._mouseEvent(e,this.on_click,"ItemClick");
        return result;
    },
    //inner ondblclick object handler
    _onDblClick: function(e) {
        return this._mouseEvent(e,this.on_dblclick,"ItemDblClick");
    },
    //process oncontextmenu events
    _onContext: function(e) {
        this._mouseEvent(e, this.on_context, "BeforeContextMenu", "AfterContextMenu");
    },
    /*
        event throttler - ignore events which occurs too fast
        during mouse moving there are a lot of event firing - we need no so much
        also, mouseout can fire when moving inside the same html container - we need to ignore such fake calls
    */
    _onMouse:function(e){
        if (this.$destructed) return;
        if (document.createEventObject)    //make a copy of event, will be used in timed call
            e = document.createEventObject(event);
        else if (!webix.$testmode && !webix.isUndefined(e.movementY) && !e.movementY && !e.movementX)
            return; //logitech mouse driver can send false signals in Chrome




        if (this._mouse_move_timer)    //clear old event timer
            window.clearTimeout(this._mouse_move_timer);

        //this event just inform about moving operation, we don't care about details
        this.callEvent("onMouseMoving",[e]);
        //set new event timer
        this._mouse_move_timer = window.setTimeout(webix.bind(function(){
            //called only when we have at least 100ms after previous event
            if (e.type == "mousemove")
                this._onMouseMove(e);
            else
                this._onMouseOut(e);
        },this),(this._settings.mouseEventDelay||500));
    },

    //inner mousemove object handler
    _onMouseMove: function(e) {
        if (!this._mouseEvent(e,this.on_mouse_move,"MouseMove"))
            this.callEvent("onMouseOut",[e||event]);
    },
    //inner mouseout object handler
    _onMouseOut: function(e) {
        this.callEvent("onMouseOut",[e||event]);
    },
    //common logic for click and dbl-click processing
    _mouseEvent:function(e,hash,name, pair){
        e=e||event;

        if (e.processed || !this._viewobj) return;
        e.processed = true;

        var trg=e.target||e.srcElement;

        //IE8 can't modify event object
        //so we need to stop event bubbling to prevent double processing
        if (webix.env.isIE8){
            var vid = this._settings.id;
            var wid = trg.w_view;

            if (!wid) trg.w_view = vid; else if (wid !== vid) return;
        }

        var css = "";
        var id = null;
        var found = false;
        //loop through all parents
        while (trg && trg.parentNode && trg != this._viewobj.parentNode){
            if (!found && trg.getAttribute){                                                    //if element with ID mark is not detected yet
                id = trg.getAttribute(this._id);                            //check id of current one
                if (id){
                    this._item_clicked = id;
                    if (this.callEvent){
                        //it will be triggered only for first detected ID, in case of nested elements
                        if (!this.callEvent("on"+name,[id,e,trg])) return;
                        if (pair) this.callEvent("on"+pair,[id,e,trg]);
                    }
                    //set found flag
                    found = true;
                }
            }
            css=webix.html._getClassName(trg);
            if (css){        //check if pre-defined reaction for element's css name exists
                css = css.toString().split(" ");
                for (var i=0; i<css.length; i++){
                    if (hash[css[i]]){
                        var functor = webix.toFunctor(hash[css[i]], this.$scope);
                        var res =  functor.call(this,e,id||webix.html.locate(e, this._id),trg);
                        if(res === false)
                            return found;
                    }
                }
            }
            trg=trg.parentNode;
        }

        return found;    //returns true if item was located and event was triggered
    }
};