Revealing text on hover image - javascript

With my code, i am using a script that generates a random set of 4 images that gets displayed on refresh. I wish to only display the text when the cursor is hovering over the respective image.
Any pointers on doing this with CSS? I am not sure where to put the hover element. http://jsfiddle.net/sugarcraving/Af72K/1/
Javascript
$(document).ready(function() {
$(".champ").hide();
var elements = $(".champ");
var elementCount = elements.size();
var elementsToShow = 4;
var alreadyChoosen = ",";
var i = 0;
while (i < elementsToShow) {
var rand = Math.floor(Math.random() * elementCount);
if (alreadyChoosen.indexOf("," + rand + ",") < 0) {
alreadyChoosen += rand + ",";
elements.eq(rand).show();
++i;
}
}
});
CSS
div.champ {
display: none;
float: left;
color: red;
}

Following what Rouse02 said, add something around the context you want to hide/show.
<p>Celebi, the 251</p>
Then in your css, hide the content and only show it when you hover on the div (you could do it on the image hover as well).
p {
visibility:hidden;
}
.champ:hover p {
visibility:visible;
}
Demo: http://jsfiddle.net/bzTnR/1/

div.champ: hover{
visibility: hidden;
}
div.champ: hover p{
visibility: visible
}
Where p is the element within your div that holds the text.
Hope this helps.
V/R

Maybe this could help! Let me know if this wasn't you were looking for
JsFiddle
I changed CSS to like this : div.text{display:none} div.champ:hover div.text{display:block}

i've updated your fiddle..here..try this
div.champ p{
visibility: hidden;
}
div.champ:hover p{
visibility: visible;
}
updated fiddle

Related

List elements animation doesn't work when hide/show

