Set New tab/window URL in Safari Extension - javascript

I am creating a safari extension. how do I manually set the new tab/window to a URL of my choosing? I used some of logic from this post to make sure I am only taking over user created tabs/windows Safari extension: Event for a completely new tab?
I set up my new tab event listener:
safari.application.addEventListener("open", handleOpen, true);
Using this to handle the open tab/window:
function handleOpen(e) {
if (e.target instanceof SafariBrowserTab) {
e.target.addEventListener('beforeNavigate', handleBeforeNavigate, false);
setTimeout(function () {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
takeOverTab();
}, 50);
}
}
function handleBeforeNavigate(e) {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
if (e.url === null) {
takeOverTab();
}
}
function takeOverTab() {
window.location.href = "http://www.yahoo.com";
}
I am able to alert when a new tab/window is opened, but I cant for the life of my figure out how to actually browse to the url. I tried window.location.href but that doesn't seem to do anything, I still get the "top sites" page when I open a new tab.
Thanks in advance!

Change your takeOverTab function as follows:
function takeOverTab(tab) {
tab.url = "http://www.yahoo.com";
}
And modify the function call to include a reference to the tab:
takeOverTab(e.target);
Also, in your beforeNavigate handler, you should add e.preventDefault() to prevent the tab from loading whatever it was going to load:
function handleBeforeNavigate(e) {
e.target.removeEventListener('beforeNavigate', handleBeforeNavigate, false);
if (e.url === null) {
e.preventDefault();
takeOverTab();
}
}

Related

How to get Chrome to throw exception when changing url if it fails

I have a reference to a new window opened with js
var theNewTab="";
theNewTab = window.open(theURL, 'winRef');
then I change the url in the as the user clicks on another link in the parent window using
theNewTab.location.href = targetLink;
theNewTab.focus();
The problem i'm having with chrome that id doesn't throw exception if the the window doesn't exist anymore "closed" unlink FF & IE which im using to open the window again.
try {
theNewTab.location.href = targetLink;
theNewTab.focus();
}catch(err) {
theNewTab = window.open(theURL, 'winRef');
theNewTab.focus();
}
PS: I tried to use "window.open" every time but if the window already open, id does not reload the page or it does but it doesn't re-execute the script I have in document ready I think.
I'm not sure what you need.
<script type="text/javascript">
var theNewTab = null;
function openNewTab(theURL) {
if (theNewTab == null || theNewTab.closed == true) {
theNewTab = window.open(theURL);
} else {
theNewTab.location.href = theURL;
}
theNewTab.focus();
};
// use the function when you need it
$('a').click(function() {
openNewTab($(this).attr('href'));
});
</script>
Is this example helpful for you?

How to right click from javascript

