How to test image preview with Capybara? - ruby-on-rails

I have js code that displays an image preview after adding a picture.
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
$(document).ready(function(){
$("#attach").change(function () {
readURL(this);
});
});
And html:
<img id="preview" style="width:400px;height:400px;">
<label for="attach">
<span>Click to add picture</span>
</label>
<input class="hidden" id="attach" type="file" name="profile[image]">
Check out Codepen example.
Question: Using capybara how can I test that image preview shows up when I attach a picture?
I know we can check img tag for a src but how can I combine Capybara with Javascript code?
Simply using attach_file() doesn't do anything useful here since Capybara isn't friendly with JS.

I'm not sure what you mean about Capybara not being friendly with JS, however there is an inconsistency in your example since your file input has an id of "attach" and your JS change listener is listening on '#inputFile' - assuming that is fixed (in this code I assumed the input id was supposed to be 'attach') then you can do
execute_script('$("#attach").removeClass("hidden")') #make input visible so you can attach to it
attach_file('attach', 'some_file.jpg') #attach the file
expect(page).to have_css('#preview[src]') #confirm a src attribute was set

Related

Materializecss tooltip not showing up

I am trying to use materialize tool tip for the first time using the example shown on its website. However, the tool tip is not showing up. What am I missing? Here is the link to the fiddle : https://jsfiddle.net/L013uvms/5/
<textarea id="causative_micro_organisms" class="materialize-textarea tooltipped" data-position="top" data-tooltip="I am a tooltip" required="" aria-required="true"></textarea>
<label for="causative_micro_organisms">What are the LIKELY causative Micro-organisms?</label>
I have also initialized the tool-tip
$(document).ready(function() {
$('select').formSelect();
$('.tooltipped').tooltip();
})
as docs of materialize website add these before document ready
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.tooltipped');
var instances = M.Tooltip.init(elems, options);
});
related link https://materializecss.com/tooltips.html

Rails 3: best way to preview image before upload

I need to preview an image prior to submitting a form.
I work with Rails 3 and needs something that is browser compatible.
Any ideas how I can achieve that?
So! :) The main idea is to use the FileReader Javascript Class, which is really handy for what you need to do.
You just have to listen to the "change" event on your file input and then call a method that will use the "readAsDataURL()" method of the FileReader class. Then you just have to fill the source of a "preview img tag" with the returned result of the method...
I've wrote you a simple jsFiddle that achieves what you want. You can see my code below:
<!-- HTML Code -->
<div class="upload-preview">
<img />
</div>
<input class="file" name="logo" type="file">
//JS File
$(document).ready(function(){
var preview = $(".upload-preview img");
$(".file").change(function(event){
var input = $(event.currentTarget);
var file = input[0].files[0];
var reader = new FileReader();
reader.onload = function(e){
image_base64 = e.target.result;
preview.attr("src", image_base64);
};
reader.readAsDataURL(file);
});
});
And in the Mozilla Documentation, you have another example (surely more robust). This solution should work with Safari (version 6.0+).
This is the only way I know to preview an image prior to submitting a form, but I think it is quite a common way. Of course it has nothing to do with Ruby On Rails as we only use Javascript here... It would be impossible to do it using Rails only as you would have to upload the image before rendering it. (As Rails is server side, I think you perfectly understand why. :) )
HTML:
<input type="file">
<div id="image_preview"></div>
JS (require jquery):
$(document).ready(function(){
$('input[type="file"]').change(function(){
var image = window.URL.createObjectURL(this.files[0]);
$("#image_preview").css("background-image", "url(" + image + ")");
});
});

jQuery unobtrusive custom adapter and method in jsFiddle

