Mouseover popup speech bubble - javascript

I'm new to javascript/css and would like to make a version of a mouseover popup similar to the one that displays over the underlined words here: http://st.japantimes.co.jp/essay/?p=ey20141219
I can see the code that is used, but I'm not sure where/how to add in my own speech bubble image when I edit the code for my own project.
Here is an example of the code used on the referenced page:
HTML:
<a style="cursor:pointer;" onclick="showChuPopup(event,'<b>’Twas</b><br />It was の省略');return false;" onmouseover="showChuPopup(event,'<b>’Twas</b><br />It was の省略');" onmouseout="endChuPopup();">’Twas</a>
Javascript:
function showChuPopup(e,text){
if(document.all)e = event;
var obj = document.getElementById('chu_popup');
var obj2 = document.getElementById('chu_popup_text');
obj2.innerHTML = text;
obj.style.display = 'block';
var st = Math.max(document.body.scrollTop,document.documentElement.scrollTop);/*
if(navigator.userAgent.toLowerCase().indexOf('safari')>=0)st=0;*/
var leftPos = e.clientX - 100;
if(leftPos<0)leftPos = 0;
obj.style.left = leftPos + 'px';
obj.style.top = e.clientY - obj.offsetHeight -1 + st + 'px';} function endChuPopup() {
document.getElementById('chu_popup').style.display = 'none';} function touchHandler(e){
document.getElementById('chu_popup').style.display = 'none';}
Thanks for any help or ideas.

