mirror of
				https://github.com/zulip/zulip.git
				synced 2025-11-04 05:53:43 +00:00 
			
		
		
		
	This commit prepares the frontend code to be consumed by webpack. It is a hack: In theory, modules should be declaring and importing the modules they depend on and the globals they expose directly. However, that requires significant per-module work, which we don't really want to block moving our toolchain to webpack on. So we expose the modules by setting window.varName = varName; as needed in the js files.
		
			
				
	
	
		
			248 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
var hotspots = (function () {
 | 
						|
 | 
						|
var exports = {};
 | 
						|
 | 
						|
// popover orientations
 | 
						|
var TOP = 'top';
 | 
						|
var LEFT = 'left';
 | 
						|
var RIGHT = 'right';
 | 
						|
var BOTTOM = 'bottom';
 | 
						|
var VIEWPORT_CENTER = 'viewport_center';
 | 
						|
 | 
						|
// popover orientation can optionally be fixed here (property: popover),
 | 
						|
// otherwise popovers.compute_placement is used to compute orientation
 | 
						|
var HOTSPOT_LOCATIONS = {
 | 
						|
    intro_reply: {
 | 
						|
        element: '.selected_message .messagebox-content',
 | 
						|
        offset_x: 0.85,
 | 
						|
        offset_y: 0.7,
 | 
						|
        popover: BOTTOM,
 | 
						|
    },
 | 
						|
    intro_streams: {
 | 
						|
        element: '#streams_header .sidebar-title',
 | 
						|
        offset_x: 1.35,
 | 
						|
        offset_y: 0.39,
 | 
						|
    },
 | 
						|
    intro_topics: {
 | 
						|
        element: '.topic-name',
 | 
						|
        offset_x: 0.8,
 | 
						|
        offset_y: 0.39,
 | 
						|
    },
 | 
						|
    intro_compose: {
 | 
						|
        element: '#left_bar_compose_stream_button_big',
 | 
						|
        offset_x: 0,
 | 
						|
        offset_y: 0,
 | 
						|
    },
 | 
						|
};
 | 
						|
 | 
						|
// popover illustration url(s)
 | 
						|
var WHALE = '/static/images/hotspots/whale.svg';
 | 
						|
 | 
						|
exports.post_hotspot_as_read = function (hotspot_name) {
 | 
						|
    channel.post({
 | 
						|
        url: '/json/users/me/hotspots',
 | 
						|
        data: { hotspot: JSON.stringify(hotspot_name) },
 | 
						|
        error: function (err) {
 | 
						|
            blueslip.error(err.responseText);
 | 
						|
        },
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
function place_icon(hotspot) {
 | 
						|
    var element = $(hotspot.location.element);
 | 
						|
    var icon = $('#hotspot_' + hotspot.name + '_icon');
 | 
						|
 | 
						|
    if (element.length === 0 || element.css('display') === 'none' ||
 | 
						|
        !element.is(':visible') || element.is(':hidden')) {
 | 
						|
        icon.css('display', 'none');
 | 
						|
        return false;
 | 
						|
    }
 | 
						|
 | 
						|
    var offset = {
 | 
						|
        top: element.outerHeight() * hotspot.location.offset_y,
 | 
						|
        left: element.outerWidth() * hotspot.location.offset_x,
 | 
						|
    };
 | 
						|
    var client_rect = element.get(0).getBoundingClientRect();
 | 
						|
    var placement = {
 | 
						|
        top: client_rect.top + offset.top,
 | 
						|
        left: client_rect.left + offset.left,
 | 
						|
    };
 | 
						|
    icon.css('display', 'block');
 | 
						|
    icon.css(placement);
 | 
						|
    return true;
 | 
						|
}
 | 
						|
 | 
						|
function place_popover(hotspot) {
 | 
						|
    if (!hotspot.location.element) {
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    var popover_width = $('#hotspot_' + hotspot.name + '_overlay .hotspot-popover').outerWidth();
 | 
						|
    var popover_height = $('#hotspot_' + hotspot.name + '_overlay .hotspot-popover').outerHeight();
 | 
						|
    var el_width = $(hotspot.location.element).outerWidth();
 | 
						|
    var el_height = $(hotspot.location.element).outerHeight();
 | 
						|
    var arrow_offset = 20;
 | 
						|
 | 
						|
    var popover_offset;
 | 
						|
    var arrow_placement;
 | 
						|
    var orientation = hotspot.location.popover ||
 | 
						|
        popovers.compute_placement(
 | 
						|
            $(hotspot.location.element),
 | 
						|
            popover_height,
 | 
						|
            popover_width,
 | 
						|
            false
 | 
						|
        );
 | 
						|
 | 
						|
    switch (orientation) {
 | 
						|
    case TOP:
 | 
						|
        popover_offset = {
 | 
						|
            top: -(popover_height + arrow_offset),
 | 
						|
            left: el_width / 2 - popover_width / 2,
 | 
						|
        };
 | 
						|
        arrow_placement = 'bottom';
 | 
						|
        break;
 | 
						|
 | 
						|
    case LEFT:
 | 
						|
        popover_offset = {
 | 
						|
            top: el_height / 2 - popover_height / 2,
 | 
						|
            left: -(popover_width + arrow_offset),
 | 
						|
        };
 | 
						|
        arrow_placement = 'right';
 | 
						|
        break;
 | 
						|
 | 
						|
    case BOTTOM:
 | 
						|
        popover_offset = {
 | 
						|
            top: el_height + arrow_offset,
 | 
						|
            left: el_width / 2 - popover_width / 2,
 | 
						|
        };
 | 
						|
        arrow_placement = 'top';
 | 
						|
        break;
 | 
						|
 | 
						|
    case RIGHT:
 | 
						|
        popover_offset = {
 | 
						|
            top: el_height / 2 - popover_height / 2,
 | 
						|
            left: el_width + arrow_offset,
 | 
						|
        };
 | 
						|
        arrow_placement = 'left';
 | 
						|
        break;
 | 
						|
 | 
						|
    case VIEWPORT_CENTER:
 | 
						|
        popover_offset = {
 | 
						|
            top: el_height / 2,
 | 
						|
            left: el_width / 2,
 | 
						|
        };
 | 
						|
        arrow_placement = '';
 | 
						|
        break;
 | 
						|
 | 
						|
    default:
 | 
						|
        blueslip.error(
 | 
						|
            'Invalid popover placement value for hotspot \'' +
 | 
						|
                hotspot.name + '\''
 | 
						|
        );
 | 
						|
        break;
 | 
						|
    }
 | 
						|
 | 
						|
    // position arrow
 | 
						|
    arrow_placement = 'arrow-' + arrow_placement;
 | 
						|
    $('#hotspot_' + hotspot.name + '_overlay .hotspot-popover')
 | 
						|
        .removeClass('arrow-top arrow-left arrow-bottom arrow-right')
 | 
						|
        .addClass(arrow_placement);
 | 
						|
 | 
						|
    // position popover
 | 
						|
    var popover_placement;
 | 
						|
    if (orientation === VIEWPORT_CENTER) {
 | 
						|
        popover_placement = {
 | 
						|
            top: '45%',
 | 
						|
            left: '50%',
 | 
						|
            transform: 'translate(-50%, -50%)',
 | 
						|
        };
 | 
						|
    } else {
 | 
						|
        var client_rect = $(hotspot.location.element).get(0).getBoundingClientRect();
 | 
						|
        popover_placement = {
 | 
						|
            top: client_rect.top + popover_offset.top,
 | 
						|
            left: client_rect.left + popover_offset.left,
 | 
						|
            transform: '',
 | 
						|
        };
 | 
						|
    }
 | 
						|
 | 
						|
    $('#hotspot_' + hotspot.name + '_overlay .hotspot-popover')
 | 
						|
        .css(popover_placement);
 | 
						|
}
 | 
						|
 | 
						|
function insert_hotspot_into_DOM(hotspot) {
 | 
						|
    if (hotspot.name === "intro_reply") {
 | 
						|
        $('#bottom_whitespace').append(templates.render('intro_reply_hotspot', {}));
 | 
						|
        return;
 | 
						|
    }
 | 
						|
 | 
						|
    var hotspot_overlay_HTML = templates.render('hotspot_overlay', {
 | 
						|
        name: hotspot.name,
 | 
						|
        title: hotspot.title,
 | 
						|
        description: hotspot.description,
 | 
						|
        img: WHALE,
 | 
						|
    });
 | 
						|
 | 
						|
    var hotspot_icon_HTML =
 | 
						|
        '<div class="hotspot-icon" id="hotspot_' + hotspot.name + '_icon">' +
 | 
						|
            '<span class="dot"></span>' +
 | 
						|
            '<span class="pulse"></span>' +
 | 
						|
            '<div class="bounce"><span class="bounce-icon">?</span></div>' +
 | 
						|
        '</div>';
 | 
						|
 | 
						|
    setTimeout(function () {
 | 
						|
        $('body').prepend(hotspot_icon_HTML);
 | 
						|
        $('body').prepend(hotspot_overlay_HTML);
 | 
						|
        if (place_icon(hotspot)) {
 | 
						|
            place_popover(hotspot);
 | 
						|
        }
 | 
						|
 | 
						|
        // reposition on any event that might update the UI
 | 
						|
        ['resize', 'scroll', 'onkeydown', 'click'].forEach(function (event_name) {
 | 
						|
            window.addEventListener(event_name, _.debounce(function () {
 | 
						|
                if (place_icon(hotspot)) {
 | 
						|
                    place_popover(hotspot);
 | 
						|
                }
 | 
						|
            }, 10), true);
 | 
						|
        });
 | 
						|
    }, hotspot.delay * 1000);
 | 
						|
}
 | 
						|
 | 
						|
exports.is_open = function () {
 | 
						|
    return $('.hotspot.overlay').hasClass('show');
 | 
						|
};
 | 
						|
 | 
						|
exports.close_hotspot_icon = function (elem) {
 | 
						|
    $(elem).animate({ opacity: 0 }, {
 | 
						|
        duration: 300,
 | 
						|
        done: function () {
 | 
						|
            $(elem).css({ display: 'none' });
 | 
						|
        }.bind(elem),
 | 
						|
    });
 | 
						|
};
 | 
						|
 | 
						|
function close_read_hotspots(new_hotspots) {
 | 
						|
    var unwanted_hotspots = _.difference(_.keys(HOTSPOT_LOCATIONS), _.pluck(new_hotspots, 'name'));
 | 
						|
    _.each(unwanted_hotspots, function (hotspot_name) {
 | 
						|
        exports.close_hotspot_icon($('#hotspot_' + hotspot_name + '_icon'));
 | 
						|
    });
 | 
						|
}
 | 
						|
 | 
						|
exports.load_new = function (new_hotspots) {
 | 
						|
    close_read_hotspots(new_hotspots);
 | 
						|
    new_hotspots.forEach(function (hotspot) {
 | 
						|
        hotspot.location = HOTSPOT_LOCATIONS[hotspot.name];
 | 
						|
    });
 | 
						|
    new_hotspots.forEach(insert_hotspot_into_DOM);
 | 
						|
};
 | 
						|
 | 
						|
exports.initialize = function () {
 | 
						|
    exports.load_new(page_params.hotspots);
 | 
						|
};
 | 
						|
 | 
						|
return exports;
 | 
						|
}());
 | 
						|
if (typeof module !== 'undefined') {
 | 
						|
    module.exports = hotspots;
 | 
						|
}
 | 
						|
window.hotspots = hotspots;
 |