Is it possible for li elements animation from here:
http://jsfiddle.net/8XM3q/light/
to animate when there is show/hide function used instead of remove?
When i have changed "remove" to "hide" elements didn't move: http://jsfiddle.net/8XM3q/90/
I wanted to use this function for my content filtering animations - thats why i have to replace "remove" to "hide/show".
I'm not good at JS but i think that it counts all elements, even when they are hidden:
function createListStyles(rulePattern, rows, cols) {
var rules = [], index = 0;
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
for (var colIndex = 0; colIndex < cols; colIndex++) {
var x = (colIndex * 100) + "%",
y = (rowIndex * 100) + "%",
transforms = "{ -webkit-transform: translate3d(" + x + ", " + y + ", 0); transform: translate3d(" + x + ", " + y + ", 0); }";
rules.push(rulePattern.replace("{0}", ++index) + transforms);
}
}
var headElem = document.getElementsByTagName("head")[0],
styleElem = $("<style>").attr("type", "text/css").appendTo(headElem)[0];
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = rules.join("\n");
} else {
styleElem.textContent = rules.join("\n");
}
So my question is how to adapt that part of code to count only "show" (displayed) elements?
If you want to have the animation and still have all of the data then use detach() function instead of remove: jQuery - detach
And to count or select elements try to do this using css's class attached to each element.
I edited your jsFiddle:
http://jsfiddle.net/8XM3q/101/
notice that I changed this line:EDIT: http://jsfiddle.net/8XM3q/101/
$(this).closest("li").remove();
to this:
$(this).closest("li").hide("slow",function(){$(this).detach()});
This means hide the item, speed = slow, when done hiding remove it.
Hope this is what you meant.
EDIT: Included detach.
As per your comment:
I wanted to use this function for my content filtering animations -
thats why i have to replace "remove" to "hide/show" I don't want to
remove elements at all. Im sorry if I mislead You with my question.
What you can do is to use a cache to store the list-items as they are hidden when you do the content filtering. Later when you need to reset the entire list, you can replenish the items from the cache.
Relevant code fragment...
HTML:
...
<button class="append">Add new item</button>
<button class="replenish">Replenish from cache</button>
<div id="cache"></div>
JS:
...
$(this).closest("li").hide(600, function() {
$(this).appendTo($('#cache'));
});
...
$(".replenish").click(function () {
$("#cache").children().eq(0).appendTo($(".items")).show();
});
Demo Fiddle: http://jsfiddle.net/abhitalks/8XM3q/102/
Snippet:
$(function() {
$(document.body).on("click", ".delete", function (evt) {
evt.preventDefault();
$(this).closest("li").hide(600, function() {
$(this).appendTo($('#cache'));
});
});
$(".append").click(function () {
$("<li>New item <a href='#' class='delete'>delete</a></li>").insertAfter($(".items").children()[2]);
});
$(".replenish").click(function () {
$("#cache").children().eq(0).appendTo($(".items")).show();
});
// Workaround for Webkit bug: force scroll height to be recomputed after the transition ends, not only when it starts
$(".items").on("webkitTransitionEnd", function () {
$(this).hide().offset();
$(this).show();
});
});
function createListStyles(rulePattern, rows, cols) {
var rules = [], index = 0;
for (var rowIndex = 0; rowIndex < rows; rowIndex++) {
for (var colIndex = 0; colIndex < cols; colIndex++) {
var x = (colIndex * 100) + "%",
y = (rowIndex * 100) + "%",
transforms = "{ -webkit-transform: translate3d(" + x + ", " + y + ", 0); transform: translate3d(" + x + ", " + y + ", 0); }";
rules.push(rulePattern.replace("{0}", ++index) + transforms);
}
}
var headElem = document.getElementsByTagName("head")[0],
styleElem = $("<style>").attr("type", "text/css").appendTo(headElem)[0];
if (styleElem.styleSheet) {
styleElem.styleSheet.cssText = rules.join("\n");
} else {
styleElem.textContent = rules.join("\n");
}
}
createListStyles(".items li:nth-child({0})", 50, 3);
body { font-family: Arial; }
.items {
list-style-type: none; padding: 0; position: relative;
border: 1px solid black; height: 220px; overflow-y: auto; overflow-x: hidden;
width: 600px;
}
.items li {
height: 50px; width: 200px; line-height: 50px; padding-left: 20px;
border: 1px solid silver; background: #eee; box-sizing: border-box; -moz-box-sizing: border-box;
position: absolute; top: 0; left: 0;
-webkit-transition: all 0.2s ease-out; transition: all 0.2s ease-out;
}
div.cache { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="items">
<li>Monday delete
</li><li>Tuesday delete
</li><li>Wednesday delete
</li><li>Thursday delete
</li><li>Friday delete
</li><li>Saturday delete
</li><li>Sunday delete</li>
</ul>
<button class="append">Add new item</button>
<button class="replenish">Replenish from cache</button>
<div id="cache"></div>
EDIT: There is a simpler way without adding any classes, is to use the :visible selector
You need to understand a concept is Javascript, which is that functions are considered objects. You can pass a function to another function, or return a function from a function.
Let's check the documentation on jQuery for the hide function
.hide( duration [, easing ] [, complete ] )
It says that it accepts a function as an argument for complete, which is called when the hide animation is complete.
The function hide does not remove the element from the DOM but simply "hides" it as the name suggests. So what we want to do, is hide the element then when the animation of hiding is done, we add a class "removed" to the list element.
We will accomplish that by passing a function (complete argument) like so :
$(this).closest("li").hide(400, function() {
$(this).addClass('removed');
});
When you want to select the list elements that are not "removed", use this selector $('li:not(.removed)')

Truncate the text and show it on mouseover

I need to truncate the text(with ... at the end) and on mouseover the entire text should get expanded.
I have tried to truncate by the below code. Problem with this code is, it expands the content on click of the ... but I need it to get opened when user mouse over anywhere on p tag
var len = 100;
var p = document.getElementById('truncateMe');
if (p) {
var trunc = p.innerHTML;
if (trunc.length > len) {
trunc = trunc.substring(0, len);
trunc = trunc.replace(/\w+$/, '');
trunc += '<a href="#" ' +
'onmouseover="this.parentNode.innerHTML=' +
'unescape(\''+escape(p.innerHTML)+'\');return false;">' +
'...<\/a>';
p.innerHTML = trunc;
}
}
DEMO
I am looking for an easy way to do it.
Thanks in advance.
PS: No CSS solution please, as it is not compatible with all browsers (IE7).
You can use Jquery Like this :
HTML :
<p>Some Text</p>
JS :
var lengthText = 30;
var text = $('p').text();
var shortText = $.trim(text).substring(0, lengthText).split(" ").slice(0, -1).join(" ") + "...";
$('p').text(shortText);
$('p').hover(function(){
$(this).text(text);
}, function(){
$(this).text(shortText);
});
DEMO : http://jsfiddle.net/1yzzbv4b/2/
Or you can also achieve this with css3 property text-overflow:ellipsis;
CSS :
p{
text-overflow:ellipsis;
width: 250px;
white-space: nowrap;
overflow: hidden;
}
p:hover{
text-overflow:clip;
width:auto;
white-space: normal;
}
DEMO : http://jsfiddle.net/1yzzbv4b/
Assuming that you set the class of your p-elements to be of escape-text, the following jQuery-code should work.
$(document).ready(function() {
$ps = $('.escape-text');
$ps.each(function(i, el) {
$(el).data('full-text', el.innerHTML);
strip(el);
});
$ps.on('mouseover', function() {
$(this).text($(this).data('full-text'));
}).on('mouseout', function() {
$(this).text(strip(this));
})
});
var length = 100;
var strip = function(el) {
el.innerHTML = el.innerHTML.substr(0, length) + '...';
}

Javascript: Memory efficient way to do this effect

I wrote the code in Javascript but any good alternative would do.
EFFECT: onmousemove over the webpage circles of random colors should create wherever the mouse moves. and they have to be added behind a mask image(circles are visible only in the transparent portion of the image which is a logo. thus creating a color paint to create logo onmousemove.
it doesn't work in jsfidde because of its memory intensiveness.
WORKING LINK: http://goo.gl/DNRxO9
I pasted the exact code you can create a new html file with the following code and IT WORKS PERFECT IN FIREFOX ONLY because of its memory intensiveness(lots of divs added in very short time so DOM becomes very very heavy).
<html>
<head>
<style type="text/css">
body{
padding:0;
margin:0;
overflow: hidden;
}
#mask{
width:100%;
height:auto;
position:absolute;
z-index:10;
}
#logo{
width:50%;
height:50%;
margin:auto;
}
.point{
width:0px;
height:0px;
background-color:#ff0000;
position:absolute;
z-index:5;
left:50px;top:50px;
border-width:50px;
border-style: solid;
border-color:red;
border-radius:50px;
opacity:1;
transition: border-width 3s ease-in-out;
}
.no-border{border-width:0px;}
</style>
<script type="text/javascript">
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 6; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
/* OptionalCode: for removing divs after a lot are created */
Element.prototype.remove = function() {
this.parentElement.removeChild(this);
}
NodeList.prototype.remove = HTMLCollection.prototype.remove = function() {
for(var i = 0, len = this.length; i < len; i++) {
if(this[i] && this[i].parentElement) {
this[i].parentElement.removeChild(this[i]);
}
}
}
i=0;
function colors(event){
var x=event.clientX;
var y=event.clientY;
var point = document.getElementsByClassName('point');
document.body.innerHTML += "<div class='point'></div>";
point[i].style.borderColor = getRandomColor();
//point[i].className += ' no-border';
point[i].style.left = x + 'px';
point[i].style.top = y + 'px';
i++;
}
function position(){
var ht = window.getComputedStyle(document.getElementById("mask"), null).getPropertyValue("height");
var ht_num = Number(ht.slice(0,ht.length - 2));
margin_top = (Number(document.body.clientHeight) - ht_num)/2;
document.getElementById('mask').style.marginTop = margin_top + "px";
}
</script>
</head>
<body onload="position();" onmousemove="colors(event)">
<img id="mask" src="http://goo.gl/EqfJ0L">
</body>
</html>
There is one HUGE, HUGE, HUGE performance killer in your code:
document.body.innerHTML += "<div class='point'></div>";
This takes your entire document, throws it away and just inserts everything back again. This is horrible! Remember this for all times and never do this again! ;)
Keep the basic rule in mind, to never add Elements via .innerHTML!
The correct way to go is the following:
// create your new div element
var circleElement = document.createElement("div");
// add all the stuff needed
circleElement.classList.add("point");
circleElement.style.borderColor = getRandomColor();
circleElement.style.left = x + 'px';
circleElement.style.top = y + 'px';
// now append the element to the body
document.body.appendChild(circleElement);
This creates a single div and nicely inserts it as a child-element of the body.
Additionally you can decrease the number of divs drawn by introducing a threshhold:
var lastX=0,lastY=0;
function colors(event){
var x=event.clientX;
var y=event.clientY;
if (Math.abs(lastX - x) + Math.abs(lastY - y) <= 10 ) return;
/* do stuff */
lastX = x;lastY = y;
}
As a third measure you can decrease the size of the image to just hold the mask element and trigger the mousemove only on the image (because divs outside the mask are hidden anyway).
Ultimately, you could kill "old" div-elements when you have reached a certain amount.
I have not included these two last optimizations, but look at the already supersmooth example now!

