Skip to content

Instantly share code, notes, and snippets.

@cou929
Created June 15, 2010 14:04
Show Gist options
  • Save cou929/439168 to your computer and use it in GitHub Desktop.
Save cou929/439168 to your computer and use it in GitHub Desktop.
window.addEventListener('load', function() { recommend.init(); }, false);
window.addEventListener("unload", function() { recommend.uninit(); }, false);
var recommend = {
recommendListUrl: 'https://secure.mozilla-japan.org/fxce/recommended-addons/rules.json',
firstRunPageUrl: 'https://dev.mozilla.jp/campusedition/recommend-howto/',
recommendNumber: 3,
htmlns: 'http://www.w3.org/1999/xhtml',
iconUri: 'https://addons.mozilla.org/en-US/firefox/images/addon_icon/',
linkUriPre: 'https://addons.mozilla.org/ja/firefox/addon/',
installUriPre: 'https://addons.mozilla.org/ja/firefox/downloads/latest/',
installUriMiddle: '/addon-',
installUriPost: '-latest.xpi',
installIcon: 'chrome://recommend/skin/images/plus-green-8x9.gif',
amoAddonApiUri: 'https://services.addons.mozilla.org/en-US/firefox/api/1.3/addon/',
oldUrl: null,
// element cache
bundle: null,
statusbar: null,
popupPanel: null,
urlbarIcons: null,
contentWrapper: null,
statusbarIconImage: null,
urlbarIconImage: null,
recommendAddonsList: {
isLoaded: false,
json: {}
},
init: function() {
// element cache
recommend.bundle = document.getElementById('recommend-strings');
recommend.statusbar = document.getElementById('status-bar');
recommend.popupPanel = document.getElementById('recommend-popup-div');
recommend.urlbarIcons = document.getElementById('urlbar-icons');
recommend.statusbarIconImage = recommend.constructIconImage('recommend-statusbar-icon-image');
recommend.urlbarIconImage = recommend.constructIconImage('recommend-urlbar-icon-image');
recommend.constructPopupPanelSkelton();
recommend.contentWrapper = document.getElementById('recommend-panel-wrap');
// add event listeners
gBrowser.addProgressListener(recommend.urlBarListener, Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
// load recomendation list
if (!recommend.recommendAddonsList.isLoaded) {
var xmlReq = new XMLHttpRequest();
xmlReq.onreadystatechange = recommend.onReadyStateChange(xmlReq);
xmlReq.open('GET', recommend.recommendListUrl, true);
xmlReq.send(null);
}
// first-run page
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService).getBranch("extensions.recommend.");
var isFirstrun = true;
try {
isFirstrun = prefs.getBoolPref("firstrun");
} catch(e) {
} finally {
if (isFirstrun){
prefs.setBoolPref("firstrun", false);
window.setTimeout(function() {
gBrowser.selectedTab = gBrowser.addTab(recommend.firstRunPageUrl);
}, 1500);
}
}
},
uninit: function() {
gBrowser.removeProgressListener(recommend.urlBarListener);
},
urlBarListener: {
QueryInterface: function(aIID) {
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
onLocationChange: function(aProgress, aRequest, aUri) {
recommend.processNewUrl(aUri);
},
onStateChange: function() {},
onProgressChange: function() {},
onStatusChange: function() {},
onSecurityChange: function() {},
onLinkIconAvailable: function() {}
},
processNewUrl: function(aUri) {
if (!aUri || aUri.spec == recommend.oldUrl)
return;
recommend.runRecommend();
recommend.oldUrl = aUri.spec;
},
runRecommend: function() {
var currentDocument = gBrowser.selectedBrowser.contentDocument;
var contents = recommend.makeContents(recommend.recommendAddonsList, currentDocument.location.href);
recommend.render(contents);
},
render: function(contents) {
recommend.clearPopupPanel();
recommend.hideIcon();
if (contents.isValid) {
var iconPath = '';
var linkUri = '';
var extensionUri = '';
for (var i=0; i<contents.addons.length; i++) {
iconPath = recommend.iconUri + contents.addons[i].id + '/';
linkUri = recommend.linkUriPre + contents.addons[i].id + '/';
extensionUri = recommend.installUriPre + contents.addons[i].id + recommend.installUriMiddle + contents.addons[i].id + recommend.installUriPost;
if (typeof contents.addons[i].id != 'number') {
iconPath = 'chrome://recommend/skin/images/default_icon.png';
linkUri = contents.addons[i].id;
extensionUri = contents.addons[i].id;
}
var html = '<div class="recommend-extension" xmlns="http://www.w3.org/1999/xhtml">'
+ '<div class="recommend-icon"><img src="' + iconPath + '" /></div>'
+ '<div class="recommend-content">'
+ '<div class="recommend-content-header">'
+ '<span class="recommend-title">' + contents.addons[i].title + '</span>'
+ '<div class="recommend-addonRating" rating="' + contents.addons[i].rating + '" ></div>'
+ '</div>'
+ '<div class="recommend-content-main">'
+ '<p class="recommend-summary">' + contents.addons[i].summary + '</p>'
+ '<p class="recommend-link">'
+ '<a onclick="recommend.openNewTab(\'' + linkUri + '\')" target="_blank">'
+ recommend.bundle.getString('popupPanel.linkText')
+ '</a></p>'
+ '<p class="recommend-install">'
+ '<a href="' + extensionUri + '" onclick="recommend.toggleInstall(event)">'
+ '<img src="' + recommend.installIcon + '" />'
+ '<span>' + recommend.bundle.getString('popupPanel.installText') + '</span>'
+ '</a></p>'
+ '</div>'
+ '<div class="recommend-clear"></div>'
+ '</div>';
var fragment = document.createRange().createContextualFragment(html);
recommend.contentWrapper.appendChild(fragment);
}
recommend.showIcon();
}
},
onReadyStateChange: function(xmlReq) {
return function() {
if (xmlReq.readyState == 4 && xmlReq.status == 200) {
recommend.recommendAddonsList.json = JSON.parse(xmlReq.responseText);
recommend.recommendAddonsList.isLoaded = true;
recommend.checkInstalledAddons();
recommend.setRatingValues();
}
};
},
onReadyStateChangeForRating: function(xmlReq, ruleNum, addonNum) {
return function() {
if (xmlReq.readyState == 4 && xmlReq.status == 200) {
try {
var ratingValue = xmlReq.responseXML.getElementsByTagName('rating')[0].childNodes[0].nodeValue;
recommend.recommendAddonsList.json.rules[ruleNum].addons[addonNum].rating = ratingValue;
} catch (x) {
Application.console.log(recommend.recommendAddonsList.json.rules[ruleNum].addons[addonNum].title);
}
}
};
},
showIcon: function() {
// recommend.statusbar.appendChild(recommend.statusbarIconImage);
recommend.urlbarIcons.insertBefore(recommend.urlbarIconImage, recommend.urlbarIcons.childNodes[0]);
},
hideIcon: function() {
var statusbarIconImage = document.getElementById('recommend-statusbar-icon-image');
if (statusbarIconImage) {
recommend.statusbar.removeChild(statusbarIconImage);
}
var urlbarIconImage = document.getElementById('recommend-urlbar-icon-image');
if (urlbarIconImage) {
recommend.urlbarIcons.removeChild(urlbarIconImage);
}
},
clearPopupPanel: function() {
while (recommend.contentWrapper.firstChild){
recommend.contentWrapper.removeChild(recommend.contentWrapper.firstChild);
}
},
popup: function(id) {
var position = (id == 'recommend-statusbar-icon-image') ? 'before_end' : 'after_end';
document.getElementById('recommend-popup-panel').openPopup(document.getElementById(id), position, -1, -1, false);
},
openNewTab: function(uri) {
document.getElementById('recommend-popup-panel').hidePopup();
gBrowser.selectedTab = gBrowser.addTab(uri);
},
constructIconImage: function(id) {
var iconImage = document.createElement('image');
iconImage.setAttribute('src', 'chrome://recommend/skin/images/puzzle16.png');
iconImage.setAttribute('id', id);
iconImage.setAttribute('onclick', "recommend.popup('" + id + "')");
iconImage.setAttribute('tooltiptext', recommend.bundle.getString('puzlleIcon.tooltiptext'));
return iconImage;
},
constructPopupPanelSkelton: function() {
var titleHtml = '<div xmlns="http://www.w3.org/1999/xhtml"><div class="recommend-panel-title">'
+ recommend.bundle.getString('popupPanel.panelTitle')
+ '</div><div id="recommend-panel-wrap"></div></div>';
var fragment = document.createRange().createContextualFragment(titleHtml);
recommend.popupPanel.appendChild(fragment);
},
checkInstalledAddons: function() {
var extensionsManager = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var itemsList = extensionsManager.getItemList(2, {});
var json = recommend.recommendAddonsList.json;
for (var i=0; i<itemsList.length; i++) {
var installedName = itemsList[i].name;
var re = new RegExp(installedName, "i");
for (var j=0; j<json.rules.length; j++)
for (var k=0; k<json.rules[j].addons.length; k++) {
var recommendName = json.rules[j].addons[k].title;
if (re.test(recommendName) || recommendName == installedName)
json.rules[j].addons[k].installed = true;
else
json.rules[j].addons[k].installed = false;
}
}
},
setRatingValues: function() {
var json = recommend.recommendAddonsList.json;
for (var i=0; i<json.rules.length; i++) {
for (var j=0; j<json.rules[i].addons.length; j++) {
json.rules[i].addons[j].rating = 0;
if (typeof json.rules[i].addons[j].id == 'number') {
var xmlReq = new XMLHttpRequest();
xmlReq.onreadystatechange = recommend.onReadyStateChangeForRating(xmlReq, i, j);
xmlReq.open('GET', recommend.amoAddonApiUri + json.rules[i].addons[j].id, true);
xmlReq.send(null);
}
}
}
},
makeContents: function(recommendAddonsList, currentUri) {
var ret = {isValid: false, addons: []};
if (recommend.recommendAddonsList.isLoaded) {
var json = recommend.recommendAddonsList.json;
for (var i=0; i<json.rules.length; i++) {
var urlRegexp = new RegExp(json.rules[i].url, "i");
if (urlRegexp.test(currentUri)) {
for (var j=0; j<json.rules[i].addons.length; j++) {
if (!json.rules[i].addons[j].installed) {
ret.addons.push({'id': json.rules[i].addons[j].id,
'title': json.rules[i].addons[j].title,
'summary': json.rules[i].addons[j].summary,
'rating': json.rules[i].addons[j].rating
});
}
}
}
}
}
if (ret.addons.length > 0)
ret.isValid = true;
if (ret.addons.length > 3)
ret.addons = recommend.shortenAddonsList(ret.addons);
return ret;
},
shortenAddonsList: function(addons) {
var ret = addons;
while (ret.length > 3) {
var index = recommend.getRandomInt(0, ret.length);
ret.splice(index, 1);
}
return ret;
},
getRandomInt: function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
toggleInstall: function(aEvent) {
var params = {
"test": aEvent.target.href
};
InstallTrigger.install(params);
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment