Jquery: Can I refer to a selector not present in the default HTML? - jquery-selectors

Sorry, this is probably a noob question. Could'nt find the source of my problem, or helpful info in SO (or elsewhere!).
I'm practising my newly acquired Jquery skills (?) on a small contact list demo project, which basically includes a table and a simple form to populate it. The project includes an HTML file, a CSS stylesheet, and some Javascript and Jquery magic in a .JS file.
EDIT: Here's a jsFiddle I've created for this.
By default, when the page first loads, the table is empty and a placeholder text is shown:
<table>
<thead>
<tr>
<th id="col_lastName">Last Name</th>
<th id="col_firstName">First Name</th>
<th id="col_email">E-Mail</th>
<th id="col_mobile">Mobile</th>
<th id="col_actions">Actions</th>
</tr>
</thead>
<tbody>
<tr id="placeholder">
<td colspan="5">No contacts yet. Feel free to add your friends!</td>
</tr>
</tbody>
</table>
Upon submittion of the form, using Jquery I set the placeholder to disappear and a new table row is appended:
$("tbody").append(
"<tr><td>" + $("#last_name").val() +
"</td><td>" + $("#first_name").val() +
"</td><td><a href='mailto:" + $("#email").val() + "'>" + $("#email").val() + "</a>" +
"</td><td>" + $("#mobile").val() +
"</td><td><p class='remove_link'>Remove</p></td></tr>");
I would like it to include a link to remove the current row, so I wrote a function that's triggered by clicking the <p class="remove_link">"Remove"</p> text that was part of the string appended upon form submittion. However I can't seem to be able to make it clickable with Jquery. I wrote this:
$(".remove_link").click(function(){
// just for chaecking the selector is ok
console.log("remove clicked");
});
But on the actual page the "Remove" isn't clickable at all.
Does it have anything to do with the fact that the class doesn't appear in the default HTML and is only declared in the appended code?
Of course, it could also mean my syntax is wrong, but I can't figure this out!

Since the element you are trying to bind the event to does not exist yet when you perform the binding you need to set up a future delgate using .on()
$("table").on('click',".remove_link",function () {
console.log("remove clicked");
});
Note that the important trick is to start the binding from an existing element (in this case the table)
I updated your fiddle here: http://jsfiddle.net/Abxzx/4/

well, I think I have a lead for an answer for this. In the page dealing with The .on() method on W3Schools there's a reference (down belew) to the fact that this method can also "work for elements not yet created". From this I deduct that the simple .click() just won't do. I'll try again with .on() tomorrow and will report my findings.
Meanwhile, if there's someone here more experienced in Jquery, I'd appreciate your opinion/advice.

Related

Find and Replace with Visual Studio Code to replace cell alignment with a class

Since the align attribute is considered obselete I am cleaning up code to remove it and replace with a CSS class. I'm trying to determine if there is a way to do this using find and replace (or something else) in VS Code.
As an example, I might have some html that looks like this:
<table>
<tr>
<td align="left" class="someclass" id="mainTitleCell" title="Title1">Title1</td>
<td align="center" title="Title2">Title2</td>
<td class="someclass" align="right" title="Title3">Title3</td> <!-- attributes are not always in the same order -->
</tr>
<tr>
<td align="left">Title</td>
<td align="center">Title</td>
<td align="right">Title</td>
</tr>
</table>
which I would like to change to
<table>
<tr>
<td class="left someclass" id="mainTitleCell" title="Title1">Title1</td>
<td class="center" title="Title2">Title2</td>
<td class="right someclass" title="Title3">Title3</td>
</tr>
<tr>
<td class="left">Content</td>
<td class="center">Content</td>
<td class="right">Content</td>
</tr>
</table>
Basically removing the align attribute and either adding a class attribute with a specific value OR adding a specific value to an existing class attribute. Is there a way to do this with the Edit...Replace option in VS Code? I know I can find based on a regex but not sure how I would go about the replace since this becomes
Find the align tag
Remove it
Find a class attribute in the <td> or <th> tag and add the appropriate class
If there is no class attribute, add one with the appropriate class.
Obviously step #1 & 2 are easy, it's #3 & 4 that I'm not sure of. I'd be totally happy with having to run 3 separate find and replace commands (one for left, center and right).
Do I have any options here (I am open to extensions)?
UPDATE:
#Mark had the right answer and I was able to chain together several find and replace commands using the Replace Rules extension. With that I can open a file, run a single keystroke to find and replace everything and clean up the extra spaces in the class attribute.
Try this:
Find: align="(.*?)"(.*?) class="(.*?)"|class="(.*?)"(.*?) align="(.*?)"|align="(.*?)"
Replace: class="$7$1$6 $3$4"$2$5
See regex101 demo.
I'm a little surprised this works as well as it does (I included a couple of other test cases you didn't). The only issue (thus far...) is that it can result in one stray space, as in:
<td class="left ">Title</td> // only happens when there is no class attribute
as you can see in the demo page. You could then search for " and replace with just ". It could be handled by a conditional replacement but vscode find/replace doesn't allow those.
To some degree attributes will be re-ordered so that the class attribute is first, but not always - you didn't mention that as a concern - any attribute that occurs before either the first class or align attribute will not be moved. Otherwise, attributes like id or title if they are between class<->attribute (in any order) will be put last.

