touchtracker.js 6.69 KB
/*
 *
 * ADOBE CONFIDENTIAL
 * __________________
 *
 *  Copyright 2014 Adobe Systems Incorporated
 *  All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains
 * the property of Adobe Systems Incorporated and its suppliers,
 * if any.  The intellectual and technical concepts contained
 * herein are proprietary to Adobe Systems Incorporated and its
 * suppliers and are protected by trade secret or copyright law.
 * Dissemination of this information or reproduction of this material
 * is strictly forbidden unless prior written permission is obtained
 * from Adobe Systems Incorporated.
 */

define('screens/player/ui/touchtracker', [
    'underscore',
    'jquery',
    './baseview'
], function(_, $, BaseView) {
    'use strict';

    var DEFAULT_OPTIONS = {};

    var TouchTrackerView = BaseView.extend(/** @lends TouchTrackerView.prototype */{

        className: 'aem-ScreensPlayer-touchtracker',

        events: {
            'click .close': 'close',
            'pointerdown': 'onPointerDown',
            'pointermove': 'onPointerMove',
            'pointerup': 'onPointerUp',
            'pointercancel': 'onPointerUp',
            'touchstart': 'onTouchStart',
            'touchmove': 'onTouchMove',
            'touchend': 'onTouchEnd',
            'touchcancel': 'onTouchEnd',
            'mousemove': 'onMouseMove',
            'mousedown': 'onMouseDown',
            'mouseup': 'onMouseUp',
            'click': 'onClick'
        },

        /**
         * @cl:assdesc View that renders thmenu
         * @class AdminView
         * @extends BaseView
         *
         * @param {Object} [options] An object of configurable options.
         */
        constructor: function(options) {
            this._initOptions(options, DEFAULT_OPTIONS);
            TouchTrackerView.__super__.constructor.apply(this, arguments);

            this.elemByPointerId = {};
            this.recycle = [];
        },

        render: function() {
            // prevent re-render
            if (this.setRendered(true)) {
                return this;
            }
            this.$el.append('<div class="close">x</div>');
            $('body').append(this.$el);
            return this;
        },

        close: function() {
            this.hide();
        },

        getPointer: function(id) {
            var el = this.elemByPointerId[id];
            if (!el) {
                el = this.recycle.pop();
                if (!el) {
                    el = document.createElement('div');
                    el.className = 'pointer';
                    this.$el.append(el);
                }
                this.elemByPointerId[id] = el;
            }
            return el;
        },

        releasePointer: function(id) {
            var el = this.elemByPointerId[id];
            if (el) {
                delete this.elemByPointerId[id];
                this.recycle.push(el);
                el.style.visibility = 'hidden';
            }
        },

        updatePointer: function(id, x, y, evt) {
            var el = this.getPointer(id);
            el.style.left = x + 'px';
            el.style.top = y + 'px';
            el.style.visibility = '';
            el.innerHTML = '<span>id:' + id + ', x:' + x + ', y:' + y + ' (' + evt.type + ')</span>';

            if (('' + id).indexOf('touch-') === 0) {
                el.className = 'pointer touch';
            } else if (id === 'mouse') {
                el.className = 'pointer mouse';
            } else {
                el.className = 'pointer';
            }
        },

        asyncUpdatePointer: function(id, x, y, evt) {
            setTimeout(this.updatePointer.bind(this, id, x, y, evt), 0);
        },

        createClick: function(x, y) {
            var el = document.createElement('div');
            el.className = 'pointer pointer-ring';
            this.$el.append(el);

            el.style.left = x + 'px';
            el.style.top = y + 'px';
            el.addEventListener('transitionend', function() {
                $(el).remove();
            }, false);

            window.requestAnimationFrame(function() {
                el.style.transform = 'scale(2)';
                el.style.opacity = 0;
            });
        },

        // pointer events
        onPointerDown: function(e) {
            e = e.originalEvent;
            this.updatePointer(e.pointerId, e.clientX, e.clientY, e);
            // console.log('PD-' + e.pointerId);
        },

        onPointerMove: function(e) {
            e = e.originalEvent;
            this.updatePointer(e.pointerId, e.clientX, e.clientY, e);
            // console.log('PM-' + e.pointerId);
        },

        onPointerUp: function(e) {
            e = e.originalEvent;
            this.releasePointer(e.pointerId);
            // console.log('PU-' + e.pointerId);
        },

        // touch events
        onTouchStart: function(e) {
            e = e.originalEvent;
            var touchlist = e.changedTouches;
            for (var i = 0; i < touchlist.length; i++) {
                var t = touchlist[i];
                this.updatePointer('touch-' + t.identifier, t.clientX, t.clientY, e);
            }
        },

        onTouchMove: function(e) {
            e = e.originalEvent;
            var touchlist = e.changedTouches;
            for (var i = 0; i < touchlist.length; i++) {
                var t = touchlist[i];
                this.updatePointer('touch-' + t.identifier, t.clientX, t.clientY, e);
            }
        },

        onTouchEnd: function(e) {
            e = e.originalEvent;
            var touchlist = e.changedTouches;
            for (var i = 0; i < touchlist.length; i++) {
                var t = touchlist[i];
                this.releasePointer('touch-' + t.identifier);
            }
        },

        // mouse events
        onMouseDown: function(e) {
            e = e.originalEvent;
            // don't do a DOM manipulation in a mouse handler, otherwise iOS safari will not trigger a 'click' event.
            this.asyncUpdatePointer('mouse', e.clientX, e.clientY, e);
        },

        onMouseMove: function(e) {
            e = e.originalEvent;
            // don't do a DOM manipulation in a mouse handler, otherwise iOS safari will not trigger a 'click' event.
            this.asyncUpdatePointer('mouse', e.clientX, e.clientY, e);
        },

        onMouseUp: function(e) {
            e = e.originalEvent;
            // don't do a DOM manipulation in a mouse handler, otherwise iOS safari will not trigger a 'click' event.
            this.asyncUpdatePointer('mouse', e.clientX, e.clientY, e);
        },

        onClick: function(e) {
            e = e.originalEvent;
            this.createClick(e.clientX, e.clientY);
        }


    });

    // return module exports
    return TouchTrackerView;
});