I'm learning and learning, currently creating a validation class. I have one little bug that I would ask you guys, what you think of it.
tooltip part of Javascript
this.toolTip = function(){
var selector = $("#regForm #"+this.idName);
$(selector).focus(function(){
tooltip = "<div class='tooltip'>"+tooltip+"</div>";
$(selector).after(tooltip);
}); // focus
$(selector).blur(function(){
$('.tooltip:parent').remove();
}); // blur
};
This is the tooltip function I wrote, basically what I expect it to do is showing the tooltip in that div, then delete not just the text, but the div, too. I think it's working perfectly, but the css don't say that.
tooltip part of CSS
.tooltip {
display: inline-block;
float: none;
background: #333;
color: #f9f9f9;
font-size: 10px;
padding: 5px;
}
My experience is pretty poor in CSS yet, but I'm developing and I'm trying.
When I focus on an input again, it's padding increasing, when I click again, it increases again. Can you guys help me inspect the code? http://purpost.me/o/form
(as design, I tried to copy tipsy tooltip)
Here is a picture of the bug:
Thanks in advance! :)
UPDATE:
Updated jsFiddle: http://jsfiddle.net/ThePianist/hExkP/3/
When I change the CSS .tooltip's padding to zero, the padding doesn't increase, but the div looking bad obviously. When I tried <div class="tooltip"><span>'+tooltip+'</span></div> and give the span the padding attribute, it started growing on focus again .. :/
What's happening is when clicking inside the form inputs there is some script appending more empty divs underneath <div class="tooltip"><div>. So when you click out and click back in, it is registering another instance of the click and appending again thus making the tooltip larger. Therefore, it would appear is a javascript error with the append/after section. If you pop your codes in a jsFiddle i can take a proper look at a solution for you :)
EDIT:
From looking at the code, it is the section:
$(selector).focus(function(){
tooltip = "<div class='tooltip'>"+tooltip+"</div>";
$(selector).after(tooltip);
}); // focus
That appears to be causing issues. Ideally it should check to see if the code added after already exists, and if it does, don't run the after function again
Found the solution! A friend of mine called my attention to this line:
JS before
tooltip = '<div class="tooltip '+selector.attr('id')+'T">'+tooltip+'</div>';
I call the class property tooltip as well, now I overwrote that with this line.
JS after
$(selector).focus(function(){
var tooltipHTML = '<div class="tooltip '+selector.attr('id')+'T">'+tooltip+'</div>';
selector.after(tooltipHTML);
}); // focus
"The problem is that you are using the variable tooltip for multiple things. The before code defining a variable called tooltip with html in it and it's used for text
+tooltip+ part in JavaScript, you don't want to declare variables globally like this."
Related
Before marking this question as a duplicate, I know there is one exact same question with the exact same problem but the solution isn't working for me. Here is the link to that question.
The problem is, I know tooltips are being initialized because when I hover over my button, this markup shows up in my DOM.
<div class="tooltip fade top in" style="top: -34px; left: 20.5px; display: block; "><div class="tooltip-arrow"></div><div class="tooltip-inner">Add Quotation.</div></div
But it isn't showing up in the browser! In case of inspect element, It shows me the exact tooltip but it isn't appearing. It's transparent! The JSfiddles and all are working but it's not working in just my code.
I am using Laravel Mix with Vue.js. Anything extra is to be done or I am missing something?
UPDATE: I have already added data-toggle, data-placement and title in my element on which I want a tooltip.
Although we need additional information ...
what you are describing is usually related to the parent position.
Try attaching the tooltip to the body when initializing it like so.
// AN EXAMPLE ELEMENT
<div class="tip" title="Some tooltip"></div>
// THE JQUERY
$('.tip').tooltip({
container: 'body'
});
Let me know if this changes things and please add your initialization code
and the item your attaching the tooltip to css position
Live Example:
https://jsfiddle.net/sagive/aq9Laaew/137936/
edit
Since originally posting this question, I've gone down a couple more paths trying to solve the issue. It's still not solved, but now my questions are different. The original question is below, and then I'll add a section below that with updates.
original question
I'm working on a Rails 4 application and having some trouble with JavaScript and the Chartkick gem.
I have two JavaScript functions that make it so that a user can click an icon and an element will drop down below the icon/appear on the page, and the icon will switch from a right-pointing arrow to a down-pointing arrow. The code is this:
function ReverseDisplay(d)
{
if(document.getElementById(d).style.display == "none")
{
document.getElementById(d).style.display = "block";
}
else
{
document.getElementById(d).style.display = "none";
}
}
$(function() {
$('.toggle-icon').click(function() {
$(this).find('i').toggleClass('fa-arrow-circle-o-right fa-arrow-circle-o-down');
});
});
And the haml:
%a{href: "javascript:ReverseDisplay('toggle-stats#{item.id}')", class: 'toggle-icon'}
%i.fa.fa-arrow-circle-o-right
%div{id: "toggle-stats#{item.id}", style: "display: none;"}
= the items to be displayed
It works. However, I expect the items that drop down to take up the full width of the page, like so:
But instead, when I first click the toggle icon, they show up squished, like this:
If I then resize the browser just a tiny bit, the graph pops out to full-width, and it stays that way no matter what I do from there. I can't figure out how to get ahold of the generated mark-up, because this chart comes from Chartkick, as a gem. The generated html in the browser has this line:
<div dir="ltr" style="position: relative; width: 300px; height: 300px;">
Where the width: 300px is what's being changed to width: 1000px when I change the browser size. I don't have to change the browser size permanently or significantly. Once that width has changed to 1000px the first time it stays there - but the minute I refresh the page and click the icon to toggle the chart again, it's back to 300px. I don't know how to hook into this div, because it's generated by the gem and I don't know how to add a class to it. I've tried adding styling to a parent element that ensures all of that parent elements' children are width: 100%, but that doesn't do anything.
Anyway, I don't think that adding a class to it is the solution here. I just have no idea what is - I don't JavaScript incredibly well. I'm pretty much completely new to all front-end work as a whole. What's going on here, and how can I make these charts always be the full width of the page when they're toggled?
Notes: Am testing this in Chrome. I tested in Firefox and it does the same thing.
OK, I'm starting to wonder if this has something to do with the fact that I'm using a JavaScript function in order to capture dynamic item IDs - a page may have any number of these toggle-able charts, and so calling a jQuery function on each id seems impossible, because I don't know what ID is.
I removed the jQuery call, however, and the problem persists.
One of those times when rubber-ducking the Stack Overflow question box has not yet answered my question. So I guess I'll submit and hope for outside help here. :/
adjusted question
This question in the Github issues for Chartkick has lead me down a different path. The solution is not necessarily in attempting to restyle the charts at all. Instead, what I'm trying to do is trigger a resize event, because the chart automatically regenerates when the browser window is resized. This is both what's causing the problem and where the solution seems to lie.
My code:
.row
.col-sm-12
%h3.title-block.second-child
Stats by Video
.panel-groupd#faqList
- #claim.presenter.videos.each_with_index do |video, index|
.panel.panel-default
.panel-heading
%h4.panel-title
%a.chart{data: { toggle: "collapse", parent: "#faqList" }, href: "#video#{index}" }
= "'#{video.title}' at #{video.event.display_name} on #{display_date(video.recorded_at)}"
%div.panel-collapse.collapse{id: "#video#{index}"}
.panel-body
- if video.impressions.count > 0
%h4
Impressions by Hours (24 hours)
= line_chart video.impressions.group_by_day(:created_at, range: 1.day.ago...Time.now).count
...a couple more charts
:javascript
$(".chart").click(function() {
window.dispatchEvent(new Event('resize'));
});
So the intention here is that when I click the .panel-heading, this both drops down the .panel-body with the charts in it and resizes the window, which makes the charts resize correctly (or, rather, should).
It kind of works, in that, when I first click the .panel-heading trigger, it does not resize the charts, but when I click it again, the charts are resized perfectly for a split second... just before they become hidden from view again. :(
I've tried adding a time out to the javascript, like so:
:javascript
$(".chart").click(function() {
setTimeout(1000);
window.dispatchEvent(new Event('resize'));
});
But it doesn't appear to do anything at all.
So what I'm wondering here is how to get this resize event to work once the dropdown .panel-body is out so that the charts will resize appropriately on their own.
Here's a screen cast of the current problem, in case I didn't describe it clearly enough:
https://youtu.be/5quMGABoDs8
I don't know anything about Ruby or Chartkick, but in order to override that inline styling, you would have to use !importantin the css.
So, if you try that technique of giving all the children of the parent element width: 100% again, you might want to implement it something like this:
.importantRule { width: 100% !important; }
$( "parentElement > childElement" ).addClass('importantRule');
(First line goes in your CSS file, second line goes in JS)
First off: I'm aware of the jQuery.css() function, but it doesn't work in my case. I'll explain why.
I have a jQuery color picker being used to change the highlighting of a website. I want to apply that color picker to the border of an element which only shows on hover.
The jQuery.css() function only applies the CSS to elements it finds, and does not work on the :hover CSS attribute.
I've tried adding a CSS class which I toggle on the hover, but it comes back to the same problem: I'm trying to change ONLY the hover value.
There's got to be a way to do this, but I've been searching StackOverflow and Google for the better part of an hour now, so I'm invoking xkcd #627
Use the hover event to achieve the same results.
$('selector').hover( function(){
//A function to execute when the mouse pointer enters the element.
$(this).css('property','value');
}, function(){
//A function to execute when the mouse pointer leaves the element.
$(this).css('property','value');
});
I'm adding this as an alternative answer.
If you need to dynamically change your CSS then there is something wrong with your CSS. It's very strange that you need a definition, that you can't toggle with a class and has to be generated dynamically.
Let's say you have a widget that can be in two modes: inactive or active. When it's active elements in it should respond visually to a hover event, when it's not, they shouldn't.
<div id="my-widget" class="my-widget-container">
<div class="element">Something to look at</div>
</div>
CSS
.my-widget-container .element { background-color: #ffffff; }
.my-widget-container.active .element:hover { background-color: #00ff00; }
You switch the mode by:
$("#my-widget").addClass("active");
This will activate the :hover line for the element which now appears interactive.
If I knew more about your situation I could perhaps fix a fitting solution.
Also, jQuery.css is poorly named, perhaps jQuery.style would be a better name since that is exactly what it does.
I'm working on a site which dynamically creates facebook-like buttons via PHP. However, the <div> that the buttons are contained in needs to have the CSS property overflow: hidden; This is the only way I've found that works to make a two-column format which forces both columns to expand to be the length of the longest one. The only problem with this method is that any facebook-like buttons placed near the bottom of the container get clipped when someone clicks on them and they expand.
Here's the way I've tried to solve this issue:
Using jQuery, I loop through all facebook like buttons on the page and calculate their document offset using the offset() method.
I then clone() each button as well as give it absolute positioning and the calculated offset using jQuery's css() method. I hope that each cloned button will be placed in the same position of the button it was cloned from when I append it to the document.
Finally, I change each old facebook-like button's css to visibility: hidden; in order to make it invisible but still take up the space it would have previously on the page. I add the clones of the facebook-like buttons to a div without the overflow: hidden; property using the appendTo() function.
Here's my entire code for this process:
// Replaces functional facebook recommend buttons with identical ones
// in a div where they won't get clipped when they expand.
// Hides the old buttons so space is still left for new ones
$(window).load(function(){
$(".fb-recommend").each(function(){ // cycle through each recommend button
var offset = $(this).offset(); // calculate offset of each button
var newButton = $(this).clone(); // clone the button
newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top});
$(this).css("visibility","hidden"); // hide the old button
newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
});
});
At the end of all this, I expect to have clones of each button placed where the old button was but in a different <div>. The whole process works, except that the cloned facebook-like buttons are appearing at a slightly different position than the ones they were cloned from (as PitaJ points out they seem to be off by vertical offset multiples of around 39px). You can view the issue here:
LINK TO TEST WEBSITE
As you can see, the first button is placed in the correct location (the empty space filled by its hidden clone) but the other offsets were not calculated correctly.
I'd appreciate any ideas or help offered. Let me know if you'd like me to explain better or post more code!
Edit: I figured I'd post the CSS for the facebook-like buttons here (even though all I'm changing is the margin):
#content .fb-recommend {
margin: 15px 0 5px 0;
}
Edit 2: As per UnLoco's suggestion, I added a min-height property to the fb-reccommend CSS and commented out the line of code that was hiding the old buttons so it's easier to see the problem (which is still there, though slightly lessened. The CSS now looks like this:
#content .fb-recommend {
margin: 15px 0 5px 0;
min-height: 39px;
}
Edit 3: The problem appears to have been solved in all browsers but IE by changing the CSS to this:
.fb-recommend {
min-height: 24px; // I used 24 because the fb-buttons are 24px in height
}
Final Edit? This seems to work on all browsers on my end, including IE:
.fb-recommend {
min-height: 39px;
}
I'm thinking now that the 39 might have come from the 15px margin of the old fb-button + its 24px height. I think I can get around it by simply setting the height to be 39px and not having a margin.
this is because you are retrieving the offset before the fb iframes actually load. just add a css rule like this
div.fb-recommend{min-height:39px}
I believe you're problem is some odd jQuery weirdness.
To fix this, simple change your code to this:
$(window).load(function(){
$(".fb-recommend").each(function(index){ // cycle through each recommend button
var offset = $(this).offset(); // calculate offset of each button
var newButton = $(this).clone(); // clone the button
newButton.css({'position':'absolute', 'left':offset.left, 'top':offset.top + (39*index)});
$(this).css("visibility","hidden"); // hide the old button
newButton.appendTo("#wrapper"); // put the new button in the wrapper where it won't get clipped
});
});
This will account for the weird offset problem.
On the first click, it works as expected:
the class is changed
and the html content is changed from 'Show...' to 'Close...'
the content area is expanded with the slideDown effect,
Good so far.
On the second click, ...
the class changes
the html content is changed from 'Close...' to 'Show...'
The content area does NOT go away as expected.
On the third click, ...
the class is changed
the html content is changed
the already-shown content is re-shown with the slidedown effect.
So everything is working except for the 2nd click when the content is supposed to be hidden again.
Here's the jQuery:
-
$('.open_user_urls').live('click', function() {
$('#user_urls').slideDown('slow');
$(this).addClass('close_user_urls');
$(this).removeClass('open_user_urls');
$(this).html('Close Search History');
return false;
});
$('.close_user_urls').live('click', function() {
$('#user_urls').slideUp('slow');
$(this).addClass('open_user_urls');
$(this).removeClass('close_user_urls');
$(this).html('Show Search History');
return false;
});
Here's the HTML it's acting on:
<h3 class='open_user_urls'>Show Search History</h3>
<div id='user_urls'>
// an OL tag with content
</div>
And the only applicable CSS:
#user_urls { display: none; }
EDIT - I replaced my jquery code with functionally equivalent code supplied in an answer below, but the problem persists. So the cause must be elsewhere. I do recall this code working originally, but then it stopped. I'm stumped. Time to strip everything else out piece by piece...
EDIT 2 - Since the bug must be elsewhere, I'm accepting a code improvement for my jquery as the answer. Thanks.
Edit 3 - Found the source of the problem.
Inside the #user_urls div I have an series of OLs with the following css:
.url_list {float: left; width: 285px; list-style-position: outside; margin-left: 25px;}
Each OL contains a list of 20 urls and is meant to display in as many multiple columns as required to display all the URLs.
Removing the float: left; on these OL tags causes the problem to go away.
So having a float on the content contained in the DIV thats showing and hiding is causing it not not hide at all. Why would this happen?
EDIT 4: Adding a inside the #user_urls DIV allows the hiding action to work properly.
Perhaps something like this would be simpler?
$(".open_user_urls").toggle(
function () {
$(this).text("Close Search History").siblings(".user_urls").slideDown("slow");
},
function () {
$(this).text("Show Search History").siblings(".user_urls").slideUp("slow");
}
);
The toggle function is designed for precisely the scenario you're encountering.
To reiterate the problem and resolution to this question...
Inside the #user_urls DIV were a series of OL tags, each floated left. It was the float that was causing the problem.
Adding a <br style='clear: left;' /> inside the #user_urls DIV fixed the problem.
From what I've found, jQuery needs to have the height style set in order to slide it correctly. A work around I've used is to set the height before you slide it closed.
$('#user_urls').css('height', $('#user_urls').height() + 'px');
After you set it once, it should work correctly from then on. Check out this tutorial for a more detailed explanation.
Since this question was opened, jQuery have put in a fix for this themselves.
Updating to the latest version of jQuery solved the problem for us with no CSS changes. (jQuery 1.4.4 as of Dec 9th 2010)
Found via discussion on Google Groups in turn found from d12's answer. According to duscussion, in some jQuery 1.3x versions this bug affected several actions, slideUp, fadeOut, and toggle, if the element being hidden/slid up is a a non-floated parent containing floated children.
I think Conor's answer might put you on the right track. I might also suggest slideToggle and toggleClass:
http://docs.jquery.com/Attributes/toggleClass
http://docs.jquery.com/Effects/slideToggle
I could be as easy as:
$("h3.open_user_urls").click(function () {
next("div#user_urls").slideToggle();
});
I can't duplicate your bug. I used your exact code and I cannot replicate your issue.
This must be a script error from a different place in your JS code.
Thanks for this question. It really got me on my way figuring out the problem toggling an element with floated children.
Another resource that really helped and explains the behavior a bit can be found
on this Google group discussion.
Putting a non breaking space in your div is another solution similar to what The Reddest suggested that worked for me on a similar issue.