I have the following jquery code to add and remove a row in a table. I have multiple tables on one page. Each row in each table has these two classes: .row-add and .row-delete
Now when I click on '.row-add'to add a new row, all the tables are affected, meaning that row is added to all of the tables on the same page. What should I do to make it only apply to its own table when clicked?
Jquery:
$(document).ready(function () {
$('.row-delete').click(function () {
$(this).closest("tr").remove();
});
$('.row-add').click(function () {
$(this).closest("tr").clone(true).appendTo(".table-comparison");
});
});
Html:
<div id="tab-1" class="tab-section">
<div class="container flat rounded-sm bspace">
<table cellspacing="0" class="display table-comparison">
<thead>
<tr>
<th><span>Effective Date</span></th>
<th><span>Price</span></th>
</tr>
</thead>
<tbody>
<tr>
<td><input class="effective-date" type="text" value="01/01/2013"> - <input class="effective-date" type="text" value="06/05/2015">
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
<td>
$<input class="price" value="50">
/
<select>
<option>Second</option>
<option>Minute</option>
<option>Hour</option>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
</select>
/
<select>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
<option>Month</option>
<option>Quarter</option>
<option>Year</option>
</select>
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
</tr>
<tr class="price-present">
<td><input class="effective-date" type="text" value="07/01/2013"> - <span class="effective-date">Present</span>
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
<td>
$<input class="price" value="40">
/
<select>
<option>Second</option>
<option>Minute</option>
<option>Hour</option>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
</select>
/
<select>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
<option>Month</option>
<option>Quarter</option>
<option>Year</option>
</select>
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
</tr>
<tr>
<td><input class="effective-date" type="text" value="01/01/2011"> - <input class="effective-date" type="text" value="06/30/2012">
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
<td>
$<input class="price" value="30">
/
<select>
<option>Second</option>
<option>Minute</option>
<option>Hour</option>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
</select>
/
<select>
<option>Day</option>
<option>Week</option>
<option>Biweek</option>
<option>Month</option>
<option>Quarter</option>
<option>Year</option>
</select>
<span class="row-add"></span>
<span class="row-delete"></span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
try to be specific ... closest("tr") you are selecting all trs.
try giving an ID, or class and select that id using jquery.
The problem is that your jQuery selector is on class attribute, if you want to refer to a single table, you have to go by id.
In this case I think the best approach is, if you generate programmatically the html code, to add to every table an auto generated id and to add to every clickable row the following code:
onclick="addrow(table_id)"
where table_id is the autogenerated id of the table. Then:
function addrow(table) {$(table).closest("tr").clone(true).appendTo(".table-comparison");}
Just be warned that also .table-comparison should be avoided switching to id, but I don't know the details of your code!
Hope this helps!
EDIT: still better, if you don't generate code, is the bind function, like
$("p").bind("click", function(event){
This way you can access ex-post who has sent the event.
In your case you I think you could write:
$(".row-delete").bind("click", function (event) {
event.target.closest("tr").remove();
});
$(".row-add").bind("click", function (event) {
event.target.closest("tr").clone(true).appendTo(".table-comparison");
});
Source: JQuery Doc
Related
I don't know how to add dynamic content in my Vue js 2 app. I'd like to add many div elements after clicking on a button. THis div should have input and after clicking on a Save button all input texts inside dynamically created divs should be sent to backend (so I use model inside my template).
<div v-if="!this.spinnerVisibleForCorrectiveActions">
<div>
<table class="p-2 table-cell">
<tr class="font-weight-bold">
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
ID
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2 criterion">
DZIAŁANIE
</div>
</td>
<td class="vue-good-table-col-200">
<div class="mt-2">
SZCZEGÓŁY
</div>
</td>
</tr>
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
</table>
<button class="addAction p-3 mb-2 bg-secondary text-white w-100 bg-info btn btn-success">NAdd new action</button>
<br>
</div>
How to add dynamically (multiple times) something like this and additionally to have the possibility to get all data from my dynamically created inputs after clicking on a button:
<tr v-for="(actions,index) in correctiveActions" :key="index">
<td class="vue-good-table-col-200">
<span> {{actions.orderNumber}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.action}}</span>
</td>
<td class="vue-good-table-col-200">
<span> {{actions.recommendations}}</span>
</td>
</tr>
Ok, the answer in my case is very simple - I have to only add an empty object to my correctiveActions array:
<button class="addAction p-2 mb-2 bg-secondary text-white w-100 bg-info btn btn-success" #click="addNewAction">Nowe
działanie
</button>
and next:
methods:{
addNewAction() {
this.correctiveActions.push
({
id: undefined,
incidentId: this.incidentId,
orderNumber: this.getNextOrderNumber(),
action: undefined,
recommendations: undefined
});
},
}
I am using Struts 1.x in my application. Recently i used Vue js.So, I use the same jsp page for Adding and updating (in this case company). So When i click edit, the details are fetched the page is redirected to that page and form values are set from the action class.
Here is the html portion
<form action="company.do" method="post" name="companyForm">
<html:hidden property="method" value="doAddUpdateCompany" />
<html:hidden property="companyId" value="${companyForm.companyId}" />
<div class="row" >
<div class="col-md-9">
<div class="grid simple">
<div class="grid-title ">
<h4>
<logic:equal value="addCompany" property="method" name="companyForm">
New <span class="semi-bold">Company</span>
</logic:equal>
<logic:equal value="updateCompany" property="method" name="companyForm">
Edit <span class="semi-bold">Company</span>
</logic:equal>
</h4>
<div class="tools"> </div>
</div>
<div class="grid-body">
<table class="tbl_wall" style="width: 100%" >
<tr >
<td class="fi_wall" >Company Name<span class="notify style16"> *</span></td>
<td class="fi_wall" ><html:text property="companyName" name="companyForm" styleClass="med_txt" /></td>
<td> </td>
</tr>
<tr>
<td class="fi_wall" valign="top" >Company Code<span class="notify style16"> *</span> (3 Letter)</td>
<td class="fi_wall" valign="middle" ><html:text property="companyCode" maxlength="3" styleClass="med_txt" name="companyForm" /></td>
<td> </td>
</tr>
<tr id="cmp">
<td class="fi_wall">Company Type </td>
<td class="fi_wall"><select name="companyType" v-model="companyType">
<option value="-1">select</option>
<option v-for=" result in results " v-bind:value="result.commonId">
{{ result.name}}</option>
</select></td>
</tr>
<tr>
<td colspan="3" align="center">
<button type="button" class="btn btn-success" onclick="doSave()" ><i class="fa fa-save"></i> Save</button>
</td>
</tr>
</table> </form>
and the vue Portion
<script type="text/javascript">
new Vue({
el: '#cmp',
data: {
results: [],
companyType : '-1'
},
mounted() {
axios.get('/easyoffice/companyType.do?method=getCompanyTypeAjax').then(response => {
this.results = response.data,
this.companyType = document.forms['companyForm'].companyType.value
})
.catch(e => {
this.errors.push(e)
})
}
});</script>
i used this.companyType = document.forms['companyForm'].companyType.value to set form value but it is not working. Any Thoughts?
In an table which can contain more rows, user is searchable using the email id. After searching, selecting the first check box. But selenium is throwing the element not visible exception.
//*[#id='share_user']/tbody/tr1/td1//label
//*[#id='share_user']/tbody/tr1/td1//input
//label[#for='checkbox_416']
last identifier is dynamic. Still getting the element not visible exception.
Table code is mentioned below
<table class="table table-striped table-hover dataTable" id="share_user"
aria-describedby="share_user_info">
<thead>
<tr role="row">
<th class="small-cell sorting" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 137px;"
aria-label="Share Profile : activate to sort column ascending">Share Profile </th>
<th class="medium-cell sorting" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 523px;"
aria-label="User Details: activate to sort column ascending">User Details</th>
<th class="medium-cell sorting_asc" role="columnheader" tabindex="0"
aria-controls="share_user" rowspan="1" colspan="1" style="width: 366px;"
aria-sort="ascending" aria-label="Access: activate to sort column descending">Access</th>
</tr>
</thead>
<tbody role="alert" aria-live="polite" aria-relevant="all">
<tr class="odd">
<td class="">
<div class="checkbox check-default">
<input name="checkUser" id="checkbox_416" value="416" class="shareCheck"
type="checkbox">
<label for="checkbox_416"></label>
</div>
</td>
<td class=" ">
<img src="" class="img-responsive display-inline share-image">
<div class="display-inline">
<p class="share-name">alexx</p>
<p class="muted">
<i class="fa fa-envelope" hidden="true"></i>
<span>alexxm360#gmail.com</span>
</p>
</div>
</td>
<td style="vertical-align: middle;" class=" sorting_1">
<div class="select2-container medium-cell" id="s2id_rolelink416"
style="float:left;">
<a href="javascript:void(0)" onclick="return false;" class="select2-choice"
tabindex="-1">
<span class="select2-chosen">PROFILE ADMIN</span>
<abbr class="select2-search-choice-close"></abbr>
<span class="select2-arrow">
<b></b>
</span>
</a>
<input class="select2-focusser select2-offscreen" id="s2id_autogen11"
type="text">
<div class="select2-drop select2-display-none select2-with-searchbox">
<div class="select2-search">
<input autocomplete="off" autocorrect="off"
autocapitalize="off" spellcheck="false" class="select2-input"
type="text">
</div>
<ul class="select2-results">
</ul>
</div>
</div>
<select name="profileUsers.roleId" id="rolelink416"
class="medium-cell select2-offscreen" style="float:left;" tabindex="-1">
<option value="6">PROFILE ADMIN</option>
<option value="7">PROFILE AGENT</option>
<option value="8">PROFILE VIEWER</option>
<option value="196">profile role</option>
</select>
</td>
</tr>
</tbody>
</table>
providing the screen shots as well.
Try to use explicit wait with Expected Conditions
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement checkbox = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='share_user']/tbody/tr[1]/td[1]//input")));
checkbox.click();
You can use the following expression, I have verified working fine.
driver.findElement(By.xpath("//*[#id='share_user']/tbody/tr[1]/td[1]/div")).click();
Try this
int ele_size=driver.findElements(By.xpath("locator")).size();
driver.findElements(By.xpath("locator")).get(ele_size-1).click();
We might encounter element not visible exception if element matching the locator existed in the DOM but is not currently visible. So we have to take the size of the element in first statement then in next statement we have to take the first element from the list and click on element.
Used this //*[#id='share_user']/tbody/tr[1]/td[1]/div worked
Is it possible for selenium to find a label element by its "for" attribute using xpath?
I'm testing a site that has 7 yes or no questions in row. The way the CSS is done, you click on the label instead of the input radio button. Normally I'd just find the element by text content, but there is a yes and no for each question.
I'm thinking that a work-around would be to do a javascript click on the input button to get around the "element is not visible" error that I get when trying to .click() the input directly, but I wanted to see if there was a better way to locate the label which is what users would actually be clicking.
*Edit for all of your who can't remember what a label element looks like. How would you select the middle one from this group?
<label for="superLongSetOfRandomCharacters123" class="common-to-all-buttons"> No </label>
<label for="superLongSetOfRandomCharacters345" class="common-to-all-buttons"> No </label>
<label for="superLongSetOfRandomCharacters456" class="common-to-all-buttons"> No </label>
More specifically, this is how they sit in the DOM
<ul class="list-view list-view-dividers">
<li class="list-view-item">
<div class="content">
<div id="variableValue1" class="multipleChoice">
<div class="form-row">
<label>Question 1</label>
<div class="form-row">
<table class="choices" id="randomlyGenerated-1">
<tbody>
<tr>
<td>
<div class="ui-radio"><label for="randomlyGenerated1" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> Yes</label><input id="randomlyGenerated1" type="radio" name="randomlyGenerated1" value="Yes"></div>
</td>
<td>
<div class="ui-radio"><label for="randomlyGenerated2" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> No</label><input id="randomlyGenerated2" type="radio" name="randomlyGenerated2" value="No"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="randomlyGenerated1-Error" class="component-error"></div>
</div>
</div>
</li>
<li class="list-view-item">
<div class="content">
<div id="variableValue2" class="multipleChoice">
<div class="form-row">
<label>Question 2</label>
<div class="form-row">
<table class="choices" id="randomlyGenerated-2">
<tbody>
<tr>
<td>
<div class="ui-radio"><label for="randomlyGenerated21" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> Yes</label><input id="randomlyGenerated21" type="radio" name="randomlyGenerated21" value="Yes"></div>
</td>
<td>
<div class="ui-radio"><label for="randomlyGenerated22" class="ui-btn ui-corner-all ui-btn-inherit ui-btn-icon-left ui-radio-off"> No</label><input id="randomlyGenerated22" type="radio" name="randomlyGenerated22" value="No"></div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="randomlyGenerated2-Error" class="component-error"></div>
</div>
</div>
</li>
</ul>
It works for selecting all labels with target 'for':
label[#for='superLongSetOfRandomCharacters123']
or you can leave #for='' blank for selecting all labels with any values (i.e. label[#for])
I guess, the XPath-Option you are looking for would be "#". so in your case something like [...]/label/#for would return you that for-value, which you could then use to check where you are ;)
Cheers
D
Use find_element_by_xpath
label = self.browser.find_element_by_xpath('//label[#for="id_field"]')
Is there a way to click further inside siblings in Selenium Webdriver? For example, here's the HTML:
<tr class="rich-table-row xx-datalist-even" onmouseover="Element.addClassName(this, 'xx-datalist-mouseover')" onmouseout="Element.removeClassName(this, 'xx-datalist-mouseover')">
<td class="rich-table-cell xx-datalist " id="userTableForm01:usersTableData:264:j_id102" style="text-align:center; width:20px;">
<img src="/static/images/graphics/status1.gif" title="Disabled" />
</td>
<td id="userTableForm01:usersTableData:264:col1" class="rich-table-cell xx-datalist">
<span id="userTableForm01:usersTableData:264:author_id">2377</span>
</td>
<td id="userTableForm01:usersTableData:264:col2" class="rich-table-cell xx-datalist">seleniumtest2312</td>
<td id="userTableForm01:usersTableData:264:col3" class="rich-table-cell xx-datalist">
<span style="margin-right:3px">Test2312</span>
Selenium
</td>
<td class="rich-table-cell xx-datalist " id="userTableForm01:usersTableData:264:col4" style="text-align:center;">
<input type="checkbox" name="userTableForm01:usersTableData:264:j_id111" onclick="A4J.AJAX.Submit('userTableForm01',event,{'similarityGroupingId':'userTableForm01:usersTableData:264:j_id112','parameters':{'userTableForm01:usersTableData:264:j_id112':'userTableForm01:usersTableData:264:j_id112'} } )" />
</td>
<td id="userTableForm01:usersTableData:264:col6" class="rich-table-cell xx-datalist">
<a id="userTableForm01:usersTableData:264:enable_link" href="#" style="margin-right:5px" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:enable_link':'userTableForm01:usersTableData:264:enable_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:enable_link_text" class="xx-datalist">Enable</span>
</a>
<a id="userTableForm01:usersTableData:264:edit_link" href="#" style="margin-right:5px" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:edit_link':'userTableForm01:usersTableData:264:edit_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:edit_link_text" class="xx-datalist">Edit</span>
</a>
<a id="userTableForm01:usersTableData:264:remove_link" href="#" onclick="if(typeof jsfcljs == 'function'){jsfcljs(document.getElementById('userTableForm01'),{'userTableForm01:usersTableData:264:remove_link':'userTableForm01:usersTableData:264:remove_link'},'');}return false">
<span id="userTableForm01:usersTableData:264:remove_link_text" class="xx-datalist">Delete</span>
</a>
</td>
</tr>
Now, this is a much bigger table than shown, so there are a lot more tr's with more users. The ID's are all auto-generated and different each time, and I am trying to click the 'Enable'-link, though the only thing unique on the same row that I can use is the username seleniumtest2312, which has brought me to this:
driver.findElement(By.xpath("//td[text()='seleniumtest2312']/following-sibling::td[3]/span[text()='Enable']")).click();
But it just won't work (no such element).
If there are better ways of solving this issue I'll be happy to try them.
The last part of your XPath is a bit off :
following-sibling::td[3]/span[text()='Enable']
because <span> you're looking for isn't direct child of <td>. You can try this XPath instead :
//td[.='seleniumtest2312']/following-sibling::td[3]/a/span[.='Enable']