I have a problem, I'm trying to add a tooltip to some already rendered elements. The code that I have makes the tooltip appear after the 2nd hover which is kind of normal because on the first one is not set yet, do you know what can I do to have it displayed from the first hover?
Thanks in advance!
I have the following code:
$(".checkWidth").live("mouseenter",function() {
var size = measureText($(this).text(), 12, 'Tahoma')
var limit = $('#my_container').width() - 67;
if( size.width > limit){
$(this).attr('title', $(this).text());
$('#tiptip_content').css('font-size', '13px');
$(this).tipTip({
maxWidth: "auto",
defaultPosition: "right",
fadeIn: 100,
fadeIn: 100,
attribute: "title"
});
}
});
Calling $(this).tipTip({...}); sets up the tooltip, it doesn't show it. So you don't actually set up the tooltip until you mouseover the element, and the tooltip is shown the next time you mouse over (handled by the plugin).
You'll need to call that on DOM ready. I think you may need something like this:
$(document).ready(function () {
$('#tiptip_content').css('font-size', '13px');
var limit = $('#my_container').width() - 67;
$('.checkWidth').each(function () {
var size = measureText($(this).text(), 12, 'Tahoma');
if (size.width > limit) {
$(this).attr('title', $(this).text());
$(this).tipTip({
maxWidth: "auto",
defaultPosition: "right",
fadeIn: 100,
fadeIn: 100,
attribute: "title"
});
}
});
});
Edit another possibility:
$('#tiptip_content').css('font-size', '13px'); //this should be able to be done elsewhere...
$("document").on("mouseenter", '.checkWidth', function () {
var $this = $(this);
if ($this.data('tipInit') === true) { return; }
$this.data('tipInit', true);
var size = measureText($(this).text(), 12, 'Tahoma')
var limit = $('#my_container').width() - 67;
if (size.width > limit) {
$this.attr('title', $this.text());
$this.tipTip({
maxWidth: "auto",
defaultPosition: "right",
fadeIn: 100,
fadeIn: 100,
attribute: "title"
});
$this.trigger('mouseenter');
}
});
it depends on your code structure. But I will try the following:
Try changing the .live() to .on()
I would try to change the function to .on('hover', function)
I would also try to use mousenter and mouseleave
Related
I have a Jquery ui slider with multiple handles that i can add and remove, i want to show a tooltip above the handle while moving it, this is the code i created:
var tooltip = $('<div id="tooltip" />').css({
position: 'absolute',
top: -25,
left: -10
}).hide();
var values = [10, 50, 70, 90];
var val = 20;
//add handle to the slider
$('button').bind('click', function(e) {
e.preventDefault();
$(".slider").slider("destroy");
values.push(val);
values = values.sort();
$(".slider").slider({
min: 0,
max: 100,
steps: 1,
values: values
})
})
//create the slider
$(".slider").slider({
min: 0,
max: 100,
steps: 1,
values: values,
slide: function(event, ui) {
tooltip.text(ui.value);
},
change: function(event, ui) {}
}).find(".ui-slider-handle").append(tooltip).hover(function() {
tooltip.show()
}, function() {
tooltip.hide()
});
//remove slider handle on double click
$(document).on('dblclick', '.ui-slider-handle', function() {
if ($('.ui-slider-handle').length > 2)
$(this).remove();
//alert($(this)[0].style.left);
})
Jsfiddle example
As you can see in the example the tooltip works fine but it doesn't appear in the right position, and also it doesn't work with newly created handles.
Please can someone help me with this
Thank you
First issue: bind is deprecated, use on
When you destroy the slider you remove also the tooltip!
Therefore, on button click, before destroying the slider you need to preserve a copy of your tooltip (jQuery.clone()) so you can reuse it again.
In order to simplify everything you may use a slider create function.
In order to solve the last issue (...but it doesn't appear in the right position) you need to change this line of code:
tooltip.text(ui.value);
to:
$(this).find('div').text(ui.value);
The snippet:
function createSlider(tooltip, values) {
$(".slider").slider({
min: 0,
max: 100,
steps: 1,
values: values,
slide: function(event, ui) {
$(this).find('div').text(ui.value);
},
change: function(event, ui) {}
}).find(".ui-slider-handle").append(tooltip).hover(function() {
$(".ui-slider-handle").find('div').hide()
$(this).find('div').show();
});
}
var tooltip = $('<div id="tooltip" />').css({
position: 'absolute',
top: -25,
left: -10
}).hide();
var values = [10, 50, 70, 90];
var val = 23;
$('button').on('click', function(e) {
e.preventDefault();
//
// preserve tooltip
//
tooltip = $('#tooltip').clone();
$(".slider").slider("destroy");
values.push(val);
values = values.sort();
createSlider(tooltip, values);
})
createSlider(tooltip, values);
$(document).on('dblclick', '.ui-slider-handle', function() {
if ($('.ui-slider-handle').length > 2)
$(this).remove();
//alert($(this)[0].style.left);
})
body {
margin-top: 80px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://code.jquery.com/ui/1.12.0/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
<div class="slider"></div>
<br>
<button>Click it!</button>
I'm trying to modify a jQuery knob plugin to use as an animated chart.
This is what I have so far:
HTML:
<ul id="chart">
<li rel="100">Cats</li>
<input class="knob animated donut" value="0" rel="70" />
Javascript:
$('.knob').each(function () {
var $this = $(this);
var myVal = $this.attr("rel");
$(this).knob({
readOnly: true,
displayInput: false,
bgColor: "cccccc",
fgColor: "e60022"
});
$({
value: 0
}).animate({
value: myVal
}, {
duration: 1000,
easing: 'swing',
step: function () {
$this.val(Math.ceil(this.value)).trigger('change');
}
})
});
$('#chart > li').mouseover(function(){
$('#donut').text($(this).attr('rel'));
});
I'd like to be able to hover over the <li> element and use the rel value to apply it to the chart. I think I might need to include some JS to redraw the chart on hover though as well, but not sure how to do that either (I don't have much JS knowledge).
Any help is appreciated.
DEMO
You need to set the animate properties in the event handler. So, initialize your "knob" element as you did, then in the event handler retrieve the values and run the animation.
In the demo I used a data attribute (it just makes more sense to me), not the rel attribute, but the following should work with your markup:
var donut = $('.knob');
donut.knob({readOnly: true,
displayInput: false,
});
$('#chart > li').on('mouseenter', function(){
var myVal = $(this).attr('rel');
donut.stop().animate({value: myVal}, {
duration: 200,
easing: 'swing',
step: function () {
donut.val(Math.ceil(this.value)).trigger('change');
}
});
});
HTML: change the input to use the data attributes for color, as there is a bug in FF
<input class="knob" data-fgColor="#e60022" data-bgColor="#ccc" value="" />
I'm starting a project that will require that users be able to create multiple custom avatars. To do this, I want them to be able to send images that are in their inventory to a manipulation frame. Within this frame, users should be able to move and resize the images - double clicking them to remove the image from the frame and sending it back into their inventory. To the right of the manipulation frame, I would like a sortable list that will dictate the z-index of the corresponding item with the item at the top being in back of the manipulation frame. So far, I have this: http://jsfiddle.net/Thaikhan/e3Gd6/10/show/.
The list generates and is sortable but does not affect the z-index of the image. Also, the code is pretty buggy and often images will disappear off frame.
See JSFiddle here: http://jsfiddle.net/Thaikhan/e3Gd6/10/
Here is the JavaScript code:
//Click into Frame
$('.inventory').on('click', 'img', function () {
$(this).resizable({
aspectRatio: 1,
autoHide: true,
containment: "parent",
minHeight: 50,
minWidth: 50
});
$(this).parent().appendTo(".frame").draggable({
containment: "parent",
cursor: "move"
});
refreshIndexList();
});
//Double Click out of Frame
$('.frame').on('dblclick', '.ui-draggable', function () {
$(this).appendTo(".inventory");
$(this).draggable("destroy");
$("img", this).resizable("destroy").attr('style', '');
refreshIndexList();
});
//Updates List Items
function refreshIndexList() {
var listitems = $('.frame').children().length;
$('#sortable').empty();
var titles = $(".frame img:nth-of-type(1)").attr('title');
for (var count = 1; count <= listitems; count++) {
var title = $(".frame img").eq(count-1).attr('title');
var $li = $("<li class='ui-state-default'/>").text(title);
$('#sortable').append($li);
}
}
//Makes List Sortable
$(function () {
$("#sortable").sortable({
placeholder: "ui-state-highlight"
});
$("#sortable").disableSelection();
});
//Inventory Grid
$(function() {
$( "#grid" ).sortable();
$( "#grid" ).disableSelection();
});
I am a novice in JavaScript and have received much help in getting this far. I am hoping that once again I can receive help from the community and figure out how to have the sortable list change the z-index of the item. Additionally, if anyone sees why it's buggy, please let me know.
Ultimately, I want to be able to grab from the manipulation frame the image_id's, their locations, their z-indices, and their sizes and store it all in a database. This will hopefully allow users to return and edit their avatar creations.
A thousand thanks for your help!
create function with editing z-index:
function zindex() {
var title = "";
var i = 9999;
$(".ui-state-default").each(function () {
i--; //z-index position counter
title = $(this).text();
$(".frame img[title='" + title + "']").parent().css("z-index", i);
});
}
call it on adding img
$('.inventory').on('click', 'img', function () {
$(this).resizable({
aspectRatio: 1,
autoHide: true,
containment: "parent",
minHeight: 50,
minWidth: 50
});
$(this).parent().appendTo(".frame").draggable({
containment: "parent",
cursor: "move"
});
refreshIndexList();
zindex();
});
and use it on mouseup (drop event emulation)
$("#sortable").mouseup(function () {
setTimeout(function() {
zindex();}, 100);
});
FIDDLE
I want to increase/decrease the font of and element, then the next element of that class and so forth, for a set of elements as <div class="test"></div> <div class="test"></div> ..... I mean
step 1: enlarging the first element and returning to normal size
step 2: enlarging the second element and returning to normal size
....
My basic code is
$(document).ready(function() {
$('.test').animate({
left:50,
fontSize: "2em"},
"slow")
.animate({
left:-50,
fontSize: "1em"},
"slow");
This will affect all the elements at once. How can I make a queue to make the changes one by one. Having one enlarged element at a time.
You could do it with
$('.test').each(function(idx){
var duration = 1200; // duration for all animations (2 x slow)
$(this)
.delay(duration*idx)
.animate({ left:50, fontSize: "2em" }, 'slow')
.animate({ left:-50, fontSize: "1em" }, 'slow');
});
Demo at http://jsfiddle.net/gaby/rz5Es/
For more precise control and more freedom on queuing look at my answer at a similar question:
A non-nested animation sequence in jQuery?
You need to use callbacks and an array of the elements you want to sequentially animate...
function animateSequence(elements){
var element = $(elements).first();
var originalSize = $(element).css('font-size');
elements = $(elements).not($(element));
$(element).animate(
{ fontSize: "2em" },
"slow",
function(){
$(this).animate(
{ fontSize: originalSize },
"slow",
function(){
if(elements.length > 0)
animateSequence(elements);
}
)
}
);
}
animateSequence($('.test'));
If you want to play with it: http://jsfiddle.net/xS7X7/
You will need to loop thru all elements and execute animate on each of them sequentially, here is sample code to do that recursively
function animate_sequential(elems, css, delay, index){
if(index===undefined) index = 0;
if(index >= elems.length) return;
$(elems[index]).animate(css, delay, function(){
animate_sequential(elems, css, delay, index+1)
})
}
animate_sequential($('div'), {'font-size':'30px'}, 500)
animate_sequential($('div'), {'font-size':'15px'}, 500)
See it in action http://jsfiddle.net/anuraguniyal/QJc9L/
It can be easily converted to a jQuery plugin, so that you can do $('div').animate_sequential and keep same interface as jQuery animate, you can also further enhance it so that it brings back to original css by passing the original css or getting it from element.
As I understand you are trying to do something like this,
$(document).ready(function() {
(function mycallback(i) {
var elems = $('.test');
elems.eq(i).animate({
left:50,
fontSize: "2em"}, function () {
mycallback(i + 1 < elems.length ? i + 1 : 0);
});
}(0));
});
DEMO
UPDATE:
It was an example code, you can change it like this if you want to reverse effects,
$(document).ready(function() {
(function mycallback(i) {
var elems = $('.test');
elems.eq(i).animate({
left:50,
fontSize: "2em"}, function () {
$(this).animate({
left:-50,
fontSize: "1em"},
"slow");
if (i + 1 < elems.length)
mycallback(i+1);
});
}(0));
});
UPDATED DEMO
So much simpler, readable, and scalable with Frame.js:
$('.test').each(function(i){
var element = $(this);
var originalSize = element.css('font-size');
Frame(function(next){
element.animate({ fontSize: "2em" }, "slow", next);
});
Frame(function(next){
element.animate({ fontSize: originalSize }, "slow", next);
});
});
Frame(function(next){
// add a callback after all the animations have finished
next();
});
Frame.start();
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
open expand/ close back to original sizes a series of boxes with img fade
I'm struggling with this logic and i can't get it to work. I need to run through each box in order to get the original height and save it. Then i need to be able to click and expand and item while checking if any other is open and if it is, close it back to its original height and width (it's a set width). The only bit which i'm struggling with is this what I have at the start of the full script, I have commented it with my (i believe wrong) logic of what i'm trying to do. The code that follows this part is fine, if you want to double check it here it is a pastebin with the full script: http://pastebin.com/u72Q5Cqj
Basic html structre
<div class="box">
<img src="test.jpg" />
<div class="info"></div>
</div>
<div class="box">
<img src="test2.jpg" />
<div class="info"></div>
</div>
<div class="box">
<img src="test3.jpg" />
<div class="info"></div>
</div>
Jquery
//run the function for all boxes
$(".box").each(function () {
var item = $(this);
var thumb = $("a", item);
var infoBox = $(".info", item);
// save each box original height
$.data(this, 'height', $(this).height());
item.click(function(e) {
e.preventDefault();
// remove any box with class "opened"
$(".box").removeClass("opened");
// this is to empty ".info" which is a child div in which
// I load content via ajax into
$(".info").empty();
// here i'm saying if any box doesn't have a class "opened"
// fadeIn its `<a>`, i am fadingOut later in the code
$(".box a").not(".opened").fadeIn("slow");
//set back `.info`width and height to auto, is empty anyway
$(".box .info").not.css({
"width": "auto",
"height": "auto"
});
// in here i'm trying to set back any box without a class "opened"
// back to its original width which is a set width
$(".box").not(".opened").css("width", "230");
// in here i'm trying to set back any box without a class "opened"
// back to its original height saved at the beginning of the code
$.data($(".box"), 'height');
// now I add the class opened to this clicked item
item.addClass("opened");
// check if it has a class "opened" and if so do the rest
if (item.hasClass("opened")) {
var url = this.href;.................etc
Well, I've no way to try a solution but your code has a few errors.
You're declaring newHeight twice, iframe is not declared and you have an unexpected ; at the end of your if statement.
Then, why are you calling the click() event on $(this) inside each()? It seems unnecessary and it's probably no good for performance. You can declare your variables outside of the loop and the chain the click event.
$('.box').each().click();
And finally, I suggest you create a function for your load() and click() events to keep things DRY.
this is my final code which works:
$(function(){
//run the function for all boxes
$(".box").each(function () {
var item = $(this);
var thumb = $("a", item);
var infoBox = $(".info", item);
thumb.click(function(e) {
e.preventDefault();
$(".box").removeClass("opened");
$(".info").empty();
$(".box a").fadeIn("slow");
$(".info").css({
"width": "auto",
"height": "auto"
});
$(".box a").css("width", "230");
$(".box a").css("height", "auto");
$(".box").css("width", "230");
$(".box").css("height", "auto");
item.addClass("opened");
if (item.hasClass("opened")) {
var url = this.href;
thumb.fadeOut("slow");
infoBox.css({
"visibility": "visible",
"height": "auto"
});
infoBox.load(url, function () {
var newHeight = infoBox.outerHeight(true);
$(".readMore", item).click(function (e) {
var selector = $(this).attr('data-filter-all');
$('#container').isotope({
filter: selector
});
$('#container').isotope('reloadItems');
return false;
});
$('Close"').appendTo(infoBox).click(function (e) {
e.preventDefault();
$("html, body").animate({scrollTop: 0}, 500);
$('#container').isotope('reLayout');
});
item.animate({
"width": "692",
"height": newHeight
}, 300);
thumb.animate({
"width": "692",
"height": newHeight
}, 300);
infoBox.animate({width: 692, height: newHeight}, function () {
$('#container').isotope('reLayout', function () {
Shadowbox.setup();
item.removeClass("loading");
infoBox.css({
"visibility": "visible"
});
var videoSpan = infoBox.find("span.video");
iframe = $('<iframe/>', {
'frameborder': 0,
'class': 'tide',
'width': '692',
'height': '389',
'src': 'http://player.vimeo.com/video/' + videoSpan.data("vimeoid") + '?autoplay=0&api=1'
});
videoSpan.replaceWith(iframe);
});
});
});
};
});
});
});