In a web application I'm working on, when someone wants to change their search location (for a map), they click on a button which brings up an overlay... the overlay has 3 tabs: Search by Location, Variables, and Stations. What I am trying to do is have the url updated whenever the overlay is up and also change depending on which tab they are on. This way when they share the URL, the exact overlay will be shown for the other person as well.
I've tried the push/replaceState() from https://developer.mozilla.org/en-US/docs/Web/API/History_API , which updates the url; but when I close the overlay, the same url is still shown... also, when I try to go back to that same url, the overlay is not shown.
Any ideas will be appreciated. Thank you!
Code... be advised I've tried several different scenarios which is why there's commented lines
// function addURL(element) {
// $(element).attr('href', function() {
// window.location.href = window.location +"&"+ "searrch";
// // return window.location.href
// });
// }
var stateObj = { foo: "bar" };
function change_my_url()
{
// history.replaceState(stateObj, "page 2", "#search");
// Prevent default click action
event.preventDefault();
// Detect if pushState is available
if(history.pushState) {
history.pushState(null, null, $(this).attr('href'));
}
return false;
}
var link = document.getElementById('nav-search-btn');
link.addEventListener('click', change_my_url, true);
Related
I made an Ajax enabled Wordpress theme with the main feature that internal links are not reloading the whole page but only the new content. So when URL's hash is changed, the new content is put in the #primary section and the map in the background stays untouched:
var $mainContent = $("#primary")
$(window).bind('hashchange', function(){
url = window.location.hash.substring(1);
url = url + " #content";
$mainContent.animate({opacity: "0.1"}).html('<p>Please wait...</>').load(url, function() {
$mainContent.animate({opacity: "1"});
});
});
Everything works fine, also history back and forward navigation. You can check out the basic funcionality here.
Now I want nice URLs hiding the hashes, so for example a link like http://geraldkogler.com/places/#/places/place/stwst/ gets changed to http://geraldkogler.com/places/place/stwst/. I do this adding this code to line 47 of ajax.js:
var oPageInfo = {
title: "places",
url: window.location.origin+window.location.hash.substring(1)
}
window.history.replaceState(oPageInfo, oPageInfo.title, oPageInfo.url);
Now the URL gets rewritten - but history doesn't work any more.
So I think I should listen to popstate events, I try to do the following and so back works once, but not more:
window.onpopstate = function(event) {
if (event.state) {
var host = "http://"+location.hostname;
location.hash = event.state.url.substring(host.length);
}
};
This (wrong) behaviour with the mentioned code is shown on this page. Any idea what I'm doing wrong in ajax.js?
I've written a Chrome extension that overrides the New Tab page:
manifest.json:
"chrome_url_overrides": {
"newtab": "new-tab.html"
},
Is there a way to make this override optional? That is, I'd like to enable the user to uncheck a checkbox in the options page and disable the New Tab override. This must be possible because when I open a new tab for the first time, there's a popup informing of an extension changing the New Tab settings and asking whether to keep changes or restore settings:
I couldn't find any API for controlling overrides. The New Tab Redirect project doesn't have an option to display the native New Tab.
Google made a Star Wars new tab replacement which allows you to view the default new tab page. The url it uses is chrome-search://local-ntp/local-ntp.html.
Example:
options.html:
<input type="checkbox"> Use default new tab page
options.js:
var checkbox = document.querySelector("input[type=checkbox]")
checkbox.addEventListener("click", function() {
chrome.storage.sync.set({ defaultnewtab: checkbox.checked })
})
newtab.js:
chrome.storage.sync.get("defaultnewtab", function(storage) {
if(storage.defaultnewtab) {
chrome.tabs.update({ url: "chrome-search://local-ntp/local-ntp.html" })
}
})
Instead of using the chrome_url_override you could write a listener that listens for when tabs update using the chrome.tabs.onUpdated.addListener(), then check if the url is chrome://newtab/ and if it is and the check box is ticked, then using chrome.tabs.update() relocate them to another page.
Using the Star Wars method as described #Daniel Herr, I did this, which is working well. Although feels a little hack-y.
I have an option being set in the popup.html whether the Extension is "on" or not.
First off, set the default new tab page using the Chrome defined method:
manifest.json
"chrome_url_overrides": {
"newtab": "newtab.html"
},
Then in your Extension's newtab.html call a new JavaScript file, newtab.js (or whatever).
I am also using jQuery, so my code uses that, but you can do this natively using DOMContentLoaded.
newtab.js
$(document).ready(function(){
// It takes a moment for the Chrome query/update so sometimes there is a flash of content
// Hiding the Body makes it look blank/white until either redirected or shown
$('body').hide();
var background = chrome.extension.getBackgroundPage();
var _app = background._app;
// App is OFF, show Default New Tab
if(!_app._on){
// Get the current Tab
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
var active = tabs[0].id;
// Set the URL to the Local-NTP (New Tab Page)
chrome.tabs.update(active, { url: "chrome-search://local-ntp/local-ntp.html" }, function() { });
});
// App is ON, show custom content
} else {
$('body').show();
}
});
Basically, the methodology is to update the Tab so that it is redirected to chrome-search://local-ntp/local-ntp.html which is the hard URL to the default Chrome NTP.
Since this is a Chrome internal URL -- the URL field still appears blank.
I am trying out the history api for changing the url after swapping out content and have run into an issue with stopping the a tags from loading a new page. So far, when you click a button, it loads the requested content within the page but then loads the page where the requested content is stored. Any suggestions about how to stop this and get a result of a webpage with new content and a fresh url that can be shared?
Here's the JS.
function supports_history_api() {
return !!(window.history && history.pushState);
}
function swapText(href) {
var req = new XMLHttpRequest();
req.open("GET",
"http://bonkmas.com/historytest/gallery/" +
href.split("/").pop(),
false);
req.send(null);
if (req.status == 200) {
document.getElementById("open-content").innerHTML = req.responseText;
setupHistoryClicks();
return true;
}
return false;
}
function addClicker(link) {
link.addEventListener("click", function(e) {
if (swapText(link.href)) {
history.pushState(null, null, link.href);
e.preventDefault();
}
}, true);
}
function setupHistoryClicks() {
addClicker(document.getElementById("next-vid"));
addClicker(document.getElementById("previous-vid"));
}
window.onload = function() {
if (!supports_history_api()) { return; }
setupHistoryClicks();
window.setTimeout(function() {
window.addEventListener("popstate", function(e) {
swapText(location.pathname);
}, false);
}, 1);
}
http://bonkmas.com/historytest/
This is because your scope is broken,
in the click listener you need to use "this" to access the link element. Because of the exception all following code will not be executed.
Use firebug or chrome developer tools to debug your code, they'll brake/pause on exceptions.
Hitting the previous button requests the following url:
http://bonkmas.com/historytest/gallery/previous.html
This url contains the text "okokokok". This text is then inserted in place of the buttons. Then your code trys to interact with those buttons, which no longer exist. Calling link.addEventListener( where link no longer exists blows up. Since you have placed e.preventDefault() after this code, it is never reached and the default action of the a tag is executed.
This is the very reason why it is normally a good idea to place e.preventDefault() at the very top of your code.
If you look at the example which you are trying to mimic; the pages it requests also contain the buttons. This is why the code re-attaches the click handlers with every request. Your pages do not contain the buttons, so it blows up.
I have the following function where I attempt to load a specified url into a new or existing tab (contentPane), I have it working for the most part, however when an existing tab is specified the original url still gets reloaded instead of adding the new html, how can I accomplish the part where an existing tab is passed without having to remove the attribute refreshOnShow upon creating a new tab??
openTab = function(url,title, id){
var tab = dijit.byId(id);
var centerPane = dijit.byId('centerPane');
if (tab){
//if target container exists then let's load the url and add it to the container
centerPane.selectChild(tab);
$.get(url, function(data) {
$('#'+id).html(data);
});
centerPane.selectChild(tab);
} else {
var newTab = new dijit.layout.ContentPane(
{
'title': title,
href:url,
closable:true,
selected:true,
parseOnLoad:true,
preventCache:true,
refreshOnShow:true
}, id);
centerPane.addChild(newTab);
centerPane.selectChild(newTab);
}
};
So what you are doing is basically saying, when this tab is re-opened, let me append my content, and dojo is saying, 'I just opened this tab, and refreshOnShow is true, so let me go get my content from the server again'.
I think the cleanest way to get around that is to do as you say and set refreshOnShow to false. Why do you have it set to true, does the tab have content that needs to be refreshed consistently from the server?
If what you want is something like this (for an existing tab):
User clicks
Dojo goes and refreshes existing tab content
Your manual (jquery based) handler goes and gets some other content
and appends it to (or otherwise uses it with) the content dojo
automatically refreshed
Then you should be able to do something like this:
newTab.connect(newTab, 'onLoad', function(){
// do my stuff after the dojo content has loaded
})
Which just adds an event handler to the contentpane for your tab that fires after the tab has gone to the server for its content.
This is how my updated function looks, it works for me:
openTab = function(url,title, id){
var tab = dijit.byId(id);
var centerPane = dijit.byId('centerPane');
if (tab){
//if target container exists then let's load the url and add it to the container
tab.href = url;
tab.set('title',title);
centerPane.selectChild(tab);
} else {
var newTab = new dijit.layout.ContentPane(
{
'title': title,
href:url,
closable:true,
selected:true,
parseOnLoad:true,
preventCache:true,
refreshOnShow:true
}, id);
centerPane.addChild(newTab);
centerPane.selectChild(newTab);
}
};
When we click with right mouse button on a any site link, there's a dropdown menu. One of the options here is "Open in new window". For some reasons, I need to disable this possibility for all site links. Is it possible?
Thanks in advance.
UPDATE
The reason for doing this
The site menu has 2 types of menu items: ordinary links to pages and fake links, that cause popup window with certain information. I have a jquery function, that shows this popup and returns false for the link. And when a user "Open in new window" some of fake links, page reloads, but popup does not appear. And the user is looking at the empty page. That's not good I think :)
No, not in all browsers, probably not in any browser. You can't change it's GUI without the specific browser giving you access to it, as the browser GUI isn't a standard in any way.
And why would you like to do that anyway?
You can use javascript to change the url and add the action on click so when the user try to open it in new windows nothing happens
As far as I know you cant disable this option since its provided by the web browser itself and each one implements the feature differently. You can however check the referrer value in the HTTP headers and ensure that its a correct value. When a user opens a new window the referrer should be set to null allowing you to intervene.
I would also hope that you consider not implementing this because some browsers have inconsistent behavior or an appliance on the network might remove the header information which would leave people unable to use your site.
If you are using javascript, you might as well make clicking links execute a javascript method. That way opening it up in a new page does nothing.
Remove the HREF attribute from the tag, but apply CSS styling to make it look like a link in all browsers. Then use a Javascript onclick function to do what it is you want to do. Easy. Case in point: look at the "add comment" link / button on this very page. If you right-click on it, you notice that there is no "Open in new Window" option :)
that ain't good for website reference, but if you REALLY need to block access from new windows...
How about generating your page content with Ajax?
something like that:
HTML
JAVASCRIPT
function xmlhttp() {
var x;
try {
x = new ActiveXObject('Microsoft.XMLHTTP');
} catch (e) {
try {
x = new ActiveXObject('Msxml2.XMLHTTP');
} catch (e) {
try {
x = new XMLHttpRequest();
} catch (e) {
x = false;
}
}
}
return x;
}
function page(idMenu) {
var http = xmlhttp();
if (!http) {
alert('XmlHttpRequest non supporté');
} else {
var url = 'pageOutput.php?pageNo=' + idMenu;
http.open('GET', url, true);
http.onreadystatechange = function () {
if (http.readyState == 4 && http.status == 200) {
document.getElementById('pageContent').innerHTML = http.responseText;
}
}
http.send();
}
}
now all you have left to do is create a PHP where you check whatever menu ID is called and echo page content according to $_GET['pageNo']. if you already got your pages on many PHP/HTML you may also just do include and echo them...
if(isset($_GET['pageNo'])){
//echo page code here according to $_GET['pageNo'] value
}else{
//echo main page
}
EDIT: You may also add URL param to refer the current page so the user can reload your page from a new window without having no params loaded...
disable right click should do it...
http://www.billybear4kids.com/clipart/riteclic.htm
UPDATE
It's possible to disable context menu on any element we want:
$('selector').contextmenu( function() {
return false;
});
To disable context menu on the page completely, we can use the following:
$('*').contextmenu( function() {
return false;
});
OLD ANSWER
OK, guys, if we can't change browsers specific features, then we have to think of some other way. As for me, the most suitable idea has been suggested by Quentin. So I wrote a little jquery script to replace all links, that I need to be fake, with span elements.
// transform links with .fake class only
$('.nav >li > a.fake').each(function () {
// save all necessary link information
var href = $(this).attr('href');
var text = $(this).html();
// add fake span
$(this).after('<span>'+text+'</span>');
// save new span into a variable and after this we can remove the link
var mySpan = $(this).siblings('span');
$(this).remove();
// emulate link default behaviour
mySpan.click(function () {
window.location.href = href;
});
});