Scroll to element in modal div - javascript

I'm using JQuery load() to place a page into a modal div set to overflow-y:auto; At the top of the loaded page inside the modal div, I want to click on an element (actually a table cell...) that will scroll the page down to a specific div:
<div id='haematopoietic_section' class='cap_h2'>Haematopoietic</div>
The code in the loaded page contains:
$('#haematopoietic').click(function(){
$(document).scrollTop($('#haematopoietic_section').offset().top);
});
The above code isn't doing anything. I can throw an alert in the click event, but it won't scroll. Any ideas?
See example at https://jsfiddle.net/z7m4c38d/3/ Note that this fiddle does not use JQuery load, but instead has code fixed inside the div...problem remains...

use the below code, in your click event
var container = $('body'),
scrollTo = $('#haematopoietic_section');
container.scrollTop(
scrollTo.offset().top - container.offset().top + container.scrollTop()
);
Since the div is contained in <div id = 'cap_module_holder'> .... </div>
so your container variable should be:
var container = $('#cap_module_holder');
i have added an extra div in middle to increase height so that you can see the scroll effect.
<div id='module_container'>
<div id='cap_module_holder'>
<p class='cap_h1'>Bone Tumours</p>
<p>Introduction</p>
<p>
<br>In the first three decades of life, benign tumours are the most frequent. In the elderly, a bone tumour is likely to be malignant, either primary or a metastasis.</p>
<p class='cap_h2'>Primary tumours involving bone</p>
<p>These are all derived from tissue of mesodermal origin.</p>
<table width="auto" border="0" align="center" cellspacing="3">
<tr>
<td width="208" valign="top">
<p align="center"><strong>Histological classification</strong>
</p>
</td>
<td width="208" valign="top">
<p align="center"><strong>Benign</strong>
</p>
</td>
<td width="208" valign="top">
<p align="center"><strong>Malignant</strong>
</p>
</td>
</tr>
<tr>
<td id='haematopoietic' class='cap_t2' width="208" valign="top">
<p>Haematopoietic</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Haemangioma</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Myeloma
<br>Malignant  lymphoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Chondrogenic</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Osteochondroma
<br>Chondroma
<br>Chondromyxoid fibroma</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Chondrosarcoma
<br>Dedifferentiated -Chondroblastoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Osteogenic</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p> Osteoma                           Osteoid osteoma
<br>Osteoblastoma</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Osteosarcoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Fibrogenic</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Fibrous cortical defect
<br>Non-ossifying fibroma</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Fibrosarcoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Neuroectodermal</p>
</td>
<td width="208" valign="top">
<p> </p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Ewing’s sarcoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Notochordial</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Benign notochordal cell tumour      </p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Chordoma</p>
</td>
</tr>
<tr>
<td class='cap_t2' width="208" valign="top">
<p>Odontogenic</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Giant cell tumour</p>
</td>
<td class='cap_t3' width="208" valign="top">
<p>Ameloblastoma
<br>
</p>
</td>
</tr>
<tr>
<td class='cap_t2' valign="top">Unknown origin</td>
<td class='cap_t3' valign="top">Unicameral cyst
<br>Aneurysmal bone cyst</td>
<td valign="top"> </td>
</tr>
</table>
<div style = "height:500px;" >ok </div>
<div id='haematopoietic_section' class='cap_h2'>Haematopoietic</div>
</div>
</div>

A more recent solution using only JavaScript:
var element = document.getElementById("scroll-here")
element.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })
See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

Late to the party here, but I am posting this in the hopes that it helps someone else who is beating their heads against the wall about scrolling inside modals.
In my case I had multiple modals that could be opened (but just one at a time), and within each modal was a form that needed to be validated on submission. I wanted it to scroll to the first invalid form input on submission.
The key thing here is that you want to scroll the contents inside the modal, not the page behind the modal, nor the position of the modal itself against the background page. So to do this you need to do the following:
1) Structure your modals correctly. Put an id into the div that has the class='modal fade' and then make sure the 'modal-body' has its own id, in this case 'newExpenseForm18'. (note I use a 'key' attribute to tell me which modal is open).
<div class="modal fade uploadExpense in" key="18" id="uploadExpense18" role="dialog" >
<div class="modal-dialog text-left">
<div class="modal-content" id="modalcontent18">
<div class="modal-header">
</div>
<div class="modal-body" id="newExpenseForm18">
..... etc followed by (at some point)
<div id = 'myExpense18'>
..... etc
2) Now you need to get three ids: the whole modal ( in this case "uploadExpense18"), the container div ( in this case "theform18"), and the target div to which you want to scroll, in this case "myExpense18". You can get these thus:
var modalId = $('.modal:visible').attr('id');
var key = $('.modal:visible').attr('key');
var bodyId = 'newExpenseForm'+key;
var targetId = 'myExpense'+key;
3) Now you find out the distance you need to scroll. To do this, find the offset of the target div, relative to the top of the page, and also the offset of the modal-body, relative to the top of the page
var position = $('#'+targetId).offset().top;
var position2 = $('#'+bodyId).offset().top;
4) subtract one from the other to get the offset of the target relative to the container div.
var distance = position-position2;
5) and, finally, scroll the body of the modal inside the modal div, so that the target is now at the place where the top of the container used to be:
$('#'+modalId).animate({ scrollTop: distance }, "slow");
Hope that helps someone!

