Tinymce double click insert new paragraph - javascript

If I have 2 tables directly under each other with margin-bottom, is it impossible to place the cursor in this gap by creating a temporary paragraph.
E.g I want to insert a new table between the other 2. This is impossible without altering the HTML directly.
Is it possible to use the double click so that it works similar to MS word and creates a blank paragraph in this area you click, this would then get replace by the table etc similar to how the trailing plugin works.
I currently use the 'trailing' plugin which fixes this similar issue at the bottom of the page.
Also I am using the jquery version of tinymce, if that makes it any easier to fix this.
Example HTML inside tinymce editor;
<table style="margin: 15px 0; width: 100%;">
<thead>
<tr>
<th scope="col">
Product Name</th>
<th scope="col">
Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Large product</td>
<td>Find out more</td>
</tr>
<tr>
<td>Large product</td>
<td>Find out more</td>
</tr>
</tbody>
</table>
<table style="margin: 15px 0; width: 100%;">
<thead>
<tr>
<th scope="col">
Product Name</th>
<th scope="col">
Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Large product</td>
<td>Find out more</td>
</tr>
<tr>
<td>Large product</td>
<td>Find out more</td>
</tr>
</tbody>
</table>
Also created a jsFiddle with example: http://fiddle.tinymce.com/Sicaab/2 I want to be able to insert extra content (paragraph,another table, list etc) between the 2 tables without editing the HTML.

The mouse position won't help you, because you do not know if the editor content has been scrolled or not.
First, i will show you how to work with the onDblClick.
Here is a helpfull function to get the paragraph of an editor html element (in case there are no html elements that are not stacked under(or better in) a paragraph.
function table_of_click(node)
{
while (node)
{
if (node.nodeName == 'BODY') { return null; }
if (node.nodeName == 'TABLE') { return node; }
else { node = node.parentNode; }
}
return null;
};
Here is the necessary call to catch the double click event.
Be aware that this solution will add a paragraph just before the paragraph you clicked in.
I assume your tables are in a paragraph each?
ed.onDblClick.add(function(ed, evt){
// get tableof click event
var table = table_of_click(evt.target);
// if the click has not been inside a table return (nothing to do)
if (!table) return;
$(table).before("<p id='new_p'><br></p>");
ed.selection.select( $(ed.getBody()).find('#new_p').get(0) );
$('.new_p:first').remove();
evt.preventDefault();
evt.stopPropagation();
return false;
});

There is a way to get the caret (text cursor) position into the text
Caret position in textarea, in characters from the start
this is just a function getCaret(element);
now we need to capture the tinymce container's body inside the iframe content_ifr
the iframe: document.getElementById("content_ifr")
the tinymce's body: ...contentDocument.getElementById("tinymce")
using jquery we listen to the dblclick event:
.dblclick(function(event){})
find the caret and inject a <p> element on its position.
html.substr(0,position)+"<p></p>"+html.substr(position)
that is, all the text from the start to position, the p element and the text from the position to the end.
The whole code will look like this:
var editor = document.getElementById("content_ifr").contentDocument.getElementById("tinymce");
$(editor).dblclick(function(event){
var position = getCaret(this);
this.innerHTML = this.innerHTML.substr(0,position)+"<p></p>"+this.innerHTML.substr(position);
}
this should do the job ;)

Related

How can I briefly highlight a table row based on a td value, in a programatically added row in a razor page

I have a table in a razor page in which I'm looping through an IENumenrable collection (vwAssignedTaskProgress) and adding rows based on conditions. One or more of the contains 'recent' to indicate it is a row that has been recently added. I want to briefly highlight these rows to indicate they are new rows.
My problem is twofold. I'm using jquery (although I'm happy with any solution) and I can't get the jquery selector to fire on rows generated inside my loop. It works fine on content outside my # block of code.
And secondly, I can't seem to get .effect to work in Jquery (trying outside the # block). Research tells me that it's part of jquery UI which is both incorporated into jquery and deprecated.
Using jquery 3.5.1
<table class="table text-center" id="tblTasks4">
<tbody>
#foreach (var tsk in Model.vwAssignedTaskProgress){
#if ((#tsk._ChildUserId == #student.ChildUserId) && (#tsk.stStatus < 2))
{
<tr >
<th scope="row">
#tsk.Description
</th>
#if(#tsk.Created > DateTime.Now.AddMinutes(-1))
{
<td >
recent
</td>
}
</tr>
}
}
</tbody>
</table>
script block, within a form and body tag.
<script>
$('#tblTasks4 td').filter(
function(t){
if($(this).text() =="recent") {
$(this).closest('tr').effect("highlight", {}, 3000);
return;
}
});
</script>
First of all jQuery UI is not included in jQuery. You have it add it to your project separately.
Then I would add a recent class to the recent tds and hightlight them using:
$('.recent').parent().effect("highlight", {}, 3000);
Example:
<table class="table text-center" id="tblTasks4">
<tbody>
#foreach (var tsk in Model.vwAssignedTaskProgress)
{
#if ((#tsk._ChildUserId == #student.ChildUserId) && (#tsk.stStatus < 2))
{
<tr>
<th scope="row">
#tsk.Description
</th>
#if (#tsk.Created > DateTime.Now.AddMinutes(-1))
{
<td class="recent">
recent
</td>
}
</tr>
}
}
</tbody>
</table>
#section Scripts {
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.js" integrity="sha256-xLD7nhI62fcsEZK2/v8LsBcb4lG7dgULkuXoXB/j91c=" crossorigin="anonymous"></script>
<script>
$('.recent').parent().effect("highlight", {}, 3000);
</script>
}

