dist/up.js in upjs-rails-0.12.3 vs dist/up.js in upjs-rails-0.12.4

- old
+ new

@@ -23,11 +23,11 @@ (function() { var slice = [].slice; up.util = (function($) { - var $createElementFromSelector, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS, ajax, any, argNames, cache, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, createSelectorFromElement, cssAnimate, debug, detect, each, emptyJQuery, endsWith, error, escapePressed, evalConsoleTemplate, extend, findWithSelf, finishCssAnimate, fixedToAbsolute, forceCompositing, identity, ifGiven, isArray, isBlank, isDeferred, isDefined, isElement, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isNumber, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, locationFromXhr, map, measure, memoize, merge, methodFromXhr, multiSelector, nextFrame, normalizeMethod, normalizeUrl, nullJquery, offsetParent, once, only, option, options, presence, presentAttr, remove, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, setMissingAttrs, startsWith, temporaryCss, times, toArray, trim, unJquery, uniq, unwrapElement, warn; + var $createElementFromSelector, ANIMATION_PROMISE_KEY, CONSOLE_PLACEHOLDERS, ajax, any, cache, castedAttr, clientSize, compact, config, contains, copy, copyAttributes, createElement, createElementFromHtml, createSelectorFromElement, cssAnimate, debug, detect, each, emptyJQuery, endsWith, error, escapePressed, evalConsoleTemplate, extend, findWithSelf, finishCssAnimate, fixedToAbsolute, forceCompositing, identity, ifGiven, isArray, isBlank, isDeferred, isDefined, isElement, isFunction, isGiven, isHash, isJQuery, isMissing, isNull, isNumber, isObject, isPresent, isPromise, isStandardPort, isString, isUndefined, isUnmodifiedKeyEvent, isUnmodifiedMouseEvent, last, locationFromXhr, map, measure, memoize, merge, methodFromXhr, multiSelector, nextFrame, normalizeMethod, normalizeUrl, nullJquery, offsetParent, once, only, option, options, presence, presentAttr, remove, resolvableWhen, resolvedDeferred, resolvedPromise, scrollbarWidth, select, setMissingAttrs, startsWith, temporaryCss, times, toArray, trim, unJquery, uniq, unwrapElement, warn; memoize = function(func) { var cache, cached; cache = void 0; cached = false; return function() { @@ -576,11 +576,11 @@ } }; forceCompositing = function($element) { var memo, oldTransforms; oldTransforms = $element.css(['transform', '-webkit-transform']); - if (isBlank(oldTransforms)) { + if (isBlank(oldTransforms) || oldTransforms['transform'] === 'none') { memo = function() { return $element.css(oldTransforms); }; $element.css({ 'transform': 'translateZ(0)', @@ -1100,22 +1100,11 @@ top: elementCoords.top - futureParentCoords.top + $viewport.scrollTop(), right: '', bottom: '' }); }; - argNames = function(fun) { - var code, match, pattern; - code = fun.toString(); - pattern = new RegExp('\\(([^\\)]*)\\)'); - if (match = code.match(pattern)) { - return match[1].split(/\s*,\s*/); - } else { - return error('Could not parse argument names of %o', fun); - } - }; return { - argNames: argNames, offsetParent: offsetParent, fixedToAbsolute: fixedToAbsolute, presentAttr: presentAttr, createElement: createElement, normalizeUrl: normalizeUrl, @@ -1318,11 +1307,11 @@ Currently Up.js supports IE9 with jQuery 1.9+. On older browsers Up.js will prevent itself from booting, leaving you with a classic server-side application. - @up.browser.isSupported + @method up.browser.isSupported */ isSupported = function() { return (!isIE8OrWorse()) && isRecentJQuery(); }; return { @@ -1353,11 +1342,11 @@ up.on('up:fragment:inserted', function($fragment) { console.log("Looks like we have a new %o!", $fragment); }); -The event is triggered *before* Up has compiled the fragment with your [custom behavior](/up.magic). +The event is triggered *before* Up has compiled the fragment with your [custom elements](/up.syntax). Upon receiving the event, Up.js will start compilation. \#\#\# `fragment:destroyed` event @@ -1375,127 +1364,21 @@ \#\#\# Incomplete documentation! We need to work on this page: -- Decide whether to refactor this into document events -- Decide whether `fragment:enter` and `fragment:leave` would be better names - Decide if we wouldn't rather document events in the respective module (e.g. proxy). @class up.bus */ (function() { var slice = [].slice; up.bus = (function($) { - var emit, nobodyPrevents, reset, u; + var defaultLiveDescriptions, emit, emitReset, live, liveDescriptions, nobodyPrevents, onEscape, restoreSnapshot, snapshot, u, upListenerToJqueryListener; u = up.util; - - /** - Emits an event with the given name and properties. - - \#\#\#\# Example - - up.on('my:event', function(event) { - console.log(event.foo); - }); - - up.emit('my:event', { foo: 'bar' }); - * Prints "bar" to the console - - @method up.emit - @param {String} eventName - The name of the event. - @param {Object} [eventProps={}] - A list of properties to become part of the event object - that will be passed to listeners. Note that the event object - will by default include properties like `preventDefault()` - or `stopPropagation()`. - @param {jQuery} [eventProps.$element=$(document)] - The element on which the event is trigered. - @protected - */ - emit = function(eventName, eventProps) { - var $target, event; - if (eventProps == null) { - eventProps = {}; - } - event = $.Event(eventName, eventProps); - $target = eventProps.$element || $(document); - u.debug("Emitting %o on %o with props %o", eventName, $target, eventProps); - $target.trigger(event); - return event; - }; - - /** - [Emits an event](/up.emit) and returns whether any listener has prevented the default action. - - @method up.bus.nobodyPrevents - @param {String} eventName - @param {Object} eventProps - @protected - */ - nobodyPrevents = function() { - var args, event; - args = 1 <= arguments.length ? slice.call(arguments, 0) : []; - event = emit.apply(null, args); - return !event.isDefaultPrevented(); - }; - - /** - Resets Up.js to the state when it was booted. - All custom event handlers, animations, etc. that have been registered - will be discarded. - - This is an internal method for to enable unit testing. - Don't use this in production. - - @protected - @method up.reset - */ - reset = function() { - return up.emit('up:framework:reset'); - }; - return { - emit: emit, - nobodyPrevents: nobodyPrevents, - reset: reset - }; - })(jQuery); - - up.reset = up.bus.reset; - - up.emit = up.bus.emit; - -}).call(this); - -/** -Registering behavior and custom elements -======================================== - -Up.js keeps a persistent Javascript environment during page transitions. -To prevent memory leaks it is important to cleanly set up and tear down -event handlers and custom elements. - -\#\#\# Incomplete documentation! - -We need to work on this page: - -- Better class-level introduction for this module - -@class up.magic - */ - -(function() { - var slice = [].slice; - - up.magic = (function($) { - var DESTROYABLE_CLASS, DESTROYER_KEY, applyCompiler, compile, compiler, compilers, data, defaultCompilers, defaultLiveDescriptions, destroy, hello, live, liveDescriptions, onEscape, reset, snapshot, u, upListenerToJqueryListener; - u = up.util; - DESTROYABLE_CLASS = 'up-destroyable'; - DESTROYER_KEY = 'up-destroyer'; liveDescriptions = []; defaultLiveDescriptions = null; /** * Convert an Up.js style listener (second argument is the event target @@ -1503,11 +1386,11 @@ */ upListenerToJqueryListener = function(upListener) { return function(event) { var $me; $me = event.$element || $(this); - return upListener.apply($me.get(0), [event, $me, data($me)]); + return upListener.apply($me.get(0), [event, $me, up.syntax.data($me)]); }; }; /** Listens to an event on `document`. @@ -1560,11 +1443,10 @@ up.on('click', '.button', function() { $(this).something(); }); - @method up.on @param {String} events A space-separated list of event names to bind. @param {String} [selector] The selector of an element on which the event must be triggered. @@ -1595,10 +1477,154 @@ return $document.off.apply($document, description); }; }; /** + Emits an event with the given name and properties. + + \#\#\#\# Example + + up.on('my:event', function(event) { + console.log(event.foo); + }); + + up.emit('my:event', { foo: 'bar' }); + * Prints "bar" to the console + + @method up.emit + @param {String} eventName + The name of the event. + @param {Object} [eventProps={}] + A list of properties to become part of the event object + that will be passed to listeners. Note that the event object + will by default include properties like `preventDefault()` + or `stopPropagation()`. + @param {jQuery} [eventProps.$element=$(document)] + The element on which the event is trigered. + @protected + */ + emit = function(eventName, eventProps) { + var $target, event; + if (eventProps == null) { + eventProps = {}; + } + event = $.Event(eventName, eventProps); + $target = eventProps.$element || $(document); + u.debug("Emitting %o on %o with props %o", eventName, $target, eventProps); + $target.trigger(event); + return event; + }; + + /** + [Emits an event](/up.emit) and returns whether any listener has prevented the default action. + + @method up.bus.nobodyPrevents + @param {String} eventName + @param {Object} eventProps + @protected + */ + nobodyPrevents = function() { + var args, event; + args = 1 <= arguments.length ? slice.call(arguments, 0) : []; + event = emit.apply(null, args); + return !event.isDefaultPrevented(); + }; + onEscape = function(handler) { + return live('keydown', 'body', function(event) { + if (u.escapePressed(event)) { + return handler(event); + } + }); + }; + + /** + Makes a snapshot of the currently registered event listeners, + to later be restored through [`up.bus.reset`](/up.bus.reset). + + @private + */ + snapshot = function() { + return defaultLiveDescriptions = u.copy(liveDescriptions); + }; + + /** + Resets the list of registered event listeners to the + moment when the framework was booted. + + @private + */ + restoreSnapshot = function() { + var description, i, len, ref; + for (i = 0, len = liveDescriptions.length; i < len; i++) { + description = liveDescriptions[i]; + if (!u.contains(defaultLiveDescriptions, description)) { + (ref = $(document)).off.apply(ref, description); + } + } + return liveDescriptions = u.copy(defaultLiveDescriptions); + }; + + /** + Resets Up.js to the state when it was booted. + All custom event handlers, animations, etc. that have been registered + will be discarded. + + This is an internal method for to enable unit testing. + Don't use this in production. + + @protected + @method up.reset + */ + emitReset = function() { + return up.emit('up:framework:reset'); + }; + live('up:framework:boot', snapshot); + live('up:framework:reset', restoreSnapshot); + return { + on: live, + emit: emit, + nobodyPrevents: nobodyPrevents, + onEscape: onEscape, + emitReset: emitReset + }; + })(jQuery); + + up.on = up.bus.on; + + up.emit = up.bus.emit; + + up.reset = up.bus.emitReset; + +}).call(this); + +/** +Custom elements +=============== + +Up.js keeps a persistent Javascript environment during page transitions. +To prevent memory leaks it is important to cleanly set up and tear down +event handlers and custom elements. + +\#\#\# Incomplete documentation! + +We need to work on this page: + +- Better class-level introduction for this module + +@class up.syntax + */ + +(function() { + var slice = [].slice; + + up.syntax = (function($) { + var DESTROYABLE_CLASS, DESTROYER_KEY, applyCompiler, compile, compiler, compilers, data, defaultCompilers, destroy, hello, reset, snapshot, u; + u = up.util; + DESTROYABLE_CLASS = 'up-destroyable'; + DESTROYER_KEY = 'up-destroyer'; + + /** Registers a function to be called whenever an element with the given selector is inserted into the DOM. $('.action').compiler(function($element) { // your code here @@ -1813,28 +1839,33 @@ The API of this method is likely to change in the future, so we can support getting or setting individual keys. @protected - @method up.magic.data + @method up.syntax.data @param {String|Element|jQuery} elementOrSelector */ /* - Stores a JSON-string with the element. + Looks for an `up-data` attribute on the given element, then parses + its value as JSON and returns the JSON object. If an element annotated with [`up-data`] is inserted into the DOM, Up will parse the JSON and pass the resulting object to any matching - [`up.compiler`](/up.magic.compiler) handlers. + [`up.compiler`](/up.syntax.compiler) handlers. Similarly, when an event is triggered on an element annotated with [`up-data`], the parsed object will be passed to any matching [`up.on`](/up.on) handlers. @ujs @method [up-data] @param {JSON} [up-data] + @return + The JSON-decoded value of the `up-data` attribute. + + Returns an empty object (`{}`) if the element has no (or an empty) `up-data` attribute. */ data = function(elementOrSelector) { var $element, json; $element = $(elementOrSelector); json = $element.attr('up-data'); @@ -1845,36 +1876,25 @@ } }; /** Makes a snapshot of the currently registered event listeners, - to later be restored through [`up.bus.reset`](/up.bus.reset). + to later be restored through `reset`. @private - @method up.magic.snapshot */ snapshot = function() { - defaultLiveDescriptions = u.copy(liveDescriptions); return defaultCompilers = u.copy(compilers); }; /** - Resets the list of registered event listeners to the + Resets the list of registered compiler directives to the moment when the framework was booted. @private - @method up.magic.reset */ reset = function() { - var description, i, len, ref; - for (i = 0, len = liveDescriptions.length; i < len; i++) { - description = liveDescriptions[i]; - if (!u.contains(defaultLiveDescriptions, description)) { - (ref = $(document)).off.apply(ref, description); - } - } - liveDescriptions = u.copy(defaultLiveDescriptions); return compilers = u.copy(defaultCompilers); }; /** Sends a notification that the given element has been inserted @@ -1899,43 +1919,32 @@ up.emit('up:fragment:inserted', { $element: $element }); return $element; }; - onEscape = function(handler) { - return live('keydown', 'body', function(event) { - if (u.escapePressed(event)) { - return handler(event); - } - }); - }; - live('ready', (function() { + up.on('ready', (function() { return hello(document.body); })); - live('up:fragment:inserted', function(event) { + up.on('up:fragment:inserted', function(event) { return compile(event.$element); }); - live('up:fragment:destroy', function(event) { + up.on('up:fragment:destroy', function(event) { return destroy(event.$element); }); - live('up:framework:boot', snapshot); - live('up:framework:reset', reset); + up.on('up:framework:boot', snapshot); + up.on('up:framework:reset', reset); return { compiler: compiler, - on: live, hello: hello, - onEscape: onEscape, data: data }; })(jQuery); - up.compiler = up.magic.compiler; + up.compiler = up.syntax.compiler; - up.on = up.magic.on; + up.hello = up.syntax.hello; - up.hello = up.magic.hello; - up.ready = function() { return up.util.error('up.ready no longer exists. Please use up.hello instead.'); }; up.awaken = function() { @@ -2228,17 +2237,17 @@ \#\#\#\# Example This will scroll a `<div class="main">...</div>` to a Y-position of 100 pixels: - up.scoll('.main', 100); + up.scroll('.main', 100); \#\#\#\# Animating the scrolling motion The scrolling can (optionally) be animated. - up.scoll('.main', 100, { + up.scroll('.main', 100, { easing: 'swing', duration: 250 }); If the given viewport is already in a scroll animation when `up.scroll` @@ -2733,21 +2742,16 @@ /** Changing page fragments programmatically ======================================== -This module contains Up's core functions to insert, change -or destroy page fragments. +This module contains Up.js's core functions to [change](/up.replace) or [destroy](/up.destroy) + page fragments via Javascript. -\#\#\# Incomplete documentation! +All the other Up.js modules (like [`up.link`](/up.link) or [`up.modal`](/up.modal)) +are based on this module. -We need to work on this page: - -- Explain the UJS approach vs. pragmatic approach -- Examples - - @class up.flow */ (function() { up.flow = (function($) { @@ -3165,32 +3169,36 @@ up.first = up.flow.first; }).call(this); /** -Animation and transitions -========================= +Animation +========= -Any fragment change in Up.js can be animated. +Whenever you change a page fragment (through methods like +[`up.replace`](/up.replace) or UJS attributes like [`up-target`](/up-target)) +you can animate the change. - <a href="/users" data-target=".list" up-transition="cross-fade">Show users</a> +For instance, when you replace a selector `.list` with a new `.list` +from the server, you can add an `up-transition="cross-fade"` attribute +to smoothly fade out the old `.list` while fading in the new `.list`: -Or a dialog open: + <a href="/users" up-target=".list" up-transition="cross-fade">Show users</a> +When we morph between an old an new element, we call it a *transition*. +In contrast, when we animate a new element without simultaneously removing an +old element, we call it an *animation*. + +An example for an animation is opening a new dialog, which we can animate +using the `up-animation` attribute: + <a href="/users" up-modal=".list" up-animation="move-from-top">Show users</a> -Up.js ships with a number of predefined animations and transitions, -and you can easily define your own using Javascript or CSS. - - -\#\#\# Incomplete documentation! - -We need to work on this page: - -- Explain the difference between transitions and animations -- Demo the built-in animations and transitions -- Explain ghosting +Up.js ships with a number of predefined [animations](/up.animate#named-animation) +and [transitions](/up.morph#named-animation). +You can also easily [define your own animations](/up.animation) +or [transitions](/up.transition) using Javascript or CSS. @class up.motion */ @@ -3356,21 +3364,21 @@ return newScrollTop = $viewport.scrollTop(); }); oldCopy.moveTop(newScrollTop - oldScrollTop); $old.hide(); showNew = u.temporaryCss($new, { - visibility: 'hidden' + opacity: '0' }); promise = block(oldCopy.$ghost, newCopy.$ghost); $old.data(GHOSTING_PROMISE_KEY, promise); $new.data(GHOSTING_PROMISE_KEY, promise); promise.then(function() { $old.removeData(GHOSTING_PROMISE_KEY); $new.removeData(GHOSTING_PROMISE_KEY); + showNew(); oldCopy.$bounds.remove(); - newCopy.$bounds.remove(); - return showNew(); + return newCopy.$bounds.remove(); }); return promise; }; /** @@ -3431,10 +3439,28 @@ separated by a slash character (`/`): - `move-to-bottom/fade-in` - `move-to-left/move-from-top` + \#\#\#\# Implementation details + + During a transition both the old and new element occupy + the same position on the screen. + + Since the CSS layout flow will usually not allow two elements to + overlay the same space, Up.js: + + - The old and new elements are cloned + - The old element is removed from the layout flow using `display: hidden` + - The new element is hidden, but still leaves space in the layout flow by setting `visibility: hidden` + - The clones are [absolutely positioned](https://developer.mozilla.org/en-US/docs/Web/CSS/position#Absolute_positioning) + over the original elements. + - The transition is applied to the cloned elements. + At no point will the hidden, original elements be animated. + - When the transition has finished, the clones are removed from the DOM and the new element is shown. + The old element remains hidden in the DOM. + @method up.morph @param {Element|jQuery|String} source @param {Element|jQuery|String} target @param {Function|String} transitionOrName @param {Number} [options.duration=300] @@ -3450,10 +3476,11 @@ @return {Promise} A promise for the transition's end. */ morph = function(source, target, transitionOrName, options) { var $new, $old, animation, deferred, parsedOptions, parts, transition; + u.debug('Morphing %o to %o (using %o)', source, target, transitionOrName); $old = $(source); $new = $(target); parsedOptions = u.only(options, 'reveal', 'restoreScroll'); parsedOptions = u.extend(parsedOptions, animateOptions(options)); if (up.browser.canCssAnimation()) { @@ -3484,11 +3511,11 @@ return skipMorph($old, $new, parsedOptions); } }; /** - Cause the side effects of a successful transitions, but instantly. + This causes the side effects of a successful transition, but instantly. We use this to skip morphing for old browsers, or when the developer decides to only animate the new element (i.e. no real ghosting or transition) . @private */ @@ -3622,11 +3649,12 @@ /** Returns a new promise that resolves once all promises in arguments resolve. Other then [`$.when` from jQuery](https://api.jquery.com/jquery.when/), - the combined promise will have a `resolve` method. + the combined promise will have a `resolve` method. This `resolve` method + will resolve all the wrapped promises. @method up.motion.when @param promises... @return A new promise. */ @@ -3812,17 +3840,17 @@ making requests to these URLs return insantly. The cache is cleared whenever the user makes a non-`GET` request (like `POST`, `PUT` or `DELETE`). -The proxy can also used to speed up reaction times by preloading -links when the user hovers over the click area (or puts the mouse/finger -down before releasing). This way the -response will already be cached when the user performs the click. +The proxy can also used to speed up reaction times by [preloading +links when the user hovers over the click area](/up-preload) (or puts the mouse/finger +down before releasing). This way the response will already be cached when +the user performs the click. Spinners ---------- +-------- You can listen to [framework events](/up.bus) to implement a spinner (progress indicator) that appears during a long-running request, and disappears once the response has been received: @@ -3833,16 +3861,19 @@ up.compiler('.spinner', function($element) { show = function() { $element.show() }; hide = function() { $element.hide() }; - up.bus.on('proxy:busy', show); - up.bus.on('proxy:idle', hide); + showOff = up.on('proxy:busy', show); + hideOff = up.on('proxy:idle', hide); + hide(); + + // Clean up when the element is removed from the DOM return function() { - up.bus.off('proxy:busy', show); - up.bus.off('proxy:idle', hide); + showOff(); + hideOff(); }; }); The `proxy:busy` event will be emitted after a delay of 300 ms @@ -4223,11 +4254,11 @@ - The `up-target` mechanism also works with [forms](/up.form). - As you switch through pages, Up.js will [update your browser's location bar and history](/up.history) - You can [open fragments in popups or modal dialogs](/up.modal). - You can give users [immediate feedback](/up.navigation) when a link is clicked or becomes current, without waiting for the server. - [Controlling Up.js pragmatically through Javascript](/up.flow) -- [Defining custom tags and event handlers](/up.magic) +- [Defining custom tags](/up.syntax) @class up.link */ @@ -5230,11 +5261,11 @@ } } else { return autoclose(); } }); - up.magic.onEscape(function() { + up.bus.onEscape(function() { return close(); }); /** When an element with this attribute is clicked, @@ -5709,11 +5740,11 @@ } } else if (!up.popup.contains($fragment)) { return autoclose(); } }); - up.magic.onEscape(function() { + up.bus.onEscape(function() { return close(); }); /** When this element is clicked, closes a currently open dialog. @@ -5754,30 +5785,65 @@ }).call(this); /** Tooltips ======== - -Elements that have an `up-tooltip` attribute will show the attribute -value in a tooltip when a user hovers over the element. - -\#\#\# Incomplete documentation! - -We need to work on this page: - -- Show the tooltip's HTML structure and how to style the elements -- Explain how to position tooltips using `up-position` -- We should have a position about tooltips that contain HTML. - +Up.js comes with a basic tooltip implementation. + +You can an [`up-tooltip`](/up-tooltip) attribute to any HTML tag to show a tooltip whenever + the user hovers over the element: + + <a href="/decks" up-tooltip="Show all decks">Decks</a> + + +\#\#\#\# Styling + +The [default styles](https://github.com/makandra/upjs/blob/master/lib/assets/stylesheets/up/tooltip.css.sass) +show a simple tooltip with white text on a gray background. +A gray triangle points to the element. + +To change the styling, simply override CSS rules for the `.up-tooltip` selector and its `:after` +selector that is used the triangle. + +The HTML of a tooltip element is simply this: + + <div class="up-tooltip"> + Show all decks + </div> + +The tooltip element is appended to the end of `<body>`. + @class up.tooltip */ (function() { up.tooltip = (function($) { - var attach, close, createElement, setPosition, u; + var attach, close, config, createElement, reset, setPosition, u; u = up.util; + + /** + Sets default options for future tooltips. + + @method up.tooltip.config + @property + @param {String} [config.position] + The default position of tooltips relative to the element. + Can be either `"top"` or `"bottom"`. + @param {String} [config.openAnimation='fade-in'] + The animation used to open a tooltip. + @param {String} [config.closeAnimation='fade-out'] + The animation used to close a tooltip. + */ + config = u.config({ + position: 'top', + openAnimation: 'fade-in', + closeAnimation: 'fade-out' + }); + reset = function() { + return config.reset(); + }; setPosition = function($link, $tooltip, position) { var css, linkBox, tooltipBox; linkBox = u.measure($link); tooltipBox = u.measure($tooltip); css = (function() { @@ -5812,11 +5878,11 @@ }; /** Opens a tooltip over the given element. - up.tooltip.open('.help', { + up.tooltip.attach('.help', { html: 'Enter multiple words or phrases' }); @method up.tooltip.attach @param {Element|jQuery|String} elementOrSelector @@ -5832,13 +5898,13 @@ if (options == null) { options = {}; } $link = $(linkOrSelector); html = u.option(options.html, $link.attr('up-tooltip-html')); - text = u.option(options.text, $link.attr('up-tooltip'), $link.attr('title')); - position = u.option(options.position, $link.attr('up-position'), 'top'); - animation = u.option(options.animation, u.castedAttr($link, 'up-animation'), 'fade-in'); + text = u.option(options.text, $link.attr('up-tooltip')); + position = u.option(options.position, $link.attr('up-position'), config.position); + animation = u.option(options.animation, u.castedAttr($link, 'up-animation'), config.openAnimation); animateOptions = up.motion.animateOptions(options, $link); close(); $tooltip = createElement({ text: text, html: html @@ -5858,11 +5924,11 @@ close = function(options) { var $tooltip; $tooltip = $('.up-tooltip'); if ($tooltip.length) { options = u.options(options, { - animation: 'fade-out' + animation: config.closeAnimation }); options = u.merge(options, up.motion.animateOptions(options)); return up.destroy($tooltip, options); } }; @@ -5870,15 +5936,23 @@ /** Displays a tooltip with text content when hovering the mouse over this element: <a href="/decks" up-tooltip="Show all decks">Decks</a> - You can also make an existing `title` attribute appear as a tooltip: + To make the tooltip appear below the element instead of above the element, + add an `up-position` attribute: - <a href="/decks" title="Show all decks" up-tooltip>Decks</a> + <a href="/decks" up-tooltip="Show all decks" up-position="bottom">Decks</a> @method [up-tooltip] + @param {String} [up-animation] + The animation used to open the tooltip. + Defaults to [`up.tooltip.config.openAnimation`](/up.tooltip.config). + @param {String} [up-position] + The default position of tooltips relative to the element. + Can be either `"top"` or `"bottom"`. + Defaults to [`up.tooltip.config.position`](/up.tooltip.config). @ujs */ /** Displays a tooltip with HTML content when hovering the mouse over this element: @@ -5898,13 +5972,14 @@ }); up.on('click', 'body', function(event, $body) { return close(); }); up.on('up:framework:reset', close); - up.magic.onEscape(function() { + up.bus.onEscape(function() { return close(); }); + up.on('up:framework:reset', reset); return { attach: attach, close: close, open: function() { return u.error('up.tooltip.open no longer exists. Use up.tooltip.attach instead.'); @@ -6027,10 +6102,10 @@ var $section, urls; $section = $(section); urls = sectionUrls($section); if (currentUrls.matchesAny(urls)) { return $section.addClass(klass); - } else { + } else if ($section.hasClass(klass) && $section.closest('.up-destroying').length === 0) { return $section.removeClass(klass); } }); };