Sorting a table with columns composed of icons - javascript

I am using the tablesorter javascript plugin to easily sort a bootstrap 3 table. My current code is simply:
$(document).ready(function() {
$('.table').tablesorter();
});
My problem arises with columns that have no data but font awesome icons in, the check and the cross.
<i class="fa fa-check"></i>
<i class="fa fa-times"></i>
Because there is no physical text in these columns, I am unable to sort them.
Aside of writing Yes and No beside the icon, is there any workaround to get tablesorter looking at HTML code instead of just text?

Answer, via spryno724 in the comments:
Add the Yes and No to the table cell, or to save characters, use Y and N.
Then, wrap them in a <span> and set it to style="display:none" in CSS.
The tablesorter plugin will read the Y and N and the table cells will become sortable, but the user will not be able to see it.

I posted this answer to your other similar question, but it was deleted for some reason.
Use the textExtraction function (demo):
$('table').tablesorter({
textExtraction: function(node){ console.log( node.className );
var $icon = $(node).find('i');
return $icon.length ? $icon[0].className : node.textContent;
}
});

Related

Issue with tree traversal, finding div ID to be used variably - jquery

so I've been trying to figure this out but I'm coming up short. Have really tried searching the best I could to come up with the answer, including jQuery API documentation and other SO posts. I feel like I'm almost there but I'm either misunderstanding something or I'm approaching this goal incorrectly.
For multiple different sections, I have 2 clickable icons in separate div's, 1 (lets say iconA) shown on load and 1 hidden (iconB) on load. When (iconA) is clicked, it hides the [sectionA] where (iconA) is located then shows the [sectionB] where (iconB) is located. I then want (iconB) to hide [sectionB] and show [sectionA].
Clearly I can't use toggle because one of the sections is always hidden at any given point. And since I'm trying to write a script that I can use for multiple sections and multiple icons, with different names, I can't just set 1-1 class names for ALL icons and sections.
I've created a jsfiddle to illustrate. Below I'll write a quick example.
HTML:
<div class="sectionAparent>
<div class="sectionA" id="example>
<i class="fa fa-code contbtn">iconA (shown on load)</i>
</div>
</div
<div class="sectionB" id="exampleSHOW">
<i class="fa fa-minus minushide">iconB (hidden on load)</i>
</div>
jQuery:
$('.contbtn').click(function(){
var contid = $(this).attr('id');
$('#'+contid+'show').slideToggle(1000);
$(this).hide(1000);
});
-this first one is to hide sectionA and show sectionB, which works fine.
$('.minushide').click(function(){
var cbtn = $(this).closest('.sectionB').siblings('.sectionAparent').find('div[id]');
var cid = $(cbtn).attr('id')
$('#'+cid+'show').slideUp(1000);
$(cid).slideDown(1000);
});
-So my thoughts were to jump up to the closest ancestor that is a sibling to the section containing the ID that I need. Then find the div with that ID, retrieve that ID, and use it show the section containing the ID and hiding the section with the ID+more. The goal is for this to be variable for multiple different sections with similar naming conventions without having to hard-code the section names in a list inside my script.
Hope this makes sense and I apologize for the wall of text, just wanted to make sure I conveyed what I'm trying to do and where I'm at. If my logic is incorrect or there is an easier way to do this, then I'm all ears! Thanks.
https://jsfiddle.net/dankbawls/wnjxwyfy/
You forgot to append the '#' character to sid in the second last line of the js
Updated fiddle
$('#'+sid).slideDown(2000);
Since you are using class (sectionhide) to toggle visibility, you can look into .toggleClass method.
It has an overriden constructor to accept 2 arguments, className and state (a boolean value)
Based on this state, it will add/remove class. True means add and false means remove
$('.minushide, .contbtn').on("click", function() {
var container = $(this).closest('.container');
var nextContainer = container.next('.container').length > 0 ? container.next('.container') : container.prev('.container');
container.toggleClass('sectionhide', true)
nextContainer.toggleClass('sectionhide', false)
})
Sample Fiddle
Note: I have added a common class container to both divs to have a common pattern
For a carousel kind of behaviour, you can use index to find index of element to be shown and hide all.
Sample Fiddle