I cannot make this jsFiddle work but it works in the browser: http://jsfiddle.net/vtortola/jYq2X/
I am trying to add a new custom rule to compare two fields. The custom adapter works, it is being called and setting the options. But the custom method is never called.
I am executing this JS on DOM ready:
$.validator.addMethod("customequal-method", function (val, el, p) {
var $other = $(el).closest('form').find('input[name=' + p.other + ']');
return $other.length && $other.val() == val;
});
$.validator.unobtrusive.adapters.add("customequal", ["other"],
function (options) {
options.rules["customequal-method"] = options.params;
options.messages["customequal-method"] = options.message;
});
$(function(){
$.validator.unobtrusive.parse($('#myform'));
$('[type=button]').click(function(e){e.preventDefault(); $('form').valid();});
$('input[type=text]').blur();
})
These are the fields in HTML:
<input type="text" name="StartDate2" id="StartDate2" value="2"
data-val="true" data-val-customequal="xx xxx" data-val-customequal-other="EndDate2"/>
<input type="text" name="EndDate2" id="EndDate2" value="3"
data-val="true" data-val-customequal="xx xx" data-val-customequal-other="StartDate2"/>
I have been trying different things but nothing seems to work.
Any idea?
Your fiddle is not working because:
all your code runs in the DOM ready so you are adding your custom unobtrusive.adapters.add after the unobtrusive.validator plugin called unobtrusive.parse(document) which registers all the inputs without your custom validator
if you call .validate() multiple times it only registers the rules for the first time and does not override them on subsequent calls. So although you've called unobtrusive.parse again in the DOM loaded this time with the custom adapter added it still won't have any effect.
So you have two ways to fix it:
Register your custom adapters before the DOM loaded event, you can do this with changing your fiddle to use
"No wrap - in <head>"
Demo JSFiddle.
Or
Remove the already added validator object with using $('#myform').data('validator', null) before calling unobtrusive.parse manually:
$(function () {
$('#myform').data('validator', null);
$.validator.unobtrusive.parse($('#myform'));
$('[type=button]').click(function (e) {
e.preventDefault();
$('form').valid();
});
$('input[type=text]').blur();
})
Demo JSFiddle.

Append html to div not working on cordova iOS

I am using cordova 2.2.0 with Xcode 4.5.2. On one of my pages I have a select component and once a particular option is selected I want to display a table within a div. My html looks like this: <div class="hero-unit" id="#facprog"></div>
The javascript/jquery looks like this:
<pre><code>
$(function() {
$('#selFaculty').change(function() {
var facultyName = $('#selFaculty').val();
var progDetails = app.fillFacultyProgramme(facultyName);
alert(progDetails);
$('#facprog').append(progDetails);
});
});
</code></pre>
Note that #selFaculty is the id of the select object. However, when the select option changes, everything in javascript executes except for the append. Nothing shows up in the div. Is there a different way to add html element to a div in jquery under cordova 2.2.0 in iOS?
Thanks in advance,
José
With jquery you can refresh a div.
This is a good example:
<script>
var auto_refresh = setInterval(
function()
{
$('#loaddiv').fadeOut('slow').load('reload.php').fadeIn("slow");
}, 20000);
</script>
and now you need to put the div in the body section of your page
<div id="loaddiv">
</div>
from http://designgala.com/how-to-refresh-div-using-jquery/
and there is another example here:
refresh div with jquery
The first example is useful when you need to load a script and refresh and the second one is useful when you need to make a change, e.g. append html and then refresh as in your case.

jQuery UI tabs: How do I load a specific element from a different page?

I have jQuery UI tabs set up, but a problem that I'm having with links to different pages is that they load all contents of the page into the tab. This includes the footer, header, and other navbars that I don't want in the tab. What if I would only like to load a single ID from that page?
My tabs are set up this way:
<div id="mytabs">
<ul>
<li>Awesome page</li>
<li>Foo</li>
</ul>
</div>
Nothing much going on in the jQuery...
$(function() {
$( "#mytabs" ).tabs();
});
Let's say this is the html of "awesomepage" (that the first link targets):
<html>
<head>
<title>awesome page</title>
</head>
<body>
<div id="header">bla</div>
<div id="awesomeness">awesomeness!</div>
<div id="footer">fdsfd</div>
</body>
</html>
...And I only want the tab to load #awesomeness from the page. How would I go about doing this? I've read into some guides that do that by adding a data-target="#youridhere" attribute to the HTML, but I'm still confused on how to implement the javascript. It seems like this is a convenient solution, as I won't be targeting the same ID in every page. Any clues on how to get the javascript working?
Thanks in advance!
The function that allow to load partial code of the response is the $.load() function.
Unfortunately, the tabs() feature does not use this function but use $.ajax instead.
You can try this solution:
You can try to stop the default processing on the beforeLoad callback and manage your ajax call with the $.load() method.
(base on the 1.9 documentation, you may should adapt)
$('#tabs').tabs({
// Callback run when selecting a tab
beforeLoad: function(event, ui) {
// If the panel is already populated do nothing
if (ui.panel.children().size() > 0)
return false;
// Make your own ajax load (with fragment feature)
ui.panel.load(ui.tab.attr('href') + ' #yourFragment');
// stop the default process (default ajax call should not be launched)
return false;
});
NOTICE: I'm not sure about extracting the URL with ui.tab.attr('href'), check before what object is ui.tab, but it should be easy to retrieve the href parameter.
Good luck
Got the solution :) Using one of the answers as a reference point, the tabs can now load a single element specified in the data-target attribute. Here is the modified version:
$(function() {
$('#tabs').tabs(
{
beforeLoad: function(event, ui) {
if (ui.panel.children().size() > 0)
return false;
ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'));
return false;
}
});
});

Resources