php / javascript - last character in string is never removed - javascript

<form action='' method='post'>
<input type='text' name='username' onkeyup='findUsers(this.value)'>
<input type='submit' value='Add Member'>
<div id='livesearch'></div>
<script>
function findUsers(str) {
if (str == "") {
return;
} else {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("livesearch").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET","/classes/livemembersearch.php?q="+str,true);
xmlhttp.send();
}
}
</script>
$q = $_GET["q"];
When getting the value in the findUsers function, everything works fine, except when I empty the textfield, it keeps showing the last value before I emptied the field.
Examples:
I type "ffff", it updates, I remove one f at a time, it keeps
updating, until I remove the last f and get an empty field, it just
keeps showing an f as value passed.
I type "hello", it updates, when I remove the entire string at once,
the value passed stays at hello.
I think the function is just not being called when the field is empty.
How would I fix this?

You state within your function:
if (str == "") {
return;
}
This means the function won't complete and the issue you're presenting will indeed happen. I assume you're emptying the livesearch element?
Since document.getElementById("livesearch").innerHTML = xmlhttp.responseText; is to be found in the else statement, it will never be executed.
Then it should be this:
if (str == "") {
document.getElementById("livesearch").innerHTML = "";
}
while leaving the rest as is.
So you empty it when str is empty, but you fill it when the ajax call is made.
p.s. the return; statement within the if statement is redundant. Since the if statement rings true, the else won't be executed either way.
edit: Also note that onkeyup might not trigger on someone copying text in instead of typing it. Although it's unlikely with a username, I thought it'd be a good thing to let you know, just in case.
-- the one that does catch this would be the oninput function.
More information here

Related

How actual parameter can be passed here?

JS function can't be called with passed parameters
I've passed actual parameters from php file to divs with onclick event, it is rendered right on the page, function itself is present, but parameters aren't passed to function call
Formal argument stays like in function definition, it isn't substituted by what was passed to onclick events
http://localhost:8000/sknt1.php?reqStr
Code itself looks like this:
for ($i=0; $i<count($json_a["tarifs"]) ; $i++) {
echo "<div onclick='fun(".$i.")' class='column' style='font-size:20px; width:100%'>
On the page it looks like this (0 through 4):
<div onclick="fun(0)" class="column" style="font-size:20px; width:100%">
<div onclick="fun(1)" class="column" style="font-size:20px; width:100%">
And so on.
fun() is an AJAX call function, it is written to page one time, I cannot embed it in php for loop:
<script type='text/javascript'>
function fun(reqStr) {
var xmlhttp = null;
function AjaxRequest(url){
if(xmlhttp != null){
if(xmlhttp.abort)
xmlhttp.abort();
xmlhttp = null;
};
if(window.XMLHttpRequest) // good browsers
xmlhttp=new XMLHttpRequest();
else if(window.ActiveXObject) // IE
xmlhttp=new ActiveXObject('Microsoft.XMLHTTP');
if(xmlhttp == null)
return null;
xmlhttp.open('GET',url,false);
xmlhttp.send(null);
if(xmlhttp.status >= 200 && xmlhttp.status < 300)// 2xx is good enough
return xmlhttp.responseText;
else
return null;
}
window.history.replaceState({}, '',`/sknt1.php?reqStr`);
var url = '/sknt1.php?reqStr';
var contents = AjaxRequest(url);
if(contents){
document.documentElement.innerHTML = contents;}
}
</script>
I want this Ajax call to substitute variable passed in and replace url for smth. like http://localhost:8000/sknt1.php?0, there's additional php file, it will render new page after manipulating the history, please help
Just make a variable inside the for loop as $iStr = ' " '.$i.' " ' and pass the new variable.
It was a noob question. Obviously I should have concatenated arguments[0], not pass it directly.
Not this /sknt1.php?reqStr, but this /sknt1.php?+reqStr

onClick event - Run a javascript AFTER previous one has finished in the same onClick event

Code looks like this (My PHP server generates this line replacing the %% variables):
<button type="submit" id="buttons" name="add_to_inv" onclick="ServInfo('inv_items','/magagest/index.php','req=add_item&item=%icode% - %idesc%&iqty=%iqty%&iprice=%iprice%&itnum='+trCount('inv_items',false),'','y');ShowFieldTotal('inv_items','iprice','sub-total',2);">+</button>;
I want THIS
ShowFieldTotal('inv_items','iprice','sub-total',2);
to run ONLY when the elements of the first script have been added on my webpage. Basically, it adds an item line in a table and, what I actually want it to do that I can't do, calculate the total of each items once their lines have been added to the table from the first script:
ServInfo('inv_items','/magagest/index.php','req=add_item&item=%icode% - %idesc%&iqty=%iqty%&iprice=%iprice%&itnum='+trCount('inv_items',false),'','y')
Modify your ServInfo function like this.
function ServInfo (args...) {
--- your code ---
....
....
//call ShowFieldTotal when ServInfo() is finished.
ShowFieldTotal(args...);
}
You can make another function which calls the two functions one after another and bind that function to the onclick event.
ControlAltDel's answer makes it simple and easy. I actually added another parameter to my ServInfo which catches a string which it converts to code. Basically, I called the "eval" function to parse the code written in a string I pass to ServInfo. My new onClick event looks like this:
<button type="submit" id="buttons" name="add_to_inv" onclick="ServInfo('inv_items','/magagest/index.php','req=add_item&item=%icode% - %idesc%&iqty=%iqty%&iprice=%iprice%&itnum='+trCount('inv_items',false),'','y','ShowFieldTotal(\'inv_items\',\'iprice\',\'sub-total\',2)');">+</button>
I added the following to my ServInfo code:
// Execute a string if a user defined one
if (exec_string != "") {
eval(exec_string);
}
For the curious, My ServInfo function now looks like this:
// AJAX simple HTTP GET request
function ServInfo(pop_field_id,web_page,params="",form_id="",append_data_to_output = "",exec_string = "") {
var sparams = params;
var swpage = web_page;
var eobj = document.getElementById(pop_field_id);
// Get form field values if a form id is specified
if (form_id != "") {
var efrm = document.getElementById(form_id);
sparams += "&"+GetDivFields(form_id);
}
// If HTML element to populate does not exist, exit
if (typeof(eobj) == "!undefined" || eobj == null) {return;}
if (window.XMLHttpRequest) {
// IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
}
else {
// IE6-
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (append_data_to_output == "y") {
document.getElementById(pop_field_id).innerHTML += this.responseText;
}
if (append_data_to_output == "") {
document.getElementById(pop_field_id).innerHTML = this.responseText;
}
// Execute a string if a user defined one
if (exec_string != "") {
eval(exec_string);
}
}
};
// Add the question mark if there is any parameters to pass
if (sparams != "") {swpage += "?";}
xmlhttp.open("GET",swpage+sparams,true);
xmlhttp.send();
}