Make some columns not editable with Mindmup editable table

I am using Mindmup editable tables.
I would like that the last column to not be editable (because in my case, it is a button to remove the row).
Can I do that with this library ?
There is currently no support for this feature.
But a quick fix is the following (based on this issue):
Change the line 113 of the plugin from this:
element.find('td').prop('tabindex', 1);
To this:
element.find('td[data-editable!="false"]').prop('tabindex', 1);
And in your table, make the appropriate columns not editable like this:
<tr data-id=123">
<td data-colname="first_name"
>Chuck</td>
<td data-colname="last_name"
>Norris</td>
<td data-editable="false"> <!-- data-editable added here -->
<button type="button" class="btn">
<i class="ti-close" aria-hidden="true"></i> Remove
</button>
</td>
</tr>
Note: the weird formatting of the td tags is intentional: this way, the editable plugging doesn't insert white spaces while editing a cell.
Update line 92 in mindmup-editabletable.js to:
$('.someClass').on('click keypress dblclick focus', showEditor)
Update line 114 in mindmup-editabletable.js to:
element.find('.someClass').prop('tabindex', 1);
Now apply class="someClass" to each of the elements that you want to be able to edit in your table.
Also, to remove the white space in the table cells, you can modify line 18 of the mindmup-editabletable.js to be:
editor.val(active.text().trim())
replace the line 16 (in the showEditor function):
active = element.find('td:focus');
with this code
active = element.find('td:focus').filter(function(){
var i= -1;
var elem = this;
do {++i} while((elem=elem.previousSibling)!=null);
return !(activeOptions.disableColumnNumbers.indexOf(i) > -1);
});
and then you will be able to declare your editor using disableColumnNumbers option like this
$("selector...").editableTableWidget({disableColumnNumbers: [0,2,3,4,5,6,7,8,9,10,11,12]});
good luck mate

Autodividers listview with collapsable option