JS : How do I get the innerHTML of a TD element when I click on it?

I've started to learn JavaScript not long ago.
I have several td elements in HTML and when I click on one of them, I would like to get it's innerHTML in JS. (Vanilla JS)
<div class="calendarCont">
<table>
<tr>
<td>Jan</td>
<td>Feb</td>
<td>Mar</td>
<td>Apr</td>
</tr>
<tr>
<td>May</td>
<td>Jun</td>
<td>Jul</td>
<td>Aug</td>
</tr>
</table>
</div>
I already know this method :
<td onclick="clickedCell = this.innerHTML; console.log(clickedCell)>Jan</td>
But what I'm looking for is a function with an addEventListener if it is possible, but I'm open to any suggestions.
Thank you.
I will suggest you to avoid inline event handler. You can first target all the tds using querySelectorAll(), then loop through them and attach the event using addEventListener():
var tds = document.querySelectorAll('.calendarCont table tr td');
tds.forEach(function(td){
td.addEventListener('click', handleTDClick);
});
function handleTDClick(){
console.log(this.textContent);
}
<div class="calendarCont">
<table>
<tr>
<td>Jan</td>
<td>Feb</td>
<td>Mar</td>
<td>Apr</td>
</tr>
<tr>
<td>May</td>
<td>Jun</td>
<td>Jul</td>
<td>Aug</td>
</tr>
</table>
</div>
In JavaScript select an element that wraps all of the elements you want to be able to click. A good candidate for this might be the <table>, or maybe the .calendarCont element.
The reason for selecting a wrapping element is for event delegation, which means that all events that are triggered within the wrapping element will also be triggered on the wrapping element itself. So you'll only have to add a single event listener for all the elements. Though this will require some checking when the user clicks.
Add an event listener with addEventListener to the table element and listen for the 'click' event. Write a function, like you already have which will handle the click.
Because every element can now be clicked inside the <table> element to trigger the click, you'll want to check which element has been clicked. Every fired event has an Event object with info about the event, which can be read from the event handler (callback function).
The event.target property is the element that triggered the click event. By evaluating if the target is the element that you are looking for you can control your event even better. For example, in your case, only show the innerHTML whenever the element is a <td>. Otherwise, do nothing.
const table = document.querySelector('table');
function onTableClick(event) {
const isCell = event.target.tagName.toLowerCase() === 'td';
if (isCell) {
console.log(event.target.innerHTML);
}
}
table.addEventListener('click', onTableClick);
<div class="calendarCont">
<table>
<tr>
<td>Jan</td>
<td>Feb</td>
<td>Mar</td>
<td>Apr</td>
</tr>
<tr>
<td>May</td>
<td>Jun</td>
<td>Jul</td>
<td>Aug</td>
</tr>
</table>
</div>
querySelectorAll and loops will be your friends.
Target each element and loop through the result to addEventListener to each of the td.
function alertInnerHTML(){
alert(this.innerHTML);
}
let tds = document.querySelectorAll("td");
tds.forEach(td => {
td.addEventListener("click", alertInnerHTML)
});
<div class="calendarCont">
<table>
<tr>
<td>Jan</td>
<td>Feb</td>
<td>Mar</td>
<td>Apr</td>
</tr>
<tr>
<td>May</td>
<td>Jun</td>
<td>Jul</td>
<td>Aug</td>
</tr>
</table>
</div>
So one method that works well is :
var selectedTableTD = document.querySelector('.calendarCont')
var tds = selectedTableTD.querySelectorAll('td');
tds.forEach(function(td){
td.addEventListener('click', function(){
console.log(this.textContent);
});
});
Thank you everyone for your help.