It seems that it is not possible to emulate a right click in javascript.
I have tried to right click an element (paragraph) in an iframe like this:
html
<button onclick="popup_context_menu_in_iframe()">
popup menu
</button>
<br/><br/>
<iframe srcdoc="<p>Hello world!</p>">
</iframe>
script
function popup_context_menu_in_iframe()
{
var $element = $('iframe').contents().find('p');
var element = $element.get(0);
if (window.CustomEvent) {
element.dispatchEvent(new CustomEvent('contextmenu'));
} else if (document.createEvent) {
var ev = document.createEvent('HTMLEvents');
ev.initEvent('contextmenu', true, false);
element.dispatchEvent(ev);
} else { // Internet Explorer
element.fireEvent('oncontextmenu');
}
}
https://jsfiddle.net/sca60d64/2/
It seems like it actually is impossible to make the context menu appear so I need to find other ways.
I first headed at creating a chrome extension to add a function to the window object, callable from any script that is using some extra power to do it.
However, A chrome extension surprisingly seems to not provide me with a way of creating functions in the window object. I have not taken a look if it even gives me the power to popup the context menu.
I did not experiment a lot with chrome extensions before giving up on that.
So I need another solution.
It doesnt matter if a solution only works in google chrome or if there is no guarantee that it will stop work in the next version.
Should I hook the chrome process with a dll? Is that it?
You can call a dll by an exe file in the chrome extension through Native Messaging. I have provided a sample of Native Messaging procedure in this answer:
See the answer of this question
I hope to be useful.
This should work with this markup:
<div id="mything">
Howdy this is my thing
</div>
event handler:(disable default)
var el=document.getElementById("mything");
el.addEventListener('contextmenu', function(ev) {
ev.preventDefault();
alert('success!');
return false;
}, false);
Then when you execute this, "sucess!" alerts followed by the text changing to "Howdy this is my thing this is canceled":
EDIT event handler:(do NOT disable default)
var el=document.getElementById("mything");
el.addEventListener('contextmenu', function(ev) {
ev.preventDefault();
alert('success!');
return true;
}, true);
Then when you execute this, "sucess!" alerts followed by the text changing to "Howdy this is my thing this is NOT canceled":
function simulateRightClick() {
var event = new MouseEvent('contextmenu', {
'view': window,
'bubbles': true,
'cancelable': true
});
var cb = document.getElementById('mything');
var canceled = !cb.dispatchEvent(event);
var cbtext = cb.textContent;
if (canceled) {
// A handler called preventDefault.
console.log("canceled");
cb.textContent = cbtext + "this is canceled";
} else {
// None of the handlers called preventDefault.
cb.textContent = cbtext + "this is NOT canceled";
console.log("not canceled");
}
}
simulateRightClick();
Test it out here: https://jsfiddle.net/MarkSchultheiss/bp29s0j4/
EDIT: alternate selector:
var fcb = document.getElementById('myframe').contentWindow.document.getElementById('pid');
fcb.addEventListener('contextmenu', function(ev) {
ev.preventDefault();
alert('successFrame!');
return false;
}, false);
Given this markup:
<iframe id='myframe' srcdoc="<p id='pid'>Hello world!</p>">
</iframe>

Why my window postMessage isn't working ? Not using iframe

So I've been trying several things in my project to send cross-domain variables.
I have a button that I click, and opens a new browser tab.
$('#btn').on('click', function(e) {
var popup = window.open("other-domain.html", "_blank");
window.popup.onload = function() {
popup.postMessage(variableToSend, '*');
}
// I even tried doing this directly, without the onload
popup.postMessage(variableToSend, '*');
});
From my other domain I do this:
(function($) {
var listener = function(event) {
console.log(event.data);
}
var setupEvents = function() {
if(window.addEventListener) {
window.addEventListener("message", listener, false);
}else{
window.attachEvent("onmessage", listener);
}
}
setupEvents();
})(jQuery);
I never receive anything from my parent window, so never gets inside listener function.
Do you know what could be wrong ? Been fighting with this for 2 days already.
Thanks in advance,
ADDED:
I tried doing this from the other domain window (children)
window.parent.postMessage('Hi!', '*');
And it receives the message correctly. Looks like I'm missing something, maybe a Timeout somewhere?

Change a parent window's URL using history pushState when link in Iframe is clicked