Related

Click on a button in a table when button name changes periodically

I'm using Python and Selenium to click through a site to select and reserve a room. The site presents a table of rooms available. I want to find a specific room and click on the button in the table that is associated with that room....but the button name changes depending on where the room is located in the table. Where it is located depends, in part, on what other rooms are available at the time I run through the website.
In this example, I want to reserve 'Room 34".
The table appears to be identified by:
<table id="MainContent_tblPage"....>
The row or section of the table that includes "Room 34" is identified by the following (which changes depending on where Room 34 appears in the table...which depends on how many other rooms are available):
<tr id=MainContent_rptrPropertyList_trContent_1" >
The button I want to click in this example is:
name="_ctl0:MainContent:rptrPropertyList:_ctl2:rptPropertyRooms:
_ctl0:btnSelect"
(...but the button name changes depending on which other rooms appear in the table...)
My question: How do I find and click the correct button in a table if the button name changes dynamically depending on table content/rows...but the button is always in a row with the text I want to find?
HTML of the section I'm looking at (...sorry, I'm not sure how to make it more readable without the possibility of changes things that might be important for answering my question):
<table id="tblPropertyList" cellpading="0" cellspacing="0" align="center" border="0" width="100%">
<tbody><tr id="MainContent_rptrPropertyList_trContent_0">
##...snip...similar code as shown under <tr id="MainContent_rptrPropertyList_trContent_1"> below...
##...I cut it out to save space but I can add it back if it helps --JRrcgp
<tr id="MainContent_rptrPropertyList_trContent_1">
<td class="room_grid_row">
<table cellpading="0" cellspacing="0" width="100%;">
<tbody><tr>
<td colspan="2" class="room_grid_heading_2">
Hornswoggle Tower
<br><span class="text2">CityPlace</span>
</td>
</tr>
<tr>
<td align="right" valign="top">
<div class="room_grid_image">
<a onclick="javascript:ShowGallery('lightSlider_1');" title="Room 34">
<img src="imgHandler.ashx?image=\\fileserver.inncenter.pms.inrd.live\\Share1\\Assets/pics/roomClass_pic_8455.jpg" id="MainContent_rptrPropertyList_Image1_1" onerror="showNoImage(this);" style="visibility:true;">
</a>
</div>
<div class="demo">
<ul id="lightSlider_1" style="display:none">
<li data-thumb="imgHandler.ashx?image=\\fileserver.inncenter.pms.inrd.live\\Share1\\Assets/pics/roomClass_pic_8455.jpg">
<img src="imgHandler.ashx?image=\\fileserver.inncenter.pms.inrd.live\\Share1\\Assets/pics/roomClass_pic_8455.jpg">
</li>
</ul>
</div>
</td>
<td valign="top" width="100%" class="padding_left_1">
<table cellspacing="0" cellpadding="0" width="100%">
<tbody><tr>
<td class="room_grid_heading" colspan="3">
<div class="floatleft">
Room 34
</div>
<div class="floatright">
<span class="room_grid_from_rate_text1">From </span>
<span id="MainContent_rptrPropertyList_lblMinRate_1" class="room_grid_from_rate_text2">$88</span>
<!--<span class="room_grid_from_rate_text1">/Night</span>-->
</div>
</td>
</tr>
<tr>
<td colspan="3">
<table width="100%" cellpading="0" cellspacing="0">
<tbody><tr>
<td valign="top" class="room_grid_discription_2">
<span id="MainContent_rptrPropertyList_reptSectionInline_1_lblSectionInline_0" class="more"><font face="Verdana">Text description of room.</font></span>
</td>
</tr>
<tr>
<td valign="top">
<table cellpadding="0" cellspacing="0">
<tbody><tr>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td id="MainContent_rptrPropertyList_tdSingleRate_1" style="display: none;">
<font class="Bold"> $<span id="MainContent_rptrPropertyList_lblratePrice_1">88</span><br></font> per night
</td>
</tr>
<tr>
<td valign="bottom" align="left">
<table align="left" width="100%" cellspacing="0" cellpadding="0">
<tbody><tr>
<td align="left" nowrap="" width="80%" class="displayRatePlan"><span class="room_grid_rateplanname">
Best Available Rate
</span><span class="room_grid_rateplan_moreinfo">(<a class="thickbox" id="lnkMoreInfo" title="Best Available Rate" href="#TB_inline?height=Div8&width=Div7&inlineId=MainContent_rptrPropertyList_rptPropertyRooms_1_Div9_0">More Info</a>)</span>
<div id="MainContent_rptrPropertyList_rptPropertyRooms_1_Div9_0" class="roomClassSection" style="display: none;">
<div class="popupWidth" id="Div7">
<div class="popupHeight" id="Div8">
<table class="more_info_table" cellspacing="0" cellpadding="0" align="center" border="0">
<tbody><tr>
<td>
<div id="MainContent_rptrPropertyList_rptPropertyRooms_1_excludeRoom_DIV_0">
</div></td></tr><tr>
<td class="alt1">
Name:
</td>
<td style="width: 90%">
Room Rate
</td>
</tr>
<tr>
<td class="alt1">
Date:
</td>
<td>
Fri, Apr 27, 2018 - Sun, Apr 29, 2018
</td>
</tr>
<tr>
<td class="alt1">
Policy:
</td>
<td>
</td>
</tr>
</tbody></table>
</div>
</div>
</div>
</td>
<td id="MainContent_rptrPropertyList_rptPropertyRooms_1_tdRateDescription_0" align="right" nowrap="nowrap" width="12%">
<span class="room_grid_fullrate">
$188
</span>
<span class="room_grid_fullrate_avgnightly">
<span id="MainContent_rptrPropertyList_rptPropertyRooms_1_lblRateMsg_0">(Avg nightly rate)</span></span>
</td>
<td width="8%" align="left">
<input type="submit" name="_ctl0:MainContent:rptrPropertyList:_ctl2:rptPropertyRooms:_ctl0:btnSelect" value="Select" onclick="ShowProgress();" language="javascript" id="MainContent_rptrPropertyList_rptPropertyRooms_1_btnSelect_0" class="button green">
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</td>
</tr>
</tbody></table>
</td>
</tr>
<tr id="MainContent_rptrPropertyList_trContent_2">
##...snip...similar code as shown under <tr id="MainContent_rptrPropertyList_trContent_1"> above...
<tr id="MainContent_rptrPropertyList_trContent_3">
##...snip...similar code as shown under <tr id="MainContent_rptrPropertyList_trContent_1"> above...
##...this continues to repeat once for each room available
EDIT: I'm currently working past this issue by hard-coding the button I'm clicking. I use Selenium to navigate to the webpage that creates a table of the rooms available and then I click on the appropriate button as it stands today. But the name of the button will change in the future:
room34 = browser.find_element_by_name('_ctl0:MainContent:rptrPropertyList:_ctl31:rptPropertyRooms:_ctl0:btnSelect')
room34.click()
EDIT 2: I've played the suggestion from #Grasshopper. His code didn't work for me, but I made some changes that I thought made progress....I was mistaken. I'm removing the rest of Edit 2 so as not to confuse the issue.
To click on the button with name as _ctl0:MainContent:rptrPropertyList:_ctl2:rptPropertyRooms:_ctl0:btnSelect with respect to the element with text as Room 34 you can use either of the following line of code :
Using following :
driver.find_element_by_xpath("//div[#class='room_grid_image']/a[contains(#title,'Room 34')]//following::input[1]").click()
Using following-sibling :
driver.find_element_by_xpath("//div[#class='room_grid_image']/a[contains(#title,'Room 34')]//following-sibling::input[1]").click()
Try this xpath - "//div[normalize-space(.)='Room 34']/ancestor::tbody/tr/td//input[#type='submit']"
The 'Room 34' can be substituted by a python variable. normalize-space is required as the text has a lot of white space.

