Reputation: 1616
I'm trying to think of a way round this in a bigger project but have put together this small example in the hope of finding a solution..
The example was put together by creating a new meteor project (using meteor 1.0.3.1) and adding mizzao:bootstrap-3 and using the following files:
test.html
<head>
<title>test</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
{{> example}}
</div>
{{> controls}}
</div>
</body>
<template name="example">
<div class="col-xs-{{zoom}}">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><span data-toggle="tooltip" data-placement="auto" title="Some text that will appear in the tooltip (which should be centered above or below this span) when hovering over the this span">Text that can spill out</span></h3>
</div>
<div class="panel-body">
<p>Foo</p>
</div>
</div>
</div>
</template>
<template name="controls">
<button id="in">+</button>
<button id="out">-</button>
</template>
test.css
.panel-title > span {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.panel-title div.tooltip {
white-space: initial;
}
test.js
if (Meteor.isClient) {
var minZoom = 1;
var maxZoom = 4;
Session.setDefault('zoom', 4);
Template.example.helpers({
zoom: function () {
return Session.get('zoom');
}
});
Template.controls.events({
'click button': function(event) {
switch(event.currentTarget.id) {
case 'in':
if (Session.get('zoom') < maxZoom)
Session.set('zoom', Session.get('zoom') + 1);
break;
case 'out':
if (Session.get('zoom') > minZoom)
Session.set('zoom', Session.get('zoom') - 1);
break;
}
}
})
test = function() {
$('.panel-heading').each(function(index) {
var h3 = $(this).find('h3');
var span = $(this).find('span');
span.width('initial');
if (span.width() > h3.width()) {
span.width('100%');
}
});
$('[data-toggle="tooltip"]').tooltip();
}
Template.example.rendered = function() {
test();
}
}
Hopefully it's clear(ish) what I'm trying to achieve which is that the span (which toggles to tooltip on hover) is set to the same width as the h3 when the span would otherwise exceed the width of the h3 - or if the h3 is bigger, then the span is set to it's default (inline / initial width). The reason for this is so that when the tooltip is initialised, the tooltip should appear centered above (or below) the span text. The call to test() when the template is rendered works as expected (you can change the default value of the 'zoom' session to alter the width of the panel when the page is first loaded - I've been using 1 and 4 to test with. However I need to make a call to test() when the DOM updates as a result of the reactive session variable 'zoom' changing which occurs when clicking the + or - buttons. When this happens the panel class col-md-# changes where # is the value of the zoom session variable.
So to summarise, the DOM changes but this isn't in response to a JavaScript call that I'm making directly and isn't due to subscribed data changing so I don't believe I can use the Tracker.afterFlush callback. Since the zoom helper has to return before the DOM is updated, I can't see a way to call 'test()' triggered by any particular event and adding something to the click of the buttons would occur too early does anyone have any ideas?
Also from what I have read, Mutation Observers aren't that widely supported yet so this probably isn't an option.
Thanks
Upvotes: 2
Views: 1453
Reputation: 19761
Here's my shameless answer after posting to the Meteor forums.
After you've made the changes to cause the reactive change, put your javascript in a Tracker.afterFlush
callback.
http://docs.meteor.com/#/full/tracker_afterflush
Upvotes: 1
Reputation: 396
If I got it right you're essentially changing a session variable and would like to have a callback when it changes? If this is correct then wrapping that variable in an autorun function will execute it every time the variable changes.
Additionally if there still are racing issues you could use a setTimeout with a small delay before calling test().
Tracker.autorun(function () {
Session.get('zoom');
test();
});
Upvotes: 2