jQuery Fullcalendar: trigger a "create" event using Capybara - capybara

I want to trigger a "create" event in jQuery Fullcalendar using Capybara, but I don't know which element to click. I'm not sure whether this is possible with Capybara anyway...

I've created a demo where if a user clicks on a calendar day a new calendar event is created.
See the dayclick callback code:
dayClick: function(date, allDay, jsEvent, view) {
if (allDay) {
alert('Clicked on the entire day: ' + date);
}else{
alert('Clicked on the slot: ' + date);
}
// change the day's background to highlight the fact that its been clicked
$(this).css('background-color', 'red');
// Create a new event for the day that was clicked
var myEvent = {
title:"my new event",
allDay: true,
start: date,
end: date
};
cal.fullCalendar( 'renderEvent', myEvent );
}
You can then click on a date in jQuery Fullcalendar (which will trigger the creation of a new event when the above code is in place) using Capybara as follows:
page.find(:css, "td[data-date='2013-11-06']").click()
Note that you'll need to tailor the CSS to choose exactly which FullCalendar day (i.e. TD element) to click, but this is just an example.
See the Caybara documentation here for how to do this.

Related

JQM registering same even multiple times on same object

I'm building a test mobile app using a multi-page template but JQM is incrementally registering the same event on the same object each time I'm navigating from the main page to the search page.
If I'm on the main page and navigate to the search page, the first time 1 onclick event attached to my "li a"'s within the UL but if I go back to the main page again using the standard JQM back button and click search page again there are 2 events exactly the same registered on the each "li a" with in the UL. If I do it a third time there are 3, and so on...
Relevant Search Page Markup:
<div id="searchResults">
<ul id="catResult" class="ui-listview" data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b">
<li data-role="listdivider" data-theme="b">Search Categories</li>
</ul>
</div>
JQM Code for search page:
$('body').on('pagebeforeshow', '#searchPage', function(event){ // check if page is shown then execute code
setScrollBar("show");
buildCategoryList();
setListMenuHeight(".ui-2col-layout .ui-2column-grid .ui-block-a", wHeight);
// This event register is being registered multiple times
$('#catList').on('click', 'li a', function(){
var href = $(this).attr('href');
var id = href.split('=');
console.log('spLoadCategoryResults('+id[1]+')');
spLoadCategoryResults(id[1]); // return results from database
});
$("[data-rel=back]").click(function(){
// removes appended elements from the DOM is they exist
cleanPage(['#catResult li','#locationMap #mapCanvas','#searchResults #spResult']);
});
// DEBUG - shows how many times the event is registered
var data = jQuery._data( catList, "events" );
console.log(data);
});
Debug results:
click
[Object { type="click", origType="click", guid=306, more...}, Object { type="click", origType="click", guid=469, more...}, Object { type="click", origType="click", guid=537, more...}]
0
Object { type="click", origType="click", guid=306, more...}
1
Object { type="click", origType="click", guid=469, more...}
2
Object { type="click", origType="click", guid=537, more...}
delegateCount
3
remove
[Object { type="remove", origType="remove", guid=210, more...}]
Each of these are registered on the "li a".
I think it has to do with this code. You are attaching another click event to the anchor items every time you navigate to the search page.
Here is jsfiddle to demonstrate http://jsfiddle.net/d2Jzb/
// This event register is being registered multiple times
$('#catList').on('click', 'li a', function(){
var href = $(this).attr('href');
var id = href.split('=');
console.log('spLoadCategoryResults('+id[1]+')');
spLoadCategoryResults(id[1]); // return results from database
});
That click event appears to be independent from anything happening in the pagebeforeshow event. Just take the event declaration out of the pagebeforeshow event declaration.

jQuery UI autocomplete select event not working with mouse click

