How can you click an href link but block the linked page from displaying - html

It was hard to encapsulate my question in the title.
I've rewritten a personal web page that made extensive use of javascript. I'm simplifying matters (or so I hope).
I use a home automation server that has a REST interface. I can send commands such as 'http://192.168.0.111/rest/nodes/7%2032%20CD%201/cmd/DON to turn on a light. I'm putting links on my simplified web page using an href tag. The problem is that it opens the rest interface page and displays the XML result. I'd like to avoid having that page show up. ie when you click on the link it 'goes' to the link but doesn't change the page.
This seems like it should/would not be possible but I've learned not to underestimate the community.
Any thoughts?

You can use the fetch function if your browser is modern enough:
document.querySelector(lightSelector).addEventListener('click', e => {
e.preventDefault(); // prevent the REST page from opening
fetch(lightURL).then // put promises here
})
The variables lightSelector and lightURL are expected to be defined somewhere.
The code listens for clicks on the link, and when one comes, we prevent the REST page from opening (your intention) then we send a request to your light URL with fetch. You can add some promises to deal with the response (e.g. print "light on" or "light off" for example) using then but that's another matter.
If you make the "link" a button, you can get rid of e.preventDefault(); which is the part preventing the REST page from opening.

Related

HTML injection into someone else's website?

