Javascript Object Ready? - javascript

I have a function that uses AJAX to get a list of items from a php script and can pass a filter. The user can set the filter by selecting from a drop down box on the page.
The problem i'm having is I am calling the function during page load to fill the form with default data and the function is just quitting silently when I try to read the filter text from the drop down box. It works fine after page load, but not during. However the function works fine if I put an alert("test") before it tries to read from the drop down so i'm assuming the drop down just hasnt finished loading properly when the function is called. How can I test to see if its safe to read so I can provide my own default value if it isnt safe?
Code Snippit:
var ProdCat = document.getElementById("prod_cat2");
var Filter = "All Products";
Filter = ProdCat.options[ProdCat.selectedIndex].text;
alert("test");
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();
So the above code is in a function called onLoad and the alert doesnt trigger at all. But if I comment out the Filter = ProdCat.(etc) line then the alert DOES trigger. Alert ALWAYS triggers even with that line AFTER page load. Looking for a solution to keep the one function both during load and after, thanks!

It sounds like the script is above the markup for the ProdCat select box in your HTML file. If so, the simplest thing is to simply move the script tag containing it down so that it's underneath the markup for the select box. The select box won't exist until its markup is parsed, but it will exists immediately once it is.
How can I test to see if its safe to read so I can provide my own default value if it isnt safe?
If you don't want to relocate the script (or you run into this in other situations where that doesn't make sense), you can test whether you got the element:
if (ProdCat) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}
If you like, you can even have it retry:
var ProdCat;
var Filter = "All Products";
function startAjax() {
ProdCat = document.getElementById("prod_cat2");
if (ProdCat) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();
else {
setTimeout(startAjax, 100); // 1/10th of a second later, try again
}
}
startAjax();
Update: In a comment, you said:
The error is: ProdCat.options[ProdCat.selectedIndex] is undefined
Okay, so you have the element, but there's nothing selected (yet). So the test would be:
if (ProdCat && // We have the select
ProdCat.selectedIndex >= 0 && // and it has a selected value
ProdCat.options[ProdCat.selectedIndex] // (Paranoia) and that option exists
) {
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}

Check if the element could be found. If not, the default filter 'All Products' is used.
var ProdCat = document.getElementById("prod_cat2");
var Filter = "All Products";
if (ProdCat)
{
Filter = ProdCat.options[ProdCat.selectedIndex].text;
}
alert("test");
xr2.open("GET","hs_shop.php?ajaxreq&r=prodlist&p1=" + Filter, true);
xr2.send();

Related

Angular JS form running only first time

I am at the very beginning with my Angular learning and I implemented this form:
http://codepen.io/jgrecule/pen/WxgqqO
What it is supposed to do is very basic: it consumes Flickr public JSONP feed as per Flicker specs https://www.flickr.com/services/feeds/docs/photos_public/ and renders the retrieved pictures thumbnails
The form I implemented has a submit button as well as a reset one. My problems I am trying too find solutions in the order of their importance are:
The very first time when you typing tags everything works but when u try to submit the request again by either adding a new tag or an user Id or anything it no longer works. I can see this warning in the logs but I have no idea what is causing it WARNING: Tried to load angular more than once.
The reset only works for the thumbnails but not for the other controls in my page
I would like to find a way to show an error message when the user pushes on the search flicker button and both tags and user ids input fields are empty. I tried to implement a custom directive but it was no way to get it working.
Thank you in advance for your inputs.
You are loading Angular more than once.
Your resetForm function doesn't reset the form at all. It just calls $setValidity on two of the form elements. It looks like it does try and reset the form in another part of your code with
document.getElementById("searchCriteriaTags").innerHTML = "";
document.getElementById("searchCriteriaIds").innerHTML = "";
document.getElementById("images").innerHTML = "";
which means you are modifying the DOM directly, about which see point 4.
You can add a simple check as to whether $scope.form.tags === '' and so the same for the other fields in your form.
Having addressed your 3 points, I'm afraid to say your code has bigger problems. You are modifying the DOM directly all over the place and you have a lot of duplicate code, plus lots of very complex conditionals.
EDIT 1 in response to OP's comment:
The Angular way of clearing form fields would be to simply clear the scope objects that the form fields are bound to. In other words it is as simple as doing something like:
$scope.tags = [] // for arrays
$scope.name = '' // for strings
Because the form fields are bound to these scope variables through the ng-model directive, changing the variables will also change the form fields.
Setting an error message when two fields are empty you can do like this:
$scope.checkFields = function(field1, field2) {
var oneEmpty = field1 === '';
var twoEmpty = field2 === '';
if (oneEmpty && twoEmpty) {
// call the failure message here
}
}
EDIT 2 in response comments:
Firstly good to see that your code is looking a lot cleaner. Secondly, the reason it fails is because in your search function you set the search fields to null, eg searchCriteria.tags = null;. You should set them to empty strings instead: searchCriteria.tags = '';.
I don't know what the purpose of checkFields is so I don't know where you want to place it. If you want to show an error message if the fields are empty then I'd say have checkFields() return a boolean and use ng-show to display the error div if checkFields() === false.
HTML:
<div ng-show="checkFields() === false">Fields can't be empty</div>
JS:
$scope.checkFields = function(field1, field2) {
var oneEmpty = field1 === '';
var twoEmpty = field2 === '';
return (oneEmpty || twoEmpty);
}