There are a few ways to go about this, but I'll recommend two options and provide links to both!
First, check out the answer on this question to see if this is what you want:
jQuery Popup Bubble/Tooltip
Second, have you thought about just using a tooltip with CSS? They're not hard to implement at all, and you can absolutely bind data to them.
(Shamelessly stolen from: https://www.w3schools.com/css/css_tooltip.asp, I would recommend poking around here and also looking into Bootstrap if you're a beginner!)
<style>
.tooltip {
position: relative;
display: inline-block;
border-bottom: 1px dotted black;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: black;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
top: 150%;
left: 50%;
margin-left: -60px;
}
.tooltip .tooltiptext::after {
content: "";
position: absolute;
bottom: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent transparent black transparent;
}
.tooltip:hover .tooltiptext {
visibility: visible;
}
</style>
<div class="tooltip">Hover over me
<span class="tooltiptext">Tooltip text</span>
</div>

Related

JavaScript and CSS not working as intended

In the following code, when I put the div with class thumb-bar, the JavaScript I have written works but if place use it after full-img div tag, it doesn't work also the CSS attribute cursor: pointer for the thumb-bar div is not applied.
Edit - I mean the click listeners I apply using JavaScript are not working
CSS:
body {
width: 640px;
margin: 0 auto;
}
.full-img {
position: relative;
display: block;
width: 640px;
height: 480px;
}
button {
border: 0;
background: rgba(150, 150, 150, 0.6);
text-shadow: 1px 1px 1px white;
border: 1px solid #999;
position: absolute;
cursor: pointer;
top: 2px;
left: 2px;
}
.thumb-bar img {
display: block;
width: 20%;
float: left;
cursor: pointer;
}
HTML:
<div class="thumb-bar"></div>
<div class="full-img">
<img class="displayed-img" src="images/pic1.jpg">
<button class="dark">Darken</button>
</div>
JavaScript:
var displayedImage = document.querySelector('.displayed-img');
var thumbBar = document.querySelector('.thumb-bar');
btn = document.querySelector('button');
var overlay = document.querySelector('.overlay');
for (var i = 1; i <= 5; i++) {
var newImage = document.createElement('img');
newImage.setAttribute('src', 'images/pic' + i + '.jpg');
thumbBar.appendChild(newImage);
newImage.addEventListener('click', function(e) {
displayedImage.setAttribute('src', e.target.getAttribute('src'))
});
}
Because you're floating .thumb-bar img, those images are taken out of the page flow which results in the .thumb-bar element to have a height of 0, which in turn causes subsequent content to not be pushed down. That means that the .full-img element is rendered on top of the images and obscures them from the mouse pointer.
You need to clear the floats in order to get the .full-img element to render below them. This can be done by either making sure the .thumb-bar clear it's own content:
.thumb-bar {
overflow: hidden;
}
... or make the .full-img element itself clear them:
.full-img {
clear: both;
}

Manipulate Pseudo Elements with Custom Fields

What I need to do is similar to this post, but I need the user to be able to change the Pseudo Element using a custom field. Still learning JavaScript and this has been a struggle!
User needs ability to change ~ border-right: 500px solid #4679BD;
The custom field is ~ $angle = get_field('contact_angle_color');
Here is my code without my failed JavaScript attempts:
.relative-wrap {
position: relative;
min-height: 150px;
}
.triangle-down-right {
width: 50%;
height: 0;
padding-top: 54%;
overflow: hidden;
position: absolute;
top: 0;
right: 0;
}
.triangle-down-right:after {
content: "";
display: block;
width: 0;
height: 0;
margin-top:-500px;
border-top: 500px solid transparent;
border-right: 500px solid #4679BD;
}
<div class="triangle-down-right"></div>
I could not understand the part about custom field, but if you are planning on having unlimited control over pseudo-elements, well, good luck with that. Currently, manipulating pseudo-elements with Javascript is possible through injecting inline css into DOM as described in this post, but it is not recommended unless, of course, you absolutely have to.
So, the other way to change pseudo-elements is to add/remove/modify class names on the element. Please see the example code below and the JSFiddle: https://jsfiddle.net/9w4d6mts/
HTML:
<input type="button" id="direction" value="Change Direction">
<br>
<input type="button" id="color" value="Change Color">
<div id="demo" class="triangle-down-right alt"></div>
CSS:
.relative-wrap {
position: relative;
min-height: 150px;
}
.triangle-down-right,
.triangle-down-left {
width: 50%;
height: 0;
padding-top: 54%;
overflow: hidden;
position: absolute;
top: 0;
right: 0;
}
.triangle-down-right:after,
.triangle-down-left:after {
content: "";
display: block;
width: 0;
height: 0;
margin-top:-500px;
border-top: 500px solid transparent;
}
.triangle-down-right:after {
border-right: 500px solid #4679BD;
}
.triangle-down-left:after {
border-left: 500px solid #4679BD;
}
.triangle-down-right.alt:after,
.triangle-down-left.alt:after {
border-color: transparent #D4679B transparent;
}
JS:
document.getElementById('direction').addEventListener('click', function(){
var d = document.getElementById('demo');
d.className = (d.className.replace(' alt','') === "triangle-down-right") ? d.className.replace('right','left') : d.className.replace('left','right');
});
document.getElementById('color').addEventListener("click", function(){
var d = document.getElementById('demo');
console.log(d.className);
d.className = (d.className.slice(-3) === "alt") ? d.className.replace(' alt','') : d.className + ' alt';
});
Basically, we are preparing the classes in CSS beforehand and switch them with Javascript based on user interaction. That's it.

Position bottom element of top parent element

I am making this simple tooltip where I want to position the tooltip bottom at the top of the parent element. I want to do this by getting the height of the tooltip element and set this number negative to the top positioning.
The problem is that at the time that I hover the element, the tooltip height is 0, according to console.log();
$('.tooltip').hover(function() {
var content = $(this).data('tip-content');
var element = $(this).find('.tip-content');
if(element.length == 0 ) {
var html = $('<p class="tip-content">' + content + '</p>');
var height = html.height();
console.log(height);
html.css('top', - height);
$(this).prepend(html);
} else {
element.remove();
}
});
.element {
height: 50px;
width: 50px;
margin: 50px auto;
background: #000;
}
.tooltip {
position: relative;
}
.tooltip .tip-content {
width: 180px;
margin-left: -98px;
padding: 10px 5px;
position: absolute;
left: 50%;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
background: #294a72;
font-size: 0.75em;
color: #fff;
text-align: center;
}
.tooltip .tip-content:after {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top-color: #294a72;
border-width: 5px;
margin-left: -5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="element tooltip" data-tip-content="This is a test content">
</div>
At the time you're checking the height, the element has not yet been added to the DOM, and therefore can have no height. You simply need to switch the order of your statements. jQuery can and will change the CSS of the element even after it has been added.
var html = $('<p class="tip-content">' + content + '</p>');
$(this).prepend(html); //This line must go before the next
var height = html.height();
console.log(height);
However, you're still missing some pieces. height() does not include either margin or padding. To get padding, you can use outerHeight(), but margin you'll have to either read from the CSS or use a hard-coded value. Even worse, your arrow is using a pseudo-element, which *cannot* be read by DOM traversal, so your best bet there is to just hardcode it, sadly.
A better height calculation might look like:
var ARROW_HEIGHT = 5;
html.outerHeight() + parseInt(html.css('marginBottom'), 10) + ARROW_HEIGHT;
I think you have to prepend the HTML, and then get the height and reposition the element. Right now, you are getting the height of a variable, not an HTML element.
You just need to get height of 'tooltip' instead of 'tip-content'.
$('.tooltip').hover(function() {
var content = $(this).data('tip-content');
var element = $(this).find('.tip-content');
if(element.length == 0 ) {
var html = $('<p class="tip-content">' + content + '</p>');
// Get height of parent element
var height = $(this).height();
console.log(height);
html.css('top', - height);
$(this).prepend(html);
} else {
element.remove();
}
});
.element {
height: 50px;
width: 50px;
margin: 50px auto;
background: #000;
}
.tooltip {
position: relative;
}
.tooltip .tip-content {
width: 180px;
margin-left: -98px;
padding: 10px 5px;
position: absolute;
left: 50%;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
background: #294a72;
font-size: 0.75em;
color: #fff;
text-align: center;
}
.tooltip .tip-content:after {
top: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
border-top-color: #294a72;
border-width: 5px;
margin-left: -5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="element tooltip" data-tip-content="This is a test content">
</div>
For html object gets a height automatically, you need first put in DOM. That the reason for you get height = 0. You need first append your object and then get the height.
See my example: https://jsfiddle.net/bwun82q4/
$('.tooltip').hover(function() {
var content = $(this).data('tip-content');
var element = $(this).find('.tip-content');
if(element.length == 0 ) {
var html = $('<p class="tip-content">' + content + '</p>');
var height = html.height();
console.log(height);
html.css('top', - height);
$(this).prepend(html);
$(this).find("p").css("top",- $(this).find("p").height());
} else {
element.remove();
}});

Removing and readding an element pushes another element down, toggling the float in dev tools causes the element to move back to the correct position

I have a container that holds three items.
One is floated left, another is centered and the last is floated right. If I remove the center item and add it back the right most item gets pushed down and I don't know why.
If you select the right item and view it in Chrome dev tools you can toggle the float: right off/on and then it will be positioned correctly.
This happens in Chrome but does not happen in FireFox. (I have not tested in IE)
I have a demo of the issue here: http://codepen.io/anon/pen/rVyRmy?editors=001
var on = true;
var l = $('<div class="left"></div>');
var r = $('<div class="right"></div>');
var clicky = function() {
if (on) {
$('.container').empty();
$('.container').append(l);
$('.container').append($(
'<div class="fill">' +
'<span>text</span>' +
'<span>text</span>' +
'<span>text</span>' +
'<span>text</span>' +
'</div>'
));
$('.container').append(r);
on = false;
} else {
$('.container').empty();
$('.container').append(l);
$('.container').append($('<input type="text" />'));
$('.container').append(r);
on = true;
}
$('.right').on('click', clicky);
};
$('.right').on('click', clicky);
.container {
width: 400px;
height: 20px;
text-align: center;
background-color: lightgray;
}
.left, .right {
display: inline-block;
width: 14px;
}
.left {
position: relative;
float: left;
}
.left:before {
position: absolute;
top: 4px;
left: 4px;
content: "";
width: 0;
height: 0;
border-style: solid;
border-width: 5px 8.7px 5px 0;
border-color: transparent orange transparent transparent;
}
.right {
position: relative;
float: right;
}
.right:before {
position: absolute;
top: 4px;
right: 4px;
content: "";
width: 0;
height: 0;
border-style: solid;
border-width: 5px 0 5px 8.7px;
border-color: transparent transparent transparent orange;
}
span {
width: 93px;
background-color: green;
display: block;
float: left;
}
div span:first-child {
margin-left: 14px;
}
<div class="container">
<div class="left"></div>
<input type="text" />
<div class="right"></div>
</div>
In the above I clear everything and redraw, I have also tried leaving the left and right elements and just removing/adding the center back but I get the same result.
You can fix this by forcing a redraw on the right element. There are a couple of ways to do this, but my preferred way is $(r).hide().show(0);
$(r).offsetHeight has been known to work, though it doesnt work in the codepen you linked to and it doesnt work in safari. For background I added the code as follows:
else {
$('.container').empty();
$('.container').append(l);
$('.container').append($('<input type="text" class="middle" />'));
$('.container').append(r);
$(r).hide().show(0);
on = true;
}
The original SO post from which I got my answer when I ran into a similar problem the other day: Force DOM redraw/refresh on Chrome/Mac

css in textfield so text is deleted as a word

I am trying to figure out how facebook does the person-highlight tagging below.
I have a <textarea> and what I want is that ability when I press backspace the whole name gets deleted.
And I also wanted the name to be highlighted in blue (but this one is easy).
Can this be done easily through css? Or do I have to use some sort of javascript to have the deletion stuff working?
TLDR: I needed a jQuery function that deletes the name that is highlighted when I press back..that's all, no need for autocompletion and such
you can make it by adding an absolute div behind the required text, and make the background transparent for the textarea.
here is a snippet of code that I just wrote, it might help you.
I just faced some problems with adding the correct left position to the highlighted div.
html :
<div class='container'>
<div class='highlighted'></div>
<textarea class='text_area'>hi my name is Ayman</textarea>
</div>
css :
.custom_table{
position: relative;
width:600px;
}
.row{
position: relative;
height:40px;
background: #c80000;
border-top:1px solid #fff;
}
.row div{
color:#fff;
text-align: center;
line-height:40px;
}
.row:hover .first,
.row:hover .second,
.row:hover .third,
.row:hover .fourth{
background:#522D2D;;
cursor:pointer;
}
.first{
position: absolute;
left:0%;
right:80%;
height:40px;
background: #00c800;
}
.second{
position: absolute;
left:20%;
right:60%;
height:40px;
background: #0000c8;
}
.third{
position: absolute;
left: 40%;
right: 25%;
height: 40px;
background: #BEBECF;
}
.fourth{
position: absolute;
left: 75%;
right: 0%;
height: 40px;
background: #D6182F;
}
JavsScript :
$(document).ready(function(e){
$('.text_area').bind('keypress', function(e) {
var code = (e.keyCode ? e.keyCode : e.which);
if (code == 64){
$('.text_area').val($('.text_area').val()+" Ayman")
line = $('.text_area').val().substr(0, $('.text_area').selectionStart).split("\n").length;
var hl = $("<div class='highlighted'></div>");
$(hl).css({'left':$('.text_area').getCursorPosition()+"px", 'top': ((line*14)-12)+"px"})
$('.container').append($(hl))
}
});
});
(function ($, undefined) {
$.fn.getCursorPosition = function() {
var el = $(this).get(0);
var pos = 0;
if('selectionStart' in el) {
pos = el.selectionStart;
} else if('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
})(jQuery);
You can use Jquery Token input https://github.com/loopj/jquery-tokeninput
More comprehensive list is here:
Facebook style JQuery autocomplete plugin

Categories

Resources