How to select the smallest element that contains text - ruby-on-rails

I'm using Rails 5 with Nokogiri. How do I select the smallest element that contains text?
I have this element on my page:
<td class="style35" style="font-size: medium; border: thin solid #000000">
Location</td>
and I thought I could select it using:
doc.at('td:contains("Location")')
Instead, a wrapping td that contains the table that contains this element is selected:
<td><span class="myClass"><table> ....
What is the proper way to write an expression that selects the smallest (most minimal?) element that contains the text I want?

If you use the at method it will only return the first result.
The css method will return all the elements matching the CSS selector, both the correct td element, and the td element wrapping around the whole table.
If you use something like this, it will find all the td tags, containing the word Location, then it will store the elements that is not wrapped around another td tag in an array:
td_with_no_child_and_have_location = []
doc.css("td:contains('Location')").each do |td_element|
if td_element.css("td").empty?
td_with_no_child_and_have_location << td_element
end
end
first_td = td_with_no_child_and_have_location.first

It's hard to help you if you don't supply us with the minimum HTML. I tried recreating it but YMMV:
require 'nokogiri'
doc = Nokogiri::HTML(<<EOT)
<html><body><table><tr>
<td><span class="myClass"><table><tr>
<td class="style35" style="font-size: medium; border: thin solid #000000">
Location</td>
</tr></table></td></tr></table></html>
EOT
doc.at('.myClass td.style35').text # => "\n Location"
If the tag you want is embedded in another table, then take advantage of some of the other characteristics to help you navigate, such as the class information.
Using at should help in this case because typically the title of a table would be in the first row which would contain the first cell. at is the equivalent of search('some selector').first.
The above selector could even be written as .myCLass .style35 or td td which would find the td inside another td. Combine that with at and you'd get the first such occurrence:
doc.at('.myClass td.style35').text # => "\n Location"
doc.at('.myClass .style35').text # => "\n Location"
doc.at('td td').text # => "\n Location"

Pick all td elements, sort by the content length and pick the first element. Change the selector as you may wish. Sort is ascending by default. So you get the smallest elements first.
doc.css('td').sort_by do |td_element|
l.text.length
end.first

Related

How would I use xpath to get the alternate ids

