How to add hover effect to <table> using CKEditor? - javascript

I draw a table in CKEditor.
You can see current my table look like this.
Currently, I want to hover columns of the table and it will auto highlights check icon with the colour orange.
I found to change CSS:
CKEDITOR.config.contentsCss = '/mycustom.css';
CKEDITOR.replace('myfield');
I don't know how to apply in the table.
My table has structure like:
<tr>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>

Here is a script to highlight columns where there is checkmarks with an orange background-color.
var CKE = $( '.editor' );
CKE.ckeditor();
var columnIndex=0;
$("#update").click(function(){
// Output CKEditor's result in a result div
$("#result").html(CKE.val());
// If there is a table in the result
if( $("#result").find("table") ){
console.log("Table found.");
// On mouse over a td
$("#result").find("td").on("mouseover",function(){
// find the column index
columnIndex = $(this).index();
// Condition is to ensure no highlighting on the 2 firsts columns
if(columnIndex>1){
$(this).closest("table").find("tr").each(function(){
var thisTD = $(this).find("td").eq(columnIndex);
// If cell is not empty
// is the html entity for a space
// CKEditor always insert a space in "empty" cells.
if( thisTD.html() != " " ){
thisTD.addClass("highlight");
}
});
}
// Clear all hightlights
}).on("mouseout",function(){
$(this).closest("table").find("td").removeClass("highlight");
});
}
// Console log the resulting HTML (Usefull to post HTML on StackOverflow!!!)
console.log("\n"+CKE.val())
});
I took the time to make a demo based on your table.
Please, next time, post your HTML!!!
See working demo on CodePen

Related

Use javascript to Transfer Text