I have a list of links, and I have this search box #reportname. When the user types in the search box, autocomplete will show the text of the links in a list.
<div class="inline">
<div class="span-10">
<label for="reportname">Report Name</label>
<input type="text" name="reportname" id="reportname" />
</div>
<div class="span-10 last">
<button type="button" id="reportfind">Select</button>
</div>
</div>
The user can then use the keyboard arrow to select one of the text, and when he press ENTER, browser will go to the address of the link. So far so good.
<script type="text/javascript">
$(document).ready(function () {
$("#reportname").autocomplete({
source: $.map($("a.large"), function (a) { return a.text }),
select: function () { $("#reportfind").click() }
})
$("#reportfind").click(function () {
var reportname = $("#reportname")[0].value
var thelinks = $('a.large:contains("' + reportname + '")').filter(
function (i) { return (this.text === reportname) })
window.location = thelinks[0].href
})
});
</script>
The issue is when the user types, autocomplete shows a list, and then the user use the mouse to click one of the result. With keyboard navigation, the content of the search box is changed, but if the user clicks one of the options, the search box is not modified and the select event is immediately triggered.
How can I make the script work with keyboard selection and mouse selection? How can I differentiate between select events that are triggered by keyboard with the ones triggered by mouse?
To your 2nd question: "How can I differentiate between select events that are triggered by keyboard with the ones triggered by mouse?"
The event object in the jQuery UI events would include a .originalEvent, the original event it wrapped. It could have been wrapped multiple times though, such as in the case of Autocomplete widget. So, you need to trace up the tree to get the original event object, then you can check for the event type:
$("#reportname").autocomplete({
select: function(event, ui) {
var origEvent = event;
while (origEvent.originalEvent !== undefined)
origEvent = origEvent.originalEvent;
if (origEvent.type == 'keydown')
$("#reportfind").click();
},
...
});
Thanks to #William Niu and firebug, I found that the select event parameter 'ui' contains the complete selected value: ui.item.value. So instead of depending on jquery UI to change the text of the textbox, which didn't happen if the user clicks with mouse, I just pick up the selected value from 'ui':
$("#reportname").autocomplete({
select: function (event, ui) {
var reportname = ui.item.value
var thelinks = $('a.large:contains("' + reportname + '")').filter(
function (i) { return (this.text === reportname) })
window.location = thelinks[0].href
};
})
I tested it in all version of IE (inlcuding 9) and always ended up with an empty input-control after I selected the item using the mouse. This caused some headaches. I even went down to the source code of jQuery UI to see what happens there but didn’t find any hints either.
We can do this by setting a timeout, which internally queues an event in the javascript-engine of IE. Because it is guaranteed, that this timeout-event will be queued after the focus event (this has already been triggered before by IE itself).
select: function (event, ui) {
var label = ui.item.label;
var value = ui.item.value;
$this = $(this);
setTimeout(function () {
$('#txtBoxRole').val(value);
}, 1);
},
Had the same issue / problem.
Jquery: 1.11.1
UI: 1.11.0
Question: Do you use bassistance jquery validte plugin simultanously?
If positive: update this to a newest version or just disable it for tests.
I updated from 1.5.5 to 1.13.0
Helped for me. Good luck!
I recently encountered the exact same problem (autocomplete items not clickable, keyboard events working).
Turned out that in my case the answer was not at all JS related. The autocomplete UI was not clickable simply because it was lacking an appropriate value for the z-index CSS property.
.ui-autocomplete {
z-index: 99999; /* adjust this value */
}
That did the trick.
This may be a bit farshot, but I had a similar situation where selecting an autocomplete value left the input field empty. The answer was to ignore the "change" events (as those were handled by default) and replace them with binds to "autocompletechange" events.
The "change" event gets triggered before the value from autocomplete is in the field => the field had "empty" value when handling the normal "change" event.
// ignore the "change" event for the field
var item = $("#"+id); // JQuery for getting the element
item.bind("autocompletechange", function(event, ui) { [call your handler function here] }
I was facing a similar problem. I wanted to submit the form when the user clicked on an option. But the form got submitted even before the value of the input could be set. Hence on the server side the controller got a null value.
I solved it using a modified version of William Niu's answer.
Check this post - https://stackoverflow.com/a/19781850/1565521
I had the same issue, mouse click was not selecting the item which was clicked.My code was supposed to make an ajax call to fetch the data as per the selection item from autocomplete source.
Previous code: mouse click not working.
select: function(event, ui) {
event.preventDefault();
for(i= 0; i< customer.length; i++)
if(document.getElementById('inputBox').value == customer[i].name)
{
$.ajax({
call
})
Changed code :mouse click working
select: function(event, ui) {
// event.preventDefault();
for(i= 0; i< customer.length; i++)
// if(document.getElementById('inputBox').value == customer[i].fields.name)
if(ui.item.value == customer[i].name)
{
$.ajax({
call
})
After inspecting the code in the developer tools console, I noticed there were two list items added. I removed the pairing <li></li> from my response code and oh yeah, the links worked
I also added this function as the click event:
$("#main-search").result(function ()
{
$("#main-search").val("redirecting...."), window.location.href = $("#main-search").attr("href").match(/page=([0-9]+)/)[1];
})
This works and you can test it here: Search for the term dress -->

jQuery ui - datepicker prevent refresh onSelect

I'm using jQuery ui Datepicker to display a yearly inline calendar full of "special dates" (with colors).
This is to allow users to batch special dates by selecting a range and some other details.
$('#calendar').datepicker({
...
, onSelect: function (selectedDate, inst) {
$('.date_pick').toggleClass('focused');
if ($('.date_pick.end').hasClass('focused')) {
$('.date_pick.end').val('');
}
# inst.preventDefault() ? <- not a function
# inst.stopPropagation() ? <- not a function
# return (false) ? <- calendar refreshes anyway
}
...
});
I'm also using qtip to show the details on each date
My problem is when I click on the calendar, it reloads itself entirely, so I loose my qtips.
I'd prefer not to use live() with qtip because I don't like the behavior.
I'd also prefer that the calendar not refresh each time I click on it (but this does not seem possible anyway) but I would probably no longer be able to highlight my selection anymore.
Do you have a suggestion for my problems ?
I was having a similar problem. I was adding custom buttons to the bottom of the datepicker (using $(id).append), but when I would select a date the datepicker would refresh and destroy them.
This is the date selection function for the datepicker in the jquery-ui library:
_selectDate: function(id, dateStr) {
...
if (onSelect)
onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
...
if (inst.inline)
this._updateDatepicker(inst);
...
},
As you can see, the function first calls the onSelect event, and then calls _updateDatepicker (which is what redraws the form) if inst.inline is true.
This is my workaround to prevent the form from refreshing while maintaining the selection functionality:
$("#cal_id").datepicker({
onSelect: function(date, inst){
//This is the important line.
//Setting this to false prevents the redraw.
inst.inline = false;
//The remainder of the function simply preserves the
//highlighting functionality without completely redrawing.
//This removes any existing selection styling.
$(".ui-datepicker-calendar .ui-datepicker-current-day").removeClass("ui-datepicker-current-day").children().removeClass("ui-state-active");
//This finds the selected link and styles it accordingly.
//You can probably change the selectors, depending on your layout.
$(".ui-datepicker-calendar TBODY A").each(function(){
if ($(this).text() == inst.selectedDay) {
$(this).addClass("ui-state-active");
$(this).parent().addClass("ui-datepicker-current-day");
}
});
}
});
setting inst.inline to false inside the onselect won't work.
instead try something like
onSelect: function() {
$(this).data('datepicker').inline = true;
},
onClose: function() {
$(this).data('datepicker').inline = false;
}
I have almost the same problem, like some other people, I have some kind of a solution.... but it's not fair:
$('#calendar').datepicker({
...,
onSelect: function (selectedDate, inst)
{
myFunction(selectedDate, inst);
}
});
function myFunction(selectedDate, inst)
{
$('.date_pick').toggleClass('focused');
if ($('.date_pick.end').hasClass('focused')) {
$('.date_pick.end').val('');
}
inst.preventDefault(); # aa; works too, but writing aa; is going too far xD
}
It is not perfect, but works... I'll try to make it works just fine, till then...
EDIT: Solved adding:
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" rel="stylesheet" type="text/css"/>
If you just want to select a single day then you have to specify the Month and the Year in JQuery:
$(".ui-datepicker-calendar TBODY [data-month='"+inst.selectedMonth+"'][data-year='"+inst.selectedYear+"'] A").each(function(){
In the case of having some datepickers on the page Yozomiri example will fail. You should do:
onSelect: function(date, inst){
//This is the important line.
//Setting this to false prevents the redraw.
inst.inline = false;
//The remainder of the function simply preserves the
//highlighting functionality without completely redrawing.
//This removes any existing selection styling.
$(this).find(".ui-datepicker-calendar .ui-datepicker-current-day").removeClass("ui-datepicker-current-day").children().removeClass("ui-state-active");
//This finds the selected link and styles it accordingly.
//You can probably change the selectors, depending on your layout.
$(this).find(".ui-datepicker-calendar TBODY td").each(function(){
if ( $(this).find('a').text() == inst.selectedDay && $(this).data('month') == inst.selectedMonth ) {
$(this).find('a').addClass("ui-state-active");
$(this).addClass("ui-datepicker-current-day");
}
});
}
https://jsfiddle.net/g2bgbdne/3/

How can I get the JqueryUI datepicker show "Today" in the input box

When the user selects today in the datepicker, I want the associated input box to show the word "Today".
Is there any reasonable way to accomplish this?
You could attach a .change() handler to the input that checks the selected date when the value is changed, and updates the value with "Today" if necessary.
Try it out: http://jsfiddle.net/gn4Fj/
$('input').datepicker()
.change(function() {
var today = new Date().getDate();
var val = new Date(this.value).getDate();
if(today === val)
this.value = "Today";
});
Are you looking the showButtonPanel: true option?

jquery tabs back button

This post talks about the problem that jQuery tabs is still having with the back button. What the customer needs is fairly simple - when they press back, they want to go back to what they were just looking at. But jQuery tabs loads the first tab, not the one that was selected when the user left the page.
I've read the accompanying link and it says "It is planned and Klaus is working on it whenever he finds the time."
Has anyone solved the back button problem with jQuery UI tabs?
Using the solution to the history problem easement posted, a dirty fix for the back button problem would be to periodically check the location.hash to see if it has changed, and if it has, fire the click event of the appropriate link.
For example, using the zachstronaut.com updated jQuery Tabs Demo, you could add this to the $(document).ready callback, and it would effectively enable the back button to switch tabs, with no more than a 500ms delay:
j_last_known_hash = location.hash;
window.setInterval(function() {
if(j_last_known_hash != location.hash) {
$('#tabs ul li a[href="'+ location.hash +'"]').click();
j_last_known_hash = location.hash;
}
}, 500);
Have you tired updating the browsers location as you switch tabs?
http://www.zachstronaut.com/posts/2009/06/08/jquery-ui-tabs-fix.html
if you had a class on your tab container that was tabContainer, to update the url when user clicks a tab, you could do this:
$(".tabContainer").tabs({
select: function(event, ui) {
window.location.hash = ui.tab.hash;
}
});
then, instead of firing click, you could use the tabs select method if you have some getIndexForHash method that can return the right tab number for the selected hash value:
var j_last_known_hash = location.hash;
window.setInterval(function() {
var newHash = location.hash;
if(j_last_known_hash != newHash) {
var index = getIndexForHash(newHash);
$('.tabContainer').tabs("select",index);
j_last_known_hash = newHash;
}
}, 100);
window.onhashchange = function () {
const $index = $('a[href="' + location.hash + '"]').parent().index();
$('.tabContainer').tabs('option', 'active', $index);
}

Resources