I am working on a listview which has auto dividers based on date it is a very long list & data-autodividers='true' works fine but I want to further improve it by making the listview collapsible on date.
This can be done from back-end using c# (I am working on an asp.net webform mobile website) where I group my list based on Month-Year and make each group collapsible.
But I would love to do it with jQuery as I do for autodivider. I have set up same on jsFiddle.
http://jsfiddle.net/5PnBT/10/
How can I make these auto-divider collapsible using jQuery without doing it from code-behind file (c#)?
I did not see where jquerymobile has this as a build in option.
$(document).on("pageinit", "#page-wrapper", function () {
$("#hp-latest-articles").listview({
autodividers: true,
autodividersSelector: function (li) {
var out = li.attr('date');
return out;
}
}).listview('refresh');
});
If I have understood your problem, I think you just have to use the $.mobile.listview.prototype.options.autodividersSelector option. I had a similar problem, so if you need to list them according to the date attribute on the single element, do:
$( document ).on( "mobileinit", function() {
$.mobile.listview.prototype.options.autodividersSelector = function( element ) {
return (element.attr('date'))
};
});
I prepared a jsbin for that: http://jsbin.com/enuwoj/1/edit
There are two solutions to your problem.
Either you use the collapsible list sets on the jQuery Mobile side, then you will be able to reach exactly what you are looking for. You might nee to edit the looks of the element using CSS to make it look like a listview.
http://jsfiddle.net/rc9Gk/
<div data-role="collapsible">
<h3>Title</h3>
<ul><li>Item1</li><li>Item2</li></ul>
</div>
Second solution would be to apply custom event handlers on click event of the listview control. Whenever a click event occurs on a list divider you can hide the following list elements till the next auto-divider. This solution needs a bit of coding. If this solution fits you, I can write that code for you do let me know.
I believe your problem is solved by adding the following to the bottom of your original fiddle
$('.ui-li-divider').click( function(ev ){
var li = $(ev.target).next(':not(.ui-li-divider)');
while ( li.length > 0 ) {
li.toggle();
li = li.next(':not(.ui-li-divider)');
}
});
Here is the updated jsFiddle
Basically, everytime you click a divider, it looks for all following LIs until the next divider and toggles their visibility.
You'll need either <div data-role="collapsible"> or <div data-role="collapsible-set">, depending on if you wanted to group them or not.
If you want them pre-collapsed by default, include the data-collapsed="true" attribute as well.

jquery or javascript: Truncate text in table cell

I need to truncate the text in the first column of a table using javascript or jQuery. Here's where I'm at:
The table:
<table id="bigTable">
<tr><td>Text is tooooo looong</td><td>Just Right</td></tr>
<tr><td>Text is tooooo looong</td><td>Just Right</td></tr>
<tr><td>Text is tooooo looong</td><td>Just Right</td></tr>
</table>
Trying stuff like the following without success ( compiled from other similar posts ):
var lbl = $("#bigTable tbody");
var newLbl = $(lbl[0].outerHTML);
$('td:eq(0)', newLbl).slice(5);
It does not seem to be getting the contents, or text from the cells. Has no effect whatsoever. Tried also -
$('td:eq(0)', newLbl)contents().slice(5);
$('td:eq(0)', newLbl).text().slice(5);
What am I doing wrong?
EDIT
Before more down-voting and general grumpy-ness occurs ...
I have to have the text from a div copied to a variable for manipulation and later display in a different window/div.
This happens in response to a button click.
...but applying the css rules sounds promising. Will try that instead.
Please see this fiddle to understand what I need to do:
http://jsfiddle.net/Vsse3/2/
I have to be able to wrap column cells with a div before using the css idea.
You don't need js, using CSS:
demo:
http://jsfiddle.net/vTDAQ/3/
#elckarns comment is correct but you also need to wrap the cell content in a div to use text-overflow.
Also note that your table is not well formed.
demo updated as requested:
http://jsfiddle.net/Vsse3/6/

sorting table rows by columns containing markup

I'm using the tablesorter JQUery plugin to sort the rows of a HTML table by clicking on a column. In most cases, the table cells contain simple markup like <td>hello</td>, so the default behaviour works fine.
However, one column of the table contains cells like this
<td>
<a id="1" class="festivalSubscribe " action="create"
controller="festivalSubscription" onclick="/* Lots of Javascript */">Not Subscribed
</a>
<a id="1" class="festivalUnsubscribe hide" action="delete"
controller="festivalSubscription" onclick="/* Lots of JavaScript */">Subscribed
</a>
</td>
Each cell of this column contains two links (as above), one of which will always be invisible (the one with the hide class). I want to sort this column by the visible link text ("Not Subscribed" or "Subscribed").
The plugin provides am option to define a function, the results of which will be used to determine how to sort the column, e.g.
textExtraction: function(node) {
// extract data from markup and return it
return node.childNodes[0].childNodes[0].innerHTML;
}
However, I can't find a way to define this function such that it will correctly sort the simple case <td>hello</td> and the more complex case described above.
Try this, it should handle both cases of having child elements and not having child elements:
textExtraction: function(node) {
// extract data from markup and return it
var $node_a = $(node).find("a");
if ($node_a.length) {
return $node_a.filter(":visible").text();
}
// normal case
return node.innerHTML;
}
I think #Kevin B's answer is best for the original plugin, but I wanted to add that I have forked a copy of the original plugin on github and added functionality to the textExtraction option to allow specifying columns. So this is possible.
$("table").tablesorter({
// Define a custom text extraction function for each column
// default extraction is obtained like this: `$(node).text()`
textExtraction: {
0: function(node) {
return $(node).find("a:visible").text();
}
}
});
You can grab first visible element found inside the node and extract text from it using this:
$(node).find(':visible:eq(0)').text();
Try this:
textExtraction: function(node) {
return $('td :not(.hide)', node).text();
}

Categories

Resources