UNPKG

formstone

Version:

Library of modular front end components.

325 lines (264 loc) 7.91 kB
/* global define */ (function(factory) { if (typeof define === "function" && define.amd) { define([ "jquery", "./core" ], factory); } else { factory(jQuery, Formstone); } }(function($, Formstone) { "use strict"; /** * @method private * @name construct * @description Builds instance. * @param data [object] "Instance data" */ function construct(data) { this.on(Events.mouseEnter, data, onMouseEnter); } /** * @method private * @name destruct * @description Tears down instance. * @param data [object] "Instance data" */ function destruct(data) { removeTooltip(); this.off(Events.namespace); } /** * @method private * @name onMouseEnter * @description Handles mouse enter event. * @param e [object] "Event data" */ function onMouseEnter(e) { removeTooltip(); var data = e.data; data.left = e.pageX; data.top = e.pageY; buildTooltip(data); } /** * @method private * @name onMouseLeave * @description Handles mouse leave event. * @param e [object] "Event data" */ function onMouseLeave(e) { var data = e.data; Functions.clearTimer(data.timer); removeTooltip(); } /** * @method private * @name onMouseLeave * @description Handles mouse move event. * @param e [object] "Event data" */ function onMouseMove(e) { positionTooltip(e.pageX, e.pageY); } /** * @method private * @name buildTooltip * @description Builds new tooltip instance. * @param data [object] "Instance data" */ function buildTooltip(data) { removeTooltip(); var html = ''; html += '<div class="'; html += [RawClasses.base, RawClasses[data.direction], data.theme, data.customClass].join(" "); html += '">'; html += '<div class="' + RawClasses.content + '">'; html += data.formatter.call(data.$el, data); html += '<span class="' + RawClasses.caret + '"></span>'; html += '</div>'; html += '</div>'; Instance = { $tooltip: $(html), $el: data.$el }; Formstone.$body.append(Instance.$tooltip); var $content = Instance.$tooltip.find(Classes.content), $caret = Instance.$tooltip.find(Classes.caret), offset = data.$el.offset(), height = data.$el.outerHeight(), width = data.$el.outerWidth(), tooltipLeft = 0, tooltipTop = 0, contentLeft = 0, contentTop = 0, caretLeft = false, caretTop = false, caretHeight = $caret.outerHeight(true), caretWidth = $caret.outerWidth(true), contentHeight = $content.outerHeight(true), contentWidth = $content.outerWidth(true); // position content if (data.direction === "right" || data.direction === "left") { caretTop = (contentHeight - caretHeight) / 2; contentTop = -contentHeight / 2; if (data.direction === "right") { contentLeft = data.margin; } else if (data.direction === "left") { contentLeft = -(contentWidth + data.margin); } } else { caretLeft = (contentWidth - caretWidth) / 2; contentLeft = -contentWidth / 2; if (data.direction === "bottom") { contentTop = data.margin; } else if (data.direction === "top") { contentTop = -(contentHeight + data.margin); } } // Modify Dom $content.css({ top: contentTop, left: contentLeft }); $caret.css({ top: caretTop, left: caretLeft }); // Position tooltip if (data.follow) { data.$el.on(Events.mouseMove, data, onMouseMove); } else { if (data.match) { if (data.direction === "right" || data.direction === "left") { tooltipTop = data.top; // mouse pos if (data.direction === "right") { tooltipLeft = offset.left + width; } else if (data.direction === "left") { tooltipLeft = offset.left; } } else { tooltipLeft = data.left; // mouse pos if (data.direction === "bottom") { tooltipTop = offset.top + height; } else if (data.direction === "top") { tooltipTop = offset.top; } } } else { if (data.direction === "right" || data.direction === "left") { tooltipTop = offset.top + (height / 2); if (data.direction === "right") { tooltipLeft = offset.left + width; } else if (data.direction === "left") { tooltipLeft = offset.left; } } else { tooltipLeft = offset.left + (width / 2); if (data.direction === "bottom") { tooltipTop = offset.top + height; } else if (data.direction === "top") { tooltipTop = offset.top; } } } positionTooltip(tooltipLeft, tooltipTop); } data.timer = Functions.startTimer(data.timer, data.delay, function() { Instance.$tooltip.addClass(RawClasses.visible); }); data.$el.one(Events.mouseLeave, data, onMouseLeave); } /** * @method private * @name positionTooltip * @description Positions active tooltip instance. * @param left [int] "Left position" * @param top [int] "Top position" */ function positionTooltip(left, top) { if (Instance) { Instance.$tooltip.css({ left: left, top: top }); } } /** * @method private * @name removeTooltip * @description Removes active tooltip instance. */ function removeTooltip() { if (Instance) { Instance.$el.off([Events.mouseMove, Events.mouseLeave].join(" ")); Instance.$tooltip.remove(); Instance = null; } } /** * @method private * @name format * @description Formats tooltip text. * @return [string] "Tooltip text" */ function format(data) { return this.data("title"); } /** * @plugin * @name Tooltip * @description A jQuery plugin for simple tooltips. * @type widget * @main tooltip.js * @main tooltip.css * @dependency jQuery * @dependency core.js */ var Plugin = Formstone.Plugin("tooltip", { widget: true, /** * @options * @param customClass [string] <''> "Class applied to instance" * @param delay [int] <0> "Hover delay" * @param direction [string] <'top'> "Tooltip direction" * @param follow [boolean] <false> "Flag to follow mouse" * @param formatter [function] <$.noop> "Text format function" * @param margin [int] <15> "Tooltip margin" * @param match [boolean] <false> "Flag to match mouse position" * @param theme [string] <"fs-light"> "Theme class name" */ defaults: { customClass: "", delay: 0, direction: "top", follow: false, formatter: format, margin: 15, match: false, theme: "fs-light" }, classes: [ "content", "caret", "visible", "top", "bottom", "right", "left" ], methods: { _construct: construct, _destruct: destruct } }), // Localize References Classes = Plugin.classes, RawClasses = Classes.raw, Events = Plugin.events, Functions = Plugin.functions, // Singleton Instance = null; }) );