DOM element not rendering html

I have built an html table that generates dynamically from a data array. It is intended to make a menu of beers on tap in my bar. The array contains the following data: [tap_number, brewery_image, beer_name, price_for_a_pint, price_for_a_pitcher]. Therefore the array dictates that the table generate with 5 columns and 14 rows (with current data). The image data consists of an html tagged image and similarly the beer_name is tagged <h3></h3>. All the html tagged data is rendering as text. What have I done wrong? btw, using Materialize css for basic table styling. Have tried with bootstrap also - same result. Here's a snippet of the html element that the js generates:
<table class = "tabel">
<thead>
<tr>
...has <td>column name</td> X5
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td><img src='[url of image]' alt=''></td>
<td><h3>[Beer_Name]</h3></td>
<td>$6</td>
<td>$10</td>
</tr>
...a bunch more rows..
</tbody>
</table>
.
So data positions 1 and 2 should be rendering according to html tag but are just appearing on the page as the text of their html. All data from the array is passed as textContent. Should I be using innerHtml? when I do, nothing at all renders. Cannot figure out what amateur mistake I've made or whether Materialize is screwing me... Thanks for any advice...
It was an amateur mistake. was using innerHtml instead of innerHTML....

Selenium IDE target of subsequent cell in table based on first cells content

Basically, in English I want to tell Selenium "look for the content ttc202 in column one, of a multi-row, multicolumn table, then mouseOver on the Edit link"
HTML is as follows:
<tr id="86" class="ui-widget-content jqgrow ui-row-ltr ui-state-highlight" tabindex="0" role="row" aria-selected="true">
<td aria-describedby="jqLst_Short Name" style="text-align:left;" role="gridcell">
ttc202
</td>
<td aria-describedby="jqLst_Long Name" style="text-align:left;" role="gridcell">
Testing Training Company 202
</td>
<td aria-describedby="jqLst_Actions" title="" style="text-align:center;" role="gridcell">
<a class="act avw" title="View this Organisation" href="company/view?lcId=86"></a>
<a class="act aed" title="Edit this Organisation" href="company/edit?lcId=86"></a>
</td>
</tr>
I have tried this:
//td[contains(text(),'ttc202')]/following-sibling::td[contains(a/title(),'Edit this Organisation')]/a
All help appreciated. I assume I am missing something to skip over the first column, but can't imagine what will enable me to do that...
Progress:
I have found the following as an alternative which should get to the correct cell, but I am not able to workout how to target the title in the link code:
//td[normalize-space() ="ttc202"])[1]/following-sibling::td[2]/a[. = 'Edit']
I think this is progress just not sufficient to get me to the finish line!
After much investigation I found the following answer, perhaps this might help others who come across this question:
//tr[contains(td[1], "ttc202")]/td[3]/a[#title='Edit this Organisation']
The trick was realising which cell the information was in (represented by the square brackets).

customizing size of form fields created using field.custom.widget

I used the following code to generate a form in attached image.
Is it possible to change the size of the fields in the form.
I want to decrease size of input field of Estimated time and the dropbox field to the right of it
{{=form.custom.begin}}
<table>
<table><tr>
<td><b>Type :</b></td><td><div>{{=form.custom.widget.type}}</div></td>
</tr><tr>
<td><b>Title :</b></td><td><div>{{=form.custom.widget.title}}</div></td>
</tr><tr>
<td><b>Description :</b></td><td><div>{{=form.custom.widget.description}}</div></td>
</tr><tr>
<td><b>Estimated Time :</b></td><div'><td>{{=form.custom.widget.estimated_time}}{{=form.custom.widget.estimated_time_unit}}</td> </div>
</tr>
<tr>
<td></td><td><div align='center'>{{=form.custom.submit}}</div></td>
</tr>
</table>
{{=form.custom.end}}
Yes. You can and there are many ways.
The recommended way is to look at the generates JS. You will find it follows a naming convention described in the book. You can use CSS to change the look-and feel of every widget.
input[name=estimate_time] { width:50px }
Similarly you can use JS/jQuery (I would recommend you do this in the view).
jQuery(document).ready(function(){ jQuery('input[name=estimate_time]').css('width','50px');});
You can also use jQuery-like syntax in python in the controller:
form.element('input[name=estimate_time]')['_style']='width:50px'

Nesting dynamically displayed components in wicket

I have a need to create following kind of markup with wicket using ajax:
<table>
<tr>
<td><a>first</a></td>
<tr>
<tr>
<td>displayed/closed if first is clicked <a>open</a></td>
</tr>
<tr><td>this and following displayed/closed if above open is clicked</td></tr>
<tr><td>there may be any number of these</td></tr>
<tr>
<td>there may be any number of these as well <a>open</a></td>
</tr>
<tr>
<td>any number of these as well <a>second</a></td>
</tr>
</table>
How to use ListViews or some other wicket element to individually toggle open "inner" rows of the table. I don't want to resort to render everything and toggling visibility but really create the rows in server side only when expand is requested. The markup should also be valid xhtml (rules out arbitrary container for row groups). I know I can put multiple tbodys, but it's good enough only for one level of nesting (no .... allowed).
From Lord Torgamus' comment, the ajax tree sounds appropriate..