How can I hide the table cells contents dynamically using plain javascript?

I am creating a table in plain JavaScript, and filling it up using onClick listener event in two ways - either clicking on a external button, or clicking on one of the cells itself.I am not able to hide the contents of my table cells dynamically i.e.I want to hide them when rendering values in them, which I want to unhide/display later-on on some other event.
I have already tried conventional methods available viz.
td {display: none;}, and td {visibilty: hidden}
I have also tried inline CSS style method to hide the cell contents, but all these methods blank the table itself i.e. oblivate the cell borders themselves.
<body>
<div class="container-fluid">
<table id="myelement">
<tr>
<td> </td>
... .... ...
<td> </td>
</tr>
</table>
</div>
</body>
<script>
...
for(let i=0;i<mycount;i++){
for(var t=0;t< Math.floor(Math.random()*td.length);t++){
td[n[i]].firstChild.nodeValue='X';
}
}
...
</script>
All the techniques available blank the table itself i.e. oblivate the cell borders themselves.
There are a number of ways to do this, and some other ways might be better depending on the content of your table cells. But assuming it's just text, one way you could hide the cell contents would be to make the fontSize of the cell equal to 0. See this example:
hide.addEventListener("click", function(event) {
document.getElementById("table").rows[1].cells[1].style.fontSize = 0;
});
show.addEventListener("click", function(event) {
document.getElementById("table").rows[1].cells[1].style.fontSize = null;
});
table, td, th {
border: 1px solid black;
}
<table id="table">
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Age</th>
</tr>
<tr>
<td>Jill</td>
<td>Smith</td>
<td>50</td>
</tr>
<tr>
<td>Eve</td>
<td>Jackson</td>
<td>94</td>
</tr>
</table>
<button id="hide">Hide Cell "Smith"</button>
<button id="show">Show Cell "Smith"</button>

How to get a background image of a table with no ID with javascript?

