adding class to a sibling on clicking on nested element - javascript

I have a problem with dom-manipulation. I would like to add class to .text element on click on .fonts-container li.
<div class="editor">
<h2 class="text">Heading</h2>
<div class="ui-resizable-handle"></div>
<div class="ui-resizable-handle"></div>
<div class="ui-resizable-handle"></div>
<img class="icon-layer-up2" >
<img class="icon-layer-down2">
<img class="icon-trash2">
<i class="icon-move"></i>
<i class="font2"></i>
<div class="fonts-container">
<ul>
<li data-fontname="Aclonica">Aclonica</li>
<li data-fontname="Acme">Acme</li>
<li data-fontname="Alegreya">Alegreya</li>
</ul>
</div>
</div>
here is my buggy JS:
$(document).on('click', '.fonts-container ul li', function(){
if ( $('.font2').hasClass("active")) {
var fontName = $(this).data("fontname");
$(this).prev().parent(".editor").find('.text').addClass("fontset");
}
});

use closest
$(document).on('click', '.fonts-container ul li', function(){
if ( $('.font2').hasClass("active")) {
var fontName = $(this).data("fontname");
$(this).closest(".editor").find('.text').addClass("fontset");
}
});

You can go up the tree until you reach .fonts-container by using .closest() and then find the sibling node using .siblings():
$(this).closest('.fonts-container').siblings('.text')

use parents
$(document).on('click', '.fonts-container ul li', function(){
if ( $('.font2').hasClass("active")) {alert('a');
var fontName = $(this).data("fontname");
$(this).parents(".editor").find('.text').addClass("fontset");
}
});

Use parents
$('li'.'.fonts-container').on('click', function(){
if ( $('.font2').hasClass("active")) {
var fontName = $(this).data("fontname");
$(this).parents(".editor").find('.text').addClass("fontset");
}
});

Related

Correct way to check if ul have li element using Jquery

I am trying to check if my <ul> has a <li> element in Jquery, if it does then it displays a div if not it hides it. So far I have the following code:
$(document).ready(function () {
$('#div-1 .div-2').each(function (index, item) {
var colorCount = $(item).find('.item ul li').length;
$(item).attr('data', colorCount);
if (colorCount > 0 ) {
$('.colourClass').show();
}
else {
$('.colourClass').hide();
}
});
});
Is this correct or is there a stricter and better way to do it?
I'd advise you to use toggle() function to achieve your requirements.
const $ul = $('#test');
$('#div').toggle($ul.find('li').length > 0);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id='test'>
<li>asdas</li>
</ul>
<div id='div' style='display: none;'>
Show if li exist!
</div>

Javascript - How to turn this into a simple function