I have got 3 tables in html that at a certain time, i want to move text from 1 table will move to another. Can someone show me a javascript function ( just a few lines long - don't spend too long) that can transfer text from one td to another.
Transferring ONE td value to another:
Well if you assign a td an ID (ex. "firstTD", "secondTD"), you could store it's value in a variable (ex. "tdToMove"):
var tdToMove = document.getElementById("firstTD").innerHTML;
document.getElementById("secondTD").innerHTML = tdToMove;
Note: This will only copy the innerHTML of a single td, and duplicate it on the other. If you wish to clear the first entry, run:
document.getElementById("firstTD").innerHTML = "";
to render the first td 'blank'.
You will have to experiment to find a way to move ALL values to the other table, this was just a pointer.
Also, If the text is moving from table to table, and the tables remain identical, why not just place the input in both to begin with, OR, simply run a code to duplicate the table when you would like to move the data?
You can use Node.textContent property to get and set the text of a Node.
Here is a link about it:https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent
I have made a fiddle to show you that in action: https://jsfiddle.net/3dep0msg/
In this fiddle i transfer the text of cell1 to cell2 and add it to the text of cell2.
I use textContent and not innerHTML property, because you wanted to transfer ONLY text!
function copyTextFromCell(id1,id2){
var cell1= document.getElementById(id1);
var cell2= document.getElementById(id2);
cell2.textContent = cell2.textContent+cell1.textContent;
}
copyTextFromCell("cell1","cell2");
if you want to do this using jquery.
<table id="table1">
<tr>
<td>1,1</td>
<td>1,2</td>
</tr>
<tr>
<td>2,1</td>
<td>2,2</td>
</tr>
</table>
<table id="table2">
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
</table>
$('#table1 tr').each(function (indexR, element) {
$(this).find('td').each(function (index, element) {
var table2Rows = $('#table2 tr');
var table2Row = table2Rows.eq(indexR);
var table2Column = table2Row.find('td');
var table2cell = table2Column.eq(index);
table2cell.html( $(this).html());
});
});
working fiddle.

jquery, remove table row when unchecked

I have a table with rows of data, when a user clicks on the row (tr) or the checkbox, it appends that row of data into another location. How do I make it that when a user unchecks from the original table AND the new appended row, that the row disappears?
I want it so that when the user unchecks from the original table, the appended row disappears. When the user unchecks from the appended row, only the appended row disappears.
// original table
<div id="searchsub">
<table class="showsub">
<tr class="datarow">
<td>data</td>
<td>data</td>
<td>data</td>
</tr>
</table>
</div>
Row appends to this new table:
<table id="datarow">
</table>
Here's the jquery I have:
$(document).ready(function() {
$("#searchsub table tr").click(function(event) {
if(event.target.type !== 'checkbox') {
$(":checkbox", this).trigger("click");
}
});
$i = 1;
$("input[type='checkbox']").change(function(e) {
if($(this).is(":checked")) {
$(this).closest("tr").addClass("highlightrow");
var datarow = $(this).closest("tr.datarow");
var row = datarow.clone();
row.addClass("append" + $i);
$("#submitshipment #datarow").append(row);
$i++;
} else {
$(this).closest("tr").removeClass("highlightrow");
$(".append").closest("tr").remove();
}
})
})
Of course this way whenever the row is unchecked ALL of the rows are deleted, which isn't what I want. Please help?
EDIT: mark up of the appended row:
<tr class="datarow highlightrow append1">
<td>120093</td>
<td>G13</td>
<td><input type="checkbox" class="searchsub" name="searchsub[]" value="1"></td>
</tr>
jsFiddle:
http://jsfiddle.net/7cXqR/1/
Yes, unfortunately the non-functional jsFiddle doesn't really help ;-)
I think I've sorted out what you're trying to do though; the issue is you don't have anything (be it using jQ .data() or in markup) that relates your appended rows to your source rows. If you look at the jsFiddle I made (forked from yours) you'll see how I use the "value" attribute you have on the checkbox in the source table to find the cloned rows in the append table:
$('#datarow').find('input:checkbox[value="' + $(this).val() + '"]').closest('tr').remove();
http://jsfiddle.net/A4w59/
This approach could be modified to use any markup (stock or custom data-* attributes) or even jQ's .data() method; the key is being able to associate the source & append rows so that you can remove the appended row when unselecting it in the source table.

Setting TD value from previous TD

I have a table that is filled in with values dependant on a previous page
those avlues are filled in with struts apparently
but I'm not very good with all that stuff so is there a simple was I can do something like this, either with HTML only or maybe a small javascript I can put in tha page?
<Table>
<TR>
<TH>ID</TH>
<TD><s:property value="groupID" /><TD> <--Number generated by the page with struts
</TR>
<TR>
<TH>ID Value</TH>
<TD>foobar</TD> <-- the text I want to add in dependant on the number from the previous TD
</TH>
</Table>
so, is there a simple way to go about doing this? HTML, CSS, JavaScript solution maybe?
Given that exact HTML, a simple script like this will do it. But if you don't know JavaScript, you should really learn it so that you understand what you're doing.
<body>
<Table>
<TR>
<TH>ID</TH>
<TD><s:property value="groupID" /><TD>
</TR>
<TR>
<TH>ID Value</TH>
<TD>foobar</TD>
</TR>
</Table>
<!-- The script is here so it won't run until the TABLE has loaded -->
<script type="text/javascript">
// This is a map of the struts values to your values
var valueMap = {
"1": "foo",
"2": "bar",
"3": "baz"
};
// Browser compatibility. Older IE uses 'innerText' instead of 'textContent'
var textContent = ('textContent' in document) ? 'textContent' : 'innerText';
// Get all the TD elements on the page
var tds = document.getElementsByTagName('td');
// Get the text content of the first TD (index 0)
var text = tds[0][textContent];
// Get the value from the map using the text we fetched above
var value = valueMap[text];
// Set the text content of the second TD (index 1) to the mapped value
tds[1][textContent] = value;
</script>
</body>
Assuming you want to place the value 'groupID' (set in the first tr's td) into the second row's td element, then the following jQuery will do the trick:
$(document).ready(function() {
// Scrape the XML out of the TD containing the xml
var tdXml = $('table tr').eq(0).find('td').html();
// Grab the value of the value attribute (groupID)
var value = $(tdXml).attr('value');
// Set this value in the second row's TD
$('table tr').eq(1).find('td').text(value);
}​);​
jsFiddle here

Grab table by ID and iterate over rows one at a time

I would like to use
var merch = document.getElementById('merch');
to retrieve a table on my webpage, which is dynamically populated. Then I would like to iterate over the table, one row at a time, grabbing the
<td>
elements and storing each of them as a string in an array. Each row will have its own array.
Can someone give me a clue as to how to accomplish this? I feel certain there is a simple method I just haven't found in my searches.
Thank you in advance for your consideration.
The working demo.
var merch = document.getElementById('merch');
// this will give you a HTMLCollection
var rows = merch.rows;
// this will change the HTMLCollection to an Array
var rows = [].slice.call(merch.rows);
// if you want the elements in the array be string.
// map the array, get the innerHTML propery.
var rows = [].slice.call(merch.rows).map(function(el) {
return el.innerHTML;
});
map
You will want to use jQuery for this, it'll make it much easier. Then you can do something like this.
HTML Table
<table id="iterateOverThisTable">
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
<tr>
<td>One</td>
<td>Two</td>
<td>Three</td>
</tr>
</table>
JS File (with jQuery already included)
$(function() {
var rows = [];
$("#tableToIterateOver tr").each(function() {
var = cells = [];
$(this).find('td').each(function() {
cells.push($(this).text());
});
rows.push(cells);
});
})

Optimizing Jquery iteration through table columns comparing with existing row

I'm trying to write a function to add color to a table based on a reference which is one of the top rows of the table. There are several questions in SO mentioning row based iteration but not so much about column.
The structure of the table is something like:
<table id="data">
<tr>
<th rowspan="2">Name</th>
<th rowspan="2">Selection</th>
<th rowspan="2">Title</th>
<th rowspan="2">Info1</th>
<th rowspan="2">Info2</th>
<th colspan="10">Data</th>
</tr>
<tr>
<th>001</th>
<th>002</th>
<th>003</th>
<th>004</th>
<th>005</th>
<th>006</th>
<th>007</th>
<th>008</th>
<th>009</th>
<th>010</th>
</tr>
<tr id="ref_control">
<td></td>
<td>RefName</td>
<td></td>
<td></td>
<td></td>
<td>A</td>
<td>B</td>
<td>J</td>
<td>L</td>
<td>Z</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
</tr>
<tr>
<td><input type="checkbox" name="checkbox"/></td>
<td>Entity 1</td>
<td>Info...</td>
<td>More info...</td>
<td>Even more...</td>
<td>A</td>
<td>T</td>
<td>M</td>
<td>L</td>
<td>Z</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>2</td>
<td>5</td>
</tr>
(...)
</table>
In addition I'm using JQuery and the JQuery column cell select plugin to perform the mentioned task.
The Javascript code looks like this:
$(document).ready(function() {
// Colorize table based on matches
// Number of Data entries - Count on the reference (2nd row)
// and only 5th column onwards (index starts at 0)
var datasize = $("#data tr:eq(2) td:gt(4)").length;
// Start with column 6 (index starts at 1)
var begin = 6;
for (var i = begin; i < begin + datasize; ++i) {
var curCol = $("#data td").nthCol(i);
var ref = curCol.eq(0).text();
curCol.not(curCol.eq(0)).each(function() {
var data = $(this);
if (data.text() == '') {
data.addClass("black");
} else if (data.text() != ref) {
data.addClass("color");
}
});
}
});
A working example can be visualized here. In the example the table has only 9 rows and 10 data columns. The actual page I'm trying to optimize has 20 rows and 90 data columns.
Using the mentioned Javascript extensions/plugins the big sized table poses no threat to the Google Chrome browser taking a few seconds to load, however Opera, Firefox and Internet Explorer have a hard time running the function or end up asking for user interaction to stop the script from running.
So my question is aimed at both alternatives to the column select plugin or ways to optimize the code such that I don't kill almost all browsers except Google Chrome.
Edit: Changes according the the two comments from #Pointy
You can easily get 10x faster code if you want. Just save references once and go row by row instead of column by column. It doesn't become more complicated yet it performs much better. The reason is that your plug-in hides the abstraction that your table is made of rows that are made of columns. And not the other way around. Emulating the second version can be costy as you noticed in this example.
You may also use DOM properties instead of jQuery methods. They are really straightforward.
// get text (modern browsers || IE <= 8)
var text = elem.textContent || elem.innerText;
// set class
elem.className = "black";
your final code will be something like:
var refcells = $("#data tr:eq(2) td:gt(4)");
var datasize = refcells.length;
// Start with column 5
var begin = 5;
var refs = [];
var i = begin;
refcells.each(function () {
refs[i++] = $(this).text();
});
$("#data tr:gt(2)").each(function () {
var cells = $("td", this);
for (var i = begin; i < begin + datasize; i++) {
var elem = cells[i];
var text = elem.textContent || elem.innerText;
if (!text) {
elem.className = "black";
} else if (text != refs[i]) {
elem.className = "color";
}
}
});
Doing what you're doing is going to be very computationally intensive. Since your table layout seems pretty regular, I'd just completely ditch that nthCol() thing (for this page anyway) and do your work by iterating over the table once:
Grab the "key" row first, and save it
Loop through each relevant <tr>, and for each one get the <td> elements and iterate over them as a raw node list, or as a jQuery list. Either way it should be a lot faster.
In the second loop, you'll do the same logic you've got (although I'd use addClass() and removeClass()), referring back to the saved "key" row for each cell.
In your current loop, you're re-building the jQuery object of every <td> in the table for each column, and then you're doing that nthCol() work! That's a lot of work to do if you do it once, so repeating that for every single column is going to really drag that CPU down. (On IE6 - especially with all those "class" changes - I bet it's almost unbearably slow.)
edit — I looked over that code (for the plugin), and while it looks like it was competently implemented it doesn't have any "magic tricks". All it does is iterate through all the table cells you give it and checks whether or not each cell is in fact in the "nth" column. Thus, your iteration will perform that test on every cell in the table for every column you care about. In your 90x20 table, that'd be about 85 iterations through all 1800 cells. And that's before you do your work!

Categories

Resources