I have a filter menu which I put inside a table, and when one of the links are clicked, the according column in another separate table becomes hidden, until the link is click on again.
<!-- Table for filter menu -->
<table>
<tr>
<td>
<a class="toggle-vis" data-column="1">hideColumn1</a> |
<a class="toggle-vis" data-column="2">hideColumn2</a> |
<a class="toggle-vis" data-column="3">hideColumn3</a>
</td>
</tr>
<table>
<script>
$('a.toggle-vis').on( 'click', function (e) {
e.preventDefault();
// Get the column API object
var column = table.column( $(this).attr('data-column') );
column.visible( ! column.visible() );
} );=
</script>
My aim is to have some way of showing which columns are hidden/shown, so onClick, I would like the link text to become bold or change color or whatever.
Do I need to loop through my table? I have no idea - very new to HTML so any help is appreciated and the getElementById doesn't seem to be working for me.
You can use this in order to get the clicked element, and then modify its inline-styling based on that (or use a class).
Inline styling
<!-- Table for filter menu -->
<table>
<tr>
<td>
<a class="toggle-vis" data-column="1">hideColumn1</a> |
<a class="toggle-vis" data-column="2">hideColumn2</a> |
<a class="toggle-vis" data-column="3">hideColumn3</a>
</td>
</tr>
<table>
<script>
$('a.toggle-vis').on( 'click', function (e) {
e.preventDefault();
// ADDED CODE
var element = $(this);
if (element.css('font-weight') === 'bold') {
element.css({
'font-weight': 'normal'
});
} else {
element.css({
'font-weight': 'bold'
});
}
// END OF ADDED CODE
// Get the column API object
var column = table.column( $(this).attr('data-column') );
column.visible( ! column.visible() );
} );=
</script>
Classes
With classes, this is even simpler. Add this to your style:
.bold-link {
font-weight: bold;
}
and then, just use this function:
<script>
$('a.toggle-vis').on( 'click', function (e) {
e.preventDefault();
// ADDED CODE
var element = $(this);
element.toggleClass('bold-link');
// END OF ADDED CODE
// Get the column API object
var column = table.column( $(this).attr('data-column') );
column.visible( ! column.visible() );
} );=
</script>
You can add a class to the last clicked link (and remove previous class).
At the beginning of your file.
<style>
.selected {
font-weight: bold;
}
</style>
In the function
$('a.selected').removeClass('selected');
$(this).addClass('selected');
Also why are you calling e.preventDefault()?
Is it for when you click the link to not do anything?
Another way is to give a href="" attribute to the links and to return false at the end of the onclick function.
Related
I'm attempting to track events for all UI elements on a page. The page contains dynamically generated content and various frameworks / libraries. Initially I tracked elements through creating a css class "track" , then adding style "track" to tracked elements. elements are then tracked using :
$('.track').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
As content can be dynamically generated I wanted a method to track these elements also. So tried this using wildcard jQuery operator.
In this fiddle : https://jsfiddle.net/xx68trhg/37/ I'm attempting to track all elements using the jquery '*' selector.
Using jQuery '*' selector appears to fire the event for all elements of given type.
So for this case if is clicked all the click event is fired for all divs. But id is just available for div being clicked.
For the th element the click event is fired twice , what is reason for this ?
Can the source be modified that event is fired for just currently selected event ?
fiddle src :
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function() {
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<th id="th">tester</th>
You can try with:
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
$(document).ready(function() {
$("body > *").click(function(event) {
console.log(event.target.id);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<tr>
<td>Cols 1</td>
<td id="td">Cols 2</td>
</tr>
</table>
<p id="th">tester</p>
You may want to use event delegation to target the elements you need. Advantage is that this also works for dynamically generated elements. See code for an example of this.
// method to add/set data-attribute and value
const nClicksInit = (element, n = "0") => element.setAttribute("data-nclicked", n);
// add data-attribute to all current divs (see css for usage)
// btw: we can't use the method directly (forEach(nClicksInit))
// because that would send the forEach iterator as the value of parameter n
document.querySelectorAll("div").forEach(elem => nClicksInit(elem));
// add a click handler to the document body. You only need one handler method
// (clickHandling) to handle all click events
document.querySelector('body').addEventListener('click', clickHandling);
function clickHandling(evt) {
// evt.target is the element the event is generated
// from. Now, let's detect what was clicked. If none of the
// conditions hereafter are met, this method does nothing.
const from = evt.target;
if (/^div$/i.test(from.nodeName)) {
// aha, it's a div, let's increment the number of detected
// clicks in data-attribute
nClicksInit(from, +from.getAttribute("data-nclicked") + 1);
}
if (from.id === "addDiv") {
// allright, it's button#addDiv, so add a div element
let newElement = document.createElement("div");
newElement.innerHTML = "My clicks are also tracked ;)";
const otherDivs = document.querySelectorAll("div");
otherDivs[otherDivs.length-1].after(newElement);
nClicksInit(newElement);
}
}
body {
font: 12px/15px normal verdana, arial;
margin: 2em;
}
div {
cursor:pointer;
}
div:hover {
color: red;
}
div:hover:before {
content: '['attr(data-nclicked)' click(s) detected] ';
color: green;
}
#addDiv:hover:after {
content: " and see what happens";
}
<div id="1">
Click me and see if clicks are tracked
</div>
<div id="2">
Click me and see if clicks are tracked
</div>
<div id="3">
Click me and see if clicks are tracked
</div>
<p>
<button id="addDiv">Add a div</button>
</p>
<h3 id="th">No events are tracked here, so clicking doesn't do anything</h3>
You can invoke the stopPropagation and the condition this === e.currentTarget to ensure invoke the handler function of the event source DOM.
And you must know the <th> tag must wrapped by <table>, otherwise it will not be rendered.
$(document).ready(function() {
$('*').each(function(i, ele) {
$(this).addClass("tracked");
});
$('.tracked').on('click', function(e) {
if (this === e.currentTarget) {
e.stopPropagation();
console.log('Div clicked' + this.id);
console.log(window.location.href);
console.log(new Date().getTime());
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<!-- <div id="1" data-track="thisdiv">
Any clicks in here should be tracked
</div>
-->
<div id="1">
Any clicks in here should be tracked 1
</div>
<div id="2">
Any clicks in here should be tracked 2
</div>
<div id="3">
Any clicks in here should be tracked 3
</div>
<table>
<th id="th">tester</th>
</table>
I have a table or articles and a toggle on each row that displays the child row content. In the child row I also display Disqus comments. This all works fine but I do not want multiple rows opened up all at once and multiple Disqus comments loading, slowing down my page.
I want to disable all toggle buttons when one toggle is activated. Each toggle link (class option_toggle) and the row it's on has a unique ID. See below. How can I accomplish this via JQuery?
//Hide main article table's options row
$(document).ready(function() {
$(".option_toggle").click(function(e) {
e.preventDefault();
aid = $(this).attr('id');
//Determine if we are showing the comments or hiding the comments
is_hidden = $(this).parent().parent().next(".options_row").is( ":hidden" );
if(is_hidden)
{
disqus_container = '#disqus_container_' + aid;
jQuery('<div id="disqus_thread"></div>').insertBefore(disqus_container);
$.ajax({
type: 'POST',
url: 'http://www.example.com/disqus',
data: {'msmm_tn' : '12d406df3c8b2e178893e2c146d318e5', 'aid' : aid},
dataType: 'json',
success : function(data) {
if (data)
{
$('#disqus_container_' + aid).html(data.script);
DISQUS.reset({
reload: true,
config: function () {
this.page.url = 'http://www.example.com/#!'+ aid;
this.page.remote_auth_s3 = data.payload;
this.page.identifier = aid;
this.page.api_key = "cULB96iURBu1pZOtLOOSVlVgBj10SY9ctXWiv0eiQdzhdxqBq9UgmVr5SeSiaFiP";
}
});
}
}
});
}
else
{
//Remove the comments
$('#disqus_container_' + aid).prev('#disqus_thread').remove();
$('#disqus_container_' + aid).html('');
}
$(this).parent().parent().next(".options_row").toggle("fast");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<tbody>
<tr class="main_row" data-id="ROWID428272">
<td class="bkgcol-sunflower wht-border">
<td>
<a id="428272" class="option_toggle" href="#" title="Ratings/Comments">
</td>
<td class="key-title dark unpadded">
<td class="artcl_info text-center">Scitech</td>
<td class="text-center" style="width:10px">
<td class="text-center">
</tr>
<tr class="options_row" style="display: table-row;">
<td colspan="6">
<div class="row article_options">
<div class="row comments_row">
<div id="comments" class="col-md-12">
<div class="text-center article_title top_pad" style="width: 100%;">Comment on This Article</div>
<div id="disqus_thread">
<div id="disqus_container_428272">
</div>
</div>
</td>
</tr>
<tr class="main_row" data-id="ROWID427694">
I want to disable all toggle buttons when one toggle is activated.
$(".option_toggle").click(function(e) {
e.preventDefault();
// Remove click event handler defined above, and add a new one which prevents
// the click from doing anything
$(".option_toggle").off('click').on('click', function(e) {
e.preventDefault();
});
aid = $(this).attr('id');
// Continue with rest of your code ...
});
But is this really what you want? It means once you click a toggle, you cannot click any others. It also means all other toggles still look like links, maybe you should update styling to indicate they are disabled or something like that, eg add a disabled class and style that:
Javascript:
$(".option_toggle").addClass('disabled-link');
CSS:
a.disabled-link {
cursor: default;
color: #666;
text-decoration: none;
}
I am trying to convert a piece of JQuery that changes the class of a tr when checked to a piece of JQuery that changes the class of a tr when a button gets a class called "active". I am a JQuery/Javascript newbie and I am at a loss.
For those who have suggested it's a duplicate, I have tried to detect class and failed (updated code below).
ORIGINAL CODE (THAT WORKS)
javascript:
var $input_class = $('.addCheckbox');
function setClass() {
var tr = $(this).closest( "tr" );
if ($(this).prop('checked') == true){
tr.addClass( "highlight" );
}
else{
tr.removeClass( "highlight" );
}
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = setClass;
}
MY HORRIBLE TRY (UPDATED BELOW...NO LONGER THIS)
javascript:
var $input_class = $('.btn-group .btn-toggle .btn');
function setClass() {
var tr = $(this).closest( "tr" );
if ($(this).prop('.btn-success .active')){
tr.addClass( "highlight" );
}
else{
tr.removeClass( "highlight" );
}
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = setClass;
}
I am using the Bootstrap Switch Plugin which converts checkboxes to toggles
http://www.bootstrap-switch.org/
The converted html looks like this:
<tr>
<td width="15px"><input class="addCheckbox" type="checkbox" value="true" style="display: none;">
<div class="btn-group btn-toggle" style="white-space: nowrap;">
<button class="btn active btn-success btn-md" style="float: none; display: inline-block; margin-right: 0px;">YES</button>
<button class="btn btn-default btn-md" style="float: none; display: inline-block; margin-left: 0px;"> </button>
</div>
</td>
<td width="85px">May 2016</td><td class="restaurant-name">
Joe's Crab Shack
</td>
<td class="text-center">
#my table info
</td>
</tr>
UPDATE!!! As per 'duplicate' suggestions.
After looking through this question (which was very helpful), I have changed my code to this, and I still can't get it to work. I am wondering if it is having trouble finding the exact input class? Because the plugin converts the checkbox to html, I can't (or don't know how) set specific names or ids for the buttons.
javascript:
var $input_class = $('.btn');
var tr = $(this).closest( "tr" );
function checkForChanges()
{
if ($('.btn').hasClass('btn-success'))
tr.addClass( "highlight" );
else
tr.removeClass( "highlight" );
}
for(var i=0; i<$input_class.length; i++) {
$input_class[i].onclick = checkForChanges;
}
There are issues in your code resulting from not being familiar with the language. Also keep in mind this jQuery what you posted, not javascript.
As I am not quite sure what is your final objective here so let's go step by step.
First of all:
$('.btn-group .btn-toggle .btn');
The above means an element with all three classes class="btn-group btn-toggle btn" and I do not see such in your code. Are you sure you didn't want to use $('.btn-group, .btn-toggle, .btn'); ? At the moment var $input_class is empty, so later in your code you loop through nothing.
Second thing:
as I posted in the comments make sure you run your script after loading jQuery and rest of the content of the page. If your script is above jQuery, like this:
<head>
<script type="text/javascript">/* Your script here */</script>
<script type="text/javascript" src="jquery-1.9.1.min.js"></script>
</head>
Above won't work for two reasons:
You run your script before you load the jQuery, so commands like $(".class") aren't understood.
You run your script before loading the content, so for example var $input_class = $('.addCheckbox'); will be empty, because the element with class addCheckbox doesn't exist yet. [for this one assume jQuery is included before the script, but the script is still inside the <head>].
I have this code :
var closeButton = $("<a class='close'/>")
.button({
icons: {
primary: "ui-icon-close"
},
text: false
})
.removeClass("ui-corner-all")
.addClass("ui-corner-right ui-combobox-toggle")
.click(function () {
if (invisibleElement != null)
jQuery(invisibleElement).val("");
//removing the close button with placaholder value
jQuery(visibleElement).val("Select");
jQuery(visibleElement).focus();
jQuery(visibleElement).blur();
var parentNode = $(this).parent();
parentNode.find(this).remove();
isCloseButton = false;
});
And I am adding this button conditionally by this:
$(visibleElement).parent().find(".showAll").after(closeButton);
This is not added by default. This is added based on some input.
These things are added within a td
<table border="0" width="100%" cellspacing='0' cellpadding='2'>
<tr>
<td style="vertical-align:middle; text-align:left; width: 45%;">
<input type="text" id="theVisibleElement" value=""/>
</td>
</tr>
But After adding the closeButton, I am not able to see the showAll element. Only the inputBox(visibleElement) and the closeButton is visible. Although, in the source code all three are there i.e visibleElement(the input TextBox), showAll element and closeButton. Strangely the td is enough big but still all three are not shown up. What to do? Any suggestion?
This is the jsfiddle: http://jsfiddle.net/8U6xq/1/
Though it's a bit messy.
This is a CSS problem. Your "close" element is right over your showAll element. See the corrected fiddle here :
http://jsfiddle.net/8U6xq/2/
I have just changed this in the css :
.close {
left: 270px;
}
I'm making an ingredients application where users insert ingredients
My application looks like this:
As you can see, the first ingredients span doesn't have a X at the end, because you must have at least one ingredient, but the rest of the ingredient spans do. I'm also using the Jquery Sortable Plugin so if you click near the outside of any of the ingredient spans, you can change the order of the ingredients. This works fine, except if you move the first ingredient span, then that span doesn't have an X at the end, even if you move it to the last spot.
So what I'm trying to do is make the first ingredient span always have no X at the end, even if switched order with another ingredient span. I tried this:
$('ingredientsCOUNT > span:first').hide(deleteButton);
but it didn't work? Any other suggestions? All help is greatly appreciated, and here's my code:
HTML (the php can just be ignored!)
<div class='formelementcontainer funky'>
<label for="ingredient">Ingredients</label>
<div id='ingredientsCOUNT' class='sortable'>
<span>
<input type="text" class='small' name="ingredient" id="ingredient" placeholder='QTY'/>
<select name='measurements'>
<option value='' name='' checked='checked'>--</option>
<?foreach ($measurements as $m):?>
<option value='<?=$m->id;?>'><?=$m->measurement;?></option>
<?endforeach;?>
</select>
<input type="text" name="ingredient" id="ingredient" placeholder='Ingredient'/>
</span>
</div>
<div class="clear"></div>
<div class='addSPAN tabover'>
<a class='float-right' id='btnAddIngredients' href='#'>Add Ingredient</a>
</div>
</div>
jQuery
(function($) {
$(document).ready(function () {
$('#btnAddIngredients').click(function () {
var num = $('#ingredientsCOUNT span').length;
var newNum = new Number(num + 1);
var deleteButton = $("<a class='float-right' style='margin:10px 2px;' href='#'><img src='<? echo base_url()."public/img/delete.png";?>' height='11' width='11' /></a>");
deleteButton.click(deleteThis);
$('#ingredientsCOUNT > span:first')
.clone()
.attr('name', 'ingredient' + newNum)
.append(deleteButton)
.appendTo('#ingredientsCOUNT')
.fadeIn();
$('ingredientsCOUNT > span:first').hide(deleteButton); //THIS IS MY SOLUTION THAT DIDN'T WORK
});
function deleteThis() {
var span = $(this).closest('span')
span.fadeOut('slow', function() { span.remove(); });
}
$( ".sortable" ).sortable(); //jQuery Sortable initialized
});
})(jQuery);
How about hiding it with CSS? The following assumes you added a class delete-button to your delete links:
#ingredientsCOUNT > span:first-child .delete-button { display: none; }
With that CSS, you can reorder the list, add or remove items, and the first delete button will never show.
Since :first-child is quirky in oldIE ( https://developer.mozilla.org/en-US/docs/CSS/:first-child#Internet_Explorer_notes ), it's possible to use the Sortable API like this:
$(".sortable").sortable({
update: function (event, ui) {
var rows = $("#ingredientsCOUNT").children("span");
rows.removeClass("first-child");
rows.first().addClass("first-child");
}
});
(there's probably a better way to utilize the event and/or ui parameters)
This way, you wouldn't have to determine which row to add a delete button to; you would always include a delete button in every row in your HTML. Then, when a sorting is done, the jQuery in the stop event (EDIT: update event) will hide the first row's delete button and show the rest (via classes).
Of course, you would need this CSS:
#ingredientsCOUNT > span.first-child a.delete-button {
display: none;
}
And to add a delete-button class to your delete buttons <a>
EDIT:
I changed the Sortable method from stop to update so that it only runs the code when the sorting arrangement has actually changed, after the sorting is done.