xmlhttp.open does not seem to do anything in MVC structure

I'm trying to add an auto-complete function to a text field.
This used to work, but then I switched to an MVC structure and now I can't get it back to work.
PHP/HTML:
echo '<br><br>Add member:<br>'
. '<form method="post"><input type="text" name="username" oninput="findUsers(this.value)" list="livesearch">'
. '<datalist id="livesearch"></datalist>'
. '<input type="submit" value="Add">'
. '</form>';
JavaScript:
<script>
function findUsers(str) {
if (str == "") {
document.getElementById("livesearch").innerHTML = "no suggestions";
xmlhttp.send();
} else {
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp = new XMLHttpRequest();
} else {
// code for IE6, IE5
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
document.getElementById("livesearch").innerHTML = xmlhttp.responseText;
}
};
xmlhttp.open("GET","/user/search/?q="+str,true);
xmlhttp.send();
}
}
</script>
/user/search opens a function called search in the class User in the UserController.php file
class UserController extends Controller
{
public function search()
{
$response = "hello";
echo $response;
}
}
So this should put the "hello" message in the livesearch datalist.
But for some reason just nothing is happening.
If I replace the xmlhttp.open by window.open, the page does load normally and shows the hello message. But that is obviously not what I want.
Figured out the exact problem:
My xmlhttp.responseText is also returning the header of my website, which is already loaded in the MVC structure.
How would I work around this?
Is it an option to just edit the string and get the last part in javascript?
Or are there better solutions?
Used JavaScript to grab the last part of the string (so without the header)
It does what it's supposed to do now, but feels like a pretty "dirty" solution.
Also had to add the <option value=""> tag, which was in my code, but not in my testcode.

same domain xmlhttprequest access denied ie8