remove table tr that have specific content

I have the following form inside SharePoint 2013 web application :-
I need to remove all the Table <tr> except the ones that start with "name" & "title". so can anyone adivce how i can achieve this ? . here is part of the markup for the above image (it show two Tr on that have Content Type (should be removed), while the other contain Name ):-
<table id="formTbl" class="ms-formtable" width="100%" cellspacing="0" cellpadding="0" border="0" style="margin-top: 8px;">
<tbody>
<tr>
<td class="ms-formlabel" valign="top" nowrap="true">
<h3 class="ms-standardheader">Content Type</h3>
</td>
<td class="ms-formbody" valign="top">
</tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<h3 class="ms-standardheader">
<nobr>
Name
<span class="ms-accentText" title="This is a required field."> *</span>
</nobr>
</h3>
</td>
<td class="ms-formbody" width="350px" valign="top">
</tr>
<tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<td class="ms-formbody" width="350px" valign="top">
</tr>
Now i have jquery version 1.7 loaded inside the web application, but i prefer to achieved using pure javaScript.
Thanks
EDIT here is a more detailed markup :-
<div id="contentRow">
<div id="sideNavBox" class="ms-dialogHidden ms-forceWrap ms-noList">
<div id="contentBox" aria-relevant="all" aria-live="polite">
<div id="notificationArea" class="ms-notif-box"></div>
<div id="DeltaPageStatusBar">
<div id="customcalender"></div>
<div id="DeltaPlaceHolderMain">
<a id="mainContent" tabindex="-1" name="mainContent"></a>
<div style="padding-left:5px">
<table id="onetIDListForm" class="ms-core-tableNoSpace">
<tbody>
<tr>
<td>
<div class="ms-webpart-zone ms-fullWidth">
<div id="MSOZoneCell_WebPartWPQ2" class="s4-wpcell-plain ms-webpartzone-cell ms-webpart-cell-vertical ms-fullWidth ">
<div class="ms-webpart-chrome ms-webpart-chrome-vertical ms-webpart-chrome-fullWidth ">
<div id="WebPartWPQ2" class="noindex " style="" allowdelete="false" width="100%" haspers="false" webpartid="6c7d849e-da6b-4138-be9f-b99bde542065">
<table class="ms-informationbar" width="100%" cellspacing="0" cellpadding="2" border="0" style="margin-bottom: 5px;">
<div id="listFormToolBarTop" style="display: none;">
<span style="display:none">
<span></span>
<table width="100%">
<tbody>
<tr>
<td width="100%" valign="top">
<table id="formTbl" class="ms-formtable" width="100%" cellspacing="0" cellpadding="0" border="0" style="margin-top: 8px;">
<tbody>
<tr>
<td class="ms-formlabel" valign="top" nowrap="true">
<h3 class="ms-standardheader">Content Type</h3>
</td>
<td class="ms-formbody" valign="top">
</tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<h3 class="ms-standardheader">
<nobr>
Name
<span class="ms-accentText" title="This is a required field."> *</span>
</nobr>
</h3>
</td>
<td class="ms-formbody" width="350px" valign="top">
</tr>
<tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<td class="ms-formbody" width="350px" valign="top">
</tr>
<tr>
<tr>
<tr>
When in doubt, filter is your friend:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/jjzx6mge/4/
$('#formTbl tr').filter(function () {
return !$(".ms-standardheader", this).text().match(/Name|Title/i);
}).remove();
The result returned of a function passed to filter is a boolean value telling which items to retain (truthy), or which to exclude (falsey).
This one targets only rows that have the requested text in the ms-standardheader classed element.
It also only targets a specific inner table to avoid the case of deep searching from the top level table and wiping out entire tables within it.
While you can do this with plain old JS, significantly more code is required.As you already have a version of jQuery installed, it makes sense to use it.
This would work:
$(function() {
$('#formTbl tr').each(function() {
var frstVal = $(this).find('td').eq(0).text();
if (!frstVal.match(/name|title/i)) {
$(this).remove()
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<table id="formTbl" class="ms-formtable" width="100%" cellspacing="0" cellpadding="0" border="0" style="margin-top: 8px;">
<tbody>
<tr>
<td class="ms-formlabel" valign="top" nowrap="true">
<h3 class="ms-standardheader">Content Type</h3>
</td>
<td class="ms-formbody" valign="top">
</tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<h3 class="ms-standardheader">
<nobr>
Title
<span class="ms-accentText" title="This is a required field."> *</span>
</nobr>
</h3>
</td>
<td class="ms-formbody" width="350px" valign="top">
</tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<h3 class="ms-standardheader">
<nobr>
Name
<span class="ms-accentText" title="This is a required field."> *</span>
</nobr>
</h3>
</td>
<td class="ms-formbody" width="350px" valign="top">
</tr>
<tr>
<tr>
<td class="ms-formlabel" width="113px" valign="top" nowrap="true">
<td class="ms-formbody" width="350px" valign="top">
</tr>
This will remove every tr that has a .ms-standardheader element that contains the text Name or Title
$('#formTbl tr').each(function() {
var that = $(this);
var label = that.find('.ms-standardheader').text();
if (label.indexOf('Name') != -1 || label.indexOf('Title') != -1) {
that.remove();
}
});
And here I am, doing this the good ol' plain JS way, since you've asked for it :)
http://jsfiddle.net/m53esfpo/3/
Edit: Updated code and fiddle (thanks #TrueBlueAussie)
Removes every tr except the ones that start with name or title.
var t = document.getElementById('formTbl');
for (var i = 0; i < t.getElementsByTagName("tr").length; i++) {
var s = t.getElementsByTagName("tr")[i].getElementsByClassName('ms-formlabel');
if (s.length > 0) {
if (s[0].innerText.indexOf('Name') < 0 && s[0].innerText.indexOf('Title') < 0) {
t.getElementsByTagName("tr")[i].parentNode.removeChild(t.getElementsByTagName("tr")[i]);
}
}
}
You can do it with this:
$("#formTbl tr td h3").not("h3:contains('Name'):contains('Title')").closest('tr').remove();

Mailchimp template issue while using repeatable blocks

I have created form template in Mailchimp, I have been through the documentation and using all the Mailchimp tags respectively its even showing me the icons to drag/ movable content editable etc.
Whenever I edit the content its visible through the campaign test area but when i copy the block and change the positioning, it changes its position in the backend but do not show any changes on the campaign test area.
Here is some piece of the html i am using, i have checked the html for issue but i am unable to find any issues.
<tr mc:repeatable="ntwologo" mc:variant="new-layout-twologo">
<td mc:hideable align="center" valign="top" class="fix-box">
<table width="100%" align="center" border="0" cellspacing="0" cellpadding="0">
<tr>
<td align="center" valign="top">
<!-- start layout-3 container width 600px -->
<table width="600" align="center" border="0" cellspacing="0" cellpadding="0" class="container" bgcolor="#ffffff" style="background-color: #ffffff; ">
<tr>
<td valign="top">
<!-- start layout-3 container width 560px -->
<table width="560" align="center" border="0" cellspacing="0" cellpadding="0" class="full-width" bgcolor="#ffffff" style="background-color:#ffffff;">
<!--start space height -->
<tr>
<td height="20"></td>
</tr>
<!--end space height -->
<!-- start image content -->
<tr>
<td valign="top" width="100%">
<table class="full-width">
<tr>
<td>
<div class="heading" style="margin-bottom:20px;" mc:edit="text heading">
Most Active Canadian
</div>
</td>
</tr>
<tr>
<td class="twologos">
<img mc:allowdesigner="" mc:allowtext="" style="border:1px solid #b5ae92;" src="https://gallery.mailchimp.com/85ff5a532432ef3d1b871c206/images/dceb568a-6e4c-48b8-a2b7-1db04b6780d8.jpg" mc:edit="layoutleftlogo">
<img mc:allowdesigner="" mc:allowtext="" style="border:1px solid #b5ae92;" src="https://gallery.mailchimp.com/85ff5a532432ef3d1b871c206/images/f1eb0308-e0ad-4f6e-b15c-e5583f72a4cf.jpg" mc:edit="layoutrightlogo">
</td>
</tr>
<tr>
<td>
<div class="yaletext" mc:edit="text content">
<!-- text here -->
<br>
Read More
</div>
</td>
</tr>
</table>
</td>
</tr>
<!-- end image content -->
</table>
<!-- end layout-3 container width 560px -->
</td>
</tr>
</table>
<!-- end layout-3 container width 600px -->
</td>
</tr>
</table>
</td>
</tr>
<!-- END LAYOUT-3 -->

Using checkboxes to update a total row based on images

I am working on code which updates a total row based on when a checkbox is checked based on whether or not an image in that row is the correct image.
Here is the HTML:
<table border="1">
<tr> <!-- Table Header -->
<td>
Checkbox
</td>
<td>
Items
</td>
<td>
Area 1
</td>
<td>
Area 2
</td>
<td>
Area 3
</td>
</tr>
<tr id="checkRow"> <!-- Row 1 -->
<td>
<form>
<input type="checkbox" name="Row1" value="Row1" onchange="onCheck(this);">
</form>
</td>
<td>
Item 1
</td>
<td class="imageBox">
<img id="image1" src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img id="image2" src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img id="image3" src="no.png" alt="Needed">
</td>
</tr>
<tr> <!-- Row 2 -->
<td>
<form>
<input type="checkbox" name="Row2" value="Row2" onchange="onCheck(this);">
</form>
</td>
<td>
Item 2
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="no.png" alt="Needed">
</td>
</tr>
<tr> <!-- Row 3 -->
<td>
<form>
<input type="checkbox" name="Row3" value="Row3" onchange="onCheck(this);">
</form>
</td>
<td>
Item 3
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
</tr>
<tr> <!-- Row 4 -->
<td>
<form>
<input type="checkbox" name="Row4" value="Row4" onchange="onCheck(this);">
</form>
</td>
<td>
Item 4
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="yes.png" alt="Needed">
</td>
<td class="imageBox">
<img src="no.png" alt="Needed">
</td>
</tr>
<tr id="outputRow"> <!-- Table Bottom -->
<td>
<!--Empty-->
</td>
<td>
Summation
</td>
<td id="total1">
0
</td >
<td id="total2">
0
</td>
<td id= "total3">
0
</td>
</tr>
</table>
Here is the Javascript (using jQuery)
//Numbers in the total row (Summation)
var total1=0;
var total2=0;
var total3=0;
function onCheck(cb)
{
var $box = $(cb);
var imageBoxes = $box.parents('td.imageBox');
if(cb.checked===true)
{
//Checks the image in the row. If it is yes.png, it adds 1 to to the total
//for that column and displays that total variable in the total row.
/*if(document.getElementById('image1').src.toString().indexOf('yes')>0){
total1++;
document.getElementById('total1').innerHTML=total1;
} */
if(imageBoxes[0].children().attr('src').toString().indexOf('yes')>0){
total1++;
document.getElementById('total1').innerHTML=total1;
}
/*else
{
document.getElementById('total1').innerHTML=no;
} */
if(document.getElementById('image2').src.toString().indexOf('yes')>0){
total2++;
document.getElementById('total2').innerHTML=total2;
}
/* else
{
document.getElementById('total2').innerHTML=no;
} */
if(document.getElementById('image3').src.toString().indexOf('yes')>0){
total3++;
document.getElementById('total3').innerHTML=total3;
}
/*else
{
document.getElementById('total3').innerHTML=no;
} */
}
//If the checkbox is unchecked, this checks for
//if the image in each box in that row is
//yes.png. If it is, then 1 is subtracted from the
//column's total and the new total is shown.
else
{
if(document.getElementById('image1').src.toString().indexOf('yes')>0){
total1--;
document.getElementById('total1').innerHTML=total1;
}
if(document.getElementById('image2').src.toString().indexOf('yes')>0){
total2--;
document.getElementById('total2').innerHTML=total2;
}
if(document.getElementById('image3').src.toString().indexOf('yes')>0){
total3--;
document.getElementById('total3').innerHTML=total3;
}
}
}
I built this in Fiddle, so all the Script imports are not shown.
EDIT: Here is the link to the Fiddle: hhttp://jsfiddle.net/GGxpX/62/
EDIT: It was pointed out that my Id's were repeating. I fixed this in the new fiddle, but this did not fix the problem.
EDIT3: Fixed more problems including using a td element as its image child. The link points to the updated Fiddle now.
EDIT4: Updated Fiddle again.
If I understand what you want, I think you are making this more complicated than it needs to be. (Correct me if I'm wrong.) I would have the handler for the checkboxes re-calculate the totals each time.
The JavaScript could be this short:
function onCheck() {
var totals = [0, 0, 0];
$('tr.checkRow').each(function () {
var $row = $(this);
if ($row.children('td:first').find('input:checkbox').prop('checked')) {
$(this).find('td.imageBox').each(function (index) {
var $imageBox = $(this);
if ($imageBox.children('img:first').attr('src').indexOf('yes') >= 0) {
++(totals[index]);
}
});
}
});
$('#total1').text(totals[0]);
$('#total2').text(totals[1]);
$('#total3').text(totals[2]);
}
Notice how the onCheck() function doesn't even take a parameter. That's because it doesn't matter what checkbox was changed, or if it was checked or unchecked.
This loops through each row, and if its checkbox is checked, it loops through each image box.
In order for the code above to work, you must put the class "checkRow" on the proper <tr> elements. (You previously had it as an "id" on those elements.)
jsfiddle
There were several things I saw wrong with your code. Here's a few:
"id" attributes must be unique.
When checking the result of calling .indexOf() use >= 0, not > 0.
imageBoxes[0] returns a DOM element, not a jQuery object.
There is no need for the calls to toString() because the src attribute is a string.
You could also attach your event handlers with jQuery, rather than use "onchange" attributes, but I left it your way in the jsfiddle.

Getting the 'co-ordinates' of a <TD> cell using jQuery

I'm building somewhat of a different website, below is my HTML markup and my question. Please don't be put off by this wall of text, I'm sure it's really not a difficult problem for someone who know's their stuff but it takes some explaining.
<div id="0" class="cell" style="top: 0px; left: 0px;">
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tbody>
<tr id="0">
<td id="0"> </td>
<td id="1"> </td>
<td id="2"> </td>
<td id="3"> </td>
<td id="4"> </td>
<td id="5"> </td>
<td id="6"> </td>
<td id="7"> </td>
<td id="8"> </td>
<td id="9"> </td>
<td id="10"> </td>
<td id="11"> </td>
<td id="12"> </td>
<td id="13"> </td>
<td id="14"> </td>
<td id="15"> </td>
</tr>
<tr id="1">
<td id="0"> </td>
<td id="1"> </td>
<td id="2"> </td>
<td id="3"> </td>
<td id="4"> </td>
<td id="5"> </td>
<td id="6"> </td>
<td id="7"> </td>
<td id="8"> </td>
<td id="9"> </td>
<td id="10"> </td>
<td id="11"> </td>
<td id="12"> </td>
<td id="13"> </td>
<td id="14"> </td>
<td id="15"> </td>
</tr>
</tbody>
</table>
</div>
This markup is repeated in a tiling sort of pastern in order to fill the entire page. A similar DIV might be:
<div id="1" class="cell" style="top: 144px; left: 0px;">
<!-- The rest of the table code here... -->
</div>
If you can't see it already, I'm creating a load of cells across the entire page sorted into DIVs. Now, when a user clicks into a cell (one of the <td>'s), I want to get it's co-ordinates represented by: 0, 1, 5.
In this example, 0, 1, 5 is the DIV with id of 0, the TR element inside that DIV with the ID of 1, and lastly the cell inside that TR element with an ID of 5. I wanted to write a javascript function to get these co-ordinates, but I am at a complete loss on what parameters to pass, and little idea how I can get out the co-ordinates.
From as far as I can think once I can pass a click event(?) to the function I can look at the <td>'s parent elements and get their IDs?
If anyone can provide a solution to this problem or provide any input, it'd be greatly appreciated.
Since it is not valid to begin an ID with a number, I'll offer a different solution.
Since your IDs are basically index numbers, you can use jQuery's .index() method to get what you need.
Test it here: http://jsfiddle.net/hBarW/
$('td').click(function(){
var $th = $(this);
var td_idx = $th.index();
var tr_idx = $th.closest('tr').index();
var div_idx = $(this).closest('div').index();
alert(td_idx + ' ' + tr_idx + ' ' + div_idx);
});
Use the closest jQuery function, which returns the parent element that you specify.
Like this:
$("td").click(function () {
var parentDIVId = $(this).closest("div").attr("id");
var parentTRId = $(this).closest("tr").attr("id");
var myId = $(this).attr("id");
}
try
$('td').click(function(){
var td = this.id;
var tr = $(this).closest('tr').attr('id');
var div = $(this).closest('div').attr('id');
});
you can test it here.
more on .closest() here
the easy thing would be
$('td').click(function(){
$this = $(this);
alert( $this.closest('div').attr('id') + ',' + $this.closest('tr').attr('id') + ',' + $this.attr('id'));
});
But you have some issues..
you cannot have numbers as IDs
IDs should be unique inside the DOM ...

Categories