Rails - Add HTML attribute without setting a value - ruby-on-rails

I'm trying to create an image_tag and specify a data- attribute that does not have any value set to it. I'm trying to add data-tooltip, for use with Foundation 5 tooltips. It seems that if any value is actually set to this, Foundation uses the same tooltip text every time and ignores the title attribute of that element (so every tooltip will say whatever the first one you hovered on was... which seems buggy in and of itself on Foundation's part also)
This is what I need to generate:
<img src="[whatever]" title="My Tooltip" data-tooltip />
This will not work for me:
<img src="[whatever]" title="My Tooltip" data-tooltip="[insert anything here]" />
I have tried a number of different combinations, and read documentation, but it seems no matter what I put as the value, it ends up generating it like data-tooltip="null", or true, or false, or any string I pass.
image_tag(my_image, class: 'has-tip', title: "My Title Here", data: { tooltip: true })

Try to pass in empty string as follows:
image_tag(my_image, class: 'has-tip', title: "My Title Here", data: { tooltip: "" })

In Rails 4.1.4 using above tip :"data-tooltip" => '' renders data-tooltip without value.

For an attribute with no value like multiple <input multiple type="file">, you can override the attribute default name, by uppercasing and setting an empty string. For example input_html: { Multiple: '' } But this is a hack.

In rails 5, I was trying to add itemscope attribute with no value in the following link tag scenario:
<%= link_to example_path(#example) do %>
<span>
<%= #example.name %>
</span>
<% end %>
I needed the resulting html a tag to show the itemscope attribute without any value like so:
<a itemscope href="example/path">
<span>
some text
</span>
</a>
Notice the itemscope has no ="" or itemscope="itemscope".
I tried solutions from SO and other places and the only thing that worked for me was adding the following to the link_to tag: " itemscope" => ''. Notice the space between the first double quote and the word itemscope.
This seems to generate the desired outcome and also validated as schema.org tag on google (that is what i used the tag for).

Related

Unable to define siteprism element from a given label text

I'm using a cucumber/ruby/capybara/siteprism framework and I'm having problems identifying elements as either we're missing the ids, names, etc or they create them with a in real time.
I was mainly trying to define some of those elements in a siteprism page object model. For example, I was trying to enter some data in the 'input' field for 'First Name' below:
<div class="control-group">
<label class="control-label" for="input_field_dec_<random_number>">
First Name
<span class="required"></span>
</label>
<div class="controls">
<input id="input_field_dec_<random_number>" class=" span5" type="text" value="" scripttofire="SetUserFirstName('input_field_dec_<random_number>')" required="required" name="input_field_dec_<random_number>" data-val-required="First Name is required" data-val-regex-pattern="^[a-zA-Z0-9_ \-\']*$" data-val-regex="Only alphabetic and numeric characters allowed" data-val="true">
<span class="field-validation-valid help-inline" data-valmsg-for="input_field_dec_<random_number>" data-valmsg-replace="true"></span>
</div>
</div>
Is there a way to pass the label text (eg: 'First Name' - ignoring the spaces around, something like - contains='First Name') and then find the input element inside to set it up?
I was thinking something along the lines of:
element :first_name_field, :xpath, "//label[contains(text()='Continue'])/<and here something to find the input field?>" but cannot figure it out...
Capybara provides a bunch of built-in "selectors" that can be used for this, and you can add your own if you find it necessary. You can see the provided selectors by either building the Capybara docs yourself (rubydocs doesn't run the custom yard code used to generate that part of the docs) or by browsing the file where they are implemented - https://github.com/teamcapybara/capybara/blob/master/lib/capybara/selector.rb#L47
For your original example you can use the :field selector
element :first_name_field, :field, 'First Name'
which will match on the inputs associated label text. For you second example (from the comments) where the input and label have no connection (wrapped or for attribute) you should be able to do something like
element :some_field, :xpath, ".//label[contains(normalize-space(string(.)), 'label text')]/following-sibling::*[1]/self::input"
If you wanted to make that reusable you could add your own "selector" like
Capybara.add_selector(:sibling_input) do
label "Label adjacent sibling input"
xpath do |locator|
XPath.descendant(:label)[XPath.string.n.is(locator)].next_sibling(:input)
end
end
which could then be used as
element :some_field, :sibling_input, 'label text'

Capybara: how to retrive the Test Services code value(F603YPW) of an element from below html page

I want to retrieve the value of Test Services code
<p>
<span class="floatLeft w30p">Test Services code:</span>
<span> <strong>F603YPW</strong> </span>
</p>
The rest of the page will really affect what selector(s) you would need to use to get that text, however given only the HTML specified you can use the css adjacent sibling selector to get the element
value = find(:css, 'span.floatLeft.w30p + span').text
if there are a bunch of other elements with the floatLeft and w30p classes then you could get more complicated using xpath selectors and do something along the lines of
value = find(:xpath, XPath.descendant(:span)[XPath.string.n.is('Test Services code:')].next_sibling).text
or with multiple finds
value = find(:css, 'span', text: 'Test Services code:').find(:xpath, XPath.next_sibling).text
If you are able to edit the HTML to
<p>
<span class="floatLeft w30p">Test Services:</span>
<span class="your_class"> <strong>F603YPW</strong> </span>
</p>
(so by adding a class to the span),
you will be able to find its value doing
value = page.find('.your_class').text
If you are not able to edit the HTML, do
value = find(:css, 'the css selector').text

Ruby on Rails & FullCalendar: Is there any way to add a link to the title header?

I have a page in my simple application that displays a calendar with the jQuery plugin http://fullcalendar.io/.
I want to add a link to the title such that the user gets navigated somewhere else to a different view. Is this possible? The calendar itself has poor documentation. Specifically I want to add a FontAwesome icon and have it redirect the user on click.
I know that customizing the title is pretty easy – just specify the custom title like this:
<div id="calendar"></div>
<script>
$('#calendar').fullCalendar({
header: {
left: 'prevYear,nextYear',
center: 'title',
},
titleFormat: '[Hello, World!]'
});
</script>
However, I am trying to add a link next to the calendar using a Rails helper link_to. Is this possible? Here is my attempt, but it does not work:
<div id="calendar"></div>
<script>
$('#calendar').fullCalendar({
header: {
left: 'prevYear,nextYear',
center: 'title',
},
titleFormat: '[<%= link_to '<i class="fa fa-icon"></i>'.html_safe, some_path %>']'
});
</script>
You have a typo on this line:
titleFormat: '[<%= link_to '<i class="fa fa-icon"></i>'.html_safe, some_path %>']'
There is an extra single quote after the %>. Try this:
titleFormat: '[<%= link_to '<i class="fa fa-icon"></i>'.html_safe, some_path %>]'
If you still have a problem after fixing that, try looking into what FullCalendar’s titleFormat property supports. I don’t know if FullCalendar tries to allow you to put arbitrary HTML into that property – that property’s docs don’t make it clear. You could check by looking in the rest of FullCalendar’s documentation or its source code that handles that property.
Your use of link_to and html_safe looks good to me.

Using complex th:attr fields with Thymeleaf

I have a Thymeleaf template with a rather complex data- attribute, like so:
<div data-dojo-props="required: true, placeholder:'Foo bar baz', more: stuff" ...>
I'd like to have Thymeleaf provide the placeholder, like so:
<div th:data-dojo-props="placeholder:'#{foo.bar.baz}'" ...>
It doesn't work, of course. I'm supposed to use th:attr like so:
<div th:attr="data-dojo-props=placeholder:'#{foo.bar.baz}'" ...>
Which also doesn't work. As soon as you add a : or ' within the th:attr, the template breaks. I also tried escaping them, e.g. \: and \', and also tried using HTML entities, e.g. &38;, but also didn't work.
So I tried th:prependattr and th:appendattr:
<div th:prependattr="data-dojo-props=placeholder:'"
th:attr="data-dojo-props=#{foo.bar.baz}"
th:appendattr="data-dojo-props='"
...>
But they also can't handle : and ', nor escaping them:
<div th:prependattr="data-dojo-props=placeholder&58;&39;"
th:attr="data-dojo-props=#{foo.bar.baz}"
th:appendattr="data-dojo-props=&39;"
...>
Any way to make this work that I'm missing?
You can use parameters in a Thymeleaf message property for example:
Messages.properties:
dojo.props=required: {0}, placeholder: {1}, more: {...}
dojo.props.required=true
dojo.props.placeholder=Foo bar baz
HTML with message properties:
<div th:attr="data-dojo-props=#{dojo.props(#{dojo.props.required}, #{dojo.props.placeholder})}"></div>
Or if you want to get the values from a object:
<div th:attr="data-dojo-props=#{dojo.props(${dojo.props.required}, ${dojo.props.placeholder})}"></div>
Even selectors work:
<div th:attr="data-dojo-props=#{dojo.props(*{dojo.props.required}, *{dojo.props.placeholder})}"></div>

Rails f.submit: how to add html attribute?

I'm having trouble adding a particular html attribute to a Rails form submit.
= form_for :model do |f|
...
= f.submit 'Submit', tabindex: '3'
The tabindex property isn't showing up in the form. I also tried a html hash to no avail.
It just produces this html markup:
<button type="submit" value="Submit">Submit</button>
EDIT: The only alternative way I can think of is to use jQuery.
$('button[type=submit]').attr('tabindex', '3');
But that seems overkill. It seems like there should be a way in Haml.
The result of f.submit 'Submit', tabindex: '3' should be:
<input type='submit' value='Submit' tabindex='3'></input>
However, you appear to be getting a button element, and the tabindex is not showing up at all - so something else is definitely going on here.
If you have a custom form builder and override the submit method, this could certainly be the result. If you need that custom form builder and still want your submit element to be a button you'll need to make sure you're allowing an options hash through the submit method. Not sure what your current method looks like, but you might update it to something like this:
def submit(value, options={})
options.reverse_merge!(
type: 'submit',
value: value
)
button_tag(value, options)
end

Resources