Spamworldpro Mini Shell
Spamworldpro


Server : Apache
System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64
User : corals ( 1002)
PHP Version : 7.4.33
Disable Function : exec,passthru,shell_exec,system
Directory :  /home/corals/old/vendor/magento/module-ui/view/base/web/js/lib/knockout/bindings/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/corals/old/vendor/magento/module-ui/view/base/web/js/lib/knockout/bindings/tooltip.js
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */

define([
    'jquery',
    'ko',
    'underscore',
    'mage/template',
    'text!ui/template/tooltip/tooltip.html',
    '../template/renderer'
], function ($, ko, _, template, tooltipTmpl, renderer) {
    'use strict';

    var tooltip,
        defaults,
        positions,
        transformProp,
        checkedPositions = {},
        iterator = 0,
        previousTooltip,
        tooltipData,
        positionData = {},
        tooltipsCollection = {},
        isTouchDevice = (function () {
            return 'ontouchstart' in document.documentElement;
        })(),
        CLICK_EVENT = (function () {
            return isTouchDevice ? 'touchstart' : 'click';
        })();

    defaults = {
        tooltipWrapper: '[data-tooltip=tooltip-wrapper]',
        tooltipContentBlock: 'data-tooltip-content',
        closeButtonClass: 'action-close',
        tailClass: 'data-tooltip-tail',
        action: 'hover',
        delay: 300,
        track: false,
        step: 20,
        position: 'top',
        closeButton: false,
        showed: false,
        strict: true,
        center: false,
        closeOnScroll: true
    };

    tooltipData = {
        tooltipClasses: '',
        trigger: false,
        timeout: 0,
        element: false,
        event: false,
        targetElement: {},
        showed: false,
        currentID: 0
    };

    /**
     * Polyfill for css transform
     */
    transformProp = (function () {
        var style = document.createElement('div').style,
            base = 'Transform',
            vendors = ['webkit', 'moz', 'ms', 'o'],
            vi = vendors.length,
            property;

        if (typeof style.transform !== 'undefined') {
            return 'transform';
        }

        while (vi--) {
            property = vendors[vi] + base;

            if (typeof style[property] !== 'undefined') {
                return property;
            }
        }
    })();

    positions = {

        /*eslint max-depth: [0, 0]*/

        map: {
            horizontal: {
                s: 'w',
                p: 'left'
            },
            vertical: {
                s: 'h',
                p: 'top'
            }
        },

        /**
         * Wrapper function to get tooltip data (position, className, etc)
         *
         * @param {Object} s - object with sizes and positions elements
         * @returns {Object} tooltip data (position, className, etc)
         */
        top: function (s) {
            return positions._topLeftChecker(s, positions.map, 'vertical', '_bottom', 'top', 'right');
        },

        /**
         * Wrapper function to get tooltip data (position, className, etc)
         *
         * @param {Object} s - object with sizes and positions elements
         * @returns {Object} tooltip data (position, className, etc)
         */
        left: function (s) {
            return positions._topLeftChecker(s, positions.map, 'horizontal', '_right', 'left', 'top');
        },

        /**
         * Wrapper function to get tooltip data (position, className, etc)
         *
         * @param {Object} s - object with sizes and positions elements
         * @returns {Object} tooltip data (position, className, etc)
         */
        bottom: function (s) {
            return positions._bottomRightChecker(s, positions.map, 'vertical', '_top', 'bottom', 'left');
        },

        /**
         * Wrapper function to get tooltip data (position, className, etc)
         *
         * @param {Object} s - object with sizes and positions elements
         * @returns {Object} tooltip data (position, className, etc)
         */
        right: function (s) {
            return positions._bottomRightChecker(s, positions.map, 'horizontal', '_left', 'right', 'bottom');
        },

        /**
         * Check can tooltip setted on current position or not. If can't setted - delegate call.
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} map - mapping for get direction positions
         * @param {String} direction - vertical or horizontal
         * @param {String} className - class whats should be setted to tooltip
         * @param {String} side - parent method name
         * @param {String} delegate - method name if tooltip can't be setted in current position
         * @returns {Object} tooltip data (position, className, etc)
         */
        _topLeftChecker: function (s, map, direction, className, side, delegate) {
            var result = {
                    position: {}
                },
                config = tooltip.getTooltip(tooltipData.currentID),
                startPosition = !config.strict ? s.eventPosition : s.elementPosition,
                changedDirection;

            checkedPositions[side] = true;

            if (
                startPosition[map[direction].p] - s.tooltipSize[map[direction].s] - config.step >
                s.scrollPosition[map[direction].p]
            ) {
                result.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] -
                    config.step;
                result.className = className;
                result.side = side;
                changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';
                result = positions._normalize(s, result, config, delegate, map, changedDirection);
            } else if (!checkedPositions[delegate]) {
                result = positions[delegate].apply(null, arguments);
            } else {
                result = positions.positionCenter(s, result);
            }

            return result;
        },

        /**
         * Check can tooltip setted on current position or not. If can't setted - delegate call.
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} map - mapping for get direction positions
         * @param {String} direction - vertical or horizontal
         * @param {String} className - class whats should be setted to tooltip
         * @param {String} side - parent method name
         * @param {String} delegate - method name if tooltip can't be setted in current position
         * @returns {Object} tooltip data (position, className, etc)
         */
        _bottomRightChecker: function (s, map, direction, className, side, delegate) {
            var result = {
                    position: {}
                },
                config = tooltip.getTooltip(tooltipData.currentID),
                startPosition = !config.strict ? s.eventPosition : {
                    top: s.elementPosition.top + s.elementSize.h,
                    left: s.elementPosition.left + s.elementSize.w
                },
                changedDirection;

            checkedPositions[side] = true;

            if (
                startPosition[map[direction].p] + s.tooltipSize[map[direction].s] + config.step <
                s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]
            ) {
                result.position[map[direction].p] = startPosition[map[direction].p] + config.step;
                result.className = className;
                result.side = side;
                changedDirection = direction === 'vertical' ? 'horizontal' : 'vertical';
                result = positions._normalize(s, result, config, delegate, map, changedDirection);
            } else if (!checkedPositions[delegate]) {
                result = positions[delegate].apply(null, arguments);
            } else {
                result = positions.positionCenter(s, result);
            }

            return result;
        },

        /**
         * Centered tooltip if tooltip does not fit in window
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} data - current data (position, className, etc)
         * @returns {Object} tooltip data (position, className, etc)
         */
        positionCenter: function (s, data) {
            data = positions._positionCenter(s, data, 'horizontal', positions.map);
            data = positions._positionCenter(s, data, 'vertical', positions.map);

            return data;
        },

        /**
         * Centered tooltip side
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} data - current data (position, className, etc)
         * @param {String} direction - vertical or horizontal
         * @param {Object} map - mapping for get direction positions
         * @returns {Object} tooltip data (position, className, etc)
         */
        _positionCenter: function (s, data, direction, map) {
            if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {
                data.position[map[direction].p] = (s.windowSize[map[direction].s] -
                    s.tooltipSize[map[direction].s]) / 2 + s.scrollPosition[map[direction].p];
            } else {
                data.position[map[direction].p] = s.scrollPosition[map[direction].p];
                data.tooltipSize = {};
                data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];
            }

            return data;
        },

        /**
         * Normalize horizontal or vertical position.
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} data - current data (position, className, etc)
         * @param {Object} config - tooltip config
         * @param {String} delegate - method name if tooltip can't be setted in current position
         * @param {Object} map - mapping for get direction positions
         * @param {String} direction - vertical or horizontal
         * @returns {Object} tooltip data (position, className, etc)
         */
        _normalize: function (s, data, config, delegate, map, direction) {
            var startPosition = !config.center ? s.eventPosition : {
                    left: s.elementPosition.left + s.elementSize.w / 2,
                    top: s.elementPosition.top + s.elementSize.h / 2
                },
                depResult;

            if (startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2 >
                s.scrollPosition[map[direction].p] && startPosition[map[direction].p] +
                s.tooltipSize[map[direction].s] / 2 <
                s.scrollPosition[map[direction].p] + s.windowSize[map[direction].s]
            ) {
                data.position[map[direction].p] = startPosition[map[direction].p] - s.tooltipSize[map[direction].s] / 2;
            } else {

                /*eslint-disable no-lonely-if*/
                if (!checkedPositions[delegate]) {
                    depResult = positions[delegate].apply(null, arguments);

                    if (depResult.hasOwnProperty('className')) {
                        data = depResult;
                    } else {
                        data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);
                    }
                } else {
                    data = positions._normalizeTail(s, data, config, delegate, map, direction, startPosition);
                }
            }

            return data;
        },

        /**
         * Calc tail position.
         *
         * @param {Object} s - object with sizes and positions elements
         * @param {Object} data - current data (position, className, etc)
         * @param {Object} config - tooltip config
         * @param {String} delegate - method name if tooltip can't be setted in current position
         * @param {Object} map - mapping for get direction positions
         * @param {String} direction - vertical or horizontal
         * @param {Object} startPosition - start position
         * @returns {Object} tooltip data (position, className, etc)
         */
        _normalizeTail: function (s, data, config, delegate, map, direction, startPosition) {
            data.tail = {};

            if (s.tooltipSize[map[direction].s] < s.windowSize[map[direction].s]) {

                if (
                    startPosition[map[direction].p] >
                    s.windowSize[map[direction].s] / 2 + s.scrollPosition[map[direction].p]
                ) {
                    data.position[map[direction].p] = s.windowSize[map[direction].s] +
                        s.scrollPosition[map[direction].p] - s.tooltipSize[map[direction].s];
                    data.tail[map[direction].p] = startPosition[map[direction].p] -
                        s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];
                } else {
                    data.position[map[direction].p] = s.scrollPosition[map[direction].p];
                    data.tail[map[direction].p] = startPosition[map[direction].p] -
                        s.tooltipSize[map[direction].s] / 2 - data.position[map[direction].p];
                }
            } else {
                data.position[map[direction].p] = s.scrollPosition[map[direction].p];
                data.tail[map[direction].p] = s.eventPosition[map[direction].p] - s.windowSize[map[direction].s] / 2;
                data.tooltipSize = {};
                data.tooltipSize[map[direction].s] = s.windowSize[map[direction].s];
            }

            return data;
        }
    };

    tooltip = {

        /**
         * Set new tooltip to tooltipCollection, save config, and add unic id
         *
         * @param {Object} config - tooltip config
         * @returns {String} tooltip id
         */
        setTooltip: function (config) {
            var property = 'id-' + iterator;

            tooltipsCollection[property] = config;
            iterator++;

            return property;
        },

        /**
         * Get tooltip config by id
         *
         * @param {String} id - tooltip id
         * @returns {Object} tooltip config
         */
        getTooltip: function (id) {
            return tooltipsCollection[id];
        },

        /**
         * Set content to current tooltip
         *
         * @param {Object} tooltipElement - tooltip element
         * @param {Object} viewModel - tooltip view model
         * @param {String} id - tooltip id
         * @param {Object} bindingCtx - tooltip context
         * @param {Object} event - action event
         */
        setContent: function (tooltipElement, viewModel, id, bindingCtx, event) {
            var html = $(tooltipElement).html(),
                config = tooltip.getTooltip(id),
                body = $('body');

            tooltipData.currentID = id;
            tooltipData.trigger = $(event.currentTarget);
            tooltip.setTargetData(event);
            body.on('mousemove.setTargetData', tooltip.setTargetData);
            tooltip.clearTimeout(id);

            tooltipData.timeout = _.delay(function () {
                body.off('mousemove.setTargetData', tooltip.setTargetData);

                if (tooltipData.trigger[0] === tooltipData.targetElement) {
                    tooltip.destroy(id);
                    event.stopPropagation();
                    tooltipElement = tooltip.createTooltip(id);
                    tooltipElement.find('.' + defaults.tooltipContentBlock).append(html);
                    tooltipElement.applyBindings(bindingCtx);
                    tooltip.setHandlers(id);
                    tooltip.setPosition(tooltipElement, id);
                    previousTooltip = id;
                }

            }, config.delay);
        },

        /**
         * Set position to current tooltip
         *
         * @param {Object} tooltipElement - tooltip element
         * @param {String} id - tooltip id
         */
        setPosition: function (tooltipElement, id) {
            var config = tooltip.getTooltip(id);

            tooltip.sizeData = {
                windowSize: {
                    h: $(window).outerHeight(),
                    w: $(window).outerWidth()
                },
                scrollPosition: {
                    top: $(window).scrollTop(),
                    left: $(window).scrollLeft()
                },
                tooltipSize: {
                    h: tooltipElement.outerHeight(),
                    w: tooltipElement.outerWidth()
                },
                elementSize: {
                    h: tooltipData.trigger.outerHeight(),
                    w: tooltipData.trigger.outerWidth()
                },
                elementPosition: tooltipData.trigger.offset(),
                eventPosition: this.getEventPosition(tooltipData.event)
            };

            _.extend(positionData, positions[config.position](tooltip.sizeData));
            tooltipElement.css(positionData.position);
            tooltipElement.addClass(positionData.className);
            tooltip._setTooltipSize(positionData, tooltipElement);
            tooltip._setTailPosition(positionData, tooltipElement);
            checkedPositions = {};
        },

        /**
         * Check position data and change tooltip size if needs
         *
         * @param {Object} data - position data
         * @param {Object} tooltipElement - tooltip element
         */
        _setTooltipSize: function (data, tooltipElement) {
            if (data.tooltipSize) {
                data.tooltipSize.w ?
                    tooltipElement.css('width', data.tooltipSize.w) :
                    tooltipElement.css('height', data.tooltipSize.h);
            }
        },

        /**
         * Check position data and set position to tail
         *
         * @param {Object} data - position data
         * @param {Object} tooltipElement - tooltip element
         */
        _setTailPosition: function (data, tooltipElement) {
            var tail,
                tailMargin;

            if (data.tail) {
                tail = tooltipElement.find('.' + defaults.tailClass);

                if (data.tail.left) {
                    tailMargin = parseInt(tail.css('margin-left'), 10);
                    tail.css('margin-left', tailMargin + data.tail.left);
                } else {
                    tailMargin = parseInt(tail.css('margin-top'), 10);
                    tail.css('margin-top', tailMargin + data.tail.top);
                }
            }
        },

        /**
         * Resolves position for tooltip
         *
         * @param {Object} event
         * @returns {Object}
         */
        getEventPosition: function (event) {
            var position = {
                left: event.originalEvent && event.originalEvent.pageX || 0,
                top: event.originalEvent && event.originalEvent.pageY || 0
            };

            if (position.left === 0 && position.top === 0) {
                _.extend(position, event.target.getBoundingClientRect());
            }

            return position;
        },

        /**
         * Close tooltip if action happened outside handler and tooltip element
         *
         * @param {String} id - tooltip id
         * @param {Object} event - action event
         */
        outerClick: function (id, event) {
            var tooltipElement = $(event.target).parents(defaults.tooltipWrapper)[0],
                isTrigger = event.target === tooltipData.trigger[0] || $.contains(tooltipData.trigger[0], event.target);

            if (tooltipData.showed && tooltipElement !== tooltipData.element[0] && !isTrigger) {
                tooltip.destroy(id);
            }
        },

        /**
         * Parse keydown event and if event trigger is escape key - close tooltip
         *
         * @param {Object} event - action event
         */
        keydownHandler: function (event) {
            if (tooltipData.showed && event.keyCode === 27) {
                tooltip.destroy(tooltipData.currentID);
            }
        },

        /**
         * Change tooltip position when track is enabled
         *
         * @param {Object} event - current event
         */
        track: function (event) {
            var inequality = {},
                map = positions.map,
                translate = {
                    left: 'translateX',
                    top: 'translateY'
                },
                eventPosition = {
                    left: event.pageX,
                    top: event.pageY
                },
                tooltipSize = {
                    w: tooltipData.element.outerWidth(),
                    h: tooltipData.element.outerHeight()
                },
                direction = positionData.side === 'bottom' || positionData.side === 'top' ? 'horizontal' : 'vertical';

            inequality[map[direction].p] = eventPosition[map[direction].p] - (positionData.position[map[direction].p] +
                tooltipSize[map[direction].s] / 2);

            if (positionData.position[map[direction].p] + inequality[map[direction].p] +
                tooltip.sizeData.tooltipSize[map[direction].s] >
                tooltip.sizeData.windowSize[map[direction].s] + tooltip.sizeData.scrollPosition[map[direction].p] ||
                inequality[map[direction].p] + positionData.position[map[direction].p] <
                tooltip.sizeData.scrollPosition[map[direction].p]) {

                return false;
            }

            tooltipData.element[0].style[transformProp] = translate[map[direction].p] +
                '(' + inequality[map[direction].p] + 'px)';
        },

        /**
         * Set handlers to tooltip
         *
         * @param {String} id - tooltip id
         */
        setHandlers: function (id) {
            var config = tooltip.getTooltip(id);

            if (config.track) {
                tooltipData.trigger.on('mousemove.track', tooltip.track);
            }

            if (config.action === 'click') {
                $(window).on(CLICK_EVENT + '.outerClick', tooltip.outerClick.bind(null, id));
            }

            if (config.closeButton) {
                $('.' + config.closeButtonClass).on('click.closeButton', tooltip.destroy.bind(null, id));
            }

            if (config.closeOnScroll) {
                document.addEventListener('scroll', tooltip.destroy, true);
                $(window).on('scroll.tooltip', tooltip.outerClick.bind(null, id));
            }

            $(window).on('keydown.tooltip', tooltip.keydownHandler);
            $(window).on('resize.outerClick', tooltip.outerClick.bind(null, id));
        },

        /**
         * Toggle tooltip
         *
         * @param {Object} tooltipElement - tooltip element
         * @param {Object} viewModel - tooltip view model
         * @param {String} id - tooltip id
         */
        toggleTooltip: function (tooltipElement, viewModel, id) {
            if (previousTooltip === id && tooltipData.showed) {
                tooltip.destroy(id);

                return false;
            }

            tooltip.setContent.apply(null, arguments);

            return false;
        },

        /**
         * Create tooltip and append to DOM
         *
         * @param {String} id - tooltip id
         * @returns {Object} tooltip element
         */
        createTooltip: function (id) {
            var body = $('body'),
                config = tooltip.getTooltip(id);

            $(template(tooltipTmpl, {
                data: config
            })).appendTo(body);

            tooltipData.showed = true;
            tooltipData.element = $(config.tooltipWrapper);

            return tooltipData.element;
        },

        /**
         * Check action and clean timeout
         *
         * @param {String} id - tooltip id
         */
        clearTimeout: function (id) {
            var config = tooltip.getTooltip(id);

            if (config.action === 'hover') {
                clearTimeout(tooltipData.timeout);
            }
        },

        /**
         * Check previous tooltip
         */
        checkPreviousTooltip: function () {
            if (!tooltipData.timeout) {
                tooltip.destroy();
            }
        },

        /**
         * Destroy tooltip instance
         */
        destroy: function () {
            if (tooltipData.element) {
                tooltipData.element.remove();
                tooltipData.showed = false;
            }

            positionData = {};
            tooltipData.timeout = false;
            tooltip.removeHandlers();
        },

        /**
         * Remove tooltip handlers
         */
        removeHandlers: function () {
            $('.' + defaults.closeButtonClass).off('click.closeButton');
            tooltipData.trigger.off('mousemove.track');
            document.removeEventListener('scroll', tooltip.destroy, true);
            $(window).off('scroll.tooltip');
            $(window).off(CLICK_EVENT + '.outerClick');
            $(window).off('keydown.tooltip');
            $(window).off('resize.outerClick');
        },

        /**
         * Set target element
         *
         * @param {Object} event - current event
         */
        setTargetData: function (event) {
            tooltipData.event = event;

            //TODO: bug chrome v.49; Link to issue https://bugs.chromium.org/p/chromium/issues/detail?id=161464
            if (event.timeStamp - (tooltipData.timestamp || 0) < 1) {
                return;
            }

            if (event.type === 'mousemove') {
                tooltipData.targetElement = event.target;
            } else {
                tooltipData.targetElement = event.currentTarget;
                tooltipData.timestamp = event.timeStamp;
            }
        },

        /**
         * Merged user config with defaults configuration
         *
         * @param {Object} config - user config
         * @returns {Object} merged config
         */
        processingConfig: function (config) {
            return _.extend({}, defaults, config);
        }
    };

    ko.bindingHandlers.tooltip = {

        /**
         * Initialize tooltip
         *
         * @param {Object} elem - tooltip DOM element
         * @param {Function} valueAccessor - ko observable property, tooltip data
         * @param {Object} allBindings - all bindings on current element
         * @param {Object} viewModel - current element viewModel
         * @param {Object} bindingCtx - current element binding context
         */
        init: function (elem, valueAccessor, allBindings, viewModel, bindingCtx) {
            var config = tooltip.processingConfig(valueAccessor()),
                $parentScope = config.parentScope ? $(config.parentScope) : $(elem).parent(),
                tooltipId;

            $(elem).addClass('hidden');

            if (isTouchDevice) {
                config.action = 'click';
            }
            tooltipId = tooltip.setTooltip(config);

            if (config.action === 'hover') {
                $parentScope.on(
                    'mouseenter',
                    config.trigger,
                    tooltip.setContent.bind(null, elem, viewModel, tooltipId, bindingCtx)
                );
                $parentScope.on(
                    'mouseleave',
                    config.trigger,
                    tooltip.checkPreviousTooltip.bind(null, tooltipId)
                );
            } else if (config.action === 'click') {
                $parentScope.on(
                    'click',
                    config.trigger,
                    tooltip.toggleTooltip.bind(null, elem, viewModel, tooltipId, bindingCtx)
                );
            }

            return {
                controlsDescendantBindings: true
            };
        }
    };

    renderer.addAttribute('tooltip');
});

Spamworldpro Mini