I have been tasked with using my skills with HTML/CSS/JavaScript/jQuery to solve a block of code according to these requirements:
Requirements:
- Use ajax via the add_user function to submit the user entered data.
- You can assume the service will respond with 200 status.
- Display an error in red at the top of the form when the add user service responds with success property with a value of false. Use the error property as the message.
- Display new users in the users list when the response returns a success property
- Highlight the email input when a user enters an invalid email address. Also, display the text "please enter a valid email address" in red.
NOTE: The service will not provide this validation functionality, and will accept invalid emails.
//example usage.
addUser('john', 'smith', function(response){
console.log('response is: ' + JSON.stringify(response));
});
/*
################################### DO NOT MODIFY BELOW THIS LINE ##########
############################################################################
*/
// Add user service wrapper.
function addUser(username, email, callback) {
var response;
if(username === "Error"){
response = JSON.stringify({
success: false,
error: "Error is not acceptable username."
});
} else {
response = JSON.stringify({
success: true,
user: {
username: username,
email: email
}
});
}
$.ajax({
url: '/echo/json/',
type: "post",
data: {
json: response
},
success: callback
});
};
The following HTML applies:
<h2>Add a User:</h2>
<form>
<input type="text" name="username" placeholder="name">
<input type="email" name="email" placeholder="email">
<button>add user</button>
</form>
<h2>Users:</h2>
<ul id="users"></ul>
CSS:
body {
font-family: Helvetica, Sans, Arial;
}
p, ul {
padding: 10px;
}
ul {
margin: 5px;
border: 2px dashed #999;
}
OK, hopefully you're still with me. I have a strong understanding of Object-Oriented JavaScript, as well as jQuery, HTML, and CSS. However, I have very little experience with AJAX, and none with JSON syntax/application. Therefore, some aspects of this project seem very straightforward to me, and I do not believe I need assistance in figuring them out. The things I already know how to do properly include:
Displaying an error in red above the form (retrieving the error information is a different story)
Displaying new users in the unordered list section
Highlight the email input when an invalid email address is entered (using client-side validation)
The issues I am having in understanding this project focus on submitting and retrieving the data that is entered in the form. It appears as though the function addUser() first defines the variable response with a 'String' data type version of an 'Object' that contains key:value pairs of 'success: boolean, error: string' or 'success: boolean, user: {username:string,email:string}' - Here is where I run into my first area of trouble...
If the objects containing those key:value pairs are to be relied on for determining whether or not an error has occurred during validation, and to retrieve data such as error messages and strings associated with the username and email, it would make sense to keep them as actual objects, rather than 'stringified' objects. As strings, I do not know how to access the value of a property of that object. If they were objects, I could simply refer to them using dot notation and retrieve their properties' values. (i.e. sampleObj.success or sampleObj.error) It seems as though JavaScript functions such as eval() and JSON.parse() would suffice to return these strings into proper objects, but I have no idea how to implement those functions properly.
The second major issues I am experiencing relates to the jQuery call of the .ajax() method. I have a very rudimentary understanding of how AJAX operates, but the syntax used here confuses me. I understand that the data: {json:response} is being sent to the url:'/echo/json/' using the type:'post', but I do not understand how that data can be retrieved after this has taken place. I also do not understand what the value of 'response' is referring to in that process.
Finally, I do not understand the use of a callback function at the end of the $.ajax() statement, and how it relates to the initial call of the addUser() function as a result of clicking the form button input. I do not understand its purpose, or how it would be used syntactically.
I understand this is a fairly complicated project, and I may be asking a lot. But I have spent many hours over several days trying to make sense of this using my own knowledge and existing online resources, but have not gotten very far despite my diligence. I hope someone can assist me in understanding this example.
A link to a live version of this project (jsfiddle.net)
//EDIT// An updated link to the jsfiddle workflow, with correct jQuery selectors and additional functionality for displaying error messages / user input: http://jsfiddle.net/brianjsullivan/5vv5w/
The problem is that you forget the # (id) in your code:
JSFIDDLE
$(document).ready(function(){
$('#button').click(function(){
$userInput = $('#username').val();
$emailInput = $('#email').val();
addUser($userInput,$emailInput,function(response){
$('#users').html(JSON.stringify(response));
});
});
});
The JSON/string issue is a matter of a little experimentation/familiarity with JSON and JSON objects, but requires tons of explanation in lieu of a little testing, so I will focus on parts 2 and 3 of your question. Perhaps someone else is better able than I to address the first part.
An AJAX code block (1) Defines some variables with values, (2) Transmits them to a server-side script for processing, (3) Receives a response from the server.
The "old" construction (we now use the Promises interface) is the easiest way to envision how AJAX works:
$.ajax({
type: "POST",
url: "pagename.php",
data: "varName=" +varValue+ "&nextVarName=" + nextVarValue,
success: function(returned_data) {
//Var returned_data is ONLY available inside this fn!
alert("Server said: " + returned_data);
}
});
On the server side (using PHP for this example):
<?php
$one = $_POST['varName']; //$one contains varValue
$two = $_POST['nextVarName']; //$one contains nextVarValue
//Do something with the received data, for eg a MySQL lookup
$result = mysql_result(mysql_query(some lookup),0);
$out = '<h1>Server says:</h1>';
$out .='<p>For the purpose of this test, the server sends back:</p>';
$out .= $result;
echo $out; //NOTE: uses echo, not return
Whatever the server side sends to the browser is received as the contents of the variable we have named returned_data.
Note that we must deal with that variable ONLY inside the success function. If we need access to it later on, we can either save the contents into global vars, or inject the data into a hidden DOM element, or ...
These days, though, you want to use the promises interface -- which essentially does the same stuff, but not as clear for the purpose of explanation in an SO post. See below:
Sources:
Kevin Chisholm on jQuery Promise Interface
jQuery 4 U
Daniel Demmel on Promises
José F. Romaniello
Change your code to
$(document).ready(function(){
$('#button').click(function(){
$userInput = $('#username').val();
$emailInput = $('#email').val();
addUser($userInput,$emailInput,function(response){
$('#users').html(JSON.stringify(response));
});
});
});
Here is Fiddle.
Related
I have a function called 'delete' like this :
<div onclick="delete($post_id, $_SESSION['id']">somelink</div>
function delete(post_id, session_id) {
var p_id = post_id;
var s_id = session_d;
$.ajax({
url:"delete.php",
type:"POST",
data: {
p_id: p_id,
s_id: s_id
},
});
})
delete.php is a page to delete the post = p_id which was added from user id = s_id.
My problem is any user can delete any post for only the console when typing in it the function 'delete();' with parameters it called and delete posts!
Any ideas, please.
You can not. Nor should you.
You should always assume that data from the client side is corrupted and should be treated accordingly. That includes form data, or in this case, a AJAX request.
This means that you have to apply validation at the server side, let PHP do it for you. E.g.: Limit the number of posts you can delete per X time. And double check that the post actually belongs to the person who is deleting it.
The reason you can't do this, is because you create javascript which is clientside. If you create a function to prevent changing the code, the client can alter the code on their machine to ignore that. You could make a function to check of the function to check is changed, but again; client can change it.
Unfortunately you can't. What you need to make sure though is making the function safe on the server which, in simple terms, boils down to
Validating every request and input parameters on the server so that people won't be able to manipulate or change server side data from client side.
make sure all data that you send to the client is originated from server as well.
one of the ways to prevent calling a function from client side is NOT to expose your methods in the global scope. and remember if your code is very critical and important, always move it to server-side. it is not a good practice to cover application design issues with programming workarounds. calling functions from client side shouldn't be an issue if the program is designed right.
First of all, this is bad. You should have authentication.
However, you can do that:
(function() {
$('#BUTTON_ID').on('click', function(post_id, session_id) {
var p_id = post_id;
var s_id = session_d;
$.ajax({
url:"delete.php",
type:"POST",
data: {
p_id: p_id,
s_id: s_id
},
});
})
})();
And add "BUTTON_ID" as id for your button.
Not that even that way, it is still not secure.
With this way, you can't call delete from the console. But someone can look into the source code and copy your ajax call and paste it into his console and it will works. It is not a good way to prevent people deleting your posts.
You should read about web application security. You should have an authentication process with tokens that expires after x time. Tokens will authenticate the user and from here, you can check if the user have the right to delete post. If the user do not have the right, you don't show the button. Then if the user call it from it console, he will get an error from the backend server.
If I have a validation tag in my asp.net mvc application for a text field called search, can I plug into it using jquery/javascript to get it to trigger if certain logic is performed? How would I do that?
It looks something like this
#Html.TextBox("SearchQuery", other stuff here, other)
#Html.ValidationMessageFor("SearchQuery")
Say I want to trigger the validation message to show if this occurs
$('form').submit( function (e) {
e.preventDefault(e);
var results = GetLocation();
if (results) {
this.submit();
} else {
// trigger validation message and display "can't find results"
}
});
Please note that I don't think I need to validate here, I just want to show a message where the validation message would be if I did validate
As far as i understand your question, for custom messages coming from server you need to send the object to server and then get the response from it.
You can perform it with an ajax call for example:
$.ajax({
url : 'example.com',
type: 'POST',
data : results,
success:function(datafromserver)
{
$('.resultState').html(datafromserver);
}
});
Another thing if do validation first in the client and then send (and check again in server), in this case remember var result can always be true if the getLocation functions returns anything (such as string , object etc...) so in this case print it with console.log and take a look if is it an object (f example: data.x === none or 'no coordinates' just evaluate it correctly and you can avoid ajax.
Hope helped!
Regards
I'm using jQuery and an $.ajax() call to post some complex HTML via POST to my database. I'm able to get the form's structure via .html(), but the user's selections are lost in the process. I thought I could use .clone() instead but I got this error:
Uncaught InvalidStateError: Failed to read the 'selectionDirection'
property from 'HTMLInputElement': The input element's type ('hidden')
does not support selection.
// Cloning my form
var myFormHTML = $("#myForm").clone();
console.log(myFormHTML);
var inputData = {
advancedSearchHTML: myFormHTML,
otherParam: otherVar
};
console.log(inputData);
// JS ERROR is down here in the $.ajax() call:
$.ajax({
type: "POST",
url: 'serverSideScript.php',
dataType: 'html',
data: inputData,
success: function (response) {
console.log(response);
}
});
These forms are very complex and they include over 100 <input type="hidden">'s which change according to the user's selections. I can't change the way this works. So my problem is that I have complex forms with HTML generated by the user and I need to copy both the HTML AND all its values so that it can be inserted into my database and eventually reloaded back into the DOM, perhaps months later. Any ideas?
EDIT: I've tried everything I can think of but I can't seem to get user input values out of the HTML, which is frustrating because I'm used to just hitting "Copy HTML" in Chrome's Inspector, so to me it seems like it should be easy to get that same HTML out of the <form> as a string. Some of the things I've tried:
$myFormHTML.html()
$myFormHTML.innerHTML
$myFormHTML.outerHTML
$myFormHTML.get(0).innerHTML
$myFormHTML.get(0).outerHTML
JSON.stringify($myFormHTML.html())
I've got it down to the point where I've got a complete jQuery Object which, when appended to the DOM, has all the user's input included (:selected states, :checked states, input values, etc.). I need to take this jQuery Object and spit out all its HTML content into a string that can be transferred to the server. Does anyone have any idea what to do? Maybe there's a way to do the same loop that gets done during an $.append() so I could build up a string from scratch? Any other ideas?
http://api.jquery.com/serialize/
This does exactly what you want, except since your form is built by user-input you cannot verify if it's a valid form or not. If the form markup is incorrect, you cannot serialize the data.
Here is the example:
http://jsfiddle.net/jyc30nxz/1/
$('#myForm').serialize();
An important aspect of this is if your form inputs do not have the "name" attribute, then you cannot return it's value during serialization which is why you end up with an empty string.
Edit:
This also works:
console.log($(this).clone().html())
My guess is your form markup is invalid
Have you tried to .serialize the form contents?
This post by #BenjaminRH (How to change/edit the text of a paragraph/div using jQuery?) provides exactly the sort of functionality I'm trying to build on.
By clicking on a button, a new paragraph is created on the page, which can be edited and saved to the page.
I want to save it to a database. When I look at the page source after editing, I don't see the changes there, which doesn't surprise me... but I don't know where to "capture" the changed text so that I can validate and post to mySQL.
JQuery is a javascript library - which runs client side. If you wanted to save that data into the database - you would have to send it to the server (php/asp/mvc etc) using ajax and then insert the data into the database.
See the jquery Ajax function for details on how to accomplish sending data asynchronously.
Create the data in javascript that you want to show and save in database.
Wrap the data in JSON and use ajax to POST the data to the server side code
Server-side retrieve the posted data and parse it into something usable
Server-side write a script to insert the data into the database.
Handle any errors that may occur.
Pseudo-code:
// step 1
var someData = 'this is my data';
$("#myDiv").html(someData);
// step 2
$.ajax({
type: "POST",
dataType: 'json', // <-- if the data is complex and needs to be object-oriented
url: "some.php", // <-- that is the file that will handle the post server-side.
data: JSON.stringify({ someData }) // <-- just pass someData if your data is not complex
})
.always(function(jqXHR, textStatus) {
if (textStatus != "success") {
// step 5: handle error.
alert("Error: " + jqXHR.statusText); //error is always called .statusText
} else {
alert("Success: " + jqXHR.response); //might not always be named .response
}});
OK, I've managed to solve it for myself, without using ajax. I took the example from (How to change/edit the text of a paragraph/div using jQuery?) and modified it by placing the elements in an (html) form.
The second modification was to use <textarea> elements, not <p> elements, as <p> elements cannot be posted.
As #caspian pointed out (in the comments) those two steps do populate the $_POST array and away we go.
Except the fact I am not able to use PHP. I have a single HTML file I can work with. So the only way is JS I think. And I have an "email" user input where the user sets his email and the n he is able to proceed, but I have to save his email first. Any ideas?
If you only need to save the element in a short term way you can use javascript and the HTML5 data element to save the email as an element of the current page. It is very temporary storage, but is the best you're going to get.
Edit:
Here's how you can do this using jQuery based javascript.
HTML:
<input type="text" id="email">
<input type="button" id="emailButton">
<div id="data_div"></div>
jQuery Javascript:
function retrieveEmail() {
var email = $('#data_div').data("email");
// do something with the email variable as needed here
// here's an example of retrieving it to send it to the server
var paramStr = "email=" + email;
$.ajax({
url: './your_server_file_here',
dataType: 'json',
data: paramStr,
success: function(data) {
callBack(data);
});
}
function callBack(data) {
// do something with information passed back from the server after you sent the data to the server (you didn't say you needed to do this, but here's where it should be done)
}
function storeEmail() {
var email = $('#email').val();
$('#data_div').data("email", email);
}
$(document).ready( function() {
$('#emailButton').click( function() {
storeEmail();
});
});
Edit: I know you already accepted this answer, but it struck me that HTML5 also includes another way to do this and it may provide the increase in power and flexibility that you're looking for. The HTML5 storage element can do pretty much the same thing as the data element except that it can persist and be accessed by other pages from the same domain either until the browser is closed (unlimited amount of data in the sessionStorage) or indefinitely (5mb of data in the localStorage). For implementation details and a greater understanding see here.
Be advised though, the HTML5 storage element is only available in HTML5 compatible browsers and should not be used if you fear your user base won't be using a modern browser. The HTML5 Data element will work even in older browsers, so it does have that advantage.
You could always use Javascript to create a text file where you can save information...