Commit a0528e49 authored by Christian's avatar Christian
Browse files

works mostly, sans fade-out-in

parent 84e44157
(function() {
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
console.log('--> content.js: chrome.runtime.onMessage.addListener');
console.log('--> content.js: msg.text: ' + msg.text);
//var baseUserURL = 'http://redddate.com/u/';
var baseUserURL = 'http://localhost:8000/u/';
if (msg.text == 'harvest_usernames') {
console.log('--> content.js: msg.text == "harvest_usernames"');
sendResponse(['user1', 'user2', 'user3']);
//sendResponse(findRedditUsernames());
}
var elHtml = document.getElementsByTagName('html')[0];
var elHead = document.getElementsByTagName('head')[0];
var elBody = document.getElementsByTagName('body')[0];
var elContent = elBody.querySelector('div.content[role="main"]');
var ico = 'icon.png';
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
//console.log('content.js: chrome.runtime.onMessage.addListener');
//console.log('content.js: msg.text: ' + msg.text);
if (msg.text === 'page_fadeout') {
// This fades only a virgin page, so its possible to open
// and close the popup repeatedly, without re-rendering
// the page every time.
var loadingGif = chrome.extension.getURL("/loading.gif");
if ( ! isPageDone()) {
elBody.style.opacity = '0';
elBody.style.transition = '0.15s';
elHtml.style.background = '#FFF url(' + loadingGif + ') center center no-repeat';
}
sendResponse(true);
}
if (msg.text === 'page_fadein') {
elBody.style.opacity = "1";
elBody.style.transition = "0.75s";
elHtml.style.backgroundColor = "#FFF";
sendResponse(true);
}
if (msg.text === 'get_usernames') {
var usernames = getUsernames();
sendResponse(usernames);
}
if (msg.text === 'mark_members') {
addStyle();
markMemberUsers(msg.userlist);
sendResponse(true);
}
});
if (msg.text == 'mark_members') {
console.log('--> content.js: msg.text == "mark_members"');
if (msg.userlist) {
console.log('--> content.js: msg.userlist.length == ' + msg.userlist.length);
function getUsernames() {
// Return usernames from cache or find them in the markup.
if (isPageDone()) {
return getCachedUsernames();
} else {
console.log('--> content.js: msg.userlist not defined');
var usernames = findRedditUsernames();
cacheUsernames(usernames);
return usernames;
}
}
markMemberUsers(msg.userlist);
sendResponse(true);
function cacheUsernames(usernames) {
// Cache usernames in a meta tag.
elHead.innerHTML += '<meta name="redddate-page-done" content="' + usernames.join(' ') + '">';
}
});
function getCachedUsernames() {
// Return usernames from cache or null.
var s = elHead.querySelector('meta[name="redddate-page-done"]').content;
//console.log('content.js: getCachedUsernames(): s == ' + s);
return (s) ? s.split(' ') : null;
}
function findRedditUsernames() {
var all = document.all[0].querySelectorAll('div.content[role="main"] p.tagline a.author');
var li = [];
function isPageDone() {
// Checks if the page is done already.
return !!elHead.querySelector('meta[name="redddate-page-done"]');
}
for (var i=0; i<all.length; i++)
li.push(all[i].innerHTML);
function findRedditUsernames() {
var all = document.all[0].querySelectorAll('div.content[role="main"] p.tagline a.author');
var li = [];
return li;
}
for (var i=0; i<all.length; i++)
li.push(all[i].innerHTML);
function markMemberUsers(userlist) {
var s = userlist.join('<br>');
var elHead = document.getElementsByTagName('head')[0];
var elContent = document.all[0].querySelector('div.content[role="main"]');
var ico = 'icon.png'
//console.log('content.js: findRedditUsernames(): Found ' + li.length + ' usernames.');
return li;
}
elHead.innerHTML += '<style>.reddmeet-icon { display: block; overflow: hidden; width: 1em; height: 1em; background: transparent url(chrome-extension://__MSG_@@extension_id__/icon12.png) center center no-repeat; background-size: cover; border: 0; margin: 0; padding: 0; }</style>';
function addStyle() {
var s = '' +
'.reddmeet-link { ' +
' display: inline-block; height: 24px; line-height: 24px; ' +
' border: 0; outline: 0; ' +
' margin: 0; padding: 0 4px 0 0; ' +
' border-radius: 10px; background-color: #F3F3F3; ' +
' box-shadow: 0 0 2px rgba(0,0,0,0.56); ' +
'} ' +
'.reddmeet-icon { ' +
' display: inline-block; width: 32px; height: 24px; border-radius: 10px 0 0 10px; ' +
' background: transparent url(http://redddate.com/static/icon32.png) center center no-repeat; ' +
' background-size: cover; ' +
' border: 0; border-right: 8px solid transparent; ' +
' outline: 0; margin: 0; padding: 0; ' +
' vertical-align: middle; ' +
'}';
elContent.innerHTML = '';
for (var i=0; i<userlist.length; i++) {
elContent.innerHTML += '<p><span class="reddmeet-icon"></span> ' + userlist[i] + '</p';
//document.getElementsByTagName('style')[0].innerText += s;
if ( ! document.getElementById('reddmeet-style')) {
elHead.innerHTML += '<style id="reddmeet-style">' + s + '</style>';
}
}
}
function markMemberUsers(userlist) {
for (var i=0; i<userlist.length; i++) { // loop through all the userlist objects.
var qs = 'a.author[href="https://www.reddit.com/user/' + userlist[i]['name'] + '"]';
var qr = elContent.querySelectorAll(qs);
if (qr && qr.length > 0) { // was there at least one element for this username?
for (var j=0; j<qr.length; j++) { // loop all the occurences of this username on the page.
if ( ! qr[j].parentNode.classList.contains('reddmeet-link')) { // only if its not already wrapped.
qr[j].outerHTML = '<span class="reddmeet-link"><a class="reddmeet-icon" href="' + baseUserURL + userlist[i]['name'] + '" style="background-image:url(' + userlist[i]['pic'] + ')"></a>' + qr[j].outerHTML + '</span>';
}
}
}
}
}
})();
\ No newline at end of file
......@@ -17,6 +17,14 @@
"permissions": [
"activeTab",
"http://localhost:8000/",
"http://redddate.com/",
"https://reddmeet.com/"
],
"web_accessible_resources": [
"loading.gif",
"*.css",
"*.js"
]
}
......@@ -6,17 +6,76 @@
body {
font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif;
font-size: 100%;
width: 500px;
width: 400px;
min-height: 300px;
max-height: 80vh;
margin: 0; padding: 0;
}
#status {
white-space: normal;
overflow: hidden;
margin: 0; padding: 0;
}
#status p {
margin: 0; padding: 4px;
}
#loading {
display: block;
overflow: hidden;
height: 300px;
background: #FFFFFF url(loading.gif) center center no-repeat;
}
#userlist {
list-style: none; margin: 0; padding: 0;
}
#userlist li {
margin: 0; padding: 0;
}
#userlist li a {
border: 1px solid transparent;
color: black;
display: block;
margin: 0; padding: 8px;
overflow: hidden;
text-decoration: none;
}
#userlist li a:hover {
background-color: #F3F3F3;
border-color: gray;
}
#userlist li a span.infoline1 {
display: block;
font-size: 20px;
line-height: 28px;
overflow: hidden;
}
#userlist li a span.infoline2 {
color: gray;
display: block;
line-height: 20px;
overflow: hidden;
}
#userlist li a img {
border: 0; outline: 0;
display: block; float: left;
margin: 0 8px 0 0; padding: 0;
vertical-align: middle;
width: 48px; height: 48px;
}
#userlist-empty {
color: gray;
display: block;
font-size: 1.25rem;
margin: 0; padding: 100px 0 0 0;
text-align: center;
}
</style>
<script src="popup.js"></script>
<script src="content.js"></script>
</head>
<body>
<div id="status"></div>
<div id="status">
<div id="loading"></div>
</div>
</body>
</html>
(function() {
var currCount = 0;
var currTab = null;
var currUsers = null;
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
document.addEventListener('DOMContentLoaded', function() {
getCurrentTabUrl(function(tab) {
if ( isRedditUrl(tab.url) ) {
currTab = tab;
// http://stackoverflow.com/a/13486540/5520354
function unique_set(arr) {
return arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});
}
if (currUsers === null) {
currCount += 1; renderStatus('['+currCount+']');
currUsers = []; // This prevents the userlist to be generated again.
chrome.tabs.sendMessage(currTab.id, {text: 'get_all_usernames'}, receiveUserlist);
}
Array.prototype.contains = function(obj) {
return !(this.indexOf(obj) < 0);
}
renderStatus('Loading...');
};
});
});
///////////////////////////////////////////////////////////////////////
var DEBUG = true;
///////////////////////////////////////////////////////////////////////
//var baseUserURL = 'http://redddate.com/u/';
//var baseApiUrl = 'http://redddate.com/api/v1/';
var baseUserURL = 'http://localhost:8000/u/';
var baseApiUrl = 'http://localhost:8000/api/v1/';
function isRedditUrl(url) {
var re = new RegExp("^https?://(\w+\.)+reddit.com(:\d+)?[$/]");
return url.match(re);
}
var isBusy = false; // only fetch one tab at a time.
var currTab = null; // the tab we are currently working on.
function getCurrentTabUrl(callback) {
var queryInfo = { active: true, currentWindow: true, };
document.addEventListener('DOMContentLoaded', function() {
getCurrentTabUrl(function(tab) {
if (!isBusy) {
if (isRedditUrl(tab.url)) {
// Only do anything if we are not already
// busy and the tab contains a Reddit URL.
isBusy = true;
currTab = tab;
setTimeout(function(){ // wait a little for the page content to fade out.
chrome.tabs.sendMessage(currTab.id, {text: 'get_usernames'}, receiveUserlist);
}, 250);
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
callback(tab);
} else {
// not reddit
replaceStatus('Visit a reddit comment thread.')
}
} else {
//replaceStatus();
}
});
});
}
function receiveUserlist(userlist) {
if (!userlist) {
renderStatus('Did NOT get userlist :( ');
return;
///////////////////////////////////////////////////////////////////////
function isRedditUrl(url) {
var re = new RegExp("^https?://(\w+\.)+reddit.com(:\d+)?[$/]");
return url.match(re);
}
currUsers = queryReddmeetUsernames(unique_set(userlist));
chrome.tabs.sendMessage(currTab.id, {text: 'mark_members', 'userlist': userlist}, function(response){
//renderStatus(' !returned from mark_member_usernames! ');
});
}
function renderStatus(statusText) {
document.getElementById('status').textContent += '\n' + statusText;
}
function queryReddmeetUsernames(users) {
// For a list of usernames, query the reddmeet API if they have an account.
// The API returns a list of usernames that do have a reddmeet profile.
// ::: TODO :::
return users;
}
///////////////////////////////////////////////////////////////////////
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
// http://stackoverflow.com/a/13486540/5520354
function unique_set(arr) {
return arr.filter(function (e, i, arr) {
return arr.lastIndexOf(e) === i;
});
}
function getCurrentTabUrl(callback) {
var queryInfo = { active: true, currentWindow: true, };
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
callback(tab);
});
}
function receiveUserlist(userlist) {
if (typeof userlist == 'undefined') {
replaceStatus('popup.js: Uhm, userlist is undefined. Do nothing.');
} else if (userlist === null) {
//replaceStatus('popup.js: Already done userlist, do not fetch it again.');
}
else if (userlist.length === 0) {
//replaceStatus('popup.js: Got empty userlist, do nothing.');
}
else {
userlist = unique_set(userlist); // remove duplicates.
if (userlist.length === 0) {
//replaceStatus('popup.js: Got empty userlist, do nothing.');
} else {
// with the list of usernames, check which have a reddmeet account
// and pass the resulting list on to the markMembers function.
queryReddmeetUsernames(userlist).then(markMembers);
}
}
}
function markMembers(userlist) {
// receives a list of usernames that are members of reddmeet.
// mark them in the page's HTML and render them as a list in
// the popup bubble.
//
// userlist = [{ 'name': 'username', 'pic': 'http://...' }, { ... }, ]
var html = '';
if (userlist.length > 0) {
for (var i=0; i<userlist.length; i++) {
var pic = '<img src="' + userlist[i]['pic'] + '" alt="">';
var ahref = '<a href="' + baseUserURL + userlist[i]['name'] + '">';
var infoLine1 = '<span class="infoline1">' + userlist[i]['name'] + '</span>';
var infoLine2 = '<span class="infoline2">33, woman who like men</span>';
html += '<li>' + ahref + pic + infoLine1 + infoLine2 + '</a></li>';
}
replaceStatus('<ul id="userlist">' + html + '</ul>');
chrome.tabs.sendMessage(currTab.id, {text: 'page_fadeout'}, function(response){ });
chrome.tabs.sendMessage(currTab.id, {text: 'mark_members', 'userlist': userlist}, function(response){ });
chrome.tabs.sendMessage(currTab.id, {text: 'page_fadein'}, function(response){ });
isBusy = false;
}
else {
replaceStatus('<p id="userlist-empty">there is nobody</p>');
isBusy = false;
}
}
function clearStatus() {
document.getElementById('status').innerHTML = '';
}
function addStatus(statusText) {
document.getElementById('status').innerHTML += '<p>' + statusText + '</p>';
}
function replaceStatus(statusText) {
document.getElementById('status').innerHTML = statusText;
}
function queryReddmeetUsernames(userlist) {
// For a list of usernames, query the reddmeet API if they have an account.
// The API returns a list of usernames that do have a reddmeet profile.
// ::: TODO :::
return new Promise(function(resolve, reject) {
// Try to fetch users from sessionStorage.
var cache = JSON.parse(sessionStorage.getItem('reddmeetUsers'));
var userlistComplete = []; // collect here all items wuth full data from cache.
var usernamesTodo = []; // collect here all items that are sent to reddmeet server.
for (var j=0; j<userlist.length; j++) {
var isCached = false;
if (cache && cache.length > 0){
for (var i=0; i<cache.length; i++) {
if (cache[i]['name'] == userlist[j]) {
userlistComplete.push(cache[i]); // Found one!
isCached = true;
break;
}
}
}
if (!isCached) {
usernamesTodo.push(userlist[j]); // add to "sent to server" list
}
}
if (usernamesTodo.length == 0) {
resolve(userlistComplete); // nothing to send to server?
}
// Only get fresh data for those users not found in sessionStorage.
var apiUrl = baseApiUrl + 'filter-members.json?userlist=' + encodeURIComponent(usernamesTodo.join(' '));
var xhr = new XMLHttpRequest();
xhr.open("GET", apiUrl, true);
xhr.onreadystatechange = function() {
if (xhr.readyState == xhr.DONE) {
if (xhr.status == 200) {
var data = JSON.parse(xhr.responseText); // TODO: add this userlist to cache, avoiding dupes.
var userlist = data['userlist'].concat(userlistComplete); // join the resulting userlist with the userlist from cache
resolve(userlist);
} else
if (xhr.status == 404) {
resolve(mockUserlist(usernamesTodo));
}
}
}
xhr.send();
});
}
function mockUserlist(usernames) {
// Return a fake list of user objects with pics if DEBUG, else an empty list.
var response = [];
var fakepics = ['https://i.imgur.com/JuJwWLCs.jpg', 'https://i.imgur.com/WgfwLfIs.jpg',
'https://i.imgur.com/P02Ejbfs.jpg', 'https://i.imgur.com/50z3fWPs.jpg',
'https://i.imgur.com/TSmS03Ds.jpg', 'https://i.imgur.com/CJQmX50s.jpg'];
if (DEBUG) {
for (var i=0; i<usernames.length; i++) {
var p = Math.floor(i % fakepics.length);
response.push({ 'name': usernames[i], 'pic': fakepics[p] });
}
}
return response;
}
})();
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment