FollowOver

Rollover for user info and follow button.

目前为 2016-12-04 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name FollowOver
  3. // @namespace https://www.ekkooff.com/
  4. // @version 1.1
  5. // @description Rollover for user info and follow button.
  6. // @author Kevin Roberts (@echo)
  7. // @match https://gab.ai/*
  8. // @include https://gab.ai/*
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function() {
  13. 'use strict';
  14.  
  15. var styles = $('<style type="text/css">\n\
  16. #followpopup {\n\
  17. font-family: freight-sans-pro!important;\n\
  18. background-color:white;\n\
  19. position:absolute;\n\
  20. z-index:10000;\n\
  21. display:none;\n\
  22. height:140px;\n\
  23. width:500px;\n\
  24. padding:4px;\n\
  25. border:1px solid #666;\n\
  26. border-radius:5px;\n\
  27. }\n\
  28. #followpopup-loading {\n\
  29. position: absolute;\n\
  30. z-index: 9999;\n\
  31. }\n\
  32. #followpopup-loading .spinning {\n\
  33. display: inline-block;\n\
  34. animation-name: spin;\n\
  35. animation-duration: 1500ms;\n\
  36. animation-iteration-count: infinite;\n\
  37. animation-timing-function: linear;\n\
  38. }\n\
  39. \n\
  40. #followpopup-head {\n\
  41. text-align: center;\n\
  42. margin-bottom:3px;\n\
  43. }\n\
  44. #followpopup-head span {\n\
  45. padding-right:5px;\n\
  46. }\n\
  47. \n\
  48. #followpopup-bio {\n\
  49. height: 82px;\n\
  50. overflow: hidden;\n\
  51. word-wrap: break-word;\n\
  52. -ms-word-break: break-all;\n\
  53. overflow-wrap: break-word;\n\
  54. word-break: break-word;\n\
  55. text-overflow: ellipsis;\n\
  56. margin-bottom:5px;\n\
  57. }\n\
  58. \n\
  59. #followpopup-info {\n\
  60. border: 1px solid #edeeee;\n\
  61. overflow:hidden;\n\
  62. white-space: nowrap;\n\
  63. text-overflow: ellipsis;\n\
  64. border-radius:4px;\n\
  65. display:block;\n\
  66. width:100%;\n\
  67. height: 28px;\n\
  68. position:relative;\n\
  69. }\n\
  70. \n\
  71. #followpopup-follow {\n\
  72. right:0;\n\
  73. position:absolute;\n\
  74. width:55px;\n\
  75. color: white;\n\
  76. text-decoration: none;\n\
  77. padding: 5px 10px;\n\
  78. display: inline-block;\n\
  79. }\n\
  80. \n\
  81. #followpopup-info span {\n\
  82. border-right: 1px solid #edeeee;\n\
  83. padding: 3px;\n\
  84. display: inline-block;\n\
  85. }\n\
  86. \n\
  87. #followpopup #followpopup-followback {\n\
  88. background-color: white;\n\
  89. right:75px;\n\
  90. position:absolute;\n\
  91. padding-right: 6px;\n\
  92. height: 100%;\n\
  93. }\n\
  94. \n\
  95. #followpopup .follow {\n\
  96. background: #34cf7f;\n\
  97. }\n\
  98. \n\
  99. #followpopup .unfollow {\n\
  100. background: red;\n\
  101. }\n\
  102. \n\
  103. #followpopup .pending {\n\
  104. background: #edeeee;\n\
  105. color: #000;\n\
  106. }\n\
  107. \n\
  108. #followpopup .empty {\n\
  109. background: transparent;\n\
  110. }\n\
  111. #followpopup .ion-checkmark-circled.verified-badge {\n\
  112. background:transparent;\n\
  113. color:#33f!important;\n\
  114. }\n\
  115. \n\
  116. </style>');
  117.  
  118.  
  119. var userInfoPopup = $('<div id="followpopup">\
  120. <div id="followpopup-head">\
  121. <strong><span id="followpopup-name"></span></strong>\
  122. <span id="followpopup-username"></span>\
  123. </div>\
  124. <div id="followpopup-bio"></div>\
  125. <div id="followpopup-info">\
  126. ?<span id="followpopup-score"></span>\
  127. <span id="followpopup-posts"></span>\
  128. <span id="followpopup-followers"></span>\
  129. <span id="followpopup-following"></span>\
  130. <span id="followpopup-followback"></span>\
  131. <a href="#" id="followpopup-follow"></a>\
  132. </div>\
  133. </div>');
  134.  
  135. var loadingPopup = $('<div id="followpopup-loading"><i class="ion-load-c spinning"> </i></div>');
  136.  
  137. var addToBody = function() {
  138. $('body').append(styles).append(userInfoPopup).append(loadingPopup);
  139. if($('body').css('background-color')!=='rgba(0, 0, 0, 0)'&&$('body').css('background-color')!=='transparent') {
  140. var bgcolor = $('body').css('background-color');
  141. userInfoPopup.css('background-color',bgcolor);
  142. loadingPopup.css('background-color',bgcolor);
  143. $('#followpopup-followback').css('background-color',bgcolor);
  144. }
  145.  
  146. $('#followpopup-follow').click(function() {
  147. var d = {};
  148. if($(this).text()==='Unfollow'||$(this).text()==='Pending') {
  149. d._method = 'delete';
  150. }
  151. var priv = $(this).hasClass('private');
  152. $.ajax({
  153. method: 'POST',
  154. url: '/users/'+id+'/follow',
  155. data: d
  156. }).done(function(data) {
  157. if(data.state==='success') {
  158. if(d._method) {
  159. $('#followpopup-follow').text('Follow').removeClass().addClass('follow');
  160. if($('#followpopup-followback i').hasClass('ion-arrow-swap')) {
  161. $('#followpopup-followback i').removeClass().addClass('ion-arrow-left-c');
  162. }
  163. } else if(!priv) {
  164. $('#followpopup-follow').text('Unfollow').removeClass().addClass('unfollow');
  165. if($('#followpopup-followback i').hasClass('ion-arrow-left-c')) {
  166. $('#followpopup-followback i').removeClass().addClass('ion-arrow-swap');
  167. }
  168. } else {
  169. $('#followpopup-follow').text('Pending').removeClass().addClass('pending');
  170. }
  171.  
  172. if(priv) {
  173. $('#followpopup-follow').addClass('private');
  174. }
  175. }
  176. });
  177. return false;
  178. });
  179.  
  180. };
  181.  
  182. window.addEventListener('load',function() {
  183. var timeout=null;
  184. var timeout2=null;
  185. var id=null;
  186.  
  187. //addToBody();
  188.  
  189. var targets = 'a.post__meta__name__full, a.post__meta__name__username, .notification-list .notification-list__item__message div:first-child span a:first-child, .notification-list__item__users a, a.notification-list__item__mention__name, a.notification-list__item__mention__username, a.inner-post-mention, a.profile-badge__name, a.profile-badge__username';
  190. var nameTarget = 'span.mini-user-list__item__name';
  191. var usernameTarget = 'span.mini-user-list__item__username';
  192. var allTargets = targets+', '+nameTarget+', '+usernameTarget;
  193.  
  194. var populatePopup = function(data,css) {
  195. id = data.id;
  196. if(!$('#followpopup').length) addToBody();
  197. $('#followpopup-name').html(data.name+(data.verified?' <i class="ion-checkmark-circled verified-badge"></i>':''));
  198. $('#followpopup-username').text('@'+data.username);
  199. $('#followpopup-bio').text(data.bio);
  200. $('#followpopup-score').text(data.score);
  201. $('#followpopup-posts').text(data.post_count+' posts');
  202. $('#followpopup-followers').text(data.follower_count+' followers');
  203. $('#followpopup-following').text(data.following_count+' following');
  204. if(data.followed) {
  205. if(data.following) {
  206. $('#followpopup-followback').html('<i class="ion-arrow-swap"></i>');
  207. } else {
  208. $('#followpopup-followback').html('<i class="ion-arrow-left-c"></i>');
  209. }
  210. } else {
  211. $('#followpopup-followback').html('');
  212. }
  213. if(authUser.username!=data.username) {
  214. if(data.follow_pending) {
  215. $('#followpopup-follow').text('Pending').removeClass().addClass('pending');
  216. } else if(!data.following) {
  217. $('#followpopup-follow').text('Follow').removeClass().addClass('follow');
  218. } else {
  219. $('#followpopup-follow').text('Unfollow').removeClass().addClass('unfollow');
  220. }
  221. } else {
  222. $('#followpopup-follow').text('').removeClass().addClass('empty');
  223. }
  224. if(data.is_private) {
  225. $('#followpopup-follow').addClass('private');
  226. }
  227. userInfoPopup.css(css).show();
  228. };
  229.  
  230. var getUserInfo = function(name,e) {
  231. clearTimeout(timeout);
  232. var offset = $(e.currentTarget).offset();
  233. var offset2 = $(e.currentTarget.parentElement).offset();
  234. var height = $(window).height();
  235. var width = $(window).width();
  236. var css = {
  237. top:((e.clientY<(height/2))?offset.top+25:offset.top-160)+'px',
  238. left:(((width-515)>offset2.left)?offset2.left:width-515)+'px'
  239. };
  240. var loadingCss = {
  241. top: ((e.clientY<(height/2))?offset.top+25:offset.top-25)+'px',
  242. left: offset.left
  243. };
  244. loadingPopup.css(loadingCss).show();
  245. $.ajax({
  246. method: 'GET',
  247. url: '/users/'+name,
  248. headers: {
  249. 'Authorization': 'Bearer '+localStorage.id_token
  250. }
  251. }).done(function(data) {
  252. loadingPopup.hide();
  253. populatePopup(data,css);
  254. }).error(function(data) {
  255. loadingPopup.hide();
  256. });
  257. };
  258.  
  259. $('body').on('mouseenter',targets ,function(e){
  260. clearTimeout(timeout);
  261. clearTimeout(timeout2);
  262. var name = e.currentTarget.href.substr(e.currentTarget.href.lastIndexOf('/')+1);
  263. timeout2 = setTimeout(function() {
  264. getUserInfo(name,e);
  265. },500);
  266. }).on('mouseenter',nameTarget,function(e) {
  267. clearTimeout(timeout);
  268. clearTimeout(timeout2);
  269. var name = $(e.currentTarget).next().text().substring(1);
  270. timeout2 = setTimeout(function() {
  271. getUserInfo(name,e);
  272. },500);
  273. }).on('mouseenter',usernameTarget,function(e) {
  274. clearTimeout(timeout);
  275. clearTimeout(timeout2);
  276. var name = $(e.currentTarget).text().substring(1);
  277. timeout2 = setTimeout(function() {
  278. getUserInfo(name,e);
  279. },500);
  280. }).on('click',allTargets,function(e){
  281. clearTimeout(timeout);
  282. clearTimeout(timeout2);
  283. userInfoPopup.hide();
  284. }).on('mouseleave',allTargets,function(){
  285. clearTimeout(timeout2);
  286. timeout = setTimeout(function(){
  287. loadingPopup.hide();
  288. userInfoPopup.hide();
  289. }, 650);
  290. });
  291.  
  292. (function(history){
  293. var pushState = history.pushState;
  294. history.pushState = function(state) {
  295. if (typeof history.onpushstate == "function") {
  296. history.onpushstate({state: state});
  297. }
  298. clearTimeout(timeout);
  299. clearTimeout(timeout2);
  300. userInfoPopup.hide();
  301. return pushState.apply(history, arguments);
  302. };
  303. })(window.history);
  304.  
  305. userInfoPopup.mouseenter(function() {
  306. clearTimeout(timeout);
  307. clearTimeout(timeout2);
  308. loadingPopup.hide();
  309. }).mouseleave(function() {
  310. clearTimeout(timeout2);
  311. timeout = setTimeout(function() {
  312. loadingPopup.hide();
  313. userInfoPopup.hide();
  314. }, 650);
  315. });
  316. },false);
  317. })();