I have a page that has a header and sidebar with a right content panel that is an Iframe.
In a page loaded into the right content panel, I am trying to have a clicked link update the Browser URL in the parent window to the URL of the new page that is loaded into the Iframe.
I do not want the actual parent window to reload the URL but simply to update the URL in the address bar.
Something like:
window.history.pushState('obj', 'newtitle', '/bookmarks/list/');
Is this possible from an Iframe?
I was able to accomplish updating the parent windows URL in the address bar using history.pushState by sending the new URL to the parent from the child Iframe window using postMessage and on the parent window listening for this event.
WHen the parent receives the child iframes postMessage event, it updates the URL with pushSTate using the URL passed in that message.
Child Iframe
<script>
// Detect if this page is loaded inside an Iframe window
function inIframe() {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
// Detect if the CTRL key is pressed to be used when CTRL+Clicking a link
$(document).keydown(function(event){
if(event.which=="17")
cntrlIsPressed = true;
});
$(document).keyup(function(){
cntrlIsPressed = false;
});
var cntrlIsPressed = false;
// check if page is loaded inside an Iframe?
if(inIframe()){
// is the CTRL key pressed?
if(cntrlIsPressed){
// CTRL key is pressed, so link will open in a new tab/window so no need to append the URL of the link
}else{
// click even on links that are clicked without the CTRL key pressed
$('a').on('click', function() {
// is this link local on the same domain as this page is?
if( window.location.hostname === this.hostname ) {
// new URL with ?sidebar=no appended to the URL of local links that are clicked on inside of an iframe
var linkUrl = $(this).attr('href');
var noSidebarUrl = $(this).attr('href')+'?sidebar=no';
// send URL to parent window
parent.window.postMessage('message-for-parent=' +linkUrl , '*');
alert('load URL with no sidebar: '+noSidebarUrl+' and update URL in arent window to: '+linkUrl);
// load Iframe with clicked on URL content
//document.location.href = url;
//return false;
}
});
}
}
</script>
Parent window
<script>
// parent_on_message(e) will handle the reception of postMessages (a.k.a. cross-document messaging or XDM).
function parent_on_message(e) {
// You really should check origin for security reasons
// https://developer.mozilla.org/en-US/docs/DOM/window.postMessage#Security_concerns
//if (e.origin.search(/^http[s]?:\/\/.*\.localhost/) != -1
// && !($.browser.msie && $.browser.version <= 7)) {
var returned_pair = e.data.split('=');
if (returned_pair.length != 2){
return;
}
if (returned_pair[0] === 'message-for-parent') {
alert(returned_pair[1]);
window.history.pushState('obj', 'newtitle', returned_pair[1]);
}else{
console.log("Parent received invalid message");
}
//}
}
jQuery(document).ready(function($) {
// Setup XDM listener (except for IE < 8)
if (!($.browser.msie && $.browser.version <= 7)) {
// Connect the parent_on_message(e) handler function to the receive postMessage event
if (window.addEventListener){
window.addEventListener("message", parent_on_message, false);
}else{
window.attachEvent("onmessage", parent_on_message);
}
}
});
</script>
Another solution using Window.postMessage().
Iframe:
/test
/test2
<script>
Array.from(document.querySelectorAll('a')).forEach(el => {
el.addEventListener('click', event => {
event.preventDefault();
window.parent.postMessage(this.href, '*');
});
});
</script>
Main page:
Current URL: <div id="current-url"></div>
<iframe src="iframe-url"></iframe>
<script>
const $currentUrl = document.querySelector('#current-url');
$currentUrl.textContent = location.href;
window.addEventListener('message', event => {
history.pushState(null, null, event.data);
$currentUrl.textContent = event.data;
});
</script>
See demo on JS Fiddle.

jquery/jscript Prevent open multiple popups

I open a popup with the click event of a hyperlink... The popup contains records from a server.
The problem is that when I click rapidly, there are multiple popups at once.
There is a way to prevent this? in which can open a single popup
My code:
$('.wrapper_form a.add').click(function(e)
{
e.preventDefault();
if(typeof(currentPopup) == 'undefined' || currentPopup.closed)
{
url = 'server_page.aspx';
currentPopup = window.open(url,'server','height=500,width=800');
if (window.focus) {currentPopup.focus()}
}
else
{
currentPopup.focus();
}
});
Here is one approach. Not the best solution but it should work. What this code will do is protect against clicking the link a bunch of times and have it open a new instance for each click. This code will not allow the window to be opened more than once in a 1/2 interval, of course you can change the timing.
var hopefullyThisIsNotInGlobalScope = false;
$('.wrapper_form a.add').click(function(e)
{
if (hopefullyThisIsNotInGlobalScope)
{
return false;
}
hopefullyThisIsNotInGlobalScope = true;
setTimeout(function () { hopefullyThisIsNotInGlobalScope = false; }, 500);
e.preventDefault();
if(typeof(currentPopup) == 'undefined' || currentPopup.closed)
{
url = 'server_page.aspx';
currentPopup = window.open(url,'server','height=500,width=800');
if (window.focus) {currentPopup.focus()}
}
else
{
currentPopup.focus();
}
});
Assuming the popup is on the same domain as the window launching it you might be able to replace hopefullyThisIsNotInGlobalScope variable with a global var attached to the window. You can then set that variable when the popup launches and alter it using the browser unload event

Categories