PageRenderTime 71ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/js/rrssb.js

https://gitlab.com/waltspence/rrssb
JavaScript | 376 lines | 255 code | 67 blank | 54 comment | 37 complexity | e6e1da4b3b2cc0ac56969a0514846f17 MD5 | raw file
  1. /*!
  2. Ridiculously Responsive Social Sharing Buttons
  3. Team: @dbox, @joshuatuscan
  4. Site: http://www.kurtnoble.com/labs/rrssb
  5. Twitter: @therealkni
  6. ___ ___
  7. /__/| /__/\ ___
  8. | |:| \ \:\ / /\
  9. | |:| \ \:\ / /:/
  10. __| |:| _____\__\:\ /__/::\
  11. /__/\_|:|____ /__/::::::::\ \__\/\:\__
  12. \ \:\/:::::/ \ \:\~~\~~\/ \ \:\/\
  13. \ \::/~~~~ \ \:\ ~~~ \__\::/
  14. \ \:\ \ \:\ /__/:/
  15. \ \:\ \ \:\ \__\/
  16. \__\/ \__\/
  17. */
  18. +(function(window, $, undefined) {
  19. 'use strict';
  20. var support = {
  21. calc : false
  22. };
  23. /*
  24. * Public Function
  25. */
  26. $.fn.rrssb = function( options ) {
  27. // Settings that $.rrssb() will accept.
  28. var settings = $.extend({
  29. description: undefined,
  30. emailAddress: undefined,
  31. emailBody: undefined,
  32. emailSubject: undefined,
  33. image: undefined,
  34. title: undefined,
  35. url: undefined
  36. }, options );
  37. // use some sensible defaults if they didn't specify email settings
  38. settings.emailSubject = settings.emailSubject || settings.title;
  39. settings.emailBody = settings.emailBody ||
  40. (
  41. (settings.description ? settings.description : '') +
  42. (settings.url ? '\n\n' + settings.url : '')
  43. );
  44. // Return the encoded strings if the settings have been changed.
  45. for (var key in settings) {
  46. if (settings.hasOwnProperty(key) && settings[key] !== undefined) {
  47. settings[key] = encodeString(settings[key]);
  48. }
  49. };
  50. if (settings.url !== undefined) {
  51. $(this).find('.rrssb-facebook a').attr('href', 'https://www.facebook.com/sharer/sharer.php?u=' + settings.url);
  52. $(this).find('.rrssb-tumblr a').attr('href', 'http://tumblr.com/share/link?url=' + settings.url + (settings.title !== undefined ? '&name=' + settings.title : '') + (settings.description !== undefined ? '&description=' + settings.description : ''));
  53. $(this).find('.rrssb-linkedin a').attr('href', 'http://www.linkedin.com/shareArticle?mini=true&url=' + settings.url + (settings.title !== undefined ? '&title=' + settings.title : '') + (settings.description !== undefined ? '&summary=' + settings.description : ''));
  54. $(this).find('.rrssb-twitter a').attr('href', 'https://twitter.com/intent/tweet?text=' + (settings.description !== undefined ? settings.description : '') + '%20' + settings.url);
  55. $(this).find('.rrssb-hackernews a').attr('href', 'https://news.ycombinator.com/submitlink?u=' + settings.url + (settings.title !== undefined ? '&text=' + settings.title : ''));
  56. $(this).find('.rrssb-reddit a').attr('href', 'http://www.reddit.com/submit?url=' + settings.url + (settings.description !== undefined ? '&text=' + settings.description : '') + (settings.title !== undefined ? '&title=' + settings.title : ''));
  57. $(this).find('.rrssb-googleplus a').attr('href', 'https://plus.google.com/share?url=' + (settings.description !== undefined ? settings.description : '') + '%20' + settings.url);
  58. $(this).find('.rrssb-pinterest a').attr('href', 'http://pinterest.com/pin/create/button/?url=' + settings.url + ((settings.image !== undefined) ? '&media=' + settings.image : '') + (settings.description !== undefined ? '&description=' + settings.description : ''));
  59. $(this).find('.rrssb-pocket a').attr('href', 'https://getpocket.com/save?url=' + settings.url);
  60. $(this).find('.rrssb-github a').attr('href', settings.url);
  61. $(this).find('.rrssb-print a').attr('href', 'javascript:window.print()');
  62. $(this).find('.rrssb-whatsapp a').attr('href', 'whatsapp://send?text=' + (settings.description !== undefined ? settings.description + '%20' : (settings.title !== undefined ? settings.title + '%20' : '')) + settings.url);
  63. }
  64. if (settings.emailAddress !== undefined || settings.emailSubject) {
  65. $(this).find('.rrssb-email a').attr('href', 'mailto:' + (settings.emailAddress ? settings.emailAddress : '') + '?' + (settings.emailSubject !== undefined ? 'subject=' + settings.emailSubject : '') + (settings.emailBody !== undefined ? '&body=' + settings.emailBody : ''));
  66. }
  67. };
  68. /*
  69. * Utility functions
  70. */
  71. var detectCalcSupport = function(){
  72. //detect if calc is natively supported.
  73. var el = $('<div>');
  74. var calcProps = [
  75. 'calc',
  76. '-webkit-calc',
  77. '-moz-calc'
  78. ];
  79. $('body').append(el);
  80. for (var i=0; i < calcProps.length; i++) {
  81. el.css('width', calcProps[i] + '(1px)');
  82. if(el.width() === 1){
  83. support.calc = calcProps[i];
  84. break;
  85. }
  86. }
  87. el.remove();
  88. };
  89. var encodeString = function(string) {
  90. // Recursively decode string first to ensure we aren't double encoding.
  91. if (string !== undefined && string !== null) {
  92. if (string.match(/%[0-9a-f]{2}/i) !== null) {
  93. string = decodeURIComponent(string);
  94. encodeString(string);
  95. } else {
  96. return encodeURIComponent(string);
  97. }
  98. }
  99. };
  100. var setPercentBtns = function() {
  101. // loop through each instance of buttons
  102. $('.rrssb-buttons').each(function(index) {
  103. var self = $(this);
  104. var buttons = $('li:visible', self);
  105. var numOfButtons = buttons.length;
  106. var initBtnWidth = 100 / numOfButtons;
  107. // set initial width of buttons
  108. buttons.css('width', initBtnWidth + '%').attr('data-initwidth',initBtnWidth);
  109. });
  110. };
  111. var makeExtremityBtns = function() {
  112. // loop through each instance of buttons
  113. $('.rrssb-buttons').each(function(index) {
  114. var self = $(this);
  115. //get button width
  116. var containerWidth = self.width();
  117. var buttonWidth = $('li', self).not('.small').eq(0).width();
  118. var buttonCountSmall = $('li.small', self).length;
  119. // enlarge buttons if they get wide enough
  120. if (buttonWidth > 170 && buttonCountSmall < 1) {
  121. self.addClass('large-format');
  122. var fontSize = buttonWidth / 12 + 'px';
  123. self.css('font-size', fontSize);
  124. } else {
  125. self.removeClass('large-format');
  126. self.css('font-size', '');
  127. }
  128. if (containerWidth < buttonCountSmall * 25) {
  129. self.removeClass('small-format').addClass('tiny-format');
  130. } else {
  131. self.removeClass('tiny-format');
  132. }
  133. });
  134. };
  135. var backUpFromSmall = function() {
  136. // loop through each instance of buttons
  137. $('.rrssb-buttons').each(function(index) {
  138. var self = $(this);
  139. var buttons = $('li', self);
  140. var smallButtons = buttons.filter('.small');
  141. var totalBtnSze = 0;
  142. var totalTxtSze = 0;
  143. var upCandidate = smallButtons.eq(0);
  144. var nextBackUp = parseFloat(upCandidate.attr('data-size')) + 55;
  145. var smallBtnCount = smallButtons.length;
  146. if (smallBtnCount === buttons.length) {
  147. var btnCalc = smallBtnCount * 42;
  148. var containerWidth = self.width();
  149. if ((btnCalc + nextBackUp) < containerWidth) {
  150. self.removeClass('small-format');
  151. smallButtons.eq(0).removeClass('small');
  152. sizeSmallBtns();
  153. }
  154. } else {
  155. buttons.not('.small').each(function(index) {
  156. var button = $(this);
  157. var txtWidth = parseFloat(button.attr('data-size')) + 55;
  158. var btnWidth = parseFloat(button.width());
  159. totalBtnSze = totalBtnSze + btnWidth;
  160. totalTxtSze = totalTxtSze + txtWidth;
  161. });
  162. var spaceLeft = totalBtnSze - totalTxtSze;
  163. if (nextBackUp < spaceLeft) {
  164. upCandidate.removeClass('small');
  165. sizeSmallBtns();
  166. }
  167. }
  168. });
  169. };
  170. var checkSize = function(init) {
  171. // loop through each instance of buttons
  172. $('.rrssb-buttons').each(function(index) {
  173. var self = $(this);
  174. var buttons = $('li', self);
  175. // get buttons in reverse order and loop through each
  176. $(buttons.get().reverse()).each(function(index, count) {
  177. var button = $(this);
  178. if (button.hasClass('small') === false) {
  179. var txtWidth = parseFloat(button.attr('data-size')) + 55;
  180. var btnWidth = parseFloat(button.width());
  181. if (txtWidth > btnWidth) {
  182. var btn2small = buttons.not('.small').last();
  183. $(btn2small).addClass('small');
  184. sizeSmallBtns();
  185. }
  186. }
  187. if (!--count) backUpFromSmall();
  188. });
  189. });
  190. // if first time running, put it through the magic layout
  191. if (init === true) {
  192. rrssbMagicLayout(sizeSmallBtns);
  193. }
  194. };
  195. var sizeSmallBtns = function() {
  196. // loop through each instance of buttons
  197. $('.rrssb-buttons').each(function(index) {
  198. var self = $(this);
  199. var regButtonCount;
  200. var regPercent;
  201. var pixelsOff;
  202. var magicWidth;
  203. var smallBtnFraction;
  204. var buttons = $('li', self);
  205. var smallButtons = buttons.filter('.small');
  206. // readjust buttons for small display
  207. var smallBtnCount = smallButtons.length;
  208. // make sure there are small buttons
  209. if (smallBtnCount > 0 && smallBtnCount !== buttons.length) {
  210. self.removeClass('small-format');
  211. //make sure small buttons are square when not all small
  212. smallButtons.css('width','42px');
  213. pixelsOff = smallBtnCount * 42;
  214. regButtonCount = buttons.not('.small').length;
  215. regPercent = 100 / regButtonCount;
  216. smallBtnFraction = pixelsOff / regButtonCount;
  217. // if calc is not supported. calculate the width on the fly.
  218. if (support.calc === false) {
  219. magicWidth = ((self.innerWidth()-1) / regButtonCount) - smallBtnFraction;
  220. magicWidth = Math.floor(magicWidth*1000) / 1000;
  221. magicWidth += 'px';
  222. } else {
  223. magicWidth = support.calc+'('+regPercent+'% - '+smallBtnFraction+'px)';
  224. }
  225. buttons.not('.small').css('width', magicWidth);
  226. } else if (smallBtnCount === buttons.length) {
  227. // if all buttons are small, change back to percentage
  228. self.addClass('small-format');
  229. setPercentBtns();
  230. } else {
  231. self.removeClass('small-format');
  232. setPercentBtns();
  233. }
  234. }); //end loop
  235. makeExtremityBtns();
  236. };
  237. var rrssbInit = function() {
  238. $('.rrssb-buttons').each(function(index) {
  239. $(this).addClass('rrssb-'+(index + 1));
  240. });
  241. detectCalcSupport();
  242. setPercentBtns();
  243. // grab initial text width of each button and add as data attr
  244. $('.rrssb-buttons li .rrssb-text').each(function(index) {
  245. var buttonTxt = $(this);
  246. var txtWdth = buttonTxt.width();
  247. buttonTxt.closest('li').attr('data-size', txtWdth);
  248. });
  249. checkSize(true);
  250. };
  251. var rrssbMagicLayout = function(callback) {
  252. //remove small buttons before each conversion try
  253. $('.rrssb-buttons li.small').removeClass('small');
  254. checkSize();
  255. callback();
  256. };
  257. var popupCenter = function(url, title, w, h) {
  258. // Fixes dual-screen position Most browsers Firefox
  259. var dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left;
  260. var dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top;
  261. var width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width;
  262. var height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height;
  263. var left = ((width / 2) - (w / 2)) + dualScreenLeft;
  264. var top = ((height / 3) - (h / 3)) + dualScreenTop;
  265. var newWindow = window.open(url, title, 'scrollbars=yes, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left);
  266. // Puts focus on the newWindow
  267. if (newWindow && newWindow.focus) {
  268. newWindow.focus();
  269. }
  270. };
  271. var waitForFinalEvent = (function () {
  272. var timers = {};
  273. return function (callback, ms, uniqueId) {
  274. if (!uniqueId) {
  275. uniqueId = "Don't call this twice without a uniqueId";
  276. }
  277. if (timers[uniqueId]) {
  278. clearTimeout (timers[uniqueId]);
  279. }
  280. timers[uniqueId] = setTimeout(callback, ms);
  281. };
  282. })();
  283. // init load
  284. $(document).ready(function(){
  285. /*
  286. * Event listners
  287. */
  288. try {
  289. $(document).on('click', '.rrssb-buttons a.popup', {}, function popUp(e) {
  290. var self = $(this);
  291. popupCenter(self.attr('href'), self.find('.rrssb-text').html(), 580, 470);
  292. e.preventDefault();
  293. });
  294. }
  295. catch (e) { // catching this adds partial support for jQuery 1.3
  296. }
  297. // resize function
  298. $(window).resize(function () {
  299. rrssbMagicLayout(sizeSmallBtns);
  300. waitForFinalEvent(function(){
  301. rrssbMagicLayout(sizeSmallBtns);
  302. }, 200, "finished resizing");
  303. });
  304. rrssbInit();
  305. });
  306. // Make global
  307. window.rrssbInit = rrssbInit;
  308. })(window, jQuery);