How to utilize :visited on parent elements? - javascript

I basically have a listing of content, which all goes to external url's (it opens them in new windows). As of right now, i have a:visited set to gray, although what i would REALLY love is for the whole list item (which contains the anchor link they click on) to have a reduced opacity.
You can see this behavior on reddit.
Say for example you have
<div class="item">
Click me
</div>
And then you have many rows of .item
I want it so that when you click on the link, the entire div can 'see' the :visited state, and so .item gets set to opacity: .5;, as opposed to just the text turning gray.
Is there a way to do this with JS or css?

This isn't exactly a solution to your technical problem, but would it be possible to alter your structure to make the <a> accomplish the stylistic needs of the <div> parent?
In other words, kill the <div>, and just use the <a>. That way, when it's "visited," you can do whatever you want right to it.

It appears there isn't a :visited selector in jQuery. Check out this plugin for including it:
http://remysharp.com/2008/02/25/visited-plugin/
Using this plugin, you can implement this effect using either this:
$("a").visited().each(function() {
$(this).parent().css("opacity", "0.5");
});
or this:
$(".item").filter(function() {
return $(this).find("a").visited().length;
}).css("opacity", "0.5");

Once CSS4 selectors are supported (assuming the present draft is accepted in something similar to its current form),
div.item! > a:visited
will select the parent div with class item of a visited a.
Until then, cssParentSelector may work.

Related

How can I exclude this element from an inherited link?

I have a site at whensayfeed.meteor.com. Each of those "Posts" is a nested in a <a></a> element. The heart on the right side of each one is supposed to be a "like button" so it also needs to be clickable. However, since it's nested in an <a> it just goes to that address when clicked. I need a way to either exclude this element, or do this in some other way. I've tried to just nest the .chant element in the link, but it doesn't pick up that click. What do you believe I should do?
Nesting tags is illegal
Try making your like button a link that's outside of the post link. You can then use position: absolute to overlap your like button on top of the post.
Try this:
Set the z-index: 0; of .post-contain instead of previous z-index: -20;.
Have a function receiving anchor click events like so:
function onAnchorClicked(e){
if(e.target.nodeName==='IMG'){
console.log('Image clicked');
e.preventDefault();
}else{
console.log('Anchor clicked');
}
}
Assign the click event to all anchor tags: $('a').on('click',onAnchorClicked);
This way, you can do what you want to do when img is clicked.
Having said that, although HTML5 does allow block-level elements to be nested inside an anchor tag but legacy browsers will have a hard time.
A solution to that perhaps could be to have your posts wrapped around a div element instead of anchor which behaves like an anchor tag accompanied by a data-link attribute with values containing your links that you can populate from backend e.g.:
<div class="anchor-link" data-link="LINK GOES HERE">...</div> and then assign the click as described above (changing the selector obviously).
Hope this helps.

slideToggle opening all links on page?

I am new to Javascript and am having a few issues with my toggle menu:
1) I set the sub links to display:none; but they are still displaying anyway. I need them to be hidden on page load.
2) When clicking one of the main links, it toggles both main links instead of just the one clicked on. What do I need to add so that only the clicked link opens?
http://jsfiddle.net/musiclvr86/5otvoxho/
Bit of hack
$(document).ready(function(){
$('.sub').slideToggle(0);
$('.main').click(function(){
$(this).nextUntil(".main").slideToggle('fast');
});
});
and remove the line from your css
.dark-link.sub {display:none; }
http://jsfiddle.net/5otvoxho/4/
When you call it like this:
$('.sub').slideToggle('fast');
You're targeting every element that has a .sub class, so all of them will toggle. To fix it, you have to subject the selection to the elements relative to the clicked one using this. Since, by your structure they are siblings, not parent/children, you may use the .nextUntil() method from Jquery:
Updated Fiddle
$(this).nextUntil(".main").slideToggle('fast');
This will select every subsequent siblings, until it finds another .main

Hide anchor, but not anchor text