I'm fairly new to the world of web development and am trying to read a txt file in internet explorer 8 and compare it to source code of a website to see if they are equal. This is so I can work out if the web page is functioning correctly.
I managed to get the source code with an xmlhttprequest and have tried the same to get the text file (which is in the same domain as my web page) and I am getting an access denied error.
After some research I can see that cross-domain xmlhttprequests won't work but that's not what I'm trying to do so I'm not sure how to proceed.
Having run the same code in Firefox(current version). It will read the file but not the web page!
I don't mind which of the two browsers I end up using but at the moment each does half of what I want it to.
my code is:
function source1(){
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET", "http://website",true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
document.getElementById('textzone').value = xmlhttp.responseText
var inputString = xmlhttp.responseText;
alert(inputString);
comparison(inputString)
}
}
xmlhttp.send(null)
}
function comparison(inputString){
xmlhttp1=new XMLHttpRequest();
xmlhttp1.open("GET", "comparisondoc.txt", false);
xmlhttp1.onreadystatechange=function() {
if (xmlhttp1.readyState==4) {
var compareString = xmlhttp1.responseText;
alert(compareString)
if(inputString==compareString){
alert("Strings are equal");
}
}
}
xmlhttp.send(null)
}
All I need to know is why either the file won't open in ie8, or why the website source code shows up blank (in the alert) in firefox. Any help would be appreciated.
It could be a browser support issue.
Try the following code to initialize your XMLHttpRequest :
function createRequest() {
try {
request = new XMLHttpRequest();
} catch (trymicrosoft) {
try {
request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (othermicrosoft) {
try {
request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (failed) {
request = false;
}
}
}
if (!request)
alert("Error initializing XMLHttpRequest!");
}
Check your comparison function. You should you xmlhttp1 instead of xmlhttp at 2 places
function comparison(inputString){
xmlhttp1=new XMLHttpRequest();
xmlhttp1.open("GET", "comparisondoc.txt", false);
xmlhttp1.onreadystatechange=function() {
if (xmlhttp1.readyState==4) {
<!--alert(xmlhttp1.responseText)-->
var compareString = xmlhttp1.responseText;
alert(compareString)
if(inputString==compareString){
alert("Strings are equal");
}
}
}
xmlhttp1.send(null)
}
Try to add the if(xmlhttp.status == 200) { } stuff. Remember both of these are looping through status' "AND" readystates.
Technically you could be erroring somewhere (I'd rather not speculate on) halting progress to next request or whatever without the status check.
Also you "should" try other request techniques. ie.. xmlhttp.onreadystatechange = function(){itsReady(inputString)}; // we keep this line short and simple calling to another func that contains your status and readystate checks, response stuff, and more func.
On a pretty normal run the Loop looks like:
hi rdySte:1///status 0////////
hi rdySte:2///status 200////////
hi rdySte:3///status 200////////
hi rdySte:4///status 200////////
I ran into a lot of weird issues trying the long onreadystatechange = function (){ ... All stuff..} I successfully run a crazy set of request functionalities using the short onreadystatechange technique.
I noticed at the last minute->
is there a reason why the async flags are different between your funcs? I'd set them all to true unless you have a great reason.
This will work: (to test: 2 pages t1.php contains a num or whatever and t2.txt that has a num in sam dir as the funcs are called in)
function source1(){
var avar = 1;
xmlhttp=new XMLHttpRequest();
xmlhttp.open("GET", "t1.php",true); // shortened f-names for ease of test
xmlhttp.onreadystatechange = function(){jsg_snd(avar)};
xmlhttp.send(null)
}
function jsg_snd(avar){
if (xmlhttp.readyState==4) {
if (xmlhttp.status == 200) {
var inputString = xmlhttp.responseText;
document.getElementById('text_zone').innerHTML = inputString;
document.getElementById('text_zone1').value = inputString;
// alert(inputString);//
comparison(inputString)
}
}
}
function comparison(inputString){
xmlhttp1=new XMLHttpRequest();
xmlhttp1.open("GET", "t2.txt", true);
xmlhttp1.onreadystatechange= function(){jsg_snd1(inputString);};
xmlhttp1.send(null)
}
function jsg_snd1(inputString){
if (xmlhttp1.readyState==4) {
if (xmlhttp1.status == 200) {
var compareString = xmlhttp1.responseText;
//alert(compareString)
if(inputString==compareString){
//alert("Strings are equal");
document.getElementById('text_zone').innerHTML += "; Ok "+inputString+"=="+compareString+"";
}
}
}
}
Now the html in your body should look like:
<tt id = 'text_go' onMouseUp="source1();" >Go!</tt>
<tt id = 'text_zone' onMouseUp="text_zone.innerHTML = '';" >Click to clear!</tt>
<input type ='text' id = 'text_zone1' onMouseUp="text_zone1.value = '';" value = 'Click to clear!' >
The extra stuf is for ___s & giggles.

Javascript and AJAX, only works when using alert()

I am having trouble with my javascript. It seems to be acting oddly. This is what's going on. I have a form, after the user submits it, it calls a function(onsubmit event) to verify the submitted data, if something bad OR if the username/email is already in database(using ajax for this part) it'll return false and display errors using DOM. Here's the code below. What's weird about it, is that it only works when I use an empty alert('') message, without it, it just doesn't work. Thanks for the help.
//////////////////////////////////////
function httpRequest() {
var xmlhttp;
if (window.XMLHttpRequest) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp=new XMLHttpRequest();
} else if (window.ActiveXObject) {
// code for IE6, IE5
xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
} else {
alert("Your browser does not support XMLHTTP!");
}
return xmlhttp;
}
function validateRegForm(reg) {
var isValidForm = true;
var warningIcon = "";//for later in case we want to use an icon next to warning msg
with(reg) {
var regFormDiv = document.getElementById("registration_form");
//Check if dynamic div exist, if so, remove it
if(document.getElementById('disp_errors') != null) {
var dispErrorsDiv = document.getElementById('disp_errors');
document.getElementById('reg_form').removeChild(dispErrorsDiv);
}
//Dynamically create new 'div'
var errorDiv = document.createElement('div');
errorDiv.setAttribute('id','disp_errors');
errorDiv.setAttribute('style','background-color:pink;border:1px solid red;color:red;padding:10px;');
document.getElementById('reg_form').insertBefore(errorDiv,regFormDiv);
var xmlhttp = httpRequest();
var available = new Array();
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState == 4)
{
var response = xmlhttp.responseText;
if(response != "") {
//Return values
var newValue = response.split("|");
available[0] = newValue[0];
available[1] = newValue[1];
}
}
}
xmlhttp.open("GET","profile_fetch_reg_info.php?do=available&un="+u_username.value+"&email="+u_email.value+"",true);
xmlhttp.send(null);
alert(' '); ////////////WITHOUT THIS, IT DOESN'T WORK. Why?
if(available[1] == "taken") {
errorDiv.innerHTML += warningIcon+'Username is already taken!<br />';
isValidForm = false;
} else if(u_username.value.length < 4){
errorDiv.innerHTML += warningIcon+'Username must be more than 4 characters long!<br />';
isValidForm = false;
} else if(u_username.value.length > 35) {
errorDiv.innerHTML += warningIcon+'Username must be less than 34 characters long!<br />';
isValidForm = false;
}
if(available[0] == "taken") {
errorDiv.innerHTML += warningIcon+'Email address entered is already in use!<br />';
isValidForm = false;
} else if(u_email.value == ""){
errorDiv.innerHTML += warningIcon+'Email address is required!<br />';
isValidForm = false;
} else {
//Determine if email entered is valid
var filter = /^([a-zA-Z0-9_\.\-])+\#(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
if (!filter.test(u_email.value)) {
errorDiv.innerHTML += warningIcon+'Email entered is invalid!<br />';
u_email.value = "";
isValidForm = false;
}
}
if(u_fname.value == ""){
errorDiv.innerHTML = warningIcon+'Your first name is required!<br />';
isValidForm = false;
}
if(u_lname.value == ""){
errorDiv.innerHTML += warningIcon+'Your last name is required!<br />';
isValidForm = false;
}
if(u_password.value.length < 4){
errorDiv.innerHTML += warningIcon+'Password must be more than 4 characters long!<br />';
isValidForm = false;
} else if(u_password.value.length > 35) {
errorDiv.innerHTML += warningIcon+'Password must be less than 34 characters long!<br />';
isValidForm = false;
} else if (u_password.value != u_password2.value) {
errorDiv.innerHTML += warningIcon+'Password and re-typed password don\'t match!<br />';
isValidForm = false;
}
if(u_squestion.value == ""){
errorDiv.innerHTML += warningIcon+'A security question is required!<br />';
isValidForm = false;
}
if(u_sanswer.value == ""){
errorDiv.innerHTML += warningIcon+'A security answer is required!<br />';
isValidForm = false;
}
if(u_address.value == ""){
errorDiv.innerHTML += warningIcon+'Address is required!<br />';
isValidForm = false;
}
if(u_city.value == ""){
errorDiv.innerHTML += warningIcon+'City is required!<br />';
isValidForm = false;
}
if(u_state.value == ""){
errorDiv.innerHTML += warningIcon+'State is required!<br />';
isValidForm = false;
}
if(u_zip.value == ""){
errorDiv.innerHTML += warningIcon+'Zip code is required!<br />';
isValidForm = false;
}
if(u_phone.value == ""){
errorDiv.innerHTML += warningIcon+'Phone number is required!<br />';
isValidForm = false;
}
if(isValidForm == false)
window.scroll(0,0);
return isValidForm;
}
}
The alert() helps because that delays the processing of the remaining javascript in that function (everything from the alert() down to the bottom), leaving enough time for the AJAX request to complete. The first letter in AJAX stands for "asynchronous" which means that (by default) the response will come in at "some point in the future" but not immediately.
One fix (which you should not implement) is to make the processing synchronous (by changing the third argument of open() to be false) which will stop further processing of your script (and the entire webpage) until the request returns. This is bad because it will effectively freeze the web browser until the request completes.
The proper fix is to restructure your code so that any processing that depends on the result of the AJAX request goes in to the onreadystatechange function, and can't be in the main function that initiates the AJAX request.
The way this is usually handled is to modify your DOM (before the AJAX request is sent) to make the form readonly and display some sort of "processing" message, then in the AJAX response handler, if everything is okay (the server responded properly and validation was successful) call submit() on the form, otherwise make the form wriable again and display any validation errors.
The problem is that XMLHTTPRequest is asynchronous - it sends the request in the background and doesn't wait for it to finish.
The alert statement causes the code to wait until the user clicks OK, during which the request finishes.
You need to use the onreadystatechange event, like this:
xmlhttp.onreadystatechange = function() {
if(xmlhttp.readyState==4) {
// Do things
}
};
The method you assign to this property will be called after the response is received. (and at other times, which is why you need to check that readyState is 4)
You're sending the request asynchronously, because of this:
xmlhttp.open(..., true);
Passing true as the third argument to open() means that the code will continue to run before the result comes back.
The alert() is giving that asynchronous request time to complete before the subsequent code runs.
I'd normally recommend moving all the code that depends on the result of the AJAX call into the callback, within the:
if(xmlhttp.readyState == 4)
block, but in your case you need the result of the call to know what to return from your validation function. In that case, you're going to have to use a synchronous call, by passing false to open(). Then your subsequent code won't run until the response has come back.
These guys are right but I would also be sure to return the bool from the validation method so the submission of the form is cancelled if the form is not valid.
Something along the lines of:
<form onsubmit="return IsValid();">
...
</form>
You could also always return false from validateRegForm and have the xmlhttp.onreadystatechange = function() submit the form if it is valid, or otherwise display your error message.
That is because your AJAX call is asynchronous. The code following xmlhttp.send() is executed immediately. It doesn't wait for your ajax call to end (unless you put the alert).
Move all the code to be executed after the ajax call to the callback method to ensure it is run after the call is finished.
[Edit]: Aside from the problem, I think using AJAX just to validate the form and then allowing the user to submit the usual way seems a bit odd to me.
Can you divide the validation into 2 parts? One that can be done purely on the client side and the other which involves the server-side validation. You can do the second part completely on server-side upon submit and return the errors back to client.
Another option is to avoid the traditional submit altogether. Since you are doing the ajax call anyway, why don't you do the save/edit/whatever in the ajax call itself removing the need for a submit? Keep in mind though, you will still need to support the regular submit if the user has javascript disabled.
You have to pass the third parameter to xmlhttp.open() as false, then it will work fine
I was having the same problem when I was using the type="submit", for example:
<button type="submit" class="btn btn-default" name="btn-login" id="btn-login" onclick="submitForm()">
<span class="glyphicon glyphicon-log-in"></span> Sign In
but I change it to type="button" and it works.
<button onclick="AddComment();">Comment</button>
this is where my ajax code started, the AddComment() function clicked a hidden Asp:Button which would send an ajax call to the backend through an updatepanel...
all i did to fix the situation was add return false; to my button.
<button onclick="AddComment(); return false;">Comment</button>
I've had the same problem. Once I remove the alert("") it doesn't work. I figured it out and that's the deal.
In HTML, when you use <button></button> to place your button, the browser acts differently; when you click on it, after calling the event handler, it reloads the page and this is why you should place an alert("") just after your code to prevent the page from reloading.
You can simply use <input type="button" value="something"> instead of <button></button> to prevent the browser from reloading the page.
I had the same problem and simply added:
<?php
usleep(200000)// 2 seconds
?>
after the javascript (which btw, entailed deferring jQuery 1.9.1 to the head

Categories

Resources