Permalink
Browse files

added bitcointip module, but STILL NEEDS WORK DONE -- it's not 100% r…

…eady.
  • Loading branch information...
1 parent f9dd0f3 commit 5115ad1d7dc7c3e9fd36c8d82b8675c680b5d94e @honestbleeps committed Mar 28, 2013
Showing with 546 additions and 8 deletions.
  1. +546 −8 lib/reddit_enhancement_suite.user.js
View
554 lib/reddit_enhancement_suite.user.js
@@ -4070,10 +4070,10 @@ modules['keyboardNav'] = {
// options must have a type and a value..
// valid types are: text, boolean (if boolean, value must be true or false)
// for example:
- focusBorder: {
+ focusBorderColor: {
type: 'text',
- value: '1px dashed #888',
- description: 'Border style of focused element'
+ value: '#08C',
+ description: 'Color of right border on focused element'
},
focusBGColor: {
type: 'text',
@@ -4404,10 +4404,10 @@ modules['keyboardNav'] = {
beforeLoad: function() {
if ((this.isEnabled()) && (this.isMatchURL())) {
var focusBorder, focusFGColorNight, focusBGColor, focusBGColorNight;
- if (typeof(this.options.focusBorder) == 'undefined') {
- focusBorder = '1px dashed #888';
+ if (typeof(this.options.focusBorderColor) == 'undefined') {
+ focusBorderColor = '#08C';
} else {
- focusBorder = this.options.focusBorder.value;
+ focusBorderColor = this.options.focusBorderColor.value;
}
if (typeof(this.options.focusBGColor) == 'undefined') {
focusBGColor = '#F0F3FC';
@@ -4427,8 +4427,12 @@ modules['keyboardNav'] = {
var borderType = 'outline';
if (BrowserDetect.isOpera()) borderType = 'border';
+ // old style: .keyHighlight { '+borderType+': '+focusBorder+'; background-color: '+focusBGColor+'; } \
+
RESUtils.addCSS(' \
- .keyHighlight { '+borderType+': '+focusBorder+'; background-color: '+focusBGColor+'; } \
+ .entry { padding-right: 5px; } \
+ .keyHighlight { border-radius: 5px; border-right: 1px solid '+focusBorderColor+'; position: relative; background-color: '+focusBGColor+'; } \
+ .keyHighlight:after { content: ""; position: absolute; right: 0px; top: 50%; margin-top: -4px; border-color: transparent '+focusBorderColor+' transparent transparent; border-style: solid; border-width: 3px 4px 3px 0; } \
.res-nightmode .keyHighlight, .res-nightmode .keyHighlight .usertext-body, .res-nightmode .keyHighlight .usertext-body .md, .res-nightmode .keyHighlight .usertext-body .md p, .res-nightmode .keyHighlight .noncollapsed, .res-nightmode .keyHighlight .noncollapsed .md, .res-nightmode .keyHighlight .noncollapsed .md p { background-color: '+focusBGColorNight+' !important; color: '+focusFGColorNight+' !important;} \
.res-nightmode .keyHighlight a.title:first-of-type {color: ' + focusFGColorNight + ' !important; } \
#keyHelp { display: none; position: fixed; height: 90%; overflow-y: auto; right: 20px; top: 20px; z-index: 1000; border: 2px solid #aaa; border-radius: 5px; width: 300px; padding: 5px; background-color: #fff; } \
@@ -17476,7 +17480,541 @@ m_chp = modules['commentHidePersistor'] = {
}
}
}
-};
+};
+
+
+modules['bitcoinTip'] = {
+ moduleID: 'bitcoinTip',
+ moduleName: 'bitcoinTip',
+ category: 'Users',
+ options: {
@andytuba
andytuba Mar 29, 2013

As of fc6920c, I'm still seeing "option not configured correctly in bitcoinTip module" errors. I believe it's limited to the very first time you load up without RES data.

@honestbleeps
honestbleeps Mar 29, 2013
@andytuba
andytuba Mar 30, 2013

it's specifically the modules['bitcoinTips'].options.balanceUnits which it's having trouble with. that's a weird ad-hoc option, did you just want somewhere persistent to stick the value?

+ baseTip: {
+ type: 'text',
+ value: '0.01 BTC',
+ description: 'Default tip amount in the form of "[value] [units", e.g. "0.01 BTC"'
+ },
+ hide: {
+ type: 'boolean',
+ value: true,
+ description: 'Hide bot verifications'
+ },
+ status: {
+ type: 'enum',
+ values: [
+ { name: 'detailed', value: 'detailed' },
+ { name: 'basic', value: 'basic' },
+ { name: 'none', value: 'none' }
+ ],
+ value: 'detailed',
+ description: 'Tip status - level of detail'
+ },
+ currency: {
+ type: 'text',
+ value: 'BTC',
+ description: 'Preferred currency (e.g. BTC, USD)'
+ },
+ balance: {
+ type: 'boolean',
+ value: true,
+ description: 'Display balance'
+ },
+ subreddit: {
+ type: 'boolean',
+ value: true,
+ description: 'Display enabled subreddits'
+ }
+ },
+ description: 'This is my module!',
+ isEnabled: function() {
+ return RESConsole.getModulePrefs(this.moduleID);
+ },
+ include: Array(
+ /https?:\/\/([a-z]+).reddit.com\/[\?]*/i
+ ),
+ exclude: Array(
+ /https?:\/\/([a-z]+).reddit.com\/[\?]*\/user\/bitcointip\/?/i
+ ),
+ isMatchURL: function() {
+ return RESUtils.isMatchURL(this.moduleID);
+ },
+ beforeLoad: function() {
+ RESUtils.addCSS('.tip-bitcoins { cursor: pointer; }');
+ RESUtils.addCSS('.tips-enabled-icon { cursor: help; }');
+ RESUtils.addCSS('#tip-menu { position: absolute; top: 0; left: 0; }');
+ },
+ go: function() {
+ if ((this.isEnabled()) && (this.isMatchURL())) {
+ // copied and adjusted from http://userscripts.org/scripts/review/153975 with permission from the authors
+ var tipregex = /\+(bitcointip|bitcoin|tip|btctip|bittip|btc)/i;
+ var tipregexFun = /(\+((?!0)(\d{1,4})) (point|internet|upcoin))/;
+ var botDownThreshold = 15 * 60 * 1000; // milliseconds
+ var botStatusHtml = {
+ up: '<span class="status-up">UP</span>',
+ down: '<span class="status-down">DOWN</span>'
+ };
+ var api = {
+ gettips: 'https://bitcointip.net/api/gettips.php?',
+ gettipped: 'https://bitcointip.net/api/gettipped.php?',
+ subreddits: 'https://bitcointip.net/api/subreddits.php',
+ balance: 'https://bitcointip.net/api/balance.php'
+ };
+ var icons = {
+ completed: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAMAAABFNRROAAAAt1BMVEX///8AAAAAyAAAuwAAwQcAvAcAvwAAwQYAyAUAxAUAxwQAwgQAvAMAxQYAvwYAxQYAxwU5yT060j460j871T89wUE9wkFGokdGu0hIzExJl09JmE9JxExJxE1K1U9K1k5Ll09LmVNMmVNM2FBNmlRRx1NSzlRTqlVUslZU1ldVq1hVrFdV2FhWrFhX21pZqlphrWJh3WRotGtrqm1stW91sXd2t3h5t3urz6zA2sHA28HG3sf4+PhvgZhQAAAAEXRSTlMAARweJSYoLTM0O0dMU1dYbkVIv+oAAACKSURBVHjaVc7XEoIwEIXhFRED1tBUxBaPFSyxK3n/5zIBb/yv9pudnVky2Ywxm345MHkVXByllPm4W24qrLbzdo1sLPPRepc+XlnSIAuz9DQYPtXnkLhUF/ysrndV3CYLRpbg2VtpxFMwfRfEl8IghEPUhB9t9lEQoke6FnzONfpU5kEIoKOn/z+/pREPWTic38sAAAAASUVORK5CYII=",
+ cancelled: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAMAAABFNRROAAAAQlBMVEX///+qAAAAAAC/AADIABSaTU3YMDDcPj7cSEjeUFDiZGTld3fmfHzoiorqkJDqlpbupKTuqqr99fX99/f+/Pz////kWqLlAAAABXRSTlMAAwcIM6KYVMQAAABfSURBVHjaXc7JDsAgCEVRsYpIBzro//9qHyHpond3AgkklIuXPKJcqleIIEB6FwEhQEW0t4rlUtt+22ZTMQ09NqZyiK8BtBCvc9iDWegY526hBVRmdcQ9RgD9f/G+P1+JEwRF2vKhRgAAAABJRU5ErkJggg==",
+ tipped: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAANCAMAAACq939wAAAA/FBMVEWqVQCqcQCZZgCLXQCdYgDMjACOXACOXwCacQCfcQCqegCwggChggCnfwCwggCthACtgQC9iACleQC+iwDMlgDJlACmfgDDiwDBjADHlQDJnQDFlQDKmAChfRGjgBOmfhKmghKnghOqhBKthxOviROvjB+vjCGvjCOwiRSwihixixWxjSGziBOzkSmzky+0kSa0kiy3jxW8kxS8mCi8n0i8oEq9lBe9mSvOoBbUrTTUrTjbukXcsTDctDrdtj/exHbexXDfwWXfwmvjrBnksRjksx7lrhnqx17qyWTqymrq377rz3nr2qftuiHtvSv67cD67sj+997/+OX///8rcy1sAAAAHXRSTlMDCQoLDRQkKystMDc5Oj0+QUlKS0tMTVFSV15/i6wTI/gAAACWSURBVHjaHcrnAoFQGADQryI7sjNKN0RKZJVNQ8io938YN+f3ASDp1B9NAhD15UzXNH26KhNQXZyDBxZcNlloKadvFIbR56owUOFV9425ai8PrGwZaITQeisXoKHs7k/MP44ZaHYl54U5El8EdmjNEWbEjesf/Ljd9v0S1ETBtD3PNgUxB8nOQIybOGknAKgMy2FsmoIflIEZdK7PshkAAAAASUVORK5CYII=",
+ pending: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABWUlEQVR4nI2Sy0sCURTGD6S2jjYFrdy0DNpEhokb8zFm5YyaO6NFYNGqF/0hPZYtR79FUbgw0BFtDKIgUCSpv8Od3XtGJzWDBj64h/l+954XdbtdGhQZkzNUd7ptifiXZygo0Wz0WsWoyHTMj4Wo6nRLQ7KdRuZz15bWSiF0GQOVXJ4hqP/COGDTjEO9SyByIcDHiUXiT+QsAaW1wabgi4KtVxVqM4lQVcFx4RS5tzy0vIgZFDVTnaYkFG6us2lbTyNws4ZAMYizwjk6nQ7KbQOJfMqCRBlERZpWruJYfvYigx02ZfUDHN2e8Pnpy8T+w6G4MIqI8HFH5Ut9SKZQ/jDYPAh4K36EGzGrkwz1avK8+/jn3n2WzaPASsNnQaJpvYG65ixwFV7Dj7iuQcul+Cwvs4Ga1fafOVUcC31Qpio1BJjO0PiNEJPn9osapeyNqLmW/lyj/+7eN1qRZT0kKLSqAAAAAElFTkSuQmCC",
+ reversed: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAABOklEQVR42p2SvU4CQRSFj+9h7DQ2VmsDCy0/Cw2wsNtuRwixIiQ8CZaWGDBaaAiJyVAg2xi1AaTQ19jyOHeSIbLBxuIkM7Pn23PvnQHJPSngNAYcK9mnPWng/LpaZVoadg9CC+BSDNsg4FcU7bRpNjkslaiAYAfZhL+AuFbjQ6PBYaXCZ6AK4Mj0IMBGH4rptVjkW73Ote9zUS5z2u/zfTzmRBL1XoNniIFjgdaeZ0yjMORNocCZ1nQwYJIk3CrFSatlIGkDM+BEouNMhndRZEyjTof3vZ5Zfy+XfOp2zQ+ND3BMkoWkhE+lxLwHzPN5rjzPTtLZ9fSRzZqPj+22MaeBlesaSIZmp3dhQZXLcaQHcev7sjZnFngBwr17mgNFC+pSRRawZV0dfBFy89ogDYvEbBMav33/ens/XHaDp7U/bFsAAAAASUVORK5CYII="
+ };
+ var displayCurrency = {
+ balanceUSD: {unit: '$', precision: 2},
+ balanceBTC: {unit: '฿'},
+ balanceJPY: {unit: '¥'},
+ balanceGBP: {unit: '£', precision: 2},
+ balanceEUR: {unit: '€', precision: 2}
+ };
+
+ // var $ = unsafeWindow.$,
+ // S = unsafeWindow.localStorage,
+ // reddit = unsafeWindow;
+
+ /* Helper functions. */
+
+ function identity(x) {
+ return x;
+ }
+
+ /**
+ * Set textarea cursor position in jQuery.
+ */
+ $.fn.setCursorPosition = function(pos) {
+ this.each(function(index, elem) {
+ if (elem.setSelectionRange) {
+ elem.setSelectionRange(pos, pos);
+ } else if (elem.createTextRange) {
+ var range = elem.createTextRange();
+ range.collapse(true);
+ range.moveEnd('character', pos);
+ range.moveStart('character', pos);
+ range.select();
+ }
+ });
+ return this;
+ };
+
+ function quantity(object) {
+ var pref = modules['bitcoinTip'].options.currency.value.toUpperCase();
+ var unit = displayCurrency['balance' + pref];
+ var amount = object['amount' + pref];
+ return unit.unit + amount;
+ }
+
+
+ /* Add the "tip bitcoins" button after "give gold". */
+ var tip =
+ $('<span class="tip-wrapper">' +
+ '<div class="dropdown">' +
+ '<a class="tip-bitcoins login-required">tip bitcoins</a>' +
@andytuba
andytuba Mar 29, 2013

in the interest of saving space on the comment button list, since it gets cramped when a comment is 7+ levels deep, how about the button just listing "tip" and the menu can show more information?

tip
|-- tip publicly
|-- tip privately
|-- [about bitcointip](/r/bitcointip)
|-- [settings](#!settings/bitcoinTip)

and maybe throw the bitcoin tip icon (the stack of gold coins) in the top right corner of the menu? i think it looks cool 😁

@honestbleeps
honestbleeps Mar 29, 2013
@andytuba
andytuba Mar 30, 2013

I just pushed andytuba/Reddit-Enhancement-Suite/bittip-gussy which has added menu option for settings. I also fixed up the options/description a little.

This module still needs a little work -- I'm not sure the "tip privately" is working correctly, is it supposed to auto-populate a username or comment URL? edit: fixed "tip privately"

I still need to fix modules['settingsNavigation'] so it's always on, but that can be a different branch.

+ '</div>' +
+ '</span>');
+
+ this.tipMenu =
+ $('<div id="tip-menu" class="drop-choices">' +
+ '<a class="choice tip-publicly" href="javascript:void(0);">tip publicly</a>' +
+ '<a class="choice tip-privately" href="javascript:void(0);">tip privately</a>' +
+ '</div>');
+
+ $(document.body).append(this.tipMenu);
+
+ $('.tip-wrapper .dropdown').live('click', function(e) {
+ modules['bitcoinTip'].toggleTipMenu(e.target);
+ });
+
+ if (/^\/r\//.test(document.location.pathname)) {
+ $('a.give-gold').parent().after($('<li/>').append(tip.clone()));
+ if ($('.link').length === 1) { // Viewing a submission?
+ $('.link ul.buttons').append($('<li/>').append(tip.clone()));
+ }
+ }
+
+ $('#tip-menu .tip-publicly').click(function(event) {
+ $('#tip-menu').hide();
+ event.preventDefault();
+ // var $target = $(event.target);
+ var $target = $(modules['bitcoinTip'].lastToggle);
+ if ($target.closest('.link').length > 0) { /* Post */
+ form = $('.commentarea .usertext:first');
+ } else { /* Comment */
+ $target.closest('ul').find('a[onclick*="reply"]').click();
+ form = $target.closest('.thing').find('FORM.usertext.cloneable:first');
+ }
+ var textarea = form.find('textarea');
+ if (!textarea.val().match(tipregex)) {
+ textarea.val(textarea.val() + '\n\n+tip ' + modules['bitcoinTip'].options.baseTip.value);
+ textarea.setCursorPosition(0);
+ }
+ });
+
+ $('#tip-menu .tip-privately').click(function(event) {
+ event.preventDefault();
+ $('#tip-menu').hide();
+ var $target = $(modules['bitcoinTip'].lastToggle);
+ var form = null;
+ if ($target.closest('.link').length > 0) { /* Post */
+ form = $('.commentarea .usertext:first');
+ } else {
+ form = $target.closest('.thing').find(".child .usertext:first");
+ }
+ if (form.length > 0 && form.find('textarea').val()) {
+ /* Confirm if a comment has been entered. */
+ if (!confirm('Really leave this page to tip privately?')) {
+ return;
+ }
+ }
+ var user = $(this).closest('thing').find('.author').first().text();
+ var message = encodeURIComponent('+bitcointip @' + user + ' ' +
+ modules['bitcoinTip'].options.baseTip.value);
+ var url = '/message/compose?to=bitcointip&subject=Tip&message=' + message;
+ window.location = url;
+ });
+
+ /* Subreddit indicator. */
+ var subreddit = (function(match) {
+ if (match) {
+ return match[1];
+ } else {
+ return null;
+ }
+ }(location.pathname.match(/\/r\/([^/]+)/)));
+ if (this.options.subreddit.value && subreddit) {
+ $.getJSON(api.subreddits, function(data) {
+ if (data.subreddits.indexOf(subreddit.toLowerCase()) >= 0) {
+ $('#header-bottom-right form.logout')
+ .before($('<span>|</span>').attr({
+ 'class': 'separator'
+ }))
+ .prev().before($('<img/>').attr({
+ 'src': icons.tipped,
+ 'class': 'tips-enabled-icon',
+ 'style': 'vertical-align: text-bottom;',
+ 'title': 'Tips enabled in this subreddit.'
+ }));
+ }
+ });
+ }
+
+ /* Balance indicator. */
+ var user = $('#header-bottom-right span.user a').first().text();
+ if (user === "login or register") {
+ user = null;
+ }
+ // TODO: replace S[] whatever with RESStorage
+ // var address = S['address.' + user];
+ var address = null;
+ if (!this.options.balanceUnits) this.options.balanceUnits = {};
@andytuba
andytuba Mar 30, 2013

calling out this todo: make this a full-fledged option! it seems a little buggy otherwise (mostly on first load after install)

+ if (this.options.balanceUnits.value == null) {
+ this.options.balanceUnits.value = 'balanceUSD';
+ }
+
+ function toggleBalanceUnits() {
+ var units = Object.keys(displayCurrency);
+ var i = (units.indexOf(modules['bitcoinTip'].options.balanceUnits.value) + 1) % units.length;
+ return (this.options.balanceUnits.value = units[i]);
+ }
+
+ function currencyString(balance) {
+ var balanceUnits = modules['bitcoinTip'].options.balanceUnits.value;
+ var meta = displayCurrency[balanceUnits];
+ var quantity = balance[balanceUnits];
+ if (meta.precision) {
+ quantity = quantity.toFixed(meta.precision);
+ }
+ return meta.unit + quantity;
+ }
+
+ function insertBalance() {
+ $.getJSON(api.balance, {
+ username: user,
+ address: address
+ }, function (balance) {
+ if (!('balanceBTC' in balance)) {
+ /* Probably got the address wrong. */
+ S.removeItem('address.' + user);
+ return;
+ }
+ var units = modules['bitcoinTip'].options.balanceUnits.value;
+ $('#header-bottom-right form.logout').before($('<span>|</span>').attr({
+ 'class': 'separator'
+ })).prev().before($('<a/>').attr({
+ 'class': 'hover',
+ 'href': '#'
+ }).on('click', function() {
+ toggleBalanceUnits();
+ $(this).text(currencyString(balance));
+ }).text(currencyString(balance)));
+ });
+ }
+
+ if (this.options.balance.value && user != null && address == null) {
+ // TODO: this can NOT be called on every page load... very inefficient!
@andytuba
andytuba Mar 30, 2013

calling out this todo because i'm also noticing how slowly/intermittently it runs

+ $.getJSON('/message/messages.json', function(messages) {
+ /* Search messages for a bitcointip response. */
+ address = messages.data.children.filter(function (message) {
+ return message.data.author === 'bitcointip';
+ }).map(function (message) {
+ var pattern = /Deposit Address: \| \[\*\*([a-zA-Z0-9]+)\*\*\]/;
+ var address = message.data.body.match(pattern);
+ if (address) {
+ return address[1];
+ } else {
+ return false;
+ }
+ }).filter(identity)[0]; // Use the most recent
+ if (address) {
+ // S['address.' + user] = address;
+ insertBalance();
+ }
+ });
+ } else if (this.options.balance.value && user != null && address != null) {
+ insertBalance();
+ }
+
+ /* Reddit jQuery plugin. */
+ // passing in jquery is unnecessary here - we already have access to it.
+ // (function($) {
+ /** Get the comment div for each element in the current set. */
+ $.fn.comment = function() {
+ return this.closest('.comment');
+ };
+
+ /** Get the comment ID for the first selected comment. */
+ $.fn.commentID = function() {
+ var full = this.first().find('input[name="thing_id"]').first().val();
+ return full.replace(/^t1_/, '');
+ };
+
+ /** Get the commenter/poster name for the first selected comment. */
+ $.fn.thingName = function() {
+ return this.first().find('.author').first().text();
+ };
+
+ /** Get the comment's post time for the first selected comment. */
+ $.fn.commentDate = function() {
+ return new Date(this.find('.tagline time').first().attr('datetime'));
+ };
+
+ /** Get the comment body for the first comment in the current set. */
+ $.fn.commentBody = function() {
+ return this.find('.md').first();
+ };
+
+ /** Get the children comments for each comment in the current set. */
+ $.fn.commentChildren = function() {
+ return this.find('.comment');
+ };
+
+ /** Get the parent comment for each comment in the current set. */
+ $.fn.commentParent = function() {
+ return this.parent().comment();
+ };
+
+ /** Determine whether the first element is the target comment. */
+ $.fn.isTarget = function() {
+ return this.first().find('form').first().hasClass('border');
+ };
+
+ /** Return true if the first comment in the current set has a tip. */
+ $.fn.hasTip = function() {
+ return this.commentBody().children().is(function() {
+ return tipregex.test($(this).text());
+ });
+ };
+
+ /** Return true if the first comment in the current set has a "fun" tip. */
+ $.fn.hasFunTip = function() {
+ return this.commentBody().children().is(function() {
+ return tipregexFun.test($(this).text());
+ });
+ };
+
+ /** Return the link ID for the first post in the selection. */
+ $.fn.postID = function() {
+ return this.attr('data-fullname').replace(/^t._/, '');
+ };
+
+ /** Return true if the first seleted item is a comment. */
+ $.fn.isComment = function() {
+ return this.closest('.link').length === 0;
+ };
+ // })(unsafeWindow.jQuery);
+
+ /* Hide verification replies. Note: t2_7vw3n is /u/bitcointip. */
+ if (this.options.hide.value) {
+ $('a.id-t2_7vw3n').comment().each(function() {
+ var $this = $(this);
+ if ($this.commentChildren().length === 0 && !$this.isTarget()) {
+ // TODO: figure out a way to get this working.
+ // reddit.hidecomment($this.find('.expand').first());
+ }
+ });
+ }
+
+ /* Find all the tip comments. */
+ var tips = {};
+ var fun = {};
+ $('div.comment').each(function() {
+ var $this = $(this);
+ if ($this.hasTip()) {
+ tips[$this.commentID()] = $this;
+ } else if ($this.hasFunTip()) {
+ tips[$this.commentID()] = $this;
+ fun[$this.commentID()] = $this;
+ }
+ });
+
+ /* Get status information about various tips. */
+ var inTipSubreddit = /^\/r\/bitcointip/.test(document.location.pathname);
+ var tipIDs = Object.keys(tips);
+ var confirmedIDs = [];
+ if (this.options.status.value !== 'none' && (tipIDs.length > 0 || inTipSubreddit)) {
+ var iconStyle = 'vertical-align: text-bottom; margin-left: 8px;';
+ $.getJSON(api.gettips + 'tips=' + tipIDs, function(response) {
+ var lastEvaluated = new Date(response.last_evaluated * 1000);
+ if (inTipSubreddit) {
+ var botStatus = null;
+ if (Date.now() - lastEvaluated > botDownThreshold) {
+ botStatus = botStatusHtml.down;
+ } else {
+ botStatus = botStatusHtml.up;
+ }
+ $('a[href="http://bitcointip.net/status.php"]').html(botStatus);
+ }
+
+ response.tips.forEach(function (tip) {
+ var id = tip.fullname.replace(/^t._/, '');
+ var tagline = tips[id].find('.tagline').first();
+ var icon = $('<a/>').attr({href: tip.tx, target: '_blank'});
+ tagline.append(icon.append($('<img/>').attr({
+ src: icons[tip.status],
+ style: iconStyle,
+ title: quantity(tip) + ' → ' + tip.receiver +
+ ' (' + tip.status + ')'
+ })));
+ confirmedIDs.push(id);
+ tips[id].attr('id', 't1_' + id);
+ delete tips[id];
+ });
+
+ /* Deal with unanswered tips. */
+ for (var id in tips) {
+ if (!fun[id] && tips[id].commentDate() < lastEvaluated) {
+ var tagline = tips[id].find('.tagline').first();
+ tagline.append($('<img/>').attr({
+ src: icons.cancelled,
+ style: iconStyle,
+ title: 'This tip is invalid.'
+ }));
+ }
+ }
+ });
+
+ /* Put receiver information on comments. */
+ var things = {};
+ $('div.comment').each(function() {
+ var $this = $(this);
+ things[$this.commentID()] = $this;
+ });
+ $('div.link').each(function() {
+ var $this = $(this);
+ things[$this.postID()] = $this;
+ });
+ var thingIDs = Object.keys(things);
+ $.getJSON(api.gettipped + 'tipped=' + thingIDs, function(response) {
+ response.forEach(function (tipped) {
+ var id = tipped.fullname.replace(/^t._/, '');
+ var thing = things[id];
+ var tagline = thing.find('.tagline').first();
+ var plural = tipped.tipQTY > 1;
+ var title = quantity(tipped) + ' to ' + thing.thingName() +
+ ' for this ';
+ if (plural) {
+ title = 'redditors have given ' + title;
+ } else {
+ title = 'a redditor has given ' + title;
+ }
+ if (thing.isComment()) {
+ title += 'comment.';
+ } else {
+ title += 'submission.';
+ }
+ var icon = $('<img/>').attr({
+ src: icons.tipped,
+ style: iconStyle,
+ title: title
+ });
+
+ /* Attempt to link to the first tip. */
+ var foundParent = false;
+ thing.commentChildren().each(function() {
+ if (!foundParent) {
+ var $this = $(this);
+ var id = $this.commentID();
+ if ($.inArray(id, confirmedIDs) >= 0) {
+ icon = $('<a/>').attr({
+ href: '#t1_' + $this.commentID()
+ }).append(icon);
+ foundParent = true;
+ }
+ }
+ });
+
+ tagline.append(icon);
+ if (plural) {
+ tagline.append($('<span/>').text('x' + tipped.tipQTY));
+ }
+ });
+ });
+ }
+
+ /* Test URLs:
+ *
+ * Rejected,
+ * http://www.reddit.com/r/bitcointip/comments/132nhq/t/c7c7iue
+ *
+ * Rejected flip,
+ * http://www.reddit.com/r/Bitcoin/comments/14i9e7/y/c7dc6w9
+ *
+ * Combination folding,
+ * http://www.reddit.com/r/bitcointip/comments/13iykn/b/c7dj8ia
+ *
+ * Multiple tips to one receiver,
+ * http://www.reddit.com/r/bitcointip/comments/12lmut/c7ny177
+ *
+ * Multiple guilded to one receiver (for comparison),
+ * http://www.reddit.com/r/AdviceAnimals/comments/15mk25/c7ntrcc
+ *
+ * Reversed,
+ * http://www.reddit.com/r/IAmA/comments/18tp7t/c8i8qto
+ */
+
+ }
+ },
+ toggleTipMenu: function(ele) {
+ var tipMenu = modules['bitcoinTip'].tipMenu;
+ var thisXY = $(ele).offset();
+ var thisHeight = $(ele).height();
+ // if already visible and we've clicked a different trigger, hide first, then show after the move.
+ if (($(tipMenu).is(':visible')) && (modules['bitcoinTip'].lastToggle !== ele)) {
+ $(tipMenu).toggle();
+ }
+ $(tipMenu).css({
+ top: (thisXY.top+thisHeight)+'px',
+ left: thisXY.left+'px'
+ });
+ $(tipMenu).toggle();
+ modules['bitcoinTip'].lastToggle = ele;
+ }
+}; // note: you NEED this semicolon at the end!
+
/* END MODULES */

0 comments on commit 5115ad1

Please sign in to comment.