FF Addon SDK page mod script to content script communication not working - firefox-addon-sdk

For starters, I've been trying to allow communication from a page script to a content script. If the docs are accurate, this should be easy. Here's what I'm doing, I believe fully in accordance with https://addons.mozilla.org/en-US/developers/docs/sdk/latest/dev-guide/guides/content-scripts/communicating-with-other-scripts.html#Using%20the%20DOM%20postMessage%20API :
And here's my live test case:
main.js:
exports.main = function() {
var data = require('sdk/self').data,
pageMod = require('sdk/page-mod');
pageMod.PageMod({
include: '*',
contentScriptFile: data.url('postMessageRelay.js'),
});
};
postMessageRelay.js
// Trying with window.addEventListener also doesn't work
document.defaultView.addEventListener('message', function (e) { // e.data, e.origin
console.log('would be good if it got here:'+e.data);
});
console.log('it gets here at least');
And the JavaScript within a regular HTML file (on a normal remote server, not file or localhost):
try {
window.postMessage('webappfind', window.location.href);
}
catch(e) {
alert(e);
}
This really looks like either a full-blown bug for this functionality or a problem with the docs... I had similar problems trying to communicate via custom events so going a little bananas...

Answered in Bug 910972, but leaving it here to for future visitors of SO:
The issue was with the page immediately firing postMessage in the head tag, so the page-mod script isn't even yet attached to the page to listen to the message event. The communication back and forth between page and content scripts as in this example works as long as this timing is taken into consideration

Related

Is it possible to display data from SeatGeek API call on my Squarespace site?

Is it possible to connect to the SeatGeek API to display local event data on a Squarespace site?
The Squarespace API docs all seem directed towards commerce-related goals.
I am familiar with how to connect to the SeatGeek API in the context of a mobile application. But I don't know whether connecting to APIs (other than those listed for commerce) from within a Squarespace is doable.
SeatGeek would be an unofficial integration . I've posted on the squarespace forums with no response, so asking here to see if anyone out there knows about it.
Thanks very much for any help!
Squarespace websites above the "Personal" plan tier support the addition of custom JavaScript via Code Blocks and Code Injection.
Therefore, if SeatGeek supports using their API via JavaScript (and it appears that they do), then you can obtain the data from within your Squarespace website.
Where within your site the code is added and what initialization methods are used will vary on a case-by-case basis. For example, factors include: whether you are using Squarespace 7.0 or 7.1 and whether the template you're using supports AJAX Loading and has it enabled.
However, regardless of where the code is added and the initialization methods used, it looks to me, based on what I see here, that obtaining data from SeatGeek via JavaScript is possible. (Select "JavaScript > XMLHttpRequest" or "JavaScript > Fetch" from the upper-right "Code Snippet" panel where it says "(Node.js) Unirest" by default):
var data = null;
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === this.DONE) {
console.log(this.responseText);
}
});
xhr.open("GET", "https://seatgeek-seatgeekcom.p.rapidapi.com/events");
xhr.setRequestHeader("x-rapidapi-host", "seatgeek-seatgeekcom.p.rapidapi.com");
xhr.setRequestHeader("x-rapidapi-key", "SIGN-UP-FOR-KEY");
xhr.send(data);
Or, via fetch:
fetch("https://seatgeek-seatgeekcom.p.rapidapi.com/events", {
"method": "GET",
"headers": {
"x-rapidapi-host": "seatgeek-seatgeekcom.p.rapidapi.com",
"x-rapidapi-key": "SIGN-UP-FOR-KEY"
}
})
.then(response => {
console.log(response);
})
.catch(err => {
console.log(err);
});
While it varies on a case-by-case basis, in most cases you'll want to use the sitewide code injection area vs. code blocks or page-level code injection. Then, on Squarespace 7.0 sites, you'll want to wrap your code in:
window.Squarespace.onInitialize(Y, function() {
// do stuff here
});
For Squarespace 7.1 sites on the other hand, one would usually wrap the code in:
document.addEventListener('DOMContentLoaded', function() {
// do stuff here
}, false);
Finally, you'll need to think about how you're outputting the data. You could either add HTML markup via a Code Block in the body of the target page, or add the markup to the page as part of your JavaScript.

Open ColorBox with link generated by hashchange event