select2 - get current search text

I'm using select2 and fetching available options from the server with this query function
var recipientsTimeout;
this.loadRecipients = function (query) {
clearTimeout(recipientsTimeout);
recipientsTimeout = setTimeout(function(){
data.transmitRequest('lookupcontacts', { search: query.term }, function(resp){
query.callback({ results: resp.items });
});
}, 500);
};
It uses our own ajax layer, and delays searching until the user stops typing, and it works fine. The only small issue is that if the user types some text, then immediately backspaces over it, my last timeout will still fire, and an ajax request will be fired, and ignored. This doesn't cause any problems, but it's less than optimal.
Is there any (preferably non-brittle) way to fetch whatever the current text is? It seems as though the query object sent in has an element property, which is a jQuery wrapper of the original hidden input I set select2 up with, but there's no direct way I can see to get the actual textbox that the user is typing in. Obviously I could inspect it and easily figure out the dom pattern and build up a selector from the hidden element back to what the user is typing in, but I really hate doing that, since the specific layout could easily change in a future version.
So what is the best way to get the currently entered text, so I could do a quick check on it when the setTimeout expires, and I'm about to run my ajax request.
I'm using 4.0.3 and the way I did it is this:
$("#mySelect2").data("select2").dropdown.$search.val()
The hidden input element (where you initialize select2 on) gets a data property select2, which contains references to all elements, that are used by select2. So you could do something like this:
var hiddenInputSelector = '#e1',
select2 = $(hiddenInputSelector).data('select2'),
searchInput = select2.search;
if($(searchInput).val() === '')
clearTimeout(recipientsTimeout);
This is not in the docs though, so it might change in the future.
In select2 version 4.0.3 this works for me, whereas the others did not:
$('.select2-search__field')[0].value;
I do something like this to get the current search term:
list.data("select2").search[0].value;

Disable Inputs on Dropdown Change

So I'm working on a webform right now and I need to disable all forms of input once one has a specific value. Is there an easy way to handle as soon as that dropdown gets to that value?
Currently I'm doing this:
setInterval('check()', 5000);
function check() {
// Disable all fields if the answer was no.
if ($("#has_contract").val() == 0) {
disable();
}
function disable() {
$("#inputs *").prop('disabled', true);
alert("There is no contract, please get a contract.");
}
has_contract is my element, and #inputs contains all of the inputs I would like to disable if #has_contract's value is 0.**
But this isn't ideal.
Is there a better way to do this rather than constantly checking every X amount of seconds?
Instead of checking for the value every 5 seconds, you can check the value on change.
// collect elements
var $hasContract = $("#has_contract");
var $inputs = $("#inputs input");
// on change, check the input
$hasContract.on('change', checkForm);
// Checks the hasContract input for a value
// of 0. If it does, disable the form.
function checkForm() {
if($hasContract.val() == 0) {
$inputs.attr('disabled', true);
}
}
Also, when you use setTimeout, or setInterval you don't have to use a string. Javascript supports passing functions as variables. See below.
// Do NOT do this
setInterval('check()', 5000);
// Do this instead
setInterval(check, 5000);
// or this
setInterval(function() {
//preform the check...
}, 5000);
I'm not completely certain that I understand your requirements, but would this work for you?
The below assumes that #has_contract is a <select> element:
$("#has_contract").change(function() {
if ($("#has_contract").val() == 0) disable();
});
First off, you should cache the elements as a variable and then run the function against that variable.
var myInputs
$(document).ready(function(){
myInputs = $("#inputs input"); // or '#inputs *' if you're excited about the asterix
});
Second thing, if I'm reading your setup correctly, you're going to pop an alert box every 5 seconds until the user has selected 'yes' to the contract. That will get QUITE annoying and they probably won't want to open a contract with you after that.
Without actually seeing your page, I'd imagine a better solution would be to check for the contract=yes when the click a submit button of some sort on the page.
$('#mySubmitButton').click(function(){
if ($("#has_contract").val() == 0) {
disable();
}
});
But maybe go one step further, what you really want to do is give them access to the form once they agree to the contract. So you should have the form disabled by default (coded into the html that everything is disabled), and attach a function to the 'yes' button that enables the form. Additionally, you can attach a function to the 'no' button that re-disables it, if they had previously clicked 'yes'.
$('#myYesBtn').click(function(){
myInputs.prop('disabled', false);
});
$('#myNoBtn').click(function(){
myInputs.prop('disabled', true);
});

Form - update "reset" button to new data

I'm using mootools in 1 of my projects. I'm working on easy to be customised menu based on sortables.
So here's the issue - I've got the form which contains menu node informations. Form is updated with JS whenever user chooses different node (form is populated with new data). Problem is that "reset" button obviously "remembers" the initial data, so whenever user clicks it, it loads initial data form.
Is there anyway to update the "default" form status, whenever i load new data? (ofc i could write piece of code which do whatever i need, but if there is some simplier solution which allows default "reset" button to work with new data would be much less work to use it :))
Thanks in advance for help
i cant think of anything else except getting a new source through ajax with data prepopulated and replace the innerhtml hence replacing the form itself.
you can use something like toQueryString to serialize the form and then reverse it based upon the mootools-more's String.parseQueryString():
(function() {
Element.implement({
saveFormState: function() {
if (this.get('tag') !== 'form')
return;
this.store("defaults", this.toQueryString());
},
restoreFormState: function() {
if (this.get('tag') !== 'form')
return;
var vals = this.retrieve("defaults");
if (!vals.length)
return;
var self = this;
Object.each(vals.parseQueryString(vals), function(value, key) {
var el = self.getElement("[name=" + key + "]");
el && el.set('value', value);
});
}
});
})();
var f = document.id('f');
// save default
f.saveFormState();
document.getElement("button").addEvent("click", f.restoreFormState.bind(f));
this ough to cover most cases and you can always save a new defaults state. need to test it somewhat with radios and suchlike, though.
here's a basic fiddle with a save/restore: http://jsfiddle.net/UWTUJ/1/
relevant docs: http://mootools.net/docs/more/Types/String.QueryString (more) and http://mootools.net/docs/core/Element/Element#Element:toQueryString (core)
implied reliance on name attributes on all form elements you want to save/restore.
I have previously created more complex save/restore states that even return field CSS class names, validation messages, etc.