$(document).ready(function()
{
// $('.pull-me').click(function()
// {
// $('.login').slideToggle('slow')
// });
$('#thumbnail1').mouseenter(function()
{
$('#thumbnailTitle1').css('visibility', 'visible')
});
$('#thumbnail1').mouseleave(function()
{
$('#thumbnailTitle1').css('visibility', 'hidden')
})
$('#thumbnail2').mouseenter(function()
{
$('#thumbnailTitle2').css('visibility', 'visible')
});
$('#thumbnail2').mouseleave(function()
{
$('#thumbnailTitle2').css('visibility', 'hidden')
})
$('#thumbnail3').mouseenter(function()
{
$('#thumbnailTitle3').css('visibility', 'visible')
});
$('#thumbnail3').mouseleave(function()
{
$('#thumbnailTitle3').css('visibility', 'hidden')
})
});
I'm very new to Javascript but am trying to learn. I aware this is jQuery but would like to know if there is a quicker way to do this code, like create a smaller function that i can call up to display/hide the text.
Because i will be adding more thumbnails and i don't want to have to write it all out for every photo and text that i display on the photo.
You can use bind a single event handler using Multiple Selector, In the event handler create the targeted selector using the current element this id property.
$('#thumbnail1, #thumbnail2, #thumbnail3').hover(function(){
var selector='#thumbnailTitle'+ this.id.replace(/[^\d.]/g,'');
$(selector).css('visibility','visible');
}, function(){
var selector='#thumbnailTitle'+this.id.replace(/[^\d.]/g,'');
$(selector).css('visibility','hidden');
})
However I would recommend you to establish the relationship using custom data-* prefixed attribute. Here example
$('.thumbnail').hover(function() {
$('#' + this.dataset.target).toggleClass('hidden');
}, function() {
$('#' + this.dataset.target).toggleClass('hidden');
})
.hidden {
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="thumbnail" data-target="thumbnailTitle1">thumbnail 1</span>
<span class="thumbnail" data-target="thumbnailTitle2">thumbnail 2</span>
<span class="thumbnail" data-target="thumbnailTitle3">thumbnail 3</span>
<div class="hidden" id="thumbnailTitle1">thumbnailTitle1</div>
<div class="hidden" id="thumbnailTitle2">thumbnailTitle2</div>
<div class="hidden" id="thumbnailTitle3">thumbnailTitle3</div>
The following is an option.
( function( $, window, undefined ) {
var handle_mouse_events = function handle_mouse_events( thumbnail_selector, thumbnail_title_selector ) {
$( thumbnail_selector ).mouseenter(
function() {
$( thumbnail_title_selector ).css( 'visibility', 'visible' );
}
);
$( thumbnail_selector ).mouseleave(
function() {
$( thumbnail_title_selector ).css( 'visibility', 'hidden' );
}
);
};
handle_mouse_events( '#thumbnail1', '#thumbnailTitle1' );
handle_mouse_events( '#thumbnail2', '#thumbnailTitle2' );
handle_mouse_events( '#thumbnail3', '#thumbnailTitle3' );
} )( jQuery, this );
.image_container > div {
display : inline-block;
width : 150px;
height : 200px;
}
span {
visibility : hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="image_container">
<div id="thumbnail1">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=150%C3%97150&w=150&h=150" />
<span id="thumbnailTitle1">Title #1</span>
</div>
<div id="thumbnail2">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=150%C3%97150&w=150&h=150" />
<span id="thumbnailTitle2">Title #2</span>
</div>
<div id="thumbnail3">
<img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=150%C3%97150&w=150&h=150" />
<span id="thumbnailTitle3">Title #3</span>
</div>
</div>
Use classes instead of ID's if you want to target similar elements with a behaviour.
The function itself is correct. The problem is that you have structured your HTML with unique ID's for every image. Trying to fix the problem by writing functions that target your unique ID's is the wrong approach, the underlying problem is your usage of ID's to target the element in the first place.
$(document).ready(function() {
$('.thumbnail').on('mouseenter', function() {
$(this).find('.thumbnail-title').css('visibility', 'visible');
})
$('.thumbnail').on('mouseleave', function() {
$(this).find('.thumbnail-title').css('visibility', 'hidden');
})
});
In the code snippet above you can see that every element with a class of thumbnail is selected. When the user hovers over a thumbnail you can reference the currently hovered element (with $(this)) and find the child element with the class thumbnail-title.
This is the simplest approach to sharing behaviour across elements of the same type.
Here's a working fiddle: https://jsfiddle.net/wq5r97ep/2/
EDIT: You can of course abstract this away into a plugin or just a general function. But this is the basic idea.
Something like this:
function handleEventsFor(index) {
$('#thumbnail' + index).mouseenter(function() {
$('#thumbnailTitle' + index).css('visibility', 'visible')
});
$('#thumbnail' + index).mouseleave(function() {
$('#thumbnailTitle' + index).css('visibility', 'hidden')
})
}
And call it like this:
handleEventsFor(1);
handleEventsFor(2);
Or like this:
for(var i = 0; i < 5; ++i) {
handleEventsFor(i);
}
You can try like this also,
Lets say your HTML
<div id="thumbnails">
<div><img class="thumbnails" src="" /></div>
<div><img class="thumbnails" src="" /></div>
<div><img class="thumbnails" src="" /></div>
<div><img class="thumbnails" src="" /></div>
</div>
Jquery
$(document).ready(function(){
$("#thumbnails").find('.thumbnails').mouseenter(function(){
var visibility = $(this).css('visibility');
if(visibility == 'hidden'){
$(this).css('visibility', 'visible');
}
});
$("#thumbnails").find('.thumbnails').mouseleave(function(){
var visibility = $(this).css('visibility');
if(visibility == 'visible'){
$(this).css('visibility', 'hidden');
}
});
});
I would write a simple visibleHover plugin for it. Using it will work like this
$(selectorForThumbnails).visibleHover(selectorForText);
Or as the example shows
// '.thumbnail' is the class of the parent elements
// 'span' is the selector for the children text elements
$('.thumbnail').visibleHover('span');
You can customize these inputs to match any HTML structure you have.
Click the Run code snippet button below to see it work
(function($) {
$.fn.visibleHover = function(selector) {
return this.each(function(idx, elem) {
$(elem).hover(
function() { $(selector, elem).css('visibility', 'visible'); },
function() { $(selector, elem).css('visibility', 'hidden'); }
);
});
};
})(jQuery);
$('.thumbnail').visibleHover('span');
.thumbnail {
float: left;
margin-right: 10px;
}
.thumbnail .image {
width: 100px;
height: 100px;
background-color: #eee;
}
.thumbnail span {
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="thumbnail">
<div class="image"></div>
<span>Text A</span>
</div>
<div class="thumbnail">
<div class="image"></div>
<span>Text B</span>
</div>
<div class="thumbnail">
<div class="image"></div>
<span>Text C</span>
</div>
Referencing by ID (i.e. $('#thumbnailn')) is very specific. You can make broader references by accessing tags or other attributes such as class instead.
Something like:
HTML:
<div id="thumbnail1" class="thumbnails"><span id="thumbnailTitle1"></span>...</div>
<div id="thumbnail1" class="thumbnails"><span id="thumbnailTitle2"></span>...</div>
<div id="thumbnail1" class="thumbnails"><span id="thumbnailTitle3"></span>...</div>
JavaScript:
$(".thumbnails").mouseenter(function() {
$(this).children("span").css('visibility', 'visible');
}).mouseleave(function() {
$(this).children("span").css('visibility', 'hidden');
});
In the above example I show how to reference a class (i.e. $(".thumbnails")) and a tag (i.e. ("span")) using JQuery
Using JQuery
$('#thumbnail3').mouseleave(function(e)
{
$(e.target).hide();
})
Using css.
#thumbnail3:hover {display:none}
Writing the whole thing inside a loop is one option.
for(var i = 1; i <= whatever_your_length_is; i++) {
$('#thumbnail' + i).mouseenter(function() {
$('#thumbnailTitle' + i).css('visibility', 'visible');
};
$('#thumbnail' + i).mouseleave(function() {
$('#thumbnailTitle' + i).css('visibility', 'hidden');
});
}

add/remove class on click and on document load

I have got 2 rows of html.
One row contains plain html and another row contains ul li lists.
First case:
On page load I want to change the text color of row one depending on which li is active.
Second Case
On click any li from second row, I would like to change the color of first row html depending on what data I have clicked in second row.
My code
First row
<div class="horizontal-link">
<div class="test">
<h4 data-id="1">Text 1</h4> <!--So on page load I would like to change the color to red as related with row 2 ul li) -->
</div>
<div class="test">
<h4 data-id="2">Text 2</h4>
</div>
</div>
Second Row
<ul>
<li class="tab active" data-id="1">Text 1</li>
<li class="tab" data-id="2">Text 2</li>
</ul>
I have tried and created a jsfiddle as demo:
Any help is highly appreciated. Thanks in advance.
You can use .filter() or attribute-selectors to check the data-id like this
jQuery
$(function(){
//Adds class on load depending on which is active
$('.test h4[data-id="'+$('ul li.active').data('id')+'"]').addClass('active');
//Adds class on click
$('li.tab').on('click',function(){
$('.test h4').removeClass('active');
$that = $(this);
$('.test h4').filter(function(){
return $(this).data('id')==$that.data('id')
}).addClass('active');
//removes class on clickable li and adds to clicked
$(this).addClass('active').siblings().removeClass('active');
});
});
CSS
.test h4.active {
color:red;
}
You need to change the css so it checked the h4 if has the class active
DEMO
You can either change text color of div or h4 by adding active class.
For div with active class use below jQuery
$(document).ready(function ($) {
var id = $('ul').find('.active').attr('data-id');
$('.horizontal-link h4[data-id="'+id+'"]').closest('.test').addClass('active');
$("li.tab").click(function () {
$('.active').removeClass('active');
var id = $(this).attr('data-id');
$('.horizontal-link h4[data-id="'+id+'"]').closest('.test').addClass('active');
});
});
DEMO
For h4, you need to change CSS like below
CSS :
.test h4.active {
color:red;
}
jQuery :
$(document).ready(function ($) {
var id = $('ul').find('.active').attr('data-id');
$('.horizontal-link h4[data-id="'+id+'"]').addClass('active');
$("li.tab").click(function () {
$('.horizontal-link h4').removeClass('active');
var id = $(this).attr('data-id');
$('.horizontal-link h4[data-id="'+id+'"]').addClass('active');
});
});
DEMO
Look at the JS fiddle here. I hope this will help you.,
Updated jQuery:
$(document).ready(function ($) {
var id = $('ul').find('.active').attr('data-id');
$('.horizontal-link h4[data-id='+id+']').addClass('active');
$("li.tab").click(function () {
$('.horizontal-link h4').removeClass('active');
var id = $(this).attr('data-id');
$('.horizontal-link h4[data-id='+id+']').addClass('active');
});
});
JS Fiddle:
http://jsfiddle.net/v1v1tqzs/34/
There is a change in your CSS :-
.test .active {
color:red;
}
you wrote it as .test.active . There should be a gap . That's why on page load the color:red was not getting implemented .
YOUR UPDATED FIDDLE:
$(document).ready(function () {
var id = $('ul').find('.active').attr('data-id');
$('.horizontal-link h4').each(function () {
if ($(this).attr('data-id') == id) {
$(this).addClass('active');
return;
}
});
$("li.tab").click(function () {
var id = $(this).attr('data-id');
$('.horizontal-link h4').each(function () {
if ($(this).hasClass('active')) {
$(this).removeClass('active');
}
});
$('.horizontal-link h4').each(function () {
if ($(this).attr('data-id') == id) {
$(this).addClass('active');
return;
}
});
});
});
Try this , code can be optimized
HTML:
<div class="horizontal-link">
<div class="test">
<h4 class = "1" data-id="1">Text 1</h4>
</div>
<div class="test">
<h4 class = "2" data-id="2">Text 2</h4>
</div>
</div>
<ul>
<li class="tab active" data-id="1">Text 1</li>
<li class="tab" data-id="2">Text 2</li>
</ul>
CSS :
.test.active {
color:red;
}
.tab {
cursor:pointer;
}
ul li.tab {
list-style:none;
display:inline-block;
width:50px
}
.active {
color:red;
}
JS:
$(document).ready(function () {
var id = $('ul').find('.active').attr('data-id');
if ($('.horizontal-link h4').attr('data-id') == id) {
$('.'+id).addClass('active');
}
});
$(".tab").click(function () {
$(".tab").removeClass('active');
$(this).addClass('active');
$('.horizontal-link h4').removeClass('active');
var id = $(this).attr('data-id');
$('.'+id).addClass('active');
});

How to unwrap all li from ul on button click

This is probably a dummy question. I am trying to export the contents of a unordered list into a text area and remove the list item on export. I have achieved it at some degree but it only brings in the first list item.
How can I export all the li's?
HTML :
<div class="wrapper">
<button id="exportBtn">Export</button>
<div class="container">
<ul class="structure">
<li>Something</li>
<li>Something else</li>
</ul>
</div>
<div class="text">
<textarea id="exportTxt" contenteditable style=""></textarea>
</div>
</div>
This is my script :
$(function() {
$( "#exportBtn" ).click(function() {
var htmlString = $('.structure li').html();
$('textarea#exportTxt').html(htmlString).parent().is( 'li' ).htmlString.unwrap();
$('textarea#exportTxt').addClass('slideIn');
});
});
View working demo
So you want it to read SomethingSomething else.
$(function() {
$( "#exportBtn" ).click(function() {
var html = ''; // start with empty
$('.structure li').each(function(){
html += $(this).html(); // append the html from each li
$(this).remove(); // remove the li
});
$('#exportTxt').val(html); // set it in the textarea
});
});
Here is a jsfiddle with a working demo: http://jsfiddle.net/Grimbode/PucV2/
Hope this is what you wanted.
js:
$( "#exportBtn" ).on('click', function() {
$('.structure li').each(function(){
var txt = $('#exportTxt').text();
$('#exportTxt').empty();
$('#exportTxt').text(txt + ' ' + $(this).text());
$(this).remove();
});
});
html:
<ul class="structure">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<button id="exportBtn">Export</button>
<textarea id="exportTxt"></textarea>
Try this:
js
$("#exportBtn").click(function() {
var list="";
$(".structure").children().each(function(){
list +=$(this).html() + " ";
});
$('textarea#exportTxt').val(list);
});
fiddle

Toggle styling for active element in group of elements

Given a group of elements with no target attribute (e.g. following code), what is the most effiecient way to set a highlight-styling for a selected element while unsetting the same styling for a previously selected element ?
<div id="uno" class="element_parent">
<a href="#" class="element">ONE</div>
</div>
<div id="dos" class="element_parent">
<a href="#" class="element">ONE</div>
</div>
<div id="tres" class="element_parent">
<a href="#" class="element">ONE</div>
</div>
I would add and remove a class on clicking the anchor, like so:
$('.element').on('click', function(e) {
e.preventDefault();
$(this).addClass('active')
.closest('div')
.siblings('div')
.find('a')
.removeClass('active')
});
CSS
.active {color: red;} /* or whatever */
or:
$('.element').on('click', function(e) {
e.preventDefault();
$('.element.active').removeClass('active');
$(this).addClass('active');
});
Something like:
$(".element").click(function() {
$(".element").removeClass("active");
$(this).addClass("active");
});
$('.element').on('click',function(e){
$(this).addClass('active');
$('.element').not($(this)).removeClass('active');
});

Categories

Resources