Mimicng caret in a textarea

I am trying to mimic the caret of a textarea for the purpose of creating a very light-weight rich-textarea. I don't want to use something like codemirror or any other massive library because I will not use any of their features.
I have a <pre> positioned behind a textarea with a transparent background so i can simulate a highlighting effect in the text. However, I also want to be able to change the font color (so its not always the same). So I tried color: transparent on the textarea which allows me to style the text in any way I want because it only appears on the <pre> element behind the textarea, but the caret disappears.
I have gotten it to work fairly well, although it is not perfect. The main problem is that when you hold down a key and spam that character, the caret seems to always lag one character behind. Not only that, it seems to be quite resource heavy..
If you see any other things in the code that need improvement, feel free to comment on that too!
Here's a fiddle with the code: http://jsfiddle.net/2t5pu/25/
And for you who don't want to visit jsfiddle for whatever reason, here's the entire code:
CSS:
textarea, #fake_area {
position: absolute;
margin: 0;
padding: 0;
height: 400px;
width: 600px;
font-size: 16px;
font: 16px "Courier New", Courier, monospace;
white-space: pre;
top: 0;
left: 0;
resize: none;
outline: 0;
border: 1px solid orange;
overflow: hidden;
word-break: break-word;
padding: 5px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
#fake_area {
/* hide */
opacity: 0;
}
#caret {
width: 1px;
height: 18px;
position: absolute;
background: #f00;
z-index: 100;
}
HTML:
<div id="fake_area"><span></span></div>
<div id="caret"></div>
<textarea id="textarea">test</textarea>
JAVASCRIPT:
var fake_area = document.getElementById("fake_area").firstChild;
var fake_caret = document.getElementById("caret");
var real_area = document.getElementById("textarea");
$("#textarea").on("input keydown keyup propertychange click", function () {
// Fill the clone with textarea content from start to the position of the caret.
// The replace /\n$/ is necessary to get position when cursor is at the beginning of empty new line.
doStuff();
});
var timeout;
function doStuff() {
if(timeout) clearTimeout(timeout);
timeout=setTimeout(function() {
fake_area.innerHTML = real_area.value.substring(0, getCaretPosition(real_area)).replace(/\n$/, '\n\u0001');
setCaretXY(fake_area, real_area, fake_caret, getPos("textarea"));
}, 10);
}
function getCaretPosition(el) {
if (el.selectionStart) return el.selectionStart;
else if (document.selection) {
//el.focus();
var r = document.selection.createRange();
if (r == null) return 0;
var re = el.createTextRange(), rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
return rc.text.length;
}
return 0;
}
function setCaretXY(elem, real_element, caret, offset) {
var rects = elem.getClientRects();
var lastRect = rects[rects.length - 1];
var x = lastRect.left + lastRect.width - offset[0] + document.body.scrollLeft,
y = lastRect.top - real_element.scrollTop - offset[1] + document.body.scrollTop;
caret.style.cssText = "top: " + y + "px; left: " + x + "px";
//console.log(x, y, offset);
}
function getPos(e) {
e = document.getElementById(e);
var x = 0;
var y = 0;
while (e.offsetParent !== null){
x += e.offsetLeft;
y += e.offsetTop;
e = e.offsetParent;
}
return [x, y];
}
Thanks in advance!
Doesn't an editable Div element solve the entire problem?
Code that does the highlighting:
http://jsfiddle.net/masbicudo/XYGgz/3/
var prevText = "";
var isHighlighting = false;
$("#textarea").bind("paste drop keypress input textInput DOMNodeInserted", function (e){
if (!isHighlighting)
{
var currentText = $(this).text();
if (currentText != prevText)
{
doSave();
isHighlighting = true;
$(this).html(currentText
.replace(/\bcolored\b/g, "<font color=\"red\">colored</font>")
.replace(/\bhighlighting\b/g, "<span style=\"background-color: yellow\">highlighting</span>"));
isHighlighting = false;
prevText = currentText;
doRestore();
}
}
});
Unfortunately, this made some editing functions to be lost, like Ctrl + Z... and when pasting text, the caret stays at the beginning of the pasted text.
I have combined code from other answers to produce this code, so please, give them credit.
How do I make an editable DIV look like a text field?
Get a range's start and end offset's relative to its parent container
EDIT: I have discovered something interesting... the native caret appears if you use a contentEditable element, and inside of it you use another element with the invisible font:
<div id="textarea" contenteditable style="color: red"><div style="color: transparent; background-color: transparent;">This is some hidden text.</div></div>
http://jsfiddle.net/masbicudo/qsRdg/4/
The lag is I think due to the keyup triggering the doStuff a bit too late, but the keydown is a bit too soon.
Try this instead of the jQuery event hookup (normally I'd prefer events to polling, but in this case it might give a better feel)...
setInterval(function () { doStuff(); }, 10); // 100 checks per second
function doStuff() {
var newHTML = real_area.value.substring(0, getCaretPosition(real_area)).replace(/\n$/, '\n\u0001');
if (fake_area.innerHTML != newHTML) {
fake_area.innerHTML = newHTML;
setCaretXY(fake_area, real_area, fake_caret, getPos("textarea"));
}
}
...or here for the fiddle:
http://jsfiddle.net/2t5pu/27/
this seems to work great and doesn't use any polls, just like i was talking about in the comments.
var timer=0;
$("#textarea").on("input keydown keyup propertychange click paste cut copy mousedown mouseup change", function () {
clearTimeout(timer);
timer=setTimeout(update, 10);
});
http://jsfiddle.net/2t5pu/29/
maybe i'm missing something, but i think this is pretty solid, and it behaves better than using intervals to create your own events.
EDIT: added a timer to prevent que stacking.

generate random opacity number using math random

I am trying to generate a random number for the css opacity.
This is what I tried so far.
CSS
.test{
position : absolute;
width : 15px;
height : 15px;
border-radius:15px;
background-color : black;
}​
Script
$(function() {
for (var i = 0; i < 300; i++) {
$("<div>", {
class: "test",
css: {
opacity: randomOpacity
}
}).appendTo("body");
}
function randomOpacity() {
var opac = 0;
opac = Math.random() < 1;
console.log(opac);
}
randomize();
});​
The Fiddle
There are multiple errors with your fiddle:
You are spawning 300 divs that are all absolutely positioned. They stack on top of each other and so would appear black regardless.
You aren't actually calling the function (missing parentheses)
Math.random() < 1 is going to return True instead of a number.
You aren't returning opac from your function.
You were calling randomize(), which isn't defined.
Corrected version: http://jsfiddle.net/RucKd/1/
Math.random() already generates a random number between 0 and 1, so:
$(function() {
for (var i = 0; i < 100; i++) {
$("<div>", {
class: "test"
}).css('opacity', Math.random()).appendTo("body");
}
});
Fiddle
edit: Re-inserted your loop in my answer and removed absolute pos from the fiddle. Read #ChristopheBiocca (+1)'s answer for a more complete code review.
JS
$(function() {
for (var i = 0; i < 300; i++){
$("<div>", {
class : "test",
css : {
opacity : randomOpacity
}
}).appendTo("body");
}
function randomOpacity(){
var opac = 0;
opac = (Math.random());
return opac;
}
});
CSS
remove position : absolute;, with this css all your divs at the same place
.test{
width : 15px;
height : 15px;
border-radius:15px;
background-color : black;
}​
The css functions alters a css attribute, Math.random() returns 0-1 so you can just drop it in. The following code alters the opac div's opacity.
<div id="opac">
lalalalala
</div>
<script>
$(document).ready(function(){
$("#opac").css('opacity', Math.random());
});
</script>
$(document).ready calls everything inside it once the page is loaded, good idea to use for things like this.
$('#foobar').css({ opacity: Math.random() });​
Math.random() always returns a value between 0 and 1 and you can put it directly in the function that creates divs. Also, the position: absolute in your CSS places every div in the same place, so you are not able to see the result correctly. Try this:
CSS
.test{
width : 15px;
height : 15px;
border-radius:15px;
background-color : black;
}​
JS
$(function() {
for (var i = 0; i < 300; i++) {
$("<div>", {
class: "test",
css: {
opacity: Math.random()
}
}).appendTo("body");
}
});​
Anyway, the randomize() function is not defined.

Categories

Resources