I've got a product that embeds into websites similarly to Paypal (customers add my button to their website, users click on this button and once the service is complete I redirect them back to the original website).
I'd like to demo my technology to customers without actually modifying their live website. To that end, is it possible to configure http://stackoverflow.myserver.com/ so it mirrors http://www.stackoverflow.com/ while seamlessly injecting my button?
Meaning, I want to demo the experience of using my button on the live website without actually re-hosting the customer's database on my server.
I know there are security concerns here, so feel free to mention them so long as we meet the requirements. I do not need to demo this for website that uses HTTPS.
More specifically, I would like to demonstrate the idea of financial bounties on Stackoverflow questions by injecting a Paypal button into the page. How would I demo this off http://stackoverflow.myserver.com/ without modifying https://stackoverflow.com/?
REQUEST TO REOPEN: I have reworded the question to be more specific per your request. If you still believe it is too broad, please help me understand your reasoning by posting a comment below.
UPDATE: I posted a follow-up challenge at How to rewrite URLs referenced by Javascript code?
UPDATE2: I discarded the idea of bookmarklets and Greasemonkey because they require customer-side installation/modification. We need to make the process as seamless as possible, otherwise many of get turned off by the process and won't let us pitch.
I would suggest to create a proxy using a HTTP handler.
In the ProcessRequest you can do a HttpWebRequest to get the content on the other side, alter it and return the adjusted html to the browser. You can rewrite the urls inside to allow the loading of images, etc from the original source.
public void ProcessRequest(HttpContext context)
{
// get the content using HttpWebRequest
string html = ...
// alter it
// write back the adjusted html
context.Response.Write(html);
}
If you're demoing on the client-side and looking to just hack it in quickly, you could pull it off with some jQuery. I slapped the button after the SO logo just for a demo. You could type this into your console:
$('head').append('<script src="https://www.paypalobjects.com/js/external/dg.js" type="text/javascript"></script>')
$('#hlogo').append('<form action="https://www.sandbox.paypal.com/webapps/adaptivepayment/flow/pay" target="PPDGFrame" class="standard"><label for="buy">Buy Now:</label><input type="image" id="submitBtn" value="Pay with PayPal" src="https://www.paypalobjects.com/en_US/i/btn/btn_paynowCC_LG.gif"><input id="type" type="hidden" name="expType" value="light"><input id="paykey" type="hidden" name="paykey" value="insert_pay_key">')
var embeddedPPFlow = new PAYPAL.apps.DGFlow({trigger: 'submitBtn'});
Now, I'm not sure if I did something wrong or not because I got this error on the last part:
Expected 'none' or URL but found 'alpha('. Error in parsing value for 'filter'. Declaration dropped.
But at any rate if you are demoing you could just do this, maybe as a plan B. (You could also write a userscript for this so you don't have to open the console, I guess?)
After playing with this for a very long time I ended up doing the following:
Rewrite the HTML and JS files on the fly. All other resources are hosted by the original website.
For HTML files, inject a <base> tag, pointing to the website being redirected. This will cause the browser to automatically redirect relative links (in the HTML file, CSS files, and even Flash!) to the original website.
For the JS files, apply a regular expression to patch specific sections of code that point to the wrote URL. I load up the redirected page in a browser, look for broken links, and figure out which section of JS needs to be patched to correct the problem.
This sounds a lot harder than it actually is. On average, patching each page takes less than 5 minutes of work.
The big discovery was the <base> tag! It corrected the vast majority of links on my behalf.

Controlling the "Oops! Chrome could not find ... " page?

When you type in an invalid address, Chrome displays a grey page that says "Oops! Google Chrome could not find X. Did you mean Y?"
Because this is not an HTTP page but rather one of the browser's built-in things, I can't put a content script in it and can't control it, so my extension is frozen until the user manually goes to another page.
Since the extension is supposed to be able to control the browser on its own, it's very important that anytime this page opens, it automatically goes back to a page I do have content script access to, and then displays a message instead.
Is this impossible?
You can use the chrome.webNavigation.onErrorOccurred to detect such errors, and redirect to a different page if you want. Unless you've got an extremely good reason to do so, I strongly recommend against implementing such a feature, because it might break the user's expectations of how the browser behaves.
Nevertheless, sample code:
chrome.webNavigation.onErrorOccurred(function(details) {
if (details.frameId === 0) {
// Main frame
chrome.tabs.update(details.tabId, {
url: chrome.runtime.getURL('error.html?error=' + encodeURIComponent(details.error))
});
}
});
According to the docs the only pages an extension can override are:
The bookmarks manager
The history
The new-tab
So, an extension can't change/contol/affect the behaviour of the browser regarding the "Oops!..." page.

Load a part of the page without AJAX

I'm developing a web site where I want the left menu to stay fix, while the content of the clicked option is loaded.
Actually, what I do is that each menu link using AJAX it return the requested content. Everything works fine but I would like to avoid it because then statistics are difficult to follow (among some other things like Google boots).
How can I do the same affect/similar (http://www.foundcrelamps.com/) without javascript?
What I would do is a bit different. I'd make the links on the menu valid links that point to the content. Eg Contacte to point to http://www.foundcrelamps.com/contacte so that if you paste that link in the browser, it will load the page directly.
Then keep the ajax, so that the user does not reload the whole page on every click.
You can use History.js to keep the browser history and modify the URL so that back/next buttons work, even with ajax.
Edit, if you use conventional a elements with standard href it might look like this:
$('a').click(function(){
$('YOUR CONTAINER').load($(this).attr('href'));
return false; // so that it does not load the whole page
});
Then on the server you should do something like this:
/* AJAX check */
$isAjax = false;
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest') {
$isAjax = true;
}
if (!$isAjax) {
outputHeader();
}
outputMainContent();
if (!$isAjax) {
outputFooter();
}
This way when you do ajax, you will load only the inner content. When not, it will load the whole page.
There is an alternative method - you might load the whole page with jQuery but only use inner part of the html to replace the original content.

How do I add a HTML hash link without it altering the URL bar...?

When I add a HTML link to a specific part of the page:
test
I noticed that it changes the URL at the address bar. Although I have come across websites where they link that way without the address bar being updated. How is this possible?
EDIT: It might be an AJAX solution were they make it work without URL change, as if I remember correctly, the page didn't reload, it went directly to the destination...
You may wish to look at the jquery plugin, scrollTo.
http://jquery.com
And a couple of links for scrollTo
http://demos.flesler.com/jquery/scrollTo/
http://flesler.blogspot.com/2007/10/jqueryscrollto.html
You can do something like this:
The HTML
click me to scroll
<div class="gap">a big gap</div>
<h1 id="scrollToMe">I should scroll to here without a # in the URL</h1>
The javascript (jquery and the scrollto plugin)
$(document).ready(function() {
$(".scrollLink").click(function(e) {
$.scrollTo($(this).attr("href"));
e.preventDefault();
});
});
What the javascript does, is when ever a link is clicked that has the class ".scrollLink", scroll the page down to the element that has the same ID, as the href for the particular link clicked. Then the e.preventDefault() stops it working like the normal hash link and stops it appearing in the URL bar.
Here is a working example for you: http://jsfiddle.net/alexkey/c3jsY/7/
And a version not in a frameset, so you can see that the URL doesn't change:
http://fiddle.jshell.net/alexkey/c3jsY/7/show/light/
This approach has a couple of good points
Simply apply the scrollLink class to links you want to stop the hash appearing (nice and easy)
It uses the normal href, which also means the links will still work even if javascript is disabled - good for accessibility and probably search engine optimisation to.
It's possible to use javascript to intercept the click event, perform your own custom logic, then cancel the navigation event so the URL never changes
Maybe you can try something like: window.scroll(0,150);
instead of "(0,150)" put the cooridnate of your target.
You'll have to experiment with the number (shown here as 200) to get the window to align properly.
test
You could use inline the next code:
link text
<div id="bookmark">Jump to here</div>

CodeIgniter + jQuery(ajax) + HTML5 pushstate: How can I make a clean navigation with real URLs?

I'm currently trying to build a new website, nothing special, nice and small, but I'm stuck at the very beginning.
My problems are clean URLs and page navigation. I want to do it "the right way".
What I would like to have:
I use CodeIgniter to get clean URLs like
"www.example.com/hello/world"
jQuery helps me using ajax, so I can
.load() additional content
Now I want to use HTML5 features like pushstate to
get rid of the # in the URL
It should be possible to go back and forth without a page refresh but the page will still display the right content according to the current URL.
It should also be possible to reload a page without getting a 404 error. The site should exist thanks to CodeIgniter. (there is a controller and a view)
For example:
A very basic website. Two links, called "foo" and "bar" and a emtpy div box beneath them.
The basic URL is example.com
When you click on "foo" the URL changes to "example.com/foo" without reloading and the div box gets new content with jQuery .load(). The same goes for the other link, just of course different content and URL.
After clicking "foo" and then "bar" the back button will bring me back to "example.com/foo" with the according content. If I load this link directly or refresh the page, it will look the same. No 404 error or something.
Just think about this page and tell me how you would do this.
I would really love to have this kind of navigation and so I tried several things.
So far...
I know how to use CodeIgniter to get the URLs like this. I know how to use jQuery to load additional content and while I don't fully understand the html5 pushstate stuff, I at least got it to work somehow.
But I can't get it to work all together.
My code right now is a mess, that's the reason I don't really want to post it here. I looked at different tutorials and copy pasted some code together. Would be better to upload my CI folder I guess.
Some of the tutorials I looked at:
Dive into HTML5
HTML5 demos
Mozilla manipulating the browser history
Saner HTML5 history
Github: History.js
(max. number of links reached :/)
I think my main problem is, that everybody tries to make it compatible with all browsers and different versions, adds scripts/jQuery plugins and whatnot and I get confused by all the additional code. There is more code between my script-tags then actual html content.
Could somebody post the most basic method how to use HTML5 for my example page?
My failed attemp:
On my test page, when I go back, the URL changes, but the div box will still show the same content, not the old one. I also don't know how to change the URL in the script according to the href attribute from the link. Is there something like $(this).attr('href'), that changes according to which link I click? Right now I would have to use a script for every link, which of course is bad.
When I refresh the site, CodeIgniter kicks in and loads the view, but really only the view by itself, the one I loaded with ajax, not the whole page. But I guess that should be easy to fix with a layout and the right controller settings. Haven't paid much attention to this yet.
Thanks in advance for any help.
If you have suggestions, ideas, or simple just want to mention something, please let me know.
regards
DiLer
I've put up a successful minimal example of HTML5 history here: http://cairo140.github.com/html5-history-example/one.html
The easiest way to get into HTML5 pushstate in my opinion is to ignore the framework for a while and use the most simplistic state transition possible: a wholesale replacement of the <body> and <title> elements. Outside of those elements, the rest of the markup is probably just boilerplate, although if it varies (e.g., if you change the class on HTML in the backend), you can adapt that.
What a dynamic backend like CI does is essentially fake the existence of data at particular locations (identified by the URL) by generating it dynamically on the fly. We can abstract away from the effect of the framework by literally creating the resources and putting them in locations through which your web server (Apache, probably) will simply identify them and feed them on through. We'll have a very simple file system structure relative to the domain root:
/one.html
/two.html
/assets/application.js
Those are the only three files we're working with.
Here's the code for the two HTML files. If you're at the level when you're dealing with HTML5 features, you should be able to understand the markup, but if I didn't make something clear, just leave a comment, and I'll walk you through it:
one.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<script src="assets/application.js"></script>
<title>One</title>
</head>
<body>
<div class="container">
<h1>One</h1>
Two
</div>
</body>
</html>
two.html
<!doctype html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.js"></script>
<script src="assets/application.js"></script>
<title>Two</title>
</head>
<body>
<div class="container">
<h1>Two</h1>
One
</div>
</body>
</html>
You'll notice that if you load one.html through your browser, you can click on the link to two.html, which will load and display a new page. And from two.html, you can do the same back to one.html. Cool.
Now, for the history part:
assets/application.js
$(function(){
var replacePage = function(url) {
$.ajax({
url: url,
type: 'get',
dataType: 'html',
success: function(data){
var dom = $(data);
var title = dom.filter('title').text();
var html = dom.filter('.container').html();
$('title').text(title);
$('.container').html(html);
}
});
}
$('a').live('click', function(e){
history.pushState(null, null, this.href);
replacePage(this.href);
e.preventDefault();
});
$(window).bind('popstate', function(){
replacePage(location.pathname);
});
});
How it works
I define replacePage within the jQuery ready callback to do some straightforward loading of the URL in the argument and to replace the contents of the title and .container elements with those retrieved remotely.
The live call means that any link clicked on the page will trigger the callback, and the callback pushes the state to the href in the link and calls replacePage. It also uses e.preventDefault to prevent the link from being processed the normal way.
Finally, there's a popstate event that fires when a user uses browser-based page navigation (back, forward). We bind a simple callback to that event. Of note is that I couldn't get the version on the Dive Into HTML page to work for some reason in FF for Mac. No clue why.
How to extend it
This extremely basic example can more or less be transplanted onto any site because it does a very uncreative transition: HTML replacement. I suggest you can use this as a foundation and transition into more creative transitions. One example of what you could do would be to emulate what Github does with the directory navigation in its repositories. It's an intermediate manoever that requires floats and overflow management. You could start with a simpler transition like appending the .container in the loaded page to the DOM and then animating the old container to {height: 0}.
Addressing your specific "For example"
You're on the right track for using HTML5 history, but you need to clarify your idea of exactly what /foo and /bar will contain. Basically, you're going to have three pages: /, /foo, and /bar. / will have an empty container div. /foo will be identical to / except in that container div has some foo content in it. /bar will be identical to /foo except in that the container div has some bar content in it. Now, the question comes to how you would extract the contents of the container through Javascript. Assuming that your /foo body tag looked something like this:
<body>
foo
bar
<div class="container">foo</div>
</body>
Then you would extract it from the response data through var html = $(data).filter('.container').html() and then put it back into the parent page through $('.container').html(html). You use filter instead of the much more reasonable find because from some wacky reason, jQuery's DOM parser produces a jQuery object containing every child of the head and every child of the body elements instead of just a jQuery object wrapping the html element. I don't know why.
The rest is just adapting this back into the "vanilla" version above. If you are stuck at any particular stage, let me know, and I can guide you better though it.
Code
https://github.com/cairo140/html5-history-example
Try this in your controller:
if (!$this->input->is_ajax_request())
$this->load->view('header');
$this->load->view('your_view', $data);
if (!$this->input->is_ajax_request())
$this->load->view('footer');