Input Checkboxes not being checked off on page load; but being checked of after using "alert()"

I have a table with a list of 5 items that is dynamically generated using AJAX with a PHP/MySQL backend. Each item has an INPUT Checkbox next to it.
Upon page load, some of the checkboxes must appear "checked" depending on a set of values returned by PHP/MySQL. Thus:
var checked_items = [];
// var checked_items = new Array(); // this is not working either
var GetItemsFromXML;
var SplitItems;
var XMLItemsObj = new Object;
// function...
function DisplayItems() {
CreateRObj(function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
GetItemsFromXML=xmlhttp.responseText; // returns pike delim list
SplitItems = GetItemsFromXML.split("|"); // split at pike
// status - either "all" or "selected"
XMLItemsObj.checkedstatus = SplitItems[0];
// drop last ","
SplitItems[1] = SplitItems[1].substr(0,SplitItems[1].lastIndexOf(","));
// split at comma and pass to variable
checked_items = SplitItems[1].split(",");
}
});
xmlhttp.open("POST","loaditems.php",true);
xmlhttp.send();
}
At this point, the variable "checked_items", contains the values returned by PHP/MySQL.
These values will determine which checkbox is checked off.
I've confirmed that this variable is populated by testing to see if it is empty (""),
undefined, or null.
Now, Once the page loads, the code below loops through all the checkboxes and checks them off depending on the "XMLItemsObj.checkedstatus" status. If status is "selected", then only some are checked off. If status is "all", all checkboxes are supposed to be checked off.
Here's the code that does this:
if (XMLItemsObj.checkedstatus=="selected") {
for (i=0; i < checked_items.length; i++) {
$(":checkbox[value="+checked_items[i]+"]").attr("checked",true);
}
} else if (XMLItemsObj.checkedstatus=="all") {
$("input:checkbox").each(function() {
$("input:checkbox").attr("checked",true);
});
}
Here's where things start getting weird...
The above only seems to work when I use the "alert" function
to check for the values in the "checked_items" variable. It works
when ".checkedstatus" is "all" or when its "selected".
Thus, if I were to use, for example this code:
alert("The values of the checked_items variable are: "+checked_items);
Then, the above code will work perfectly.
However, it doesn't work otherwise. Neither when status is "all", nor
when status is "selected".
I'm at a loss, but my guess it that the variable is either losing its
value, or the event(s) are not being triggered. However, I'm not sure.
Anyone has any ideas? All comments, insights, solutions, and thoughts
are welcome. Thanks in advance!
Here is catch Upon page load, some of the checkboxes must appear "checked" Ensure your script runs when DOM structure of target is created. Then it must work.

Categories

Resources