jQuery $(document).ready() issue - jQuery 1.7.2 - jquery-ui

I have a page on which I am loading a select tag with options that I am getting from an ajax call to a service. It is working just fine and loading the select tag correctly. I only want this loading to happen once when the user first arrives at the page so I put the call to the function that does this inside the $(document).ready(function call. The problem that I am seeing is that when the user selects one of the options and then clicks a button under certain circumstances I pop a dialog (jQuery UI) telling them they need to take a certain action. The first time this happen and only the first time the selected option is getting reset somehow to the first option in the list. I ran in debug many times and discovered that if this is the first time on the page the selector is loaded on arrival at the page as is expected but if the dialog gets popped it is loaded again - only the first time - after that if the dialog gets popped the reload does not occur and all is well. The abbreviated code:
$(document).ready(function () {
$.fn.LoadStuff();
});
jQuery.fn.LoadStuff = function () {
//load up the select tag with options
};
LoadStuff does not get called anywhere else. selOffers is the select tag and dvConflict is the dialog. They are not sharing a common parent div.
<select id="selOffers"></select>
<div id="dvConflict"><div id="dvConflictMsg" /></div>
jQuery for the dialog:
var optSave = {
width: 400,
modal: true,
resizable: false,
draggable: false,
closeOnEscape: true,
zIndex: 1320,
buttons: [
{
text: 'Ok',
click: function () {
$(this).dialog('close');
}
}
]
}
$(".ui-dialog-titlebar").hide(); //Hides the title
$('#dvConflict').css('background', 'none'); //Takes out our custom background
$('#dvConflict').dialog(optSave);

EDIT: Two things
Use $.LoadStuff = function () { } instead of $.fn.LoadStuff = function () {...}. The first is to be called at any context via $.LoadStuff();. The latter is to be used on an element-selection, like $("div.to-load").LoadStuff();.
$(document).ready is fired every time the DOM finishes loading. In some AJAX calls, you could be reloading parts of your DOM, or an internal frame (I don't know, though I don't have your code).
The following code sample will help you bypass the problem:
var first = true;
$(document).ready(function () {
if (first) $.LoadStufF();
...
first = false;
}
When opening a dialog, make sure there are no <script> tags inside the dialog-wrapped element. Say you have the code line:
$('#dialoged').dialog({ ... });
So a bad practice is to have:
<div id="dialoged">
<script>
var first = true;
$(document).ready(function () {
if (first) $.LoadStufF();
...
first = false;
}
</script>
</div>

Related

JQuery mobile persistent navbar (outside page div)

I've got a navbar outside the page div in a footer (it is on every page) I tried to do a simple fix for the persistent active state of the navbar It worked for the tabs on one of the pages but does not seem to work for this.
Actually, everything works except for some reason ui-btn-active does not get added
Here is the code
$(document).one( "pageinit", function() {
$('div[data-role="footer"] [data-role="navbar"] a').click(function(e) {
$(this).html("abc");
$('div[data-role="footer"] [data-role="navbar"] .ui-btn-active').removeClass('ui-btn-active ui-state-persist');
$(this).addClass('ui-btn-active ui-state-persist');
});
});
The html of the anchor changes, ui-state-persist gets added on the last line but ui-btn-active just does not get added for some reason...
Ok it seems jquery mobile automatically removes ui-btn-active on page transition, even if your navbar is out of page div (which I find kind of lame...) It seems it does this on or after pagebeforeshow, because this did not work with that event... so I just used pageshow instead.
Here is the working code:
var navbar;
$(document).on("pageshow", function() {
if(navbar) {
$(navbar).addClass('ui-btn-active')
}
});
$(document).one( "pageinit", function() {
$('div[data-role="footer"] [data-role="navbar"] a').click(function() {
navbar = $(this);
});
});

How to disable toolbar buttons during page transition?

I am using an external toolbar in a jQuery Mobile site I'm working on. I initialize it like so:
$(document).ready(function () {
$("[data-role='header'], [data-role='footer']").toolbar();
});
I have a couple of buttons in the toolbar and want to disable them during page transitions so users don't click them multiple times which seems to get the framework into a weird state. My first attempt has been to listen for the pagebeforeshow and pageshow events to programmatically disable and enable the buttons:
$(function() {
$("[data-role='header'], [data-role='footer']").toolbar({
create: function (event, ui) {
$(document).on('pagebeforeshow', function () {
$('#page-header .ui-btn').button('disable');
});
$(document).on('pageshow', function () {
$('#page-header .ui-btn').button('enable');
});
}
});
});
I have the code nested inside like that because I don't want to register the handlers until the toolbar has been initialized. However, I'm running into a separate problem:
Uncaught Error: cannot call methods on button prior to initialization; attempted to call method 'disable'
Since I'm not explicitly initializing the buttons myself, I'm not sure I understand how / where I can wait for them to be initialized.
Is there a better approach to this, and does anyone have any suggestions to get this working?
Use .button() on input with type button, reset and submit. For anchor or button tag you need to add / remove ui-state-disabled class.
$(document).on("pagecontainerbeforehide", function () {
$('#page-header .ui-btn').addClass('ui-state-disabled');
});
$(document).on("pagecontainershow", function () {
$('#page-header .ui-btn').removeClass('ui-state-disabled');
});
Demo

Reusable JQuery UI dialog does not work from AngularJS partial

I am trying to use JQuery UI Dialog from AngularJS partial HTML pages.
The problem is that the dialog works fine, and even can be opened multiple types, from a view - as long as the view is opened for the 1st time.
Yet when navigating to another view, and then back to the view using the dialog - an attempt to open the dialog works as if there would be 2 dialogs to show, not one. Browser "refresh" of the view URL makes the problem disappear, till the next back-and-forth navigation.
I put a test application (not integrated with real back end) to show the problem:
Navigate to:
http://socialtodow.cloudapp.net/app/tdg_test/#!/new
Click on red "Get Advice" button: the dialog shows up OK, and can be closed with Esc.
Now, please navigate to http://socialtodow.cloudapp.net/app/tdg_test/#!/search and then back to http://socialtodow.cloudapp.net/app/tdg_test/#!/new
Click red "Get Advice". You get 2 dialogs, one on top of another - the buggy behavior I am talking about.
The relevant directive code:
.directive('advice', [function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var self = $(element),
adviceDialog = $(attrs.advice);
adviceDialog.dialog({
width: 260,
height: 405,
autoOpen: false,
modal: true,
dialogClass: "advice_dialog"
});
self.click(function () {
adviceDialog.dialog('open');
});
adviceDialog.find('button').click(function() {
adviceDialog.dialog('close');
});
}
}
}])
Checking
adviceDialog.is('dialog'))
does not seem to work - it's always true.
I am looking for a fix (not infrastructure replacement).
Any hint will be appreciated.
Max.
This is the modification to the directive, found by a developer wokring on the project, that seems to resolve the issue:
.directive('advice', [function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var self = $(element),
adviceDialog = $(attrs.advice);
self.click(function () {
adviceDialog.dialog({
width: 260,
height: 405,
autoOpen: false,
modal: true,
dialogClass: "advice_dialog",
close: function() {
adviceDialog.dialog('destroy');
}
});
adviceDialog.dialog('open');
});
adviceDialog.find('button').click(function() {
adviceDialog.dialog('close');
});
}
}
}])
Note: the URl mentioned in the original question may not be operational - sorry for that.
Max.

AJAX jQuery UI modal dialog

Edited to add the solution suggested by #alistair-laing.)
After reading this post reply by #jek, I could make multiple links on my page that would pass an id variable through the URL so that the content of the dialog could be loaded in on the fly. However, I really want this to be a modal dialog:
(edited to include the fix; nb: the original script was in the post linked to above, all I did was break it)
$(function (){
$('a.ajax').click(function() {
var url = this.href;
var dialog = $('<div style="display:none"></div>')
.appendTo('body')
// load remote content
dialog.load(
url,
{},
function (responseText, textStatus, XMLHttpRequest) {
dialog.dialog({
modal: true,
width: 500
});
}
);
//prevent the browser to follow the link
return false;
});
});
quiet a few things. Try move the content from your first .dialog into your second .dialog which you call as part of the the .load callback. What youare doing is creating dialog then injecting content into it only to call it again. You could also remove the the autoOpen so that the dialog opens with the content.

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 -->

Resources