How can I decouple this JavaScript code further? - javascript

I have a JavaScript object. And you can see the line:
window.gv.borderiseTDCell(this);
Is tigthly coupled to the window (if gv is not initialised it crashes). However what I really want is to be able to do is:
//bind the click event
jQuery('.highlightableTDCell').click(function () {
borderiseTDCell(this);
});
But that doesn't work. Any ideas what I can do? This is the full lisinng (with tight coupling):
gridview = function () {
//bind the click event
jQuery('.highlightableTDCell').click(function () {
window.gv.borderiseTDCell(this);
});
};
//selecting cell
gridview.prototype.selectCell = function (obj) {
//dostuff to cell
};
And a page...
<table class="EditTable" cellpadding="0" cellspacing="0">
<tr>
<td>
<div style="">0</div>
</td>
<td>
<div style="">0 akudsfsa fdhsad fiasgdf swae</div>
</td>
<td class="highlightableTDCell">
<div>
<input value="0.00"/>
</div>
</td>
</tr>
</table>

It's probably because you're using this when you should be using $(this)
borderiseTDCell($(this));
Also, gridview doesn't seem to be defined:
var gridview = function (){}

Not sure why you'd need a library to outline a table cell. How about creating a class called outlinedCell
.outlinedCell{border:1px solid #f00;}
Then you can add, remove, or toggle this class
//bind the click event
$('.highlightableTDCell').click(function () {
$(this).addClass('outlinedCell');
// or // $(this).removeClass('outlinedCell');
// or // $(this).toggleClass('outlinedCell');
});
LIVE SAMPLE: http://jsfiddle.net/WJp2Z/

Related

JavaScript doesn't work in Thymeleaf and Spring Boot [duplicate]

JavaScript doesn't work in thymeleaf.
In Spring Boot Thymeleaf, first thing can open modal. But second, third ... things can not open modal.
Every thing has className, but only first thing can open modal.
I think JavaScript works only the first thing, and doesn't work other things.
<tr th:each="board, i : ${boards}">
<th scope="row" th:text="${i.count}">1</th>
<td>
<p class="show" th:text="${board.title}">Title</p>
<div class="modal"> .... </modal>
</td>
<td th:text="${board.writer}">Son</td>
<td th:text="${board.createDate}">2022-02-01</td></p>
</tr>
js
function show() {
document.querySelector(".background").className = "background show";
}
function close() {
document.querySelector(".background").className = "background";
}
document.querySelector(".show").addEventListener("click", show);
document.querySelector(".close").addEventListener("click", close);
please help me
With your code you are only adding event listener to the first element of the class ".show". You should be adding event listeners to all members of the class. The following code should do the work:
document.querySelectorAll('.show').forEach(item => {
item.addEventListener('click', show);
})

Stop Propagation not working

I'm trying to stop the bubbling of event of an inner checkbox to the click event of the tr element.
I have the following mark up:
<table border="1">
<tr class="row">
<td>
Item 1
</td>
<td>
<input type="checkbox" class="cb">
</td>
</tr>
<tr class="row">
<td>
Item 2
</td>
<td>
<input type="checkbox" class="cb">
</td>
</tr>
</table>
The rows are dynamically added, so to add listeners automatically to dynamically added elements, I used the following code:
$(document).ready(function() {
$('body').off('click.row').on('click.row', '.row', function() {
alert(1);
});
$('body').off('change.cb').on('change.cb', '.cb', function(e) {
e.stopPropagation();
alert(2);
});
});
However the event still bubble up to the tr element. I tried also the following:
e.stopImmediatePropagation();
window.event.cancelBubbles = true;
e.bubbles = false;
none seemed to work.
I reproduced this issue with JSFiddle:
JSFiddle
In this case, there is no event bubbling occuring because you have different events defined on different elements that just so happen to both fire when a mouse clicks on the check box (because you have also clicked a row).
You should either not add the row click event listener at all, or move stopPropagation to the the other handler to stop it from firing.
$(document).ready(function() {
$('body').off('click.row').on('click.row', '.row', function() {
e.stopPropagation();
alert(1);
});
$('body').off('change.cb').on('change.cb', '.cb', function(e) {
alert(2);
});
});

How to blur a table cell within content editable

I have a simple table within a content editable div like so:
<div contenteditable="true">
<table class="rwd-table" width="100%">
<tr>
<td> </td>
<td> </td>
<td> </td>
<td> </td>
</tr>
</table>
</div>
When you click a cell, I'm using jQuery to add an ID to that cell. The ID has CSS applied to highlight it.
$(document).on('click', 'td, th', function (event) {
// remove previous highlighted cell
$('#selectedCell').removeAttr('id');
// highlight new cell
$(this).attr('id', 'selectedCell');
});
When the highlighted cell looses focus, the ID should be removed. This is my problem.
// DOES NOT WORK :( //
$(document).on('blur', '#selectedCell', function (event) {
$('#selectedCell').removeAttr('id');
});
I'm assuming it's because table cells don't normally have focus/blur events.
Is there a way to detect blur on a table cell within contenteditable?
Here is a live example: http://jsfiddle.net/5c7br6zc/
Yes, the problem with blur event. Instead of relying on it try to bind click event on document and prevent it from bubbling in case if click occurred on TD:
$(document).on('click', 'td, th', function (event) {
$('#selectedCell').removeAttr('id');
$(this).attr('id', 'selectedCell');
event.stopPropagation();
});
$(document).on('click', function (event) {
$('#selectedCell').removeAttr('id');
});
Demo: http://jsfiddle.net/5c7br6zc/1/

Jquery will not remove div

I have form in which I am adding some dynamic actions. I have a table in which I have rows of positions
applicants applied for. There is an offer postion button and when they click on the offer button I want to insert the offer fields to be submitted and updated. I can get the feilds to insert but when I click on the cancel transaction button, I can't get it to empty the div addapptrans where the form is built. Below is the code. I know it must be something simple I am missing.
<head>
<script type="text/javascript">
$(function(){
$(".offerposition").click(function(){
var row = $(this).closest('tr').find('td:nth-child(1)').text();
alert('You clicked on ' +row);
$("#addapptrans").empty();
$("#addapptrans").append(
$("<input>").attr('type','hidden').attr( 'value',row).attr('Name','Mchposid'))
.append(
$("<input>").attr('type','submit').attr( 'value','Complete Offer').attr('id','completeoffertrx').attr('name','completeoffertrx').addClass("buttonlarge buttonmargin")
).append(
$("<input>").attr('type','button').attr( 'value','Cancel Transaction').attr('id','canceloffertrx').attr('name','canceloffertrx').addClass("buttonlarge buttonmargin")
);
}
)
}
);
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
</script>
</head>
<body>
<form >
<div id="addapptrans"></div>
<p class="posttitle">Positions applied For</p>
<table class="tabpositions">
<tbody>
<tr>
<th class="position">Position</th>
<th class="department">Department</th>
<th class="dateapp">Date Applied</th>
<th class="appdate">Offer?</th>
</tr>
<tr>
<td style="display: none;">2281</td>
<td>Building Service Worker - Part time</td>
<td>Environmental Services</td>
<td>08/13/2001</td>
<td><input type="button" class="offerposition" value="Offer Position"></td>
</tr>
</tbody>
</table>
</form>
This code here:
$(function(){
$("#canceloffertrx").click(function(){
$("#addapptrans").empty();
})
})
Runs before #canceloffertrx exists on the page. So $("#canceloffertrx").click(fn) Matches zero elements on the page, and binds a click handler to all zero of them.
You can fix this by binding the click handler to the document, or closest parent that is present, instead.
$('#addapptrans').on('click', '#canceloffertrx', function(){
This says that when the element #addapptrans receives a click event, and element that matches the selector #canceloffertrx was the one that was actually clicked, fire the event handler function.
Or by binding the click handler when you create the button.
$("<input>")
.attr('type','submit')
.attr( 'value','Complete Offer')
.attr('id','completeoffertrx')
.attr('name','completeoffertrx')
.addClass("buttonlarge buttonmargin")
.click(function() { ... });
Lastly, some style advice :) Especially when chaining jQuery methods, you can put each call on it's own line which makes it much more readable.
And you should also know that attr() can accept an object as an argument, allowing to call it just once to set many attributes.
$("<input>")
.attr({
type: 'submit',
value: 'Complete Offer',
id: 'completeoffertrx',
name: 'completeoffertrx'
})
.addClass("buttonlarge buttonmargin")
.click(function() { ... });

Using each() for checking which class is clicked

So here's my problem, I'm new to jQuery. What I am trying to do here is check for user to click on a certain table cell/row and it would then display a div named popup of an index the same as the table cell votes. Without having to make separate functions of all the rows in my table.
Using some numerical value will display all the dialogs from a click of the cell of the same value the first time and from the second time only the correct one.
I bet there's some other way to do it and maybe there's just a stupid error.
Using the index value in the click and dialog function won't work.
I am open to suggestions on improvement also.
The scripts:
<script type='text/javascript'>
$(document).ready( function() {
$('.votes').each(function(index) {
$('.votes:eq(index)').click(function() {
$('.popup:eq(index)').dialog();
});
});
});
</script>
HTML for the table part, only a snippet
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
HTML for the div part, only a snippet of the div:
<div class='popup'>
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class='popup'>
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
jsFiddle Demo
You don't have to iterate using each for .click, that will happen internally. You can use .index() to get the index of the element clicked with reference to its parent.
$('.votes').click(function() {
$('.popup').eq($(this).index()).dialog();
});
Initially, the main problem is that you are not using string concatenation to apply the index to the selector (demo):
$('.votes:eq(index)')
// the Sizzle selector engine doesn't know what the string "index" is.
instead of
$('.votes:eq(' + index + ')')
// using concatenation calls the .toString() method of index to apply "0" (or "1", "2", etc.)
// so that the parsed string becomes '.votes:eq(0)' which the Sizzle selector engine understands
Once the Sizzle selector engine understands which elements to target (demo), the second problem is how jQueryUI changes the DOM with the .dialog method.
Inital markup:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>John Johnsson</li>
<li>John Doe</li>
</ul>
</div>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
Once the first click event is handled, one of the div.popup elements is transformed into a jQueryUI Dialog and is appended to the body, removing it from its initial position, like so:
<table>
<tbody>
<tr>
<td class="votes">5</td>
<td class="votes">15</td>
<td class="votes">25</td>
</tr>
</tbody>
</table>
<div class="popup">
<ul>
<li>Matt Theman</li>
<li>Peter Watley</li>
</ul>
</div>
<div class="ui-dialog ui-widget ..."> ... </div>
So your initial indexes no longer apply. Fortunately, there are several solutions to both problems (a few of which I've listed below).
Solutions to Problem 1:
Use string concatenation as described above.
Use the .eq method instead, which will accept the index variable as-is
Use a delegate handler instead and grab the index from within the handler:
Example of 2:
$('.votes').eq(index);
Example of 3:
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.parent().index(vote);
});
Solutions to Problem 2:
Create all of the dialogs initially and open them as needed.
Create the dialogs using a deep clone of the div element. (Not recommended)
Remove the td element to match the removed and re-appended div element. (Not recommended)
Example of 1:
var popups = [];
$('.popup').each(function (i, elem) {
var popup = $(elem).data('index', i).dialog({
"autoOpen": false
});
popups.push(popup)
});
$('table').on('click', '.votes', function (e) {
var vote = $(this),
index = vote.index();
popups[index].dialog('open');
});
I'm sure there are other solutions as well, but these are the ones I thought of of the top of my head.
Functional demo: http://jsfiddle.net/2ChvX/2/
UPDATE:
With your chosen table structure, you're actually looking for the index of the parent tr element as that is what corresponds with the div.popup element. To get the index of the parent tr element, change the line that gets the index from:
index = vote.index();
to:
index = vote.parent().index();
Updated fiddle: http://jsfiddle.net/AZpUQ/1/
Updated
FWIW, here's an example using the jQueryUI dialog (which I presume you are using?) and javascript sectionRowIndex and cellIndex.
Reusable code allowing you to identify the cell the user clicked in and perform appropriate action.
http://jsfiddle.net/KbgcL/1/
HTML:
<table id="myTable">
<tr>
<th>Label:</th>
<th>Washington</th>
<th>Idaho</th>
<th>California</th>
</tr>
<tr>
<td class='label'>Votes</td>
<td class='votes'>5</td>
<td class='votes'>15</td>
<td class='votes'>25</td>
</tr>
<tr>
<td class='label'>Voters</td>
<td class='voters'>5,000</td>
<td class='voters'>15,000</td>
<td class='voters'>25,000</td>
</tr>
</table>
<div id="msg"></div>
jQuery/javascript:
var myTr;
$('#msg').dialog({
autoOpen:false,
title: 'Report:'
});
$('#myTable tr td').click(function() {
myTr = $(this).closest('td').parent()[0].sectionRowIndex;
myCell = this.cellIndex;
myState = $('#myTable').find('tr:eq(0)').find('th:eq(' +myCell+ ')').html();
myVoters = $('#myTable').find('tr:eq(' +myTr+ ')').find('td:eq(' +myCell+ ')').html();
if (myTr==2 && myCell==3){
//California
$('#msg').html('There are ' +myVoters+ ' voters in ' +myState);
$('#msg').dialog('open');
}else if(myTr==1 && myCell==1){
$('#msg').html('There were ' +myVoters+ ' votes made in ' +myState);
$('#msg').dialog('open');
}
});

Categories

Resources