I have a Javascript file running on a page and I would like to log certain events as they occur. For example, I have a web store - and when people add an item to their cart, I want to log this event by visiting a page that I built:
function log_event(id) {
window.location.href = 'https://example.com/log/cart.php?id=' + id;
return false;
}
The log/cart.php page doesn't really have anything to display, all it does is insert a record into a database containing the item that was added to the cart, and the date.
The code that calls this function looks like:
document.getElementById('add-to-cart').addEventListener('click', function() {
// Add to the cart
...
// Track the item that was added
let id = document.getElementById('add-to-cart').getAttribute('data-id');
log_event(id);
});
With my current code, the log/cart.php actually replaces the current page. I want the opening of log/cart.php to only happen in the background without the user being interrupted. I don't want it to actually open a browser tab or window and let the user stay in the product page.
You can send an AJAX request to that endpoint:
function log_event(id) {
var xhttp = new XMLHttpRequest();
xhttp.open("GET", 'https://example.com/log/cart.php?id=' + id, true);
xhttp.send();
return false;
}
fetch() can also be used, but be aware of its browser support (no IE).
Related
I login into my website (running on localhost), and store the user id in a session variable
$_SESSION['user_id'] = $user_id;
The main page loads, and all is fine. I show the user id on the main page, so I'm sure of its value. When I load another page, using
php = 'some_php_file.php';
window.open(php,php);
The second page opens ok. But if I try to open the same page again, clicking on the same button on the main page, the system will logout. If I omit the second php in window.open() (using '' instead), I may have multiple copies of the same window (what I don't want), but no problem of automatic logout.
Any idea what may be happening?
EDIT: If I close the second window and repeat the process, I have no logout problem. I can close and reopen the second window as many times as I wish. The problem only happens if I try to open the second window, but it is already open. I can also open different 'second windows' (different php files). I'm only getting logged off if I try to open TWICE the same window.
EDIT 2: Seems I've found it. Before I call window.open(), I'm testing for the existence of the php file, using this function:
function fileExists(url){
var http = new XMLHttpRequest();
http.open('HEAD',url,true);
http.send();
return http.status != 404;
}
If I change the http.open() line to
http.open('HEAD',url,false);
it works! But the manual tells us to use 'true' in the third parameter... What should I do?
It seems to me that your fileExists function simply returns true all the time because it does not wait for the XHR to complete. Except when you specify async = false.
Time to read How to return the response from an asynchronous call? probably.
I have no clue what is the consequence of this always being true, as you do not share exactly what you do with that result.
Now if you want to "stick with the manual" and keep async = true (you should really indeed), then simply wrap your following code in a callback. E.g.:
function fileExistsAsync(url, callback){
var http = new XMLHttpRequest();
http.open('HEAD',url,true);
http.send();
http.onreadystatechange = function () {
if (http.readyState === 4) {
callback(http.status != 404);
}
}
}
fileExistsAsync(url, function (exists) {
console.log("async " + exists);
});
Demo: http://jsfiddle.net/52xqLfow/
function publicViewHandler(){
//var pubView = new post();
publish.set("publicView", true);
publish.save();
var publicQuery = new Parse.Query("Post");
publicQuery.equalTo("publicView", true);
publicQuery.equalTo("objectId", this.postId);
// publicQuery.find({
// success:function(){
// // var myClone = $(this).parent().clone(true);
// // myClone.appendTo(".storyBoard");
// // myClone.append($(commentWindow).clone());
// }
var myClone = $(this).parent().clone(true);
myClone.appendTo(".storyBoard");
myClone.append($(commentWindow).clone());
//});
}
My cloning works out side of the success function but it doesn't save to the element that it is appending to. When the page is refreshed the clones disapear.
Checkout my url at http://www.subdomain.jason-c.com. Both login and password is kio.. If you make a new story, save it then publish it, the clone will be appended but then refresh and they disapear.
Also, how would I work that code in to my query because the way I did it does not seem to be even apending the clones of the selected stories.
Javascript/jQuery is a client side manipulation.
You're making changes on the client side (browser) and not on the server side (your website), that's why the changes disappear on refresh.
To make it not disappear on refresh, you need to make it server side. Add the code on your HTML or use an ajax request and tell the server what code should be included on the HTML code.
I have created a chrome extension that sends a POST request to some server and gets its response then displays an number badge according to the data.
Now I want to create a link inside the popup.html based on the data used to send the POST request to the server it self so the users can see the data on the website (data source).
This is the code I use in popup.js to send the POST request
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://someserver/path', true);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.onload = function () {
var regex = new RegExp(/ID:\d+/g);
var testregex = regex.test(this.responseText);
if (testregex == true) {
var count = this.responseText.match(/ID:\d+/g).length;
var countext = count.toString();
chrome.browserAction.setBadgeText({text: countext});
} else {
chrome.browserAction.setBadgeText({text: "0"});
}
};
getCurrentTabUrl(function(url) {
var cleanurl = url.match(/^https?\:\/\/([^\/:?#]+)(?:[\/:?#]|$)/i);
xhr.send('search=' + cleanurl[1] +'&submit=Search');
});
Question is how do I create a link with the same POST data I used before?
Thanks for the help
So, you want to query an external service, then display some information in the popup with a link to more information.
Let's make a scaffold of how you're going to display it. In your popup, include the following:
<div id="data-container">
<div id="data-loading">
<!-- Maybe add an animated spinner here, or something else -->
Loading...
</div>
<div id="data-display">
<!-- Currently empty, will add a link here -->
</div>
</div>
Style this as you wish. Then, from your XHR:
xhr.onload = function () {
/* ... */
// Hide the loading notice
document.getElementById("data-loading").style.display = "none";
// Create the element that will show more details;
// <a href="#"> works okay, but consider making a button
var link = document.createElement("a");
link.href = "#";
link.text = "More details..." // Add data from xhr.responseText?
link.addEventListener("click", clickHandler);
var container = document.getElementById("data-display");
// Make sure the container is empty (in case we're calling this again)
while (container.lastChild) node.removeChild(container.lastChild);
// Append more elements if you want to display some data
container.appendChild(link);
};
Now the interesting part: the clickHandler click handler. To open a new tab from the popup, you should use chrome.tabs.create():
function clickHandler() {
chrome.tabs.create({
url: /* ??? */
});
}
It would be trivial if we wanted to open a normal GET page. To open a POST page, we have to cheat. There are two main possibilities:
Open a javascript: URL that performs a POST. Conceptually easier, but only works for short parameters.
Open a helper page in your extension that will perform POST. This allows you to pass arbitrarily large arguments before the POST happens.
Both are covered in this question: Chrome Extension Development - POST to new tab
So I'm trying to redirect the browser to another webpage when the page he is attempting to load matches my conditions (regex). Currently it looks like this: (came up with it here)
function listener(event) {
var channel = event.subject.QueryInterface(Ci.nsIHttpChannel);
var url = event.subject.URI.spec;
if (isToBeRedirected(url)) {
// replace url
}
}
exports.main = function() {
events.on("http-on-modify-request", listener);
}
But the problem is, that this will also replace urls to images for example, which are embedded in the page. My question would be, is there a way of varyfying that the http request is made by typing in a url or clicking a link to a page? So simply everytime a url shows up in the address-bar.
I thought about reading the url of the current tab and comparing it to the request url, but I wasnt able to find out exactly how yet.
I have an idea.
If you do console.log(Ci.nsIHttpChannel) you see it has a bunch of flags, see img at bottom.
So I'm thinking test if it's the main load, meaning its not in a sub frame, but its the whole document of the tab by testing for flag of Ci.nsIHttpChannel.LOAD_INITIAL_DOCUMENT_URI. If its the whole document, its likely from a link, or url bar, or search bar.
So try this:
function listener(event) {
var channel = event.subject.QueryInterface(Ci.nsIHttpChannel);
var url = event.subject.URI.spec;
if (channel.loadFlags & Ci.nsIHttpChannel.LOAD_INITIAL_DOCUMENT_URI) {
//the whole document of the tab is changing
if (isToBeRedirected(url)) {
// replace url
}
}
}
exports.main = function() {
events.on("http-on-modify-request", listener);
}
My other idea, is if you want only url bar changes. Than add an event listener to change of the url bar value. And after change if user hits enter or clicks go, then it register the observer. Then after testing for Ci.nsIHttpChannel.LOAD_INITIAL_DOCUMENT_URI than unregister the observer.
Let's say I have a web page (/index.html) that contains the following
<li>
<div>item1</div>
details
</li>
and I would like to have some javascript on /index.html to load that
/details/item1.html page and extract some information from that page.
The page /details/item1.html might contain things like
<div id="some_id">
picture
map
</div>
My task is to write a greasemonkey script, so changing anything serverside is not an option.
To summarize, javascript is running on /index.html and I would
like to have the javascript code to add some information on /index.html
extracted from both /index.html and /details/item1.html.
My question is how to fetch information from /details/item1.html.
I currently have written code to extract the link (e.g. /details/item1.html)
and pass this on to a method that should extract the wanted information (at first
just .innerHTML from the some_id div is ok, I can process futher later).
The following is my current attempt, but it does not work. Any suggestions?
function get_information(link)
{
var obj = document.createElement('object');
obj.data = link;
document.getElementsByTagName('body')[0].appendChild(obj)
var some_id = document.getElementById('some_id');
if (! some_id) {
alert("some_id == NULL");
return "";
}
return some_id.innerHTML;
}
First:
function get_information(link, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", link, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) {
callback(xhr.responseText);
}
};
xhr.send(null);
}
then
get_information("/details/item1.html", function(text) {
var div = document.createElement("div");
div.innerHTML = text;
// Do something with the div here, like inserting it into the page
});
I have not tested any of this - off the top of my head. YMMV
As only one page exists in the client (browser) at a time and all other (virtual/possible) pages are on the server, how will you get information from another page using JavaScript as you will have to interact with the server at some point to retrieve the second page?
If you can, integrate some AJAX-request to load the second page (and parse it), but if that's not an option, I'd say you'll have to load all pages that you want to extract information from at the same time, hide the bits you don't want to show (in hidden DIVs?) and then get your index (or whoever controls the view) to retrieve the needed information from there ... even though that sounds pretty creepy ;)
You can load the page in a hidden iframe and use normal DOM manipulation to extract the results, or get the text of the page via AJAX, grab the part between <body...>...</body>ยจ and temporarily inject it into a div. (The second might fail for some exotic elements like ins.) I would expect Greasemonkey to have more powerful functions than normal Javascript for stuff like that, though - it might be worth to thumb through the documentation.