What I'm really after is to detect when the cursor changes to type "text", that is, when I'm hover over a piece of text. I have tried looking at the element types I am hovering over, but this isn't too accurate because I don't know what they actually contain.
I understand that detecting the CSS cursor attribute is only possible if it has previously been assigned by me.
Is this possible at all? How would you go about doing this?
EDIT:
I do not want to check If I am currently over a specific element, I want to know if I am hover over any text within that element. A div could be 100% width of the browser, but with a shorter piece of text at the far left. I don't want to detect when hovering over just any part of an element.
No need to try to detect if the cursor changed.
You can simply detect if the mouse is hovering your text by using this kind of construct :
document.getElementById('myTextId').onmouseover = function() {
// do something like for example change the class of a div to change its color :
document.getElementById('myDivId').className = 'otherColor';
};
If you don't have an id but a class or a tag, you can replace getElementById by getElementsByClassName or getElementByTagName (which will return arrays on which you'll iterate).
If you want to restore the color when leaving the element, I suggest you bind the event onmouseout in the same way.
For example, if you want to do something on any paragraph, you may do that :
var paras = document.getElementByClassName('p');
for (var i=0; i<paras.length; i++) {
paras[i].onmouseover = function() {
// do something like for example change the class of a div to change its color :
document.getElementById('myDivId').className = 'otherColor';
};
}
I you plan to do a lot of things like this, I suggest you look at jquery and its tutorial.
One possible way is to find all the text nodes in your DOM and wrap them in a span with a certain class. Then you could select that class and do whatever you want with it:
// Wrap all text nodes in span tags with the class textNode
(function findTextNodes(current, callback) {
for(var i = current.childNodes.length; i--;){
var child = current.childNodes[i];
if(3 === child.nodeType)
callback(child);
findTextNodes(child, callback);
}
})(document.body, function(textNode){ // This callback musn't change the number of child nodes that the parent has. This one is safe:
$(textNode).replaceWith('<span class="textNode">' + textNode.nodeValue + '</span>');
});
// Do something on hover on those span tags
$('.textNode').hover(function(){
// Do whatever you want here
$(this).css('color', '#F00');
},function(){
// And here
$(this).css('color', '#000');
});
JSFiddle Demo
Obviously this will fill your DOM with a lot of span tags, and you only want to do this once on page load, because if you run it again it will double the number of spans. This could also do weird things if you have custom css applied to spans already.
If you're using jQuery (which you should, because jQuery is awesome), do this:
$("#myDiv").mouseover(function() {
$("#myDiv").css("background-color", "#FF0000");
});
Related
I've bene bursting my head for the last few hours. Here's the situation:
I have a website that has many divs, but many of them share classes (they are equal) but have some different texts. Example:
<div class="summary-title">
I Am That Girl</div>
<div class="summary-title">
I Am That Girl</div>
What I want to do is select each one of these divs and add a span whenever another div is hovered.
I mean, this is what I want to do: hover a div that's before the sumary-title div, a span with a class is appended inside the sumary-title div or out of it, whatever works.
That's what I got so far:
$('summary-title').each(function(index) {
var content = $(index).next().text();
$(index).append("<span class='hover-text'>"+content+"</span>");
});
But I get an error that $ is not defined, probably because it is a closure?
I have no idea what to do. The code seems horrible too — i need to do this quickly and I just can't do. Would anyone help me at least know what to do?
Thanks
append() is already an implicit iteration ( that loops through the set of elements in the jQuery collection.) and it's unnecessary to call .each() .
$('.summary-title').append(function() {
return "<span class='hover-text'>" + $('a', this).text() + "</span>";
});
Outside of making sure you have jQuery on your page and properly referring it, your code should go like:
$('.summary-title').each(function() {
var content = $(this).children('a:first').text();
$(this).append("<span class='hover-text'>"+content+"</span>");
});
Notice:
dot in class selector - $('.summary-title')
this instead of index - $(this)
children selector instead of next
Check demo - Fiddle.
To append this to a preceding element on hover use:
$(document).ready( function() {
$('.summary-title').hover( function() {
var content = $(this).children('a:first').text();
$(this).prev().append("<span class='hover-text'>"+content+"</span>");
});
});
I have this html code:
<a onclick='addSelector(this)'>
<img src='resources/img/produkti/test.jpg'>
<input type='checkbox' value='test.jpg' name='main_image'>
</a>
And this is my javascript:
function addSelector(elem) {
var a = document.getElementsByTagName('a')
for (i = 0; i < a.length; i++) {
a[i].classList.remove('selected')
}
elem.classList.add('selected');
elem.find( 'input[type=checkbox]').prop('checked', true);
}
So, when 'a' is clicked, it gets 'selected' class. I want to make it so child input gets 'checked' too. Is there any way to solve this?
epascarello's comment is correct, but ultimately your problem is that elem is not a jQuery object. You might have better success with $(elem) on your last line (or wherever you are applying jQuery functions).
A much better way of writing the whole thing would be to have a click listener on the element instead like this:
// Listen for an anchor being clicked
$('a').on('click', function(event) {
// Remove selected class from all anchors
$('a').removeClass('selected');
// Add selected class to this element
$(this).addClass('selected');
// Make the relevant checkbox ticked
$(this).find('input[type="checkbox"]').prop('checked', true);
});
Although as mentioned on here elsewhere, a label is better than an anchor :).
Replace the anchor (which isn't being used as an anchor anyway) with a <label>.
This will have the behaviour you want by default. It will also associate the alt text (which you should add) of the image with the input for screen readers.
I created a function in Jquery which is supposed to center elements vertically (I could not do it using css, got tired and just made it programically ^^). The problem now is that I initially created it using .each, and then, since it was already creator, I tried calling it using the selector ($('something').center), but it is behaving differently for some reason.
Using the selector, it seems to be doing just the same to every element. It does it with the first element, and then just applies all values to the remaining elements. So, for example, my function takes the element height and does some operations with it, but the selector just takes the first one and then applies its parameters to everyone..
I'll keep using each since it works best right now, but I still can't understand why they are doing that..
Centering Function:
$.fn.center = function (){
/*If this is the highest element, or
if this element has full use of the width,
then there's no need to align it.
*/
if(this.height() == this.parent().height() ||
this.width() == this.parent().width())
{
this.css({
position : "relative",
top : 0
});
}
else //Should be aligned.
{
this.css({
position : "relative",
top : (this.parent().height()/2)-(this.height()/2)
});
}
return this; //Used for chaining.
};
Here's an example of what I mean ^^
http://jsfiddle.net/lrojas94/pmbttrt2/1/
For simple things, like just changing the CSS in the same way for all elements with the same class, you can call it directly without using .each(). For example:
$('.elem').css('color', '#fff');
But if each of the divs needs to end up with an individual value, you should use .each(). For example (sorry it's a bit weird):
var border = 1;
$('.elem').each(function() {
$(this).css('border', border + 'px solid #000');
border += 1;
});
Basically, if you don't use .each(), it'll check what you want to change (just once!) and apply it to all elements with that class. If you do use .each(), it'll do it individually for each element.
Simply put, this within a jQuery plugin function is not a DOM node. It's the jQuery object that wraps around all the nodes that were matched by the selector.
Your function's body should rather look like:
return this.each(function () {
var $el = $(this);
//centering logic for $el goes here
});
I see that this has been asked many times. But, unfortunately I have not come across a straight forward solution. Most solutions revolve around multiple nodes within the div.
So here's problem. I have the following markup:
<div class="test">Text1<span></span></div>
I need "Text1" to be replaced with "Text2" without affecting the span tag and event handlers attached to the span tag.
Doing something like $('.test')html('Text2<span></span>') does replace the text. But, removes the event handlers on the span tag, which is not desired. I am looking for a quick and efficient method for this one.
Wrap replaceable text with a tag:
<div class="test"><span class="test-text">Text1</span><span></span></div>
You can access the Text Node itself with contents. Now if you know that the element starts with text you can do this:
$($('.test').contents()[0]).replaceWith('New Text');
Now if you didn't know the location in the array of the Text Node, you can filter with:
return this.nodeType === 3;
and compare the text values (if you know those).
Fiddle
if you would add event handler with .live or .on functions (depends on jQuery version) .html('Text2') would work just fine.
On the assumption that the text to be replaced will always precede the existing span, that it will always be the firstChild and that it will be an unwrapped textNode:
$('.test').click(
function() {
this.firstChild.nodeValue = 'Text2';
});
JS Fiddle demo.
To ensure that only the first textNode is changed, regardless of where it's found within the .test element:
$('.test').click(
function(e) {
var newText = 'Text2',
children = e.target.childNodes;
for (var i=0,len=children.length;i<len;i++){
if (children[i].nodeName == '#text'){
children[i].nodeValue = newText;
return false;
}
}
});
JS Fiddle demo.
I'm trying to change the alt of the image, I'm clicking by
selecting the image's class (add_answer)
Note: .add_answer shows up multiple times inside different containing div's
jQuery(function(){ // Add Answer
jQuery(".add_answer").click(function(){
var count = $(this).attr("alt");
count++;
$('.a_type_'+count+'').show();
$(this).parents("div:first").$('.add_answer').attr("alt", count);
});
});
This line doesn't seem to be working, how do I select this add_answer class by way of it's parent div
$(this).parents("div:first").$('.add_answer').attr("alt", count);
Anyone else have an idea?
I'm trying having trouble decreasing the alt value on the .add_answer image when .destroy_answer is clicked
jQuery(function(){ // Hide Answer
jQuery(".destroy_answer").click(function(){
$(this).parents("div:first").hide();
var count = $('.add_answer').attr("alt");
count--;
$('.add_answer',$(this).parent('div:first')).attr('alt',count);
});
});
Problem line:
$('.add_answer',$(this).parent('div:first')).attr('alt',count);
you can use the parent div as the scope:
$('.add_answer',$(this).parent('div:first')).attr('alt',count);
This should work:
$(this).parent("div").find(".add_answer").attr("alt", count);
You code is almost correct. Required change is to use .find instead of .$ after .parents method. Use of .parent instead of .parents should be avoided, this way your code will be more unobtrusive (precisely - this way img can be non-direct child of the div).
$(this).parents('div:eq(0)').find('.add_answer')
You can manipulate :eq(0) to select eg third parent div using :eq(2).