summaryrefslogtreecommitdiff
path: root/src/client/rz_observer.js
blob: 718fd0a2d84031e58993bc813445cc3755fc2e5f (plain)
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
"use strict"

/**
 * DOM object observers
 */
define(
[],
function() {

var MutationObserver = window.MutationObserver;
// more portable version: var MutationObserver =
// window.MutationObserver ||
// window.WebKitMutationObserver;

/**
 * observe SVG object's translate attribute (x,y values), measure
 * change rate & invoke on_slowdown_threshold_reached() upon
 * reaching change slowdown threshold.
 *
 * Caller is responsible to disconnect observer.
 */
function Mutation_Handler__on_dxy_slowdown(
        on_slowdown_threshold_reached) {

    var x_cur, y_cur, d, dx, dy, avg_d = 0;

    this.on_slowdown_threshold_reached = on_slowdown_threshold_reached;

    /**
     * handle observer mutation
     */
    this.handle_mutation = function(m) {
        if ('transform' != m.attributeName || null == m.oldValue) {
            return;
        }

        /*
         * parsed txt example:
         * "translate(173.6007550157428,275.43228723527193)"
         */
        var rgx_m = m.oldValue.match(/\((\d+.\d+),(\d+.\d+)\)/);
        x_cur = rgx_m[1];
        y_cur = rgx_m[2];
        if (undefined == this.x_prv) {
            this.x_prv = x_cur;
            this.y_prv = y_cur;
            return;
        }
        dx = x_cur - this.x_prv;
        dy = y_cur - this.y_prv;

        var d = Math.sqrt(dx * dx + dy * dy);
        // average across last samples
        avg_d = (1.0 - this.most_recent_sample_weight) * avg_d
                + this.most_recent_sample_weight * d;

        // debug
        // console.log({
        //     'dx' : dx,
        //     'dy' : dy,
        //     'd' : d,
        //     'avg_d' : avg_d,
        // });

        if (avg_d < this.slowdown_threshold) {
            // slowdown threshold reached
            if (this.on_slowdown_threshold_reached) {
                this.on_slowdown_threshold_reached();
            }
        }

        this.x_prv = x_cur;
        this.y_prv = y_cur;
    }
}

function new_Mutation_Handler__on_dxy_slowdown(
        on_slowdown_threshold_reached, slowdown_threshold,
        most_recent_sample_weight) {
    slowdown_threshold = slowdown_threshold || 0.07;
    most_recent_sample_weight = most_recent_sample_weight || 0.3;
    var ret = new Mutation_Handler__on_dxy_slowdown(
            on_slowdown_threshold_reached);
    ret.slowdown_threshold = slowdown_threshold;
    ret.most_recent_sample_weight = most_recent_sample_weight;
    return ret;
}

function new_MutationObserver(handler) {
    /*
     * FIXME implemente with inheritence - currently triggers
     * 'illegal invocation', possibly due to some interaction with
     * requirejs
     */
    // var o = new
    // window.MutationObserver(Mutation_Observer.handler);
    // var ret = Object.create(o);
    // ret. = undefined;
    // return ret;
    var for_each_mutaion = function(m_set) {
        m_set.forEach(function(m) {
            handler.handle_mutation(m);
        })
    };

    return new MutationObserver(for_each_mutaion);
}

return {
    new_MutationObserver : new_MutationObserver,
    new_Mutation_Handler__on_dxy_slowdown : new_Mutation_Handler__on_dxy_slowdown,
};

});