I have tried to get the each alternate ID from that box but with no avail I'm using Ruby on rails with Nokogiri
Here's the link to the page with alternate ID's (Look below the picture Alternate ID's) http://lol.gamepedia.com/Cain
<tr>
<th> Alternate IDs:
</th>
<td> wvwvvwvwwvwvvvwv (NA), 나진 카인, Nurinim, 나진 카인
</td></tr>
You can try the following XPath to get the alternate Ids value :
//tr/th[normalize-space()='Alternate IDs:']/following-sibling::td[1]
Brief explanation :
//tr : find all <tr> elements anywhere in the HTML document
/th[normalize-space()='Alternate IDs:'] : from the found tr elements, find child element th having inner text (after removing excess whitespaces) equals "Alternate IDs:"
following-sibling::td[1] : from such th, return the first td element that follow the th element within the same parent tr

Line Breaks not working in Textarea Output

line breaks or pharagraph not working in textarea output? for example i am using enter for pharagraph in textarea but not working in output? How can i do that?
$("#submit-code").click(function() {
$("div.output").html($(".support-answer-textarea").val());
}).next().click(function () {
$(".support-answer-textarea").val($("div.output").html());
});
.support-answer-textarea{width:100%;min-height:300px;margin:0 0 50px 0;padding:20px 50px;border-top:1px solid #deddd9;border-bottom:1px solid #deddd9;border-left:none;border-right:none;box-sizing:border-box;letter-spacing:-1px;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<textarea id="support-answer-textarea" class="support-answer-textarea" placeholder="Destek Konusunu Cevapla!"></textarea>
<button type="submit" id="submit-code" class="btn btn-success">Submit Your Code</button>
<div class="output"></div>
The best and easy way to fix line breaks on the output use these simple css:
.support-answer-textarea {
white-space: pre-wrap;
}
When you hit enter in a <textarea>, you're adding a new line character \n to the text which is considered a white space character in HTML. HTML generally converts the sequence of all white spaces to a single space. This means that if you enter a single or a dozen of whitespace characters (space, new line character or tab) in a row, the only effect in resulting HTML is just a single space.
Now the solution. You can substitute the new line character (\n) to <br> or <p> tag using replace() method.
$("#submit-code").click(function() {
$("div.output").html($(".support-answer-textarea").val().replace(/\n/g, "<br>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<textarea id="support-answer-textarea" class="support-answer-textarea"></textarea>
<button type="submit" id="submit-code">Submit Your Code</button>
<div class="output"></div>
for me, I had a e.preventDefault() for only Enter keypress on a parent element, this prevents a new line from adding.
If you are capturing an input from a textarea, sending it via ajax (saving to database, e.g. mysql) and then want to display the result in a textarea (e.g. by echoing via php), use the following three steps in your JS:
#get value of textarea
var textarea_value = $('#id_of_your_textarea').val();
#replace line break with line break input
var textarea_with_break = textarea_value.replace(/(\r\n|\n|\r)/gm, '
');
#url encode the value so that you can send it via ajax
var textarea_encoded = encodeURIComponent(textarea_with_break);
#now send via ajax
You can also perform all of the above in one line. I did it in three with separate variables for easier readability.
Hope it helps.
Posting this here as it took me about an hour to figure this out, fumbling together the solutions from the answers below (see for more details):
The .val() of a textarea doesn't take new lines into account
New line in text area
URL Encode a string in jQuery for an AJAX request

Reveal.js: Add fragments inside code

I've got a presentation running with reveal.js and everything is working. I am writing some sample code and highlight.js is working well within my presentation. But, I want to incrementally display code. E.g., imagine that I'm explaining a function to you, and I show you the first step, and then want to show the subsequent steps. Normally, I would use fragments to incrementally display items, but it's not working in a code block.
So I have something like this:
<pre><code>
def python_function()
<span class="fragment">display this first</span>
<span class="fragment">now display this</span>
</code></pre>
But the <span> elements are getting syntax-highlighted instead of read as HTML fragments. It looks something like this: http://imgur.com/nK3yNIS
FYI without the <span> elements highlight.js reads this correctly as python, but with the <span>, the language it detects is coffeescript.
Any ideas on how to have fragments inside a code block (or another way to simulate this) would be greatly appreciated.
To make fragments work in code snippets, you can now use the attribute data-noescape with the <code> tag
Source: Reveal.js docs
I got this to work. I had to change the init for the highlight.js dependency:
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() {
[].forEach.call( document.querySelectorAll( '.highlight' ), function( v, i) {
hljs.highlightBlock(v);
});
} },
Then I authored the section this way:
<section>
<h2>Demo</h2>
<pre class="stretch highlight cpp">
#pragma once
void step_one_setup(ofApp* app)
{
auto orbit_points = app-><span class="fragment zoom-in highlight-current-green">orbitPointsFromTimeInPeriod</span>(
app-><span class="fragment zoom-in highlight-current-green">timeInPeriodFromMilliseconds</span>(
app->updates.
<span class="fragment zoom-in highlight-current-green" data->milliseconds</span>()));
}
</pre>
</section>
Results:
I would try to use multiple <pre class="fragment">and change manually .reveal pre to margin: 0 auto; and box-shadow: none; so they will look like one block of code.
OR
Have you tried <code class="fragment">? If you use negative vertical margin to remove space between individual fragments and add the same background to <pre> as <code> has then you get what you want.
Result:

Are dynamically created table rows not targetable by jQuery?

I'm trying to make table rows draggable and then connectToSortable -able.
For some reason, when I put the ID of the tbody ("#sem1") in the selector, it works but obviously drags the whole table-body with all of its rows.
However, when I put "#sem1 tr" in the selector the webpage seems to just ignore that code, meaning the table still shows up correctly, but nothing becomes draggable.
HTML:
<table class = "sem">
<thead>
<th class = "header1">header</th>
<th class = "header2">header</th>
<tr>
<td class = "static1">static1</td>
<td class = "static2">static2</td>
</tr>
</thead>
<tbody id = "sem1">
</tbody>
</table>
Through some JavaScript table rows get added to sem1 like so.
JavaScript:
First pos0[0] (an array) gets populated:
for(var i in setPos[0]){
setPos[0][i]=("<tr><td class = " + String(setClass[i])+ ">" + setPos[0][i].slice(2) + "</td><td class = 'someClass'>"+setThis[i]+"</td></tr>");
}
Then pos0[0][a] gets added to sem1 like this:
for(var a in pos0[0]){
document.getElementById("sem1").innerHTML += pos0[0][a];
}
and when I try to make the rows draggable, it just doesn't work.
jQuery:
$("#sem1 tr").draggable()
Putting just tr in the selector doesn't work either (I don't mind if all the table rows in the whole document are draggable)
**I know that the code says setPos[0] - it's part of a function that does the same thing to pos1, pos2...
Thanks in advance for any help!
My guess is that you are calling the $("#sem1 tr").draggable() line before the code that has inserted the new <tr>'s has been run, so it doesn't see the rows you've added.
Also, have you tried manually inserting some markup to check that the draggable code actually works on a per row basis?
It would help if you could post an example in jsfiddle or something so we can work on this with you.
Finally it could be overkill for this situation but have you looked into using a JavaScript templating engine if you are going to be building chunks of html in your app?

Styling select_tag

I cannot find any way to change the font styling in a Rails select_tag list
If I try this:
<%= select_tag :weight_lbs, options_for_select([['0', 0],['1', 1],['2', 2],['3', 3],['4', 4],['5', 5],['6', 6],['7', 7],['8', 8],['9', 9],['10', 10],['11', 11],['12', 12],['13', 13]]), :class => 'formfield'%>
then I can change the width of the select box in my CSS class but I cannot change anything else - height, font-size and color, eg, all have no affect
Similarly, if I try and change style at element level, and even using an example from Rails documentation
<%= select_tag 'testname', options_for_select(options_for_select([ "Denmark", ["USA", {:class => 'select'}], "Sweden" ]))%>
the class attribute has no affect on output (Chrome & Safari on a Mac, Rails 3.1)
So, how can I change the height & text styles within a select_tag in Rails?
I found this on Reddit. posted by u/GroceryBagHead
You cannot style select options. Those are dependent and rendered by your OS/browser. It's possible to replace this control with html elements though.
He posted a link that's now dead for something called bootstrap-select. A google search should help you find more resources
Well, this question is old, but sure you can:
<%= select_tag :blah, options_for_select(#some_options), {:multiple => true, :style => "min-width: 200px"} %>
My suggestion is to check the page source generated by Rails. It will make easier to understand the HTML structure in order to select the elements in your CSS file.
Having the HTML code generated by Rails, your question became related to CSS.
You can include your select inside a div, for example:
<div class="myclass">
<%= select_tag :weight_lbs, options_for_select([['0', 0],['1', 1],['2', 2],['3', 3],['4', 4],['5', 5],['6', 6],['7', 7],['8', 8],['9', 9],['10', 10],['11', 11],['12', 12],['13', 13]])%>
</div>
So your CSS:
.myclass select {
font: # whatever you want
...
}
.myclass select option {
# in case you want to style the options of a select
}
ETC...
A work around I used was installing a gem called select2
gem 'select2-rails'
If you follow setup process in the docs, you can edit the dropdown list properties pretty easily in CSS. After some messing around in Chrome inspector, I found the relative tags.
/* The dropdown background */
.select2-dropdown{
background-color: #3a3a3a;
font-size: 10px;
font-family: sans-serif;
}
/* Individual styling of list items that are selected (previously chosen) */
.select2-results__option--selected {
opacity: 0.9;
background-color: #505050 !important;
}
/* Individual styling of list items that are highlighted (mouse hover) */
.select2-results__option--highlighted {
background-color: #e66d2d !important;
}
If you want to look into Chrome Inspector yourself, click on the "Select" form field and open the dropdown list. This creates a span element as a child of the body tag shown in the screenshot attached.

Resources