Hi folks!!
This is all regarding the UI technologies.
Below are the frameworks which I come across so far:
CSS, JS best practices:
https://www.w3schools.com/js/js_best_practices.asp
Imagine the site alice.com has some data that the site bob.com wants to access. This type of request traditionally wouldn’t be allowed under the browser’s same origin policy. However, by supporting CORS requests, alice.com can add a few special response headers that allows bob.com to access the data.
Sample data:
CORS(cross origin resource sharing):
allows cross-domain communication from the browser.Imagine the site alice.com has some data that the site bob.com wants to access. This type of request traditionally wouldn’t be allowed under the browser’s same origin policy. However, by supporting CORS requests, alice.com can add a few special response headers that allows bob.com to access the data.
Access-Control-Allow-Origin which defines which sites can interact with, the header can be either a list of origins or a wildcard (*).
Access-control-Allow-credentials header defines whether or not the browser will send cookies with the request. Cookies will only be sent if the allow-credentials header is set to true and the allow-origin is not set to a *.
What is JSONP?
JSONP is a method for sending JSON data without worrying about cross-domain issues. JSONP does not use the XMLHttpRequest object. JSONP uses the <script> tag instead.The important thing to remember with jsonp is that it isn't actually a protocol or data type. Its just a way of loading a script on the fly and processing the script that is introduced to the page. In the spirit of JSONP, this means introducing a new javascript object from the server into the client application/ script.
When is JSONP needed?
It is 1 method of allowing one domain to access/ process data from another in the same page asyncronously. Primarily, it is used to override CORS (Cross Origin Resource Sharing) restrictions which would occur with an XHR (ajax) request. Script loads are not subject to CORS restrictions.
How is it done
Introducing a new javascript object from the server can be implemented in many ways, but the most common practice is for the server to implement the execution of a 'callback' function, with the required object passed into it. The callback function is just a function you have already set up on the client which the script you load calls at the point the script loads to process the data passed in to it.
If we dont mention callback then it would be like below:
<script type="text/javascript">
//Response data goes here
</script>
How to use jsonp in javascript
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title>jsonp</title>
</head>
<body>
<span></span>
<script>
//this function is the callback, it needs to be a global variable
function readResponse(response){
document.getElementsByTagName('SPAN')[0].innerHTML = response.feed.entry.length + ' entries returned';
console.log(response);
}
(function(){
//note the "readResponse" at the end
var src = 'http://spreadsheets.google.com/feeds/list/o13394135408524254648.240766968415752635/od6/public/values?alt=json-in-script&callback=readResponse',
script = document.createElement('SCRIPT');
script.src = src;
document.body.appendChild(script);
})();
</script>
</body>
</html>
JSONP in jQuery
function logResults(json){
console.log(json);
}
$.ajax({
url: "https://api.github.com/users/jeresig",
dataType: "jsonp",
jsonpCallback: "logResults"
});
This can also be written as:
$.getJSON("https://api.github.com/users/jeresig?callback=?",function(json){
console.log(json);
});
1. Using JSONP only without CORS:
If using JSONP, there is always a need to make server side change to get json response with acallback
method. Also thecallback
method must be present in thejavascript
to execute. So in the below example, when we call the destination url, if we get the response asmyCallBackMethod({ "customerData": { "name": "testName", "age": 26 } })
, then we must have ajavascript method
with the namemyCallBackMethod
. Using jsonp,cookies can also be shared across domains
- in this approach, no need to set any headers in the response by the destination server to allow the requested domains.
- The
callback
method used in this example ismyCallBackMethod
. This name can be anything, except the names injavascript
and theresponse jsonp string must match
client / javascript:
function makeTheCall(queryString) {
var destinationUrl = "www.otherdestinationserver.com";
$.ajax({
type: 'GET',
url: destinationUrl + queryString,
dataType: 'jsonp',
jsonpCallback: 'myCallBackMethod',
async: false, // this is by default false, so not need to mention
crossDomain: true // tell the browser to allow cross domain calls.
// success: successResopnse, jsonpCallback will call the successCallback
// error: failureFunction jsonp does not support errorCallback. So cannot use this
});
}
window.myCallBackMethod = function(data) {
successResponse(data);
}
successResponse = function(data) {
//functionality goes here;
}
// the json response from the server when calling the url must be in the below format only.
myCallBackMethod({ "customerData": { "name": "testName", "age": 26 } })
2. Using CORS only without JSONP and WITHOUT URL REWRITES:
If using CORS, there is always aneed to make changes on server and client/javascript
. In this approach,no need to get any callback
method as part of json response. Responsemust be a pure json
. However, make appropriate code changes on the destination server to let the requests pass through. So need to set theheader
in theresponse
object.
Client / javascript:
function makeTheCall(queryString) {
var destinationUrl = "www.otherdestinationserver.com";
$.ajax({
type: 'GET',
url: destinationUrl + queryString,
dataType: 'json', // use json only, not jsonp
crossDomain: true, // tell browser to allow cross domain.
success: successResopnse,
error: failureFunction
});
}
successResponse = function(data) {
//functionality goes here;
}
failureFunction = function(data) {
//functionality goes here;
}
On server, add the below header.
httpServletResponse.setHeader("Access-Control-Allow-Origin", "*"); // Here need to give the origin url (the url in the address bar of the page which is making request). Using * means allow any value
- However, with the above code added to server, there wont be any cookies shared between the server and the requested page. To also get the cookies across the requested page and server, we need to add the following properties on client and server.
On client / javascript:
If we'd like to send any cookies to requested website in the request then withCredentials should be true
If we'd like to send any cookies to requested website in the request then withCredentials should be true
xhrFields: {
'withCredentials': true // tell the client to send the cookies if any for the requested domain
}
On server:
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
- These changes allows the client and server to share the cookies.
- However, if using header
Access-Control-Allow-Credentials
in response, there is a restriction on the value for the headerAccess-Control-Allow-Origin
. It shouldnever be * if we want to use Access-Control-Allow-Credentials header
. Hence give exact domain name.
Update on server:
httpServletResponse.setHeader("Access-Control-Allow-Origin", "www.mytestsite.com"); // Give the origin url (the url in the address bar of the page which is making request).
final client / javascript: (CORS only approach)
function makeTheCall(queryString) {
var destinationUrl = www.otherdestinationserver.com;
$.ajax({
type: 'GET',
url: destinationUrl + queryString,
dataType: 'json', // use json only, not jsonp
crossDomain: true, // tell browser to allow cross domain
xhrFields: {
'withCredentials': true // tell the client to send the cookies if any for the requested domain
},
success: successResopnse,
error: failureFunction
});
}
successResponse = function(data) {
//functionality goes here;
}
failureFunction = function(data) {
//functionality goes here;
}
Final Server code: (CORS only approach)
httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Origin", "www.mytestsite.com");
3. Using CORS only WITH A URL REWRITE FILTER setting RESPONSE HEADERS:
If the application is using a url rewrite filter, (mostly all the web applications does), this would give much easier implementation. Instead of following the Final Server code: (CORS only approach) in the approach 2 above, follow the below url to change at xml ( url rewrite filter).
Same code pasted below for quick reference.
<rule enabled="true" match-type="regex">
<name>Enabling CORS Headers</name>
<from>^/path/someMorePath.*$</from>
<condition name="origin" operator="equal">([a-z]+)</condition>
<set type="response-header" name="Access-Control-Allow-Origin">%1</set>
<set type="response-header" name="Access-Control-Allow-Credentials">true</set>
// Create the XHR object. function createCORSRequest(method, url) { var xhr = new XMLHttpRequest(); if ("withCredentials" in xhr) { // XHR for Chrome/Firefox/Opera/Safari. xhr.open(method, url, true); } else if (typeof XDomainRequest != "undefined") { // XDomainRequest for IE. xhr = new XDomainRequest(); xhr.open(method, url); } else { // CORS not supported. xhr = null; } return xhr; } // Helper method to parse the title tag from the response. function getTitle(text) { return text.match('<title>(.*)?</title>')[1]; } // Make the actual CORS request. function makeCorsRequest() { // All HTML5 Rocks properties support CORS. var url = 'http://www.tutorialspoint.com'; var xhr = createCORSRequest('GET', url); if (!xhr) { alert('CORS not supported'); return; } // Response handlers. xhr.onload = function() { var text = xhr.responseText; var title = getTitle(text); alert('Response from CORS request to ' + url + ': ' + title); }; xhr.onerror = function() { alert('Woops, there was an error making the request.'); }; xhr.send(); }
How to mention timeout in XHR:
function showMessage (message) {
console.log(message + this.responseText);
}
loadFile("message.txt", 2000, showMessage, "New message!\n");
function loadFile(url, timeout, callback) {
var args = Array.prototype.slice.call(arguments, 3);
var xhr = new XMLHttpRequest();
xhr.ontimeout = function () {
console.error("The request for " + url + " timed out.");
};
xhr.onload = function() {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
callback.apply(xhr, args);
} else {
console.error(xhr.statusText);
}
}
};
xhr.open("GET", url, true);
xhr.timeout = timeout;
xhr.send(null);
}
How do you maintain state with HTTP being stateless/non-persistent
- With sessions(server will generate JSESSION ID and send to the client/browser through cookies)
- URL rewriting(when cookies turned off; URL re-writing will append the state information as a query string to the URL. This should not be used to maintain private or sensitive information)
- HTML form hidden fields(The disadvantage of hidden fields is that they may expose sensitive or private information to others)
- https://www.tuturself.com/posts/view?menuId=111&postId=505
Detailed Explanation:
HTTP is a stateless (or non-persistent) request/response based protocol. Each request is treated by its own. A request will not know what was done in the previous requests. The protocol is designed to be stateless for simplicity.
Scenarios in which we need to maintain state:
- Some Internet applications, such as e-commerce shopping cart, require the state information to be passed one request to the next. Since the protocol is stateless, it is the responsibility of the application to maintain state information within their application.
- Consider a situation where you need to store certain information across requests like when a User logs into your website, no matter on which web page he visits after logging in, his credentials will be with the server, until he logs out. For such case you can retain the state information between different page requests as follows:
Care should be taken to minimize size of objects stored in session and objects stored in session should be serializable. The following code is describing that in Servlet how can we obtain the session and store information in it.
//import statements would go here!!
public class MyServlet extends HttpServlet {
.......
// returns a current session or a new session
HttpSession session = request.getSession(true);
session.setAttribute("user", name);
.......
}
Retrieve the Session Object and getting information in it:
//improt statements would go here!!
public class MyServlet extends HttpServlet {
.....
HttpSession session = request.getSession();
String user = (String)session.getAttribute("user"); .....
}
Now when the user logged-out from the system then we can invalidate the HttpSeesion by the following code:
//If a session is no longer required e.g. user has logged out, etc then it can be
//If a session is no longer required e.g. user has logged out, etc then it can be
invalidated. session.invalidate();
- Cookie
- Hidden fields of the HTML form.
- URL rewriting.
Cookies
HTTP is a stateless protocol. That is, the server does not hold any information on previous requests sent by the client. Client-side cookies were introduced by Netscape to maintain state, by storing client-specific information on the client's machine and later retrieved to obtain the state information. Montulli, the creator of cookie from Netscape, chose the term "cookie" as "a cookie is a well-known computer science term that is used when describing an opaque piece of data held by an intermediary". The term opaque here implies that the content is of interest and relevance only to the server and not the client.
A cookie is a small piece of information that a server sends to a browser and stored inside the browser. The browser will automatically include the cookie in all its subsequent requests to the originating host of the cookie. Take note that cookies are only sent back by the browser to their originating host and not any other hosts. In this way, the server can uniquely identify a client (or a browser).
A cookie has a name and a value, and other attribute such as domain and path, expiration date, version number, and comments. Domain and path specifies which server (and path) to return the cookie. Cookie could be persistent (with a future expiration date) or last only for that particular browser’s session (i.e., removed when you close the browser). A web browser is only required to accept up to 20 cookies per server and 300 cookies in total. Each cookie is limited to 4 KB.
A server can set the cookie's value to uniquely identify a client. Hence, cookies are commonly used for session and user management. Cookie can be used to hold personalized information, or to help in on-line sales/service (e.g. shopping cart), or tracking popular links, or for demographics purpose.
The main limitation of using cookie for tracking is users may disable cookie in their browser.
"
"
Set-Cookie
" Response Header
A cookie is created when a client visits a site for the first time. A server-side program sends a response message containing a "
The problem on using cookie is some users disable cookie due to the real and perceived privacy concerns over cookies.
Set-Cookie
" response header. The header contains a name/value pair of the cookie plus some additional information.
Most often cookie is used to store a session ID. The session management is done at the server side, instead of client side.
Cookie Version 0 "Set-Cookie
" Header (Netscape)
Set-Cookie: cookie-name=cookie-value; expires=date; path=path-name; domain=domain-name; securecookie-name
=cookie-value
: Required, the name and value of the cookie to be set.expires=date
: Specifies the expired date of that cookie in the form "Day, DD-Mon-YYYY HH:MM:SS GMT
". If not specified, the cookie will expire when the current user's session ends (i.e., non-persistent cookie).domain=domain-name
: Specifies the domain that this cookie is valid. "Tail matching" is performed, e.g. "test.com
" matches hostnames "my.test.com
" and "a.b.test.com
". The default value is the hostname of the server which generates the cookie.path=path-name
: Specifies the subset of URLs in the domain for which the cookie is valid. The cookie must first pass the domain matching, before performing the path matching. If the path is not specified, it is default to current page.Secure
: If a cookie is marked secure, it will only be transmitted over secure link, e.g., SSL.- Multiple
Set-Cookie
headers can be used in the same message. - You can delete a cookie by setting the "
expires
" to a value in the past, with the same domain and path.
Cookie Version 1 "Set-Cookie
" Header (RFC2109/RFC2965)
Max-Age
: maximum age of the cookie in seconds. A positive value indicates that the cookie will expire after that many seconds have passed. Note that the value is the maximum age when the cookie will expire, not the cookie's current age. A negative value means that the cookie is not stored persistently and will be deleted when the web browser exits. A zero value causes the cookie to be deleted.Max-Age
is used in version 1 in place ofExpires
.Version
: set the version of the cookie protocol this cookie complies with. Value of 0 complies with the original Netscape cookie specification. Value of 1 complies with RFC2965/RFC2109.
"Cookie
" Request Header
The client returns the cookie(s) to the matching domain and path in the subsequent requests, using a "Cookie" request header.
Cookie: cookie-name-1=cookie-value-1; cookie-name-2=cookie-value-2; ...Security and Privacy Issues
- Cookie is not a program: A cookie is just a simple piece of text. It is not a program (like JavaScript or Java Applets), macro, or plug-in. It cannot be used a virus. It cannot access your hard disk, read/write your files or format your hard disk.
- Cookie cannot fill up your hard disk: The number of cookie a particular host can send to you is 20. The cookie size is limited to 4KB. The total number of cookie (from all hosts) is 300. Hence, cookie cannot fill up your hard disk.
- Cookie can only be sent back to its originated host and not to a third party host.
- Cookie is sent and stored in clear text and not encrypted. This is susceptible to eavesdropping and malicious tampering during transit. Cookie SHOULD NOT hold confidential information such as password or credit card number as they are sent in clear text.
- Cookie could pose some privacy concern: A cookie cannot snoop the hard disk and find out who you are or what your income is. The only way such information could end up in a cookie is if you provide them (e.g., filling up a form) to a site that creates the cookie. Furthermore, it is important to note that you will only get the cookie if you have visited the originated host. Many users wonder why they have a cookie from "ad.doubleclick.net" but they have never explicitly visited the host. This is because many sites on the Internet do not keep their advertisements locally, but they subscribe to a media service that places the ads for them thru a hyperlink. That hyperlink returns a ads image together with a cookie, also check the previous cookie saved, for demographic purpose.
Hidden Field in the HTML Form
The principle is to include an HTML form with a hidden field containing a session ID in all the HTML pages sent to the client. This hidden field will be returned back to the server in the request. No cookie needed. The disadvantage of this approach is it requires careful and tedious programming effort, as all the pages have to be dynamically generated to include this hidden field. The advantage is all browser supports HTML form.
<form method="post" action="url"> <input type="hidden" name="sessionid" value="1111"> ... <input type="submit"> </form>
URL rewriting
The principle is to include a unique session ID in all the URLs issued by the client, which identifies the session. For example,
http://host:port/shopping.html;sessionid=value
To accomplish this objective, you must rewrite all the URLs in all the HTML files that is send to the client with this unique session ID (such as
<a href='url'>
, <form action='url'>
etc.). Again, careful and tedious programming efforts are required. The advantage is all browser supports URL rewriting. URL rewriting works even if the browsers do not support cookies or the user disables cookies.history.pushState(stateObject, title, url)
pushState()
takes three parameters: a state object, a title (which is currently ignored), and (optionally) a URL. Let's examine each of these three parameters in more detail:- state object — The state object is a JavaScript object which is associated with the new history entry created by
pushState()
. Whenever the user navigates to the new state, apopstate
event is fired, and thestate
property of the event contains a copy of the history entry's state object.The state object can be anything that can be serialized. Because Firefox saves state objects to the user's disk so they can be restored after the user restarts the browser, we impose a size limit of 640k characters on the serialized representation of a state object. If you pass a state object whose serialized representation is larger than this topushState()
, the method will throw an exception. If you need more space than this, you're encouraged to usesessionStorage
and/orlocalStorage
. - title — Firefox currently ignores this parameter, although it may use it in the future. Passing the empty string here should be safe against future changes to the method. Alternatively, you could pass a short title for the state to which you're moving.
- URL — The new history entry's URL is given by this parameter. Note that the browser won't attempt to load this URL after a call to
pushState()
, but it might attempt to load the URL later, for instance after the user restarts the browser. The new URL does not need to be absolute; if it's relative, it's resolved relative to the current URL. The new URL must be of the same origin as the current URL; otherwise,pushState()
will throw an exception. This parameter is optional; if it isn't specified, it's set to the document's current URL.
URL rewriting without refreshing the page:
https://medium.com/@galopin/javascript-url-rewriting-and-user-experience-a4dab153669
With URL rewriting, the URL and the resource that it leads to can be completely independent of each other. In practice, they’re usually not wholly independent: the URL usually contains some code or number or name that enables the CMS to look up the resource. But in theory, this is what URL rewriting provides: a complete separation.
Have you ever wondered how does Facebook do to dynamically change the page URL whithout refreshing it or redirecting you.
This is the case when you click on a picture: Facebook’s lightbox is opened, displays the picture, and the url changes to become the picture’s one.
For example, if you go to Barack Obama’s official page and click on his profile picture, this will appear:
The interesting part is that since the new url is the one of the picture’s page, you can copy the link and share it directly, without having to open the image itself. From a user experience perspective, this is extremely convenient.
And if you refresh the page, you are directly taken to the picture’s page.
How does it work?
Concretely, it works with the javascript history object, and this is really easy to do.
With URL rewriting, the URL and the resource that it leads to can be completely independent of each other. In practice, they’re usually not wholly independent: the URL usually contains some code or number or name that enables the CMS to look up the resource. But in theory, this is what URL rewriting provides: a complete separation.
Have you ever wondered how does Facebook do to dynamically change the page URL whithout refreshing it or redirecting you.
This is the case when you click on a picture: Facebook’s lightbox is opened, displays the picture, and the url changes to become the picture’s one.
For example, if you go to Barack Obama’s official page and click on his profile picture, this will appear:
The interesting part is that since the new url is the one of the picture’s page, you can copy the link and share it directly, without having to open the image itself. From a user experience perspective, this is extremely convenient.
And if you refresh the page, you are directly taken to the picture’s page.
How does it work?
Concretely, it works with the javascript history object, and this is really easy to do.
For example, to change the url of a page, you just need this small javascript code:
history.pushState({ foo: 'fake' }, 'Fake Url', 'hy, this is a fake url.html');
This function prevents the loading of a new page when you click on a link, and loads the content thanks to AJAX instead.
You can see that you do not have hashes in the URL, but only the page name.
I then created a function to handle the clicks on the “go back” and “go next” buttons of the browser:
window.onpopstate = function(event){
event.preventDefault();
hash=location.pathname;
loadPage(hash.replace('/webdesign/pushstate/', ''));
}
Basically, it does exactly the same as the previous one.
As you can see, this is very simple! This is definitely a better method in therms of user experience than using a hash in the url, and I am glad to be able to use it now, and to have shared it with you!
HTML5 History API allows browsers to modify the URL without reloading or refreshing the page using pushState function.
HTML5 History pushState method
The pushState method works similar to window.location but it does not refresh or reload the page and it will modify the URL even if the page does not exists. The pushState method actually inserts an entry into the history of the browsers which allows us to go back and forth using the browser’s forward and back buttons.
The pushState method accepts the following three parameters.
1. State object: - The state object is a JavaScript object which can contain any details about the page and must be serializable.
2. Title: - The title of the page.
3. URL – The URL of the page.
Change Browser URL without reloading using JavaScript
The HTML Markup consists of 3 buttons which make a call to a function ChangeUrl. This function accepts the page Title and URL as parameters.
It first checks whether browser supports HTML5 and if yes then a State object containing the page Title and URL is created and is passed to the HTML5 History pushState method along with the page Title and URL as the other two parameters.
<script type="text/javascript">
function ChangeUrl(title, url) {
if (typeof (history.pushState) != "undefined") {
var obj = { Title: title, Url: url };
history.pushState(obj, obj.Title, obj.Url);
} else {
alert("Browser does not support HTML5.");
}
}
</script>
<input type="button" value="Page1" onclick="ChangeUrl('Page1', 'Page1.htm');" />
<input type="button" value="Page2" onclick="ChangeUrl('Page2', 'Page2.htm');" />
<input type="button" value="Page3" onclick="ChangeUrl('Page3', 'Page3.htm');" />
Preflight request and response:
It is an
OPTIONS
request, using three HTTP request headers: Access-Control-Request-Method
, Access-Control-Request-Headers
, and the Origin
header.
A preflight request is automatically issued by a browser, when needed. In normal cases, front-end developers don't need to craft such requests themselves.
For example, a client might be asking a server if it would allow a
DELETE
request, before sending a DELETE
request, by using a preflight request:OPTIONS /resource/foo
Access-Control-Request-Method: DELETE
Access-Control-Request-Headers: origin, x-requested-with
Origin: https://foo.bar.org
If the server allows it, then it will respond to the preflight request with a
Access-Control-Allow-Methods
response header, which lists DELETE
:HTTP/1.1 200 OK
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: https://foo.bar.org
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Access-Control-Max-Age: 86400
How to defer an element’s event handler if it depends on an external script that takes some time to load?
First we'll have to check if that external script is loaded or not. So based on this we would set a variable(like flag isScriptLoaded). If it's true then only we would enable that button otherwise we won't.
Case 1:
If the script creates any variables or functions in the global space, then we can check for their existence.
var myCustomFlag = true;
if (typeof window.myCustomFlag == 'undefined') {
//the flag was not found, so the code has not run
loadScript('Javascript/MyScript.js');}
Case 2:
If script is not creating any global variables/functions, then do this:
var len = $('script[src*="Javascript/MyScript.js"]').length;
if (len === 0) {
alert('script not loaded');
loadScript('Javascript/MyScript.js');
if ($('script[src*="Javascript/MyScript.js"]').length === 0) {
alert('still not loaded');
}
else {
alert('loaded now');
}
}
else {
alert('script loaded');
}
function loadScript(scriptLocationAndName) {
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = scriptLocationAndName;
head.appendChild(script);//or document.body.appendChild(script);
}
Method chaining:
// define the class
var Kitten = function() {
this.name = 'Garfield';
this.color = 'brown';
this.gender = 'male';
};
Kitten.prototype.setName = function(name) {
this.name = name;
return this;
};
Kitten.prototype.setColor = function(color) {
this.color = color;
return this;
};
Kitten.prototype.setGender = function(gender) {
this.gender = gender;
return this;
};
Kitten.prototype.save = function() {
console.log(
'saving ' + this.name + ', the ' +
this.color + ' ' + this.gender + ' kitten...'
);
// save to database here...
return this;
};
// WITHOUT CHAINING
var bob = new Kitten();
bob.setName('Bob');
bob.setColor('black');
bob.setGender('male');
bob.save();
// OUTPUT:
// > saving Bob, the black male kitten...
///////////////////
// WITH CHAINING
new Kitten()
.setName('Bob')
.setColor('black')
.setGender('male')
.save();
// OUTPUT:
// > saving Bob, the black male kitten...
2 way data binding in vanilla javascript
Javascript error monitoring in production:
The web can be a hostile place and our javascript apps will inevitably break for some users. Browser changes, invasive plugins, unstable networks or just plain bugs-something is going to go wrong. When it does, we need to be ready. We need to know what went wrong and how to fix it or our users just won't come back.
To capture errors from our application, we’ll need to add the TrackJS tracker agent to the page. It will wrap up our application and the browser’s API to catch errors and send them off to be normalized and logged. This doesn’t have to be in the `<head>`, but it should probably be the first script on the page. Otherwise, any errors that happen before we can capture it would never get reported! There is also an NPM package so that you could bundle their script with the rest of your app.
If you’d prefer to do-it-yourself without TrackJS, you should start with attaching to `window.onerror`. This global function hook is supported by all browsers (really, all of them) as is notified when the browser hits an unhandled error in any JavaScript on the page.
<!-- BEGIN TRACKJS --><script type="text/javascript">window._trackJs = { token: 'YOUR_TOKEN_HERE' };</script>
<script type="text/javascript" src="https://cdn.trackjs.com/releases/current/tracker.js"></script>
<!-- END TRACKJS -->
window.onerror = function(message, file, line, column, error) { error = error || {};
$.ajax({
method: 'POST',
url: 'https://yourapp.com/path/to/error/log',
data: JSON.stringify({
message: message,
file: file,
line: line,
column: column,
error: {
name: error.name,
message: error.message,
stack: error.stack
}
})
});
};
window.onerror = function(message, file, line, column, error) { error = error || {};
$.ajax({
method: 'POST',
url: 'https://yourapp.com/path/to/error/log',
data: JSON.stringify({
message: message,
file: file,
line: line,
column: column,
error: {
name: error.name,
message: error.message,
stack: error.stack
}
})
});
};
Other tools are:
Javascript pass by value vs pass by reference
- Primitive type variable like string,number are always pass as pass by value.
- Array and Object is passed as pass by reference or pass by value based on these two condition.
- if you are changing value of that Object or array with new Object or Array then it is pass by Value.
object1 = {item: "car"}; array1=[1,2,3];
here you are assigning new object or array to old one.you are not changing the value of property of old object.so it is pass by value.- if you are changing a property value of an object or array then it is pass by Reference.
object1.item= "car"; array1[0]=9;
here you are changing a property value of old object.you are not assigning new object or array to old one.so it is pass by reference.
Code
function passVar(object1, object2, number1) {
object1.key1= "laptop";
object2 = {
key2: "computer"
};
number1 = number1 + 1;
}
var object1 = {
key1: "car"
};
var object2 = {
key2: "bike"
};
var number1 = 10;
passVar(object1, object2, number1);
console.log(object1.key1);
console.log(object2.key2);
console.log(number1);
Output: -
laptop
bike
10
https://codeburst.io/javascript-passing-by-value-vs-reference-explained-in-plain-english-8d00fd06a47c
Coding questions:
https://www.interviewcake.com/question/javascript/js-whats-wrongCORS:
https://gist.github.com/jesperorb/6ca596217c8dfba237744966c2b5ab1e
Message Queue, Call stack and Event loop:
https://www.youtube.com/watch?v=8aGhZQkoFbQ
Online editor toc heck how call stack and event loop works: http://latentflip.com/loupe/?code=!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D
js is single threaded but async behvior is not the default behavior of javascript. Rather it's built in browser(as APIs) on top of javascript.
Online editor toc heck how call stack and event loop works: http://latentflip.com/loupe/?code=!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D
js is single threaded but async behvior is not the default behavior of javascript. Rather it's built in browser(as APIs) on top of javascript.
https://medium.com/front-end-hacking/javascript-event-loop-explained-4cd26af121d4
Heap:
Unstructured region of memory. Objects are allocated here. All the memory allocations to objects and variables happens here.Call stack(LIFO):
it keeps track of function calls(what function we're currently executing and what function is to be executed after that).All of the aync functions like settimeout, setinterval, click, mousehover, ajax would be sent to Event table. Event table is the one which stores the data of events and their callbacks.
Event messages would be sent to event queue when particular call back has to be executed.
Then Event loop (is like a clock; )when it ticks, it checks whether the call stack is empty. If it's empty, then only it would send the event messages to call stack from message queue.
Closure with regard to call stack
a closure is a stack frame which is allocated when a function starts its execution, and not freed after the function returns (as if a 'stack frame' were allocated on the heap rather than the stack!)
stack frame vs stack:
A stack frame is a frame of data that gets pushed onto the stack. In the case of a call stack, a stack frame would represent a function call and its argument data.
If I remember correctly, the function return address is pushed onto the stack first, then the arguments and space for local variables. Together, they make the "frame," although this is likely architecture-dependent. The processor knows how many bytes are in each frame and moves the stack pointer accordingly as frames are pushed and popped off the stack.
A call stack is composed of 1 or many several stack frames. Each stack frame corresponds to a call to a function or procedure which has not yet terminated with a return.
"A call stack is composed of stack frames..." — Wikipedia
A stack frame is a thing that you put on the stack. They are data structures that contain information about subroutines to call.
Things to be considered before we send our application production
=====Yet to complete=======
Design patterns in Javascript:
Module pattern:
If we would like to have private, public or protected methods or variables then we should go for Module pattern otherwise we can make use of simple object in which everything is public.
The objective is to hide the variable accessibility from the outside world.
what are modules ?
In JavaScript, the word “modules” refers to small units of independent, reusable code. They are the foundation of many JavaScript design patterns and are critically necessary when building any non-trivial JavaScript-based application.
The closest analog in the Java language are Java Classes. However, JavaScript modules export a value, rather than define a type. In practice, most JavaScript modules export an object literal, a function, or a constructor. Modules that export a string containing an HTML template or a CSS stylesheet are also common.
ECMAScript, the JavaScript standards body, expects to ratify a final specification for modules in ECMAScript version 6 by the end of 2014. ECMAScript 6 modules (“ES6 modules”), however, will likely not be feasible to use in production until 2016 due to the long upgrade cycles of some browsers and operating systems.
Why use modules?
There are a lot of benefits to using modules in favour of a sprawling, interdependent codebase. The most important ones, in my opinion, are:
1) Maintainability: By definition, a module is self-contained. A well-designed module aims to lessen the dependencies on parts of the codebase as much as possible, so that it can grow and improve independently. Updating a single module is much easier when the module is decoupled from other pieces of code.
Going back to our book example, if you wanted to update a chapter in your book, it would be a nightmare if a small change to one chapter required you to tweak every other chapter as well. Instead, you’d want to write each chapter in such a way that improvements could be made without affecting other chapters.
2) Namespacing: In JavaScript, variables outside the scope of a top-level function are global (meaning, everyone can access them). Because of this, it’s common to have “namespace pollution”, where completely unrelated code shares global variables.
Sharing global variables between unrelated code is a big no-no in development.
As we’ll see later in this post, modules allow us to avoid namespace pollution by creating a private space for our variables.
3) Reusability: Let’s be honest here: we’ve all copied code we previously wrote into new projects at one point or another. For example, let’s imagine you copied some utility methods you wrote from a previous project to your current project.
That’s all well and good, but if you find a better way to write some part of that code you’d have to go back and remember to update it everywhere else you wrote it.
This is obviously a huge waste of time. Wouldn’t it be much easier if there was — wait for it — a module that we can reuse over and over again?
How can you incorporate modules?
There are many ways to incorporate modules into your programs. Let’s walk through a few of them:
Module pattern
The Module pattern is used to mimic the concept of classes (since JavaScript doesn’t natively support classes) so that we can store both public and private methods and variables inside a single object — similar to how classes are used in other programming languages like Java or Python. That allows us to create a public facing API for the methods that we want to expose to the world, while still encapsulating private variables and methods in a closure scope.
There are several ways to accomplish the module pattern. In this first example, I’ll use an anonymous closure. That’ll help us accomplish our goal by putting all our code in an anonymous function. (Remember: in JavaScript, functions are the only way to create new scope.)
var modularpattern = (function() {
// your module code goes here
var sum = 0 ;
return {
add:function() {
sum = sum + 1;
return sum;
},
reset:function() {
return sum = 0;
}
}
}());
alert(modularpattern.add()); // alerts: 1
alert(modularpattern.add()); // alerts: 2
alert(modularpattern.reset()); // alerts: 0
Factory Pattern:
const FactoryFunction = string => {
const capitalizeString = () => string.toUpperCase();
const printString = () => console.log(`----${capitalizeString()}----`);
return { printString };
};
const taco = FactoryFunction('taco');
printString(); // ERROR!!
capitalizeString(); // ERROR!!
taco.capitalizeString(); // ERROR!!
taco.printString(); // this prints "----TACO----"
The factory function pattern is similar to constructors, but instead of using new
to create an object, factory functions simply set up and return the new object when you call the functionFactory
var Car = function(){
var car = {};
car.running = false;
car.toggleEngine = function(){
this.running = !this.running;
}
return car;
};
car1 = Car(); // running false
car2 = Car(); // running false
car1.toggleEngine(); // running true
car2.toggleEngine = undefined; // to broke down.
car1.toggleEngine(); //running false
Constructor
var Car = function (){
this.running = false;
};
Car.prototype.toggleEngine = function(){
this.running = !this.running;
}
var car1 = new Car; //running false
var car2 = new Car; //running false
car2.toggleEngine() //running true
Car.prototype.toggleEngine = function(){};
car1.toggleEngine() //running false
As we can see after the objects were created they still were very much linked together.
To be clear you can still do the following and not effect the objects created by the constructor. With functional shared method and mask the prototype function given by the constructor. So there are not fully linked but they are linked through the constructors prototype.
var car1 = new Car; //running false
var car2 = new Car; //running false
car2.toggleEngine() //running true
car2.toggleEngine = function(){};
car1.toggleEngine() //running true
Other instances in factory pattern would be impacted if any of the instance makes a change. It's not the case in constructor pattern
Additionally, constructor have the prototype option
In fact, the facade is a design pattern, and doesn't have much to do with code structure. One can use the JS "module pattern" to implement a facade
facade vs module:
A singleton pattern ensures that you always get back the same instance of whatever type you are retrieving, whereas the factory pattern generally gives you a different instance of each type.
The purpose of the singleton is where you want all calls to go through the same instance. An example of this might be a class that manages a disk cache, or gets data from a static dictionary; wherever it is important only one known instance interacts with the resource. This does make it less scalable.
The purpose of the factory is to create and return new instances. Often, these won't actually be the same type at all, but they will be implementations of the same base class. However, there may be many instances of each type
Facade pattern:
When we put up a facade, we present an outward appearance to the world that may conceal a very different reality. This was the inspiration for the name behind the next pattern we’re going to review: the Facade pattern. This pattern provides a convenient higher-level interface to a larger body of code, hiding its true underlying complexity. Think of it as simplifying the API being presented to other developers, something that almost always improves usability
This allows us to interact with the Facade directly rather than the subsystem behind the scenes. Whenever we use jQuery’s
$(el).css()
or $(el).animate()
methods, we’re actually using a Facade: the simpler public interface that lets us avoid having to manually call the many internal methods in jQuery core required to get some behavior working. This also circumvents the need to manually interact with DOM APIs and maintain state variables.
Let’s take a look at the pattern in action. This is an unoptimized code example, but here we’re using a Facade to simplify an interface for listening to events across browsers. We do this by creating a common method that can be used in one’s code which does the task of checking for the existence of features so that it can provide a safe and cross-browser compatible solution.
In a similar manner, we’re all familiar with jQuery’s
$(document).ready(..)
. Internally, this is actually powered by a method called bindReady()
, which is doing this:
This is another example of a Facade, in which the rest of the world simply uses the limited interface exposed by
$(document).ready(..)
and the more complex implementation powering it is kept hidden from sight.
Facades don’t just have to be used on their own, however. They can also be integrated with other patterns, such as the Module pattern. As we can see below, our instance of the Module pattern contains a number of methods that have been privately defined. A Facade is then used to supply a much simpler API to accessing these methods:
In this example, calling
module.facade()
will actually trigger a set of private behavior within the module, but again, the users aren’t concerned with this. We’ve made it much easier for them to consume a feature without needing to worry about implementation-level details.Notes on Abstraction
Facades generally have few disadvantages, but one concern worth noting is performance. Namely, one must determine whether there is an implicit cost to the abstraction a Facade offers to our implementation and, if so, whether this cost is justifiable. Going back to the jQuery library, most of us are aware that both
getElementById("identifier")
and $("#identifier")
can be used to query an element on a page by its ID.
Did you know however that
getElementById()
on its own is significantly faster by a high order of magnitude? Take a look at this jsPerf test to see results on a per-browser level: http://jsperf.com/getelementbyid-vs-jquery-id. Now of course, we have to keep in mind that jQuery (and Sizzle, its selector engine) are doing a lot more behind the scenes to optimize our query (and that a jQuery object, not just a DOM node is returned).
The challenge with this particular Facade is that in order to provide an elegant selector function capable of accepting and parsing multiple types of queries, there is an implicit cost of abstraction. The user isn’t required to access
jQuery.getById("identifier")
or jQuery.getbyClass("identifier")
and so on. That said, the trade-off in performance has been tested in practice over the years and, given the success of jQuery, a simple Facade actually worked out very well for the team.
When using the Facade pattern, try to be aware of any performance costs involved and make a call on whether they are worth the level of abstraction offered.
Singleton pattern
var
mySingleton = (
function
() {
// Instance stores a reference to the Singleton
var
instance;
function
init() {
// Singleton
// Private methods and variables
function
privateMethod(){
console.log(
"I am private"
);
}
var
privateVariable =
"Im also private"
;
var
privateRandomNumber = Math.random();
return
{
// Public methods and variables
publicMethod:
function
() {
console.log(
"The public can see me!"
);
},
publicProperty:
"I am also public"
,
getRandomNumber:
function
() {
return
privateRandomNumber;
}
};
};
return
{
// Get the Singleton instance if one exists
// or create one if it doesn't
getInstance:
function
() {
if
( !instance ) {
instance = init();
}
return
instance;
}
};
})();
var
singleA = mySingleton.getInstance();
var
singleB = mySingleton.getInstance();
console.log( singleA.getRandomNumber() === singleB.getRandomNumber() );
// true
Bad singleton
var
myBadSingleton = (
function
() {
// Instance stores a reference to the Singleton
var
instance;
function
init() {
// Singleton
var
privateRandomNumber = Math.random();
return
{
getRandomNumber:
function
() {
return
privateRandomNumber;
}
};
};
return
{
// Always create a new Singleton instance
getInstance:
function
() {
instance = init();
return
instance;
}
};
})();
var
badSingleA = myBadSingleton.getInstance();
var
badSingleB = myBadSingleton.getInstance();
console.log( badSingleA.getRandomNumber() !== badSingleB.getRandomNumber() );
// true
// Note: as we are working with random numbers, there is a
// mathematical possibility both numbers will be the same,
// however unlikely. The above example should otherwise still
// be valid.
No comments:
Post a Comment