Our company wants to include a LinkedIn Share Button in the news section of our website. It is relatively simple and consists of a carousel that open up the news items individually in Colorbox windows. We want the LinkedIn button to be within the Colorbox windows so that we can share the details of each news item.
So, I have successfully got the hashchange event to work when Colorbox is activated in order to show the correct url for each news item and the LinkedIn button does return the correct url when the news item is shared, however Colorbox doesn't open, it simply links to the index page of our site. My question is how do I fire up Colorbox from this shared link?
I have researched a lot of similar questions but cannot seem to get it working. Any help would be much appreciated. Thank you.
Below is my js and also a jsfiddle: http://jsfiddle.net/stegern/WvfsA/11/
$(document).ready(function()
{
//Carousel for news items
$('#news-carousel').show();
$('#news-carousel').jcarousel({
vertical:true,
scroll:true,
wrap:'circular'
}
);
$('.popup').colorbox({
title: function()
{
var url = $(this).attr('href');
return '#' + url;
},
onOpen:function()
{
window.location.hash = $(this).attr('href');
},
onClosed:function()
{
window.location.hash = "";
},
opacity: 0.7,
transition: 'fade'
}
);
//Attempt to open ColorBox when url is shared
$(function(){
var hash = window.location.hash;
if ('onhashchange' in window)
{
window.onhashchange = hashChanged;
}
else
{
setInterval(function(){
if (window.location.hash != hash)
{
hash = window.location.hash;
hashChanged();
}
}, 500);
}
var hashChanged = function(){
$.colorbox();
}
}
);
});
UPDATE
I have done some more research and discovered that I need to load my content in an iframe rather than using Ajax. I then need to add a querystring to my news item links and parse the parameters from the querystring in order to pass them to ColorBox.
However I am now getting a semantic issue with my js (line 8 Expected ')' token) which I don't know how to resolve. Can someone please explain.
Here is my html markup:
<ul>
<li>News Item One
</li>
<li>News Item Two
</li>
<li>News Item Three
</li>
And here is my js:
function getParameters() {
var
settingsObject = {},
hash,
hashes = location.search.substring(1).split(/&/),
i;
for (i = 0; i & lt; hashes.length; i++) {
hash = hashes[i].split('=');
settingsObject[hash[0]] = hash[1];
}
return settingsObject;
}
$('a.cb').colorbox($.extend({
iframe: true,
width: '800',
height: '600'
}, getParameters()));
I also have a jsfiddle setup at: http://jsfiddle.net/stegern/NtSvg/7/
Try putting some example code in a fiddle at http://jsfiddle.net/ then share here.
You posted your js, but we don't have the markup you're trying to use it on, so post the minimum necessary html code to make your example work in a fiddle.
It will help others visualize your problem much easier and quite possibly get you a solution a lot faster.
Ajax isn't loading because browsers typically disallow cross-origin file access for security reasons.Since the main code is hosted on jsfiddle, it forbids you to load pages from your site via ajax.
A quick workaround, if you're using Chrome, you can start it in a less secure mode, like indicated here: https://superuser.com/questions/593726/is-it-possible-to-run-chrome-with-and-without-web-security-at-the-same-time
I just tested now by opening a command prompt in the folder where chrome.exe is located and ran chrome.exe --user-data-dir="C:/Chrome dev session" --disable-web-security
Then I opened http://jsfiddle.net/WvfsA/12/ , where I stripped down your js to the minimum. You'll see your content is now loaded via ajax by colorbox, however, you're doing something wrong with those paths, because the images can't be found.
I took a look at http://jsfiddle.net/WvfsA/13/ and I'm not sure exactly why you have 2 nested $(function () {}), I saw that in Framework & Extensions, ondomready is already selected, so you don't really need to wrap your main function(s) in anything.
Here's a quick screenshot as proof that it works:
http://i.imgur.com/jAiUW28.png?1
When you were developing, were you running your example through a server? You need to have a local server in order for anything ajax-related to work.
Install XAMPP http://www.apachefriends.org/en/xampp.html if you haven't already?
Edit: or you could develop on Chrome launched with that flag I mentioned, to bypass the need of a local webserver, but it's not a really good idea.

jquery.form.js is not working in Internet Explorer 9