Basically, I want to do the opposite of this: how do i hide anchor text without hiding the anchor
I'd like to be able to have a link on my page which under a certain set of client-side determined conditions would be able to deactivate the link, but still show the text. Is there any way to do this without having two separate elements (one with both the anchor and the text and one with just the text) and then flipping visibility between the two?
EDIT: Sorry, should have clarified. I'd like the link to not be styled like a link when it's deactivated.
Replace the <a> with a generic <span>, and back again.
A simple strategy to replace would be:
find the node.
add the replaced node before it
remove the first node
--
var node = document.getElementById("example");
var new_node = document.createElement("a"); // or "span"
new_node.innerText = text;
node.parentNode.insertBefore(new_node, node);
node.parentNode.removeChild(node);
This code isn't complete, but just to give you an idea.
You can remove the href attribute when the condition is met.
Check this example.
HTML
Link to google
<p> Hover over me to remove the link from the anchor</p>
Javascript(Using jquery)
$("p").on("mouseover", function(){
$("a").removeAttr("href");
});
When you hover over the paragraph tag the href is removed but if u never hover over it u can go to google.com, hovering over the p tag is the example condition.
Example Fiddle
This will remove the href permanently from the anchor tag. You will have to add it back when another condition is met.
The short answer is, no. Any hidden or invisible element will hide it's children as well. You may find it easier to simply modify the attributes of the anchor tag when needed.
Hot link:
Text here
Non-hot link
<a class="no-link" data-url="#some-url-here">Text here</a>
You can use JavaScript to remove the href attribute, store it's value and add a class that you can use to override any styling.
There's no direct "correct" answer for what you've asked, as there are too many ways to achieve a similar effect. This answer is what I judge to be one of the simplest methods in case you need disable and re-enable the anchor(s) based on conditions.
You can add a click handler such as .on('click.disabledLink', false) to deactivate the anchor functionality (prevents default and stops propagation), then style it with a class that makes it look like normal text in your page.
To re-enable it you just have to off the handler and remove the added class.
//disable link
$('a').on('click.disabledLink', false).addClass('disabledLink');
//re-enable link
$('a').off('.disabledLink').removeClass('disabledLink');
Fiddle
In Firefox and WebKit browsers, you can use pointer-events: none; to make an element "transparent" to pointer (in a functional sense, not a visual sense!). What you're really clicking is the element below. See http://jsfiddle.net/Hqk49/ for demo.
Beware that it'll only work if CSS are enabled (and JS, in order to toggle a class to restore the normal behavior of the link). No support in IE9 and maybe IE10, no support in Opera: https://developer.mozilla.org/fr/docs/CSS/pointer-events
Refer the below CSS:
a{
line-height: 0;
font-size: 0;
color: transparent;
}

Change class value based on element ID

