shipshapecode / tether Goto Github PK
View Code? Open in Web Editor NEWA positioning engine to make overlays, tooltips and dropdowns better
Home Page: https://tetherjs.dev/docs/welcome
License: MIT License
A positioning engine to make overlays, tooltips and dropdowns better
Home Page: https://tetherjs.dev/docs/welcome
License: MIT License
Is Tether compatible with RequireJS? Usually, this kind of functionality will exist in only one factored module. Having it hang around in memory at all times seems excessive.
Thank you.
I started using tether (which works brilliantly btw - thanks!) at version 0.5.2, and will update to 0.6.4 today.
However, that's hard to do because it's unclear what has changed since then (the commit history shows this is mostly documentation a few bugfixes).
A short changelog would be really helpful to clarify what aspects of an upgrade might need attention (which if I understand correctly is likely to be not much for 0.5.2 -> 0.6.4).
Hello everyone,
In our project we have a lot of tethered elements (30+) and the goal is to make them visible when they're inside the parent element.
Everything work fine in Chrome, slow in FF and in Safari tethered elements move only after a delay during scroll.
Can someone explain the difference in behaviours?
Compass
includes a lot of overhead that is mostly unnecessary. It also makes it harder for others to contribute since it requires the Compass
gem to be installed. A tools like autoprefixer
can handle most of the use-cases here.
This changes should applies to all tether
based projects as well: drop, tooltip, shepherd, select
Evented is obsolete and never used by Tether
itself. So there is point having it in the main codebase.
It seems that the only place when Evented
is used is drop. It maybe also used in some other libs that extend/depend on Tether
.
Evented
has no usefull features, - it does not even provide things like event.preventDefault()
or event.stopPropagation
.
The provided by Evented
functionality can be easily implemented in using native CustomEvent on target
Using DOM
as EventBus
would provide a more advanced solution.
It seems reasonable to remove Evented
from the codebase - if that is not possible because of some legacy code or libs depending on this functionality - I suggest replacing it with implementation based on CustomEvent
( polyfill may be included for legacy browser )
When using a SVG element as the target for tethering, the library doesn't quite work. This is due to the differences in the SVG DOM vs the HTML DOM.
It seems that in some browsers, an SVG element's classname is not guaranteed to be a string, sometimes it is [object SVGAnimatedStringPrototype]. Therefore the removeClass utility doesn't work as expected and produces the error:
TypeError: Object doesn't support property or method 'replace'.
I've got tether to work with SVG elements by changing the one line in the removeClass method from referencing the el.className to using el.getAttribute('class').
Information:
http://stackoverflow.com/questions/3294553/jquery-selector-svg-incompatible
http://toddmotto.com/hacking-svg-traversing-with-ease-addclass-removeclass-toggleclass-functions/
In this example, why doesn't the yellow box ever sit with its right edge flush with the right edge of the green box (as you scroll to the right)? Instead it immediately flips such that the top left corner of the yellow box is attached to the bottom right corner of the green box.
When using a constraint, e.g. together
to switch both the attachments of element
and target
, the defined offset
is not inverted.
Example element is positioned like a dropdown, 6px below the target.
new Tether({
element: this.el,
attachment: 'top center',
target: this.target,
targetAttachment: 'bottom center',
offset: '-6px 0',
constraints: [{ to: 'scrollParent', attachment: 'together' }]
});
When switching both attachments, for example to attachment bottom center
and targetAttachment top center
due to constaint, the target is not 6px above the target - which it should be.
I've been looking through an issue with TetherJS that occurs only when I minify and combine my script files. Initially, I thought it was a problem with the minification process, but I think it's caused by "use strict" mode triggering.
The Tether JS 0.6.5 file uses 'this' in a global context, which in strict mode is undefined. See this StackOverflow post: http://stackoverflow.com/questions/9822561/why-is-this-in-an-anonymous-function-undefined-when-using-strict
Looking to try this out, but npm install
didn't work out of the box for me. nbd, but wanted to file a ticket anyway
On the documentation page, many examples are broken in Firefox 26, notably in the Constraints chapter.
See the first Constraints example in Chrome 32, compared with the same one in Firefox 26.
I was pretty happy to find this on npm, as I'm looking to integrate it with a browserify workflow. Unfortunately the published version is 0.5.2, from January (which looks like it was published for issue #19).
Any chance we can get an update? whoever has access just has to type npm publish
... would be great if the npm version could be kept up to date with releases.
As with one other user, I saw that CSS right attachments are correct in IE, but messed up on Chrome. I added an 'offset' field to my tether options, and fixed the Chrome layout--but it was broken in IE. Easy enough to fix, I think--if Zepto tells me the browser is IE, I'll simply delete the field:
delete attachDesc.offset;
When I do that, the tethered element just flies up to the upper-left corner of the target element, even though attachDesc hasn't been used yet. I can't even set the offset field to null and get away with it, and I'd prefer not to have to define attachDesc individually for each browser in which there's quirky behavior.
calling setOptions always requires a complete set of options including element and target
For existing tether instances, setOptions should just update the keys provided (like _.extend() )
Here is an example: http://codepen.io/kizu/pen/wDyzE and the full-page view: http://codepen.io/kizu/full/wDyzE/
I can see there two problems:
What is expected: when the element is attached to the bottom of the block's visible area, it should always be at the bottom of it, without any gaps. Maybe there are some rounding errors that prevent it from happening?
I have a case a bit similar to the content-visible one: I need to have an element that would be attached to the visible parts of another element, like in the example, but with a condition: it should never leave the bounds of the .content-box
. It should pin to its top and bottom when it is placed outside the .content-box
, while in all other time be positioned to a visible part of it.
Is it possible using constraints? I couldn't make it so, the most closest thing that I thought should work like I'd like was
constraints: [
{
to: '.content-box',
pin: true
},
]
But it just doing anything and I couldn't find anything that would make it work.
Is it possible with Tether at all?
I came across a situation where the element I want to tether has multiple scroll parents. Event listener is bound to the first one found and naturally does not receive events from other parents.
A simplified example of the issue can be seen in http://jsfiddle.net/mchc2tny/3/
Amendment: The above is with Google Chrome 35.0.1916.114 ... with Firefox 29.0, the tethered element seems to receive absolutely no scroll-events :(
Hi there, I created a NuGet package for your project, let me know if you'd like anything changed.
http://dropthebit.com/demos/tether-bug.html
the sticky element's own bottom
is set to 0
and it's top
is set to the bottom
of another position:fixed
element.
it will only work well if the window scroll is at the top (0
). otherwise if you scroll and then refresh, the page will re-render at the last scroll position and Tether will fail to position the sticky element unless the user scrolls the page somewhere.
Also note - the sticky element must be set to position:fixed
also for this trick to work in all possible situations
I have a questions for the maintainers here,
You have a bunch of projects ("Tooltip", "Shepherd" and "Select") which are all based off Tether's positioning system. But still you keep bundling the whole tether into each of these library's distributable builds. WHY?
If I am to use more than of your projects, there is no simple way to include the common code (tether) once, say using RequireJS, and then just have the tooltip's and shepherd's code separately, all pulled using Bower.
Right now, I only observed that Shepherd has the stand-alone build without the bundled tether code, but none of the other libraries have such organization.
Also, even with Shepherd, when I install it using bower, everything is pulled BUT NOT the standalone builds, which should make more sense than :-(
Can I file this as a feature request? Have the AMD standalone builds of the libraries be distributable along with the bundled-up versions.
Hi.
When the element is positioned like "inside" a target, i.e. when attachment
is the same as targetAttachment
, Tether seems to fail flipping the elements
I expected this configuration
new Tether({
element: '.element',
target: '.target',
attachment: 'top left',
targetAttachment: 'top left',
constraints: [{
to: 'window',
attachment: 'together'
}]
});
on this page to:
top right
corner of the element to the top right
corner of the target, since with default top left
-top left
the element goes beyond the window borders; instead it sticks to the default top left
no matter what;top left
-top left
to bottom left
-bottom left
so that the element goes out of sight long before it should.I should mention that the example is a modified examples/testbed/index.html
from the repository. There at least horizontal flipping works while the vertical one fails the same way. Didn't study the code, but it might have something to do with the sizes of the target and the element.
Trying to var Tether = require('tether');
and build with browserify, produces this error: Error: Cannot find module 'tether'
In node_modules/tether/package.json, there is no "main" key which would indicate where to look for a file. This is why browserify/node can't find any file matching name "tether"
Here is the most minimal setup to reproduce the problem: https://github.com/kimmobrunfeldt/tether-browserify-bug
I am trying to do a timeline navigation and want bubbles attached to the little number balls, tether seemed like a perfect fit.
months = ['sept', 'oct', 'nov', 'dec', 'jan', 'feb', 'march', 'april', 'may', 'june'];
months.forEach(function(month){
var monthNav = "nav-"+ month;
var monthPanel
new Tether({
element: monthNav,
target: monthPanel,
attachment: 'top center'
})
})
Unfortunately this throws an error about class list, "Uncaught TypeError: Cannot read property 'classList' of null ". Did I do something wrong in my syntax or have others experienced the same problem.
Hello All,
Are there any plans in the near future to get a TypeScript def file up on DefinitelyTyped?
Thank you.
A bug in mobile safari (http://stackoverflow.com/questions/19012135/ios-7-ipad-safari-landscape-innerheight-outerheight-layout-issue) causes the calling of getScrollBarSize-method and style recalculation on every position-method call.
This causes flickering when the position of a tethered component is updated during scrolling.
Reproducing the bug is slightly involved since it requires an iOS device or emulator connected to OS X Safari for remote debugging.
When attempting to disable classes like suggested within the docs, chrome is throwing Error: Failed to execute 'add' on 'DOMTokenList': The token provided must not be empty.
I really need Tether to position an element using right
css property instead of calculate the distance using left
, when gpu: false
.
The reason is, that the element that is being "Tethered" can change its width and thus, it must stay on the right, no matter what it's width is, and currently this cannot be done in a smooth easy way without hacking using negative margin to push it back, which causes flickering due to browsers way of rendering.
As seen in the picture, the element change state from A to B
or B to A
, doesn't batter, it just needs to stick to the right all the time, and that "right" would be an attachment point of course.
Awesome plugin, thanks a lot.
Hi,
First thank you for your great project. It's a really good idea.
I just went to the demo page (http://tether.io/) on chrome and saw that the scrolling was really lagging a lot (it is quite unusable). The corresponding "chrome helper" process was using a lot of CPU. Here is the version I am using: 34.0.1847.131. Also I am on a Mac with Maverick 10.9.2.
On the other hand there was no problem with firefox.
It's quite strange as chrome is faster with javascript thanks to its V8 interpreter.
Example js fiddle: http://jsfiddle.net/sEemL/1/
Hi
Great lib, thanks!
I only had a quick glance at the source so I might say a lot of nonsensical stuff :
Should not it be better to concat the coffee files first, and then covert them in the final js in the next step ?
I have not tested yet but the final output could get even smaller considering the fact that each independent js produced by the corresponding coffee piece brings boiletplate code that could be mutualised ?
Coffeescript helpers like :
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
should not be repeated inside each IIFE.
Also the Utils object is created :
Tether.Utils = {
getScrollParent: getScrollParent,
getBounds: getBounds,
getOffsetParent: getOffsetParent,
extend: extend,
addClass: addClass,
removeClass: removeClass,
hasClass: hasClass,
updateClasses: updateClasses,
defer: defer,
flush: flush,
uniqueId: uniqueId,
Evented: Evented
};
And just a few lines below is almost unecessaraly destructured to be used in the main Tether object :
if (typeof Tether === "undefined" || Tether === null) {
throw new Error("You must include the utils.js file before tether.js");
}
_ref = Tether.Utils, getScrollParent = _ref.getScrollParent, getSize = _ref.getSize, getOuterSize = _ref.getOuterSize, getBounds = _ref.getBounds, getOffsetParent = _ref.getOffsetParent, extend = _ref.extend, addClass = _ref.addClass, removeClass = _ref.removeClass, updateClasses = _ref.updateClasses, defer = _ref.defer, flush = _ref.flush;
One could say 20000 chars is already quite small but in some critical projects every bit removed is a huge win.
Thanks.
Currently when a tether is destroyed, the element retains its classes, styles, and DOM manipulation. I would expect these changes would be returned to their original states on destroy.
I develop an app that should work on both desktops and mobiles. On desktops, I will have some medium sized tooltips. My tooltips will all be displayed above the target, like a speech bubble (i.e. drop.options.position = 'top center'
) and they should flip to the bottom when there is not enough space to be displayed above the target (i.e. tetherOptions.constraints=[{to: 'window', attachment: 'together'}]
).
Now, let's say I would like to target an "info" icon, for example. Let's further assume that my medium sized tooltip expands to a height of, let's say 400px. On desktops, everything works fine (the tooltip is not too large for desktops).
The thing gets tricky as soon as the tooltip is taller than half the viewport height:
Now, when viewing the same page on a mobile device (e.g. nexus 5 which has a height of 598px, see http://viewportsizes.com/?filter=nexus%205) I might have my info icon positioned in the middle of the screen (because I scrolled there). That leaves roughly 300px above and 300px below the info icon. This means, that the tooltip can neither fit above, nor below the target (and pinning is assumed not to be an option here, see footnote 1
).
Right now, the constraint module will flip the attachments, see line 95.
But afterwards, it will flip them back once more, see line 109
While this does not make much difference in case the info icon is positioned in the middle of the screen, the difference will be more apparent if you consider the info icon was positioned at top: 40%
. While still not able to fit either above or below the target, there is much more space below the target and I'd say, the constraint module should be able to recognize this.
Unfortunately, it is not as easy as switching the if
in line 109 into an else if
. This is, because when we once more mentally change the position of the info icon to top: 60%
, we now would approve of the tooltip being shown above the target (as there is more space).
Therefore:
The constraint module should be able to apply additional logic in cases where both positions (the original and the flipped one) result in the target being out-of-bounds. It should be able to determine which side is better, i.e. which side will have more of the tethered element being displayed on the viewport. The benefits are obvious but I'd like to repeat them here, nonetheless:
footnote 1
pinning is not suitable, because as soon as the tooltip is taller than the viewport we easily run into at least one of two problems:
I believe AMD support is broken at the moment. Tether loads fine if added as a script
tag, but fails to load as AMD module โ ReferenceError: Tether is not defined @ line 294
.
To see this issue, update examples/simple/index.html
to load Tether through RequireJS:
<script src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.10/require.min.js"></script>
<script>
require(['../../tether'], function (Tether) {
new Tether({
element: '.element',
target: '.target',
attachment: 'top left',
targetAttachment: 'top right',
constraints: [{
to: 'window',
attachment: 'together'
}]
});
});
</script>
The title says it all. Is there a way that I can tether to an element that has yet to be inserted into the DOM. My usecase for this is I'm creating backbone views and attaching an element to them. This element may/may not be inserted into the DOM as I'm initializing the view. I want to be able to setup all my tooltip logic in the initialize function of each view, and then when the elements are put into the DOM, everything should just work. Here is the relevant codepen to explain http://codepen.io/jayd3e/pen/kLiKF.
What would be the ideal way to switch the placement of a Tether based on viewport size? For instance, I normally have my Tether attached to the right of a target. At smaller viewport sizes, Tether tries to switch to the other side of the target which doesn't actually work and places it outside of the viewport. It doesn't seem to be smart enough to try switching to the top or bottom of the target even if there is plenty of room available there, and I can't seem to find a way to to configure it to explicitly make this switch.
Any suggestions?
Converted from my own positioning engine to tether. Fantastic! Thanks for all of your hard word!
Now, on to the question...
I have just implemented a contextual menu widget using Durandal, and the thought occurred to me that it would be nice to be able to tether to the mouse's location. On first blush, it may not seem necessary. But edge detection (are we near the edge of the screen or container?) is just as necessary when we're talking about mouse pointer coordinates as it is for other elements.
Is this feasible?
I use mCustomScrollbar as the framework of choice for custom scrollbars. I otherwise style the scrolling container in the same as I would for the built-in scrollbars--position absolute, overflow hidden, etc.
Will Tether work with custom scrollbar libraries?
Thank you.
I've found an interesting edge case in which the tether object is not positioned correctly:
The edge case concerns only these attachment settings:
options.attachment: 'bottom left'
options.attachment: 'bottom right'
options.attachment: 'bottom center'
The targetAttachment has no effect.
The Bug:
As soon as the tethered element is larger than the available viewport, it seems that tether has the "top" position wrong as if it would only consider the height of the viewport as the height of the tethered element, instead of its actual height.
Using Ember, if I tether an element that has bindings inside then it potentially wreaks havoc with the metamorph tags. Is there a way to prevent Tether from picking up elements and moving them around in the DOM?
Thanks
It is moved in https://github.com/HubSpot/tether/blob/master/tether.js#L1013, called from https://github.com/HubSpot/tether/blob/master/tether.js#L910 (note that this line is executed regardless of moveElement
).
As a follow up to my previous issue (#44) I'd like to propose a new keyword for the to
in constraints: target
. There are a lot of cases when this would make sense, for example when you'd need to have some kind of a sidebar or header that would be always visible, but only while inside its target's bounds.
Here is a brief example of how it could work: http://codepen.io/kizu/pen/qDxcA, with this keyword an example from this pen could be written just as
new Tether({
element: '.element',
target: '.content-box',
attachment: 'bottom center',
targetAttachment: 'bottom center',
targetModifier: 'visible',
constraints: [
{
to: 'target',
pin: true
},
]
});
What do you think of it?
http://github.hubspot.com/tether/docs/welcome (See the console errors)
Would you be open to a PR that would fail more gracefully if in IE 8?
Right now it throws an exception (that's not entirely clear it's IE 8 related) -- it could be helpful to both have a more descriptive error, as well as not throwing an exception to stop the compiler if it is included in an IE 8 build.
Even with optimizations.moveElement
set to false
the DOM node is moved. That makes it extremely hard to use Tether with e.g. React that depends on a non-changing DOM.
In the example on tether.io the attachment is moved to the body too. The documentation indicates that it should not be moved.
Do I miss anything?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.