I have a simple form with a file upload control. The form will be posted once I click on the upload button. I'm trying to do a jquery-ajax post, using the jquery.form.js.
My code is as follows,
var options = {
beforeSubmit: function (formData, jqForm, options) {
$(".loaderImage").show();
return true;
},
success: function (responseText, statusText, xhr, $form) {
$("#result").html(responseText);
},
error: function(xhr) { alert(xhr.responseText); }
};
$("#AjaxFileUpload").ajaxSubmit(options);
return false;
It works fine in Google Chrome, Firefox and Internet Explorer 10. The problem with Internet Explorer 9 is, after debugging, it doesn't enter the success(). Any pointers on what's going wrong? There are no errors in the console either.
I added the error option as well, but the issue is the same, the breakpoint doesn't hit the alert.
I just had a look at the network traffic. There is no POST request going (in Internet Explorer 9) when I click the upload button, but there's a POST request going in Internet Explorer 10.
I cleared the cache and reset browser settings as well. But the issue persists.
badZoke, I was experiencing this same problem yesterday and most of today and finally figured out what was causing it (in my case). This might be helpful for your situation, as well:
Internet Explorer has restrictions about form submission when the form is not currently in the DOM. In my case, a user interacted with a button in a modal popup (which also contained the form). When they clicked, the form was removed from the DOM (but still accessible via a js var) and replaced with a loading bar. I then called myForm.ajaxSubmit(options); which in IE<10 attempts a submission of that form to a temporary <iframe/>. Not allowed unless the form is in the DOM.
If your code above was a simplification of your actual scenario and you were doing something similar to me, this may be your problem. Best of luck.
The first step would be to see if the error callback is invoked:
var options = {
beforeSubmit: function (formData, jqForm, options) {
$(".loaderImage").show();
return true;
},
success: function (responseText, statusText, xhr, $form) {
$("#result").html(responseText);
},
error: function(xhr) { alert(xhr.responseText); }
};
$("#AjaxFileUpload").ajaxSubmit(options);
Your code is working fine on my computer, and I'm using Internet Explorer 9. Maybe the problem is not here.

What is the best practise to create a notification services such as in facebook website?

What is the best practise to create a notification services such as in facebook website. I see it is noy good to make a http request periodically to check if there is updates on the server or not.
This is calling long polling (type of an AJAX).
I'll try to describe a situation where you use PHP and JS, as Facebook does.
You send an AJAX request to the server.
Infinite loop starts on the server side
<?php
$seconds = 0;
while(true) {
if ($seconds >= 55) {
die("no_notifications");
}
if (false !== ($notifications_json = getNotifications()) {
echo $notifications_json;
die();
}
$seconds++;
sleep($TIME_TO_WAIT_BEFORE_NEXT_CHECK); //this number should be based on your performance
}
?>
When there's a new notification, script die() s and response is handled by javascript
New request is sent to the server, again, waiting to new notifications
With javascript (I'll show you an example with jQuery), you can use something like
$(function() {
pollForNotifications();
});
function pollForNotifications() {
$.get("/notifications", function(response) {
if (response != "no_notifications") {
alert("You've got one new notification!");
//more proccessing here
}
pollForNotifications();
});
}
Remember that there are time limits in specific browsers to complete the request! You SHOULD die() after some amount of time (55 seconds) even if you don't have any notifications, to prevent troubles (this prevention is included in script above)!
You could use the WebSocket api for a real push service (not ajax polling). But it is part of HTML5 and not supported by all browsers and web servers at the moment.
You might want to check out Pusher. It'll handle pushing notifications and supports many browsers.

Google Chrome Extension - Accessing The DOM

I have been searching around the web to find out how to access the current tabs DOM to extract information out of a page from the background.html. So far I have had no luck, or at least nothing I could get to work properly.
To state the problem simply. I would like to get src of a iFrame on the page. Any Suggestions?
One way, you an treat this as a single one time request to the content-script which will fetch the dom you want to access.
http://code.google.com/chrome/extensions/messaging.html#simple
Basically, your content script sets up the listener:
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
else
sendResponse({}); // snub them.
});
And your background page sends a single lived request:
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});
});
When you send your response, you send it as JSON data, you can fetch whatever you want (such as html, dom, text, etc).
That is currently the only way to let the background page know anything about the contents of a page. Remember you would need content scripts and tab permissions.