Slap me if I am going about this wrong, I am quite the beginner.
Here is my setup, which is very similar visually to Outlook's UI I guess.
Left pane (floating div) contains a list of containers you can click on (like emails). Right hand pane contains a set of non-visible containers that should become visible when their class is changed to a different css class.
I'm trying to set it up where if you click on the element in the left pane, it then performs an onclick javascript action (stored in an external .js file) that toggles the right div's class value between two css classes.
The onclick in the left pane div passes $_row['uniqueID'] to the function. That is the uniquely incremented column name. It is also the ID value of the right pane 's.
Putting this altogether, can someone direct me on how to do this?
left pane...
<div onclick=\"toggleMenu('".$row['uniqueIdentifier'],"'); \">
right pane...
<div id=".$row['uniqueIdentifier']," class=\"mL\">
css...
div.mL {display:none;}
div.mL.active {display:block;}
function toggleMenu(div){
$('#'+div).addClass('active');
}
jQuery has .addClass() and .removeClass() methods.
I think that's what you're after, let me know if not.
By not changing too much code I suggest doing this :
div.mL {display:none;}
div.mLactive {display:block;}
I erased the dot, so u have now 2 different classes.
So on clicking you just change the class of the div with the correct id to mLactive.
In Jquery this canbe done with $(#'theid').addClass('mLactive');
This only adds the new class. You also want to remove the previous class with $(#'theid').removeClass('mL');
Another way : $(#'theid').attr( "class" , "mLactive" ); Which doesn't require to remove the previous class. Your choice. Another advantage of this method is that javascript has a method to do that which doesn't require Jquery.
Jquery has also the easy options $(#'theid').show(); and $(#'theid').hide() btw.

HTML5,draggable and contentEditable not working together

When a draggable attribute is enabled on a parent element(<li>) I cant make contenteditable work on its child element (<a>).
The focus goes on to child element (<a>),but I cant edit it at all.
Please check this sample
http://jsfiddle.net/pavank/4rdpV/11/
EDIT: I can edit content when I disable draggable on <li>
I came across the same problem today, and found a solution [using jQuery]
$('body').delegate('[contenteditable=true]','focus',function(){
$(this).parents('[draggable=true]')
.attr('data-draggableDisabled',1)
.removeAttr('draggable');
$(this).blur(function(){
$(this).parents('[data-draggableDisabled="1"]')
.attr('draggable','true')
.removeAttr('data-draggableDisabled');
});
});
$('body') can be replaced by anything more specific.
If new contenteditable elements are not added in the runtime, one can use bind instead of delegate.
It makes sense that the draggable and contenteditable properties would collide. contenteditable elements, like any text field, will focus on mousedown (not click). draggable elements operate based on mousemove, but so does selecting text in a contenteditable element, so how would the browser determine whether you are trying to drag the element or select text? Since the properties can't coexist on the same element, it appears that you need a javascript solution.
Try adding these two attributes to your anchor tag:
onfocus="this.parentNode.draggable = false;"
onblur="this.parentNode.draggable = true;"
That works for me if I add it to the <a> tags in your jsFiddle. You could also use jQuery if it's more complicated than getting the parentNode.
Note: This is a workaround since I believe the inability for these two functionalities to work together resides in the HTML spec itself (i.e. the not working together thing is intentional since the browser can't determine whether you want to focus or drag on the mousedown event)
I noticed you explicitly set 'no libraries', so I will provide a raw javascript/HTML5 answer
http://jsfiddle.net/4rdpV/26/
This was my crack at it.
First of all, it might be better to include the data in one single localStorage item, rather than scatter it.
storage={
'1.text':'test 1',
'2.text':'test 2'
}
if(localStorage['test']){
storage=JSON.parse(localStorage['test'])
}
this creates that ability, using JSON to convert between object and string. Objects can indeed be nested
I also added (edit) links next to the items, when clicked, these links will transform the items into input elements, so you can edit the text. After hitting enter, it transforms it back and saves the data. At the same time, the list items remain draggable.
After saving, hit F12 in chrome, find the console, and look in the localStorage object, you will see all the data was saved in localStorage['test'] as an Object using JSON.stringify()
I tried my best to design this to be scaleable, and I think I succeeded well enough; you just need to replace the HTML with a container and use a javascript for loop to write out several items, using the iterator of your choice to fill the parameter for edit(). For example:
Say you changed storage to hold "paradigms" of lists, and you have one called "shopping list". And say the storage object looks something like this:
{
"shopping list":{
1:"Milk",
2:"Eggs",
3:"Bread"
}
}
This could render that list out:
for(i in storage['shopping list']){
_item = storage['shopping list'][i];
container.innerHTML+='<li draggable=true><a id="item'+i+'">'+_item+'</a> (edit)</li>'
}
Of course, if you were to edit the structure of the storage object, you would need to edit the functions as well.
The output would look something like this:
Milk (edit)
Eggs (edit)
Bread (edit)
Don't worry about the input elements if that worries you; CSS can easily fix it to look like it didn't just change.
If you don't want the (edit) links to be visible, for example, you can do this in CSS:
a[href="#"]{
display:none;
}
li[draggable="true"]:hover a[href="#"]{
display:inline;
}
Now the edit links will only appear when you hover the mouse over the list item, like this version:
http://jsfiddle.net/4rdpV/27/
I hope this answer helped.
Using html5sortable and newer JQuery events (delegate is deprecated, answer 3 years after initial question), bug still affects Chrome 37. Contenteditable spans and html5sortable seem to play nice in other browsers. I know this is only partially relevant, just keeping documentation on changes I've noticed.
$(document).on('focus', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable('destroy'); // removes sortable from the whole parent UL
});
$(document).on('blur', 'li span[contenteditable]', function() {
$(this).parent().parent().sortable({ connectWith: '.sortable' }); // re-adds sortable to the parent UL
});

Categories