I'm trying to get a backround image from a table but this table has no ID, it just says "" to the ID. All the functions to get the images that I've found ask for the 'tableid' but none of them work. :(
To be more specific about the problem, I need to check if this background image has a specific name, if so, I'll need the text of this table. But I can't get the text without knowing how to identify which table has that image on the background.
Any ideas?
Just editing to set a code (yes, it's a beginner code...)
var a = 44
var b = ""
var c = ""
for (i=0; i < a; i++)
{
b = document.getElementsByTagName("table")[i].getAttribute("background")
if b = "common/imgs/tabfade1.gif"
{
c = document.getElementsByTagName("b")[i].getProperty("textContent")
}
}
return c;
Thanks in advance.
Lets say you have those tables with different backgrounds:
<table style="background: url('/file/Fw7FiAU/0b3f6fce-b461-488c-bb6e-cc92987cf6fb.jpg') no-repeat center center;"><tbody><tr><td>hey</td></tr><tr></tr></tbody></table>
<table style="background:url('/file/Fw7FiAU/teki.jpg') no-repeat center center;"><tbody><tr><td>hi</td></tr><tr></tr></tbody></table>
<table style="background:url('/file/Fw7FiAU/beki.jpg') no-repeat center center;"><tbody><tr><td>ho</td></tr><tr></tr></tbody></table>
<table style="background:url('/file/Fw7FiAU/yuli.jpg') no-repeat center center;"><tbody><tr><td>hiya</td></tr><tr></tr></tbody></table>
Use any element selector depending on browser support - e.g. "getElementsByTagName" etc. For this example I have used "querySelectorAll" .Use the "getComputedStyle(tables[i],null)" to grab the background style and check for the desired image name in order to identify which table is the one you need.
var tables= document.querySelectorAll('table');
for(var i=0;i<tables.length;i++){
if(window.getComputedStyle(tables[i],null).background.match(/yuli/i)){
/*do what you have to do with this table*/
console.log(window.getComputedStyle(tables[i],null).background);
//console outputs the style: rgba(0, 0, 0, 0) url("https://****************/file/Fw7FiAU/yuli.jpg") no-repeat scroll 50% 50% / auto padding-box border-box
}
}
Modify the style selector accordingly if it is background-image.
Cheers
You don't need to have an id attribute to select elements using JavaScript. You can do stuff like selecting all tables on the page, or the second one, or table with a given class etc.
A great way to do that would be jQuery, a JavaScript library for querying and interacting with the DOM.
EDIT:
Here is a simple example, that uses jQuery to select all tables and logs their background-image css property to the browser's console. Hopefully you can use this as a starting point:
$('table').each(function(index, table){
var bgImage = $(table).css('background-image');
console.log('bgImage: ' + bgImage);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table style="background-image: url(https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png);">
<tr>
<td>aaa</td>
<td>bbb</td>
<td>ccc</td>
<td>ddd</td>
<td>eee</td>
</tr> <tr>
<td>aaa aaa aaa aaa aaa aaa</td>
<td>bbb</td>
<td>ccc</td>
<td>ddd</td>
<td>eee</td>
</tr> <tr>
<td>aaa</td>
<td>bbb</td>
<td>ccc</td>
<td>ddd</td>
<td>eee</td>
</tr> <tr>
<td>aaa</td>
<td>bbb</td>
<td>ccc</td>
<td>ddd</td>
<td>eee</td>
</tr>
</table>

Binding Click event after append Jquery not working

I've got a modal box that pops up popups when the plus icon is clicked in a table. After the page is loaded five rows are displayed in the table and clicking the plus sign opens the modal box. (Works perfectly).
But now we are changing the content of the table by an AJAX call. Once the TR's are replaced by new ones, the plus signs aren't working any more.
I'm aware of the fact that the event-handler
Table:
<table class="table table-hover" id="carsTable">
<thead>
<tr>
<th>Car Title</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr id="car-1836">
<td>ferrari f50</td>
<td><i class="glyph-icon icon-plus-circle">+</i></td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Product Title</th>
<th>Actions</th>
</tr>
</tfoot>
</table>
The Jquery Part that handles the AJAX (and works, replaced the table according to the JSON respons).
$.post("../../../scripts/getCars.php", {s: carSearch}, function (data) {
$("tr[id='carLoader']").remove();
$.each(data, function (index) {
if ($('#selectedCar-' + data[index].externalProductId + '').length == 0) {
$('#carsTable')
.append('<tr id="car-'+ data[index].id+'"><td>' + data[index].title + '</td><td><i class="glyph-icon icon-plus-circle"></i></td></tr>');
}
});
}, "json");
Now the event Handler, works after document is ready, but stops working once the AJAX call has replaced the data.
$('#carsTable').on('click', '.black-modal-80', function () {
console.log('Click detected; modal will be displayed');
});
What's wrong with the binding?
When you append something to the window, the element doesn't exist until you run the jQuery. That means the element the click event points to doesn't exist when the click event is defined. So you can use the body as a selector like this.
$('body').on('click', '.black-modal-80', function () {
console.log('Click detected; modal will be displayed');
});
Hope this helped!

Categories

Resources