Advertisement
tblop

Working-ChaturbateEasyTipping.js

Jan 21st, 2018
2,516
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name         Chaturbate Easy Tipping Fixed Version
  3. // @namespace    madTipper
  4. // @version      0.11
  5. // @author       omgmikey - fixed on 1/21/2018 by tblopgreg
  6. // @match        https://chaturbate.com/*
  7. // @require      https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js
  8. // @require      https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js
  9. // @require      https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js
  10. // @grant        GM_getValue
  11. // @grant        GM_setValue
  12. // @license      MIT
  13. // @run-at       document-idle
  14. // @description Adds a new tipping popup and modifies the existing one
  15. // ==/UserScript==
  16.  
  17. var CSS_GREY  = {'color': 'rgb(88,141,61)'};
  18. var CSS_WHITE = {'color': '#FFFFFF'};
  19. var CSS_BLACK = {'color': '#000000'};
  20.  
  21. var ID_PREFIX    = '#madTipper'
  22. var CLASS_PREFIX = '.madTipper'
  23. var CLASS_INPUT  = CLASS_PREFIX + '_input';
  24.  
  25. var HTML_IDS = {
  26.     'BUTTON': 'button',
  27.     'POPUP': 'popup',
  28.     'AMOUNT': 'amount',
  29.     'COUNT': 'count',
  30.     'INTERVAL': 'interval',
  31.     'VARIANCE_LOWER': 'variance_lower',
  32.     'VARIANCE_UPPER': 'variance_upper',
  33.  
  34.     'START': 'start',
  35.     'STOP': 'stop',
  36.     'TOTAL': 'total',
  37.     'ETA': 'eta'
  38. }
  39.  
  40. for (var key in HTML_IDS) {
  41.     HTML_IDS[key] = ID_PREFIX + '_' + HTML_IDS[key];
  42. }
  43.  
  44. var shell = $('.tip_shell');
  45. var tipsLeft = 0;
  46. var tipFunctionTimeout = null;
  47. var juration = loadJuration();
  48.  
  49. (function initialize() {
  50.  
  51.     createTipperButton();
  52.     createTipperPopup();
  53.     injectCSS();
  54.     improveDefaultTipPopup();
  55.  
  56.     loadPreviousSettings();
  57.     initializeButtonCallbacks();
  58.     updateTipperButton();
  59. })();
  60.  
  61. function createTipperButton() {
  62.  
  63.     shell.append('<div id="madTipper_button_bg"><a href="#" id="madTipper_button"></a></div>');
  64. }
  65.  
  66. function updateTipperButton() {
  67.  
  68.     if (tipsLeft == 0) {
  69.         $(HTML_IDS['BUTTON']).html('MAD TIPPER').css({'width': '80px'});
  70.     }
  71.     else {
  72.         $(HTML_IDS['BUTTON']).html('MAD TIPPER (' + tipsLeft + ')').css({'width': '120px'});
  73.     }
  74. }
  75.  
  76. function createTipperPopup() {
  77.  
  78.     shell.append(
  79.         '<div class="overlay_popup" id="madTipper_popup">' +
  80.             '<table width="100%" border="0" cellspacing="0" cellpadding="0">' +
  81.                 '<tbody>' +
  82.                     '<tr>' +
  83.                         '<td class="formborder">' +
  84.                             '<div class="title">Mad Tipper</div>' +
  85.                             '<div class="body">' +
  86.                                 '<form>' +
  87.                                     '<label>Amount per tip:</label><br >' +
  88.                                     '<input type="text" id="madTipper_amount" class="madTipper_input">' +
  89.                                     '<br />' +
  90.  
  91.                                     '<label>Number of tips:</label><br >' +
  92.                                     '<input type="text" id="madTipper_count" class="madTipper_input">' +
  93.                                     '<br /><hr />' +
  94.  
  95.                                     '<label>Interval:</label><br >' +
  96.                                     '<input type="text" id="madTipper_interval" class="madTipper_input">' +
  97.                                     '<br />' +
  98.  
  99.                                     '<label>Interval variance lower (optional):</label><br >' +
  100.                                     '<input type="text" id="madTipper_variance_lower" class="madTipper_input">' +
  101.                                     '<br />' +
  102.  
  103.                                     '<label>Interval variance upper (optional):</label><br >' +
  104.                                     '<input type="text" id="madTipper_variance_upper" class="madTipper_input">' +
  105.                                     '<br /><hr />' +
  106.  
  107.                                     'Total tip:  ' + '<a id="madTipper_total"></a>' +
  108.                                     '<br />' +
  109.                                     'Estimated duration:  ' + '<a id="madTipper_eta"></a>' +
  110.                                 '</form>' +
  111.                                 '<hr />' +
  112.                                 '<button id="madTipper_start">Start</button>' +
  113.                                 '<button id="madTipper_stop" disabled="disabled">Stop</button>' +
  114.                             '</div>' +
  115.                         '</td>' +
  116.                     '</tr>' +
  117.                 '</tbody>' +
  118.             '</table>' +
  119.         '</div>'
  120.     );
  121. }
  122.  
  123. function injectCSS() {
  124.  
  125.     var buttonBackgroundUrl =
  126.         'url("https://ssl-ccstatic.highwebmedia.com/images/btn-sprites2.gif?ac5eba7d5cf3") no-repeat right';
  127.  
  128.     var buttonFontFamily =
  129.         'UbuntuMedium,Arial,Helvetica,sans-serif';
  130.  
  131.     var genericButtonCSS = {
  132.         'height':'21px',
  133.         'width':'100px',
  134.         'padding-left':'10px',
  135.         'margin-right':'10px',
  136.         'font-size':'12px',
  137.         'text-shadow':'1px 1px 0 #588d3d',
  138.         'color': '#FFFFFF'
  139.     };
  140.  
  141.     genericButtonCSS['font-family'] = buttonFontFamily;
  142.     genericButtonCSS['background'] = buttonBackgroundUrl + ' -84px';
  143.  
  144.     var mainButtonCSS = {
  145.         'position': 'absolute',
  146.         'left': '500px',
  147.         'top': '30px',
  148.         'height': '18px',
  149.         'padding': '3px 10px 0 0',
  150.         'text-decoration': 'none',
  151.         'text-align': 'center',
  152.         'width': '80px'
  153.     }
  154.  
  155.     for (var key in genericButtonCSS) {
  156.         if (mainButtonCSS[key] === undefined) {
  157.             mainButtonCSS[key] = genericButtonCSS[key];
  158.         }
  159.     }
  160.  
  161.     $(HTML_IDS['BUTTON']).css(mainButtonCSS);
  162.  
  163.     $(CLASS_INPUT).css({
  164.         'width': 'auto',
  165.         'margin-bottom': '10px'
  166.     });
  167.  
  168.     $(HTML_IDS['POPUP']).css({
  169.         'position': 'absolute',
  170.         'z-index': 1000,
  171.         'width': '280px',
  172.         'top': '-456px',
  173.         'left': '452px',
  174.         'display': 'none'
  175.     }).draggable();
  176.  
  177.     $(HTML_IDS['POPUP'] + ' .formborder').css({
  178.         'border-bottom': '2px solid #0b5d81',
  179.         'height': '420px'
  180.     });
  181.  
  182.     $(HTML_IDS['START']).css(genericButtonCSS);
  183.     genericButtonCSS['background'] = buttonBackgroundUrl + ' -42px';
  184.  
  185.     delete genericButtonCSS['color'];
  186.     $(HTML_IDS['STOP']).css(genericButtonCSS);
  187. }
  188.  
  189. function improveDefaultTipPopup() {
  190.  
  191.     $('.overlay_popup.tip_popup').css({
  192.         'top': '-240px'
  193.     }).draggable();
  194.  
  195.     $('#tip_message').css({
  196.         'margin-bottom': '20px'
  197.     })
  198.     .append('<input type="checkbox" class="float_right" id="tip_keepopen"></input><br />')
  199.     .append('<br /><label class="float_right" for="tip_keepopen">Keep this window open after tipping</label>');
  200.  
  201.     $('.float_right').css({
  202.         'float': 'right'
  203.     });
  204.  
  205.     setPopupHeight('250px');
  206.  
  207.     var tipPopup = $('.tip_popup');
  208.     var keepOpenCheckbox = $('#tip_keepopen');
  209.     var popupIsForcedOpen = false;
  210.  
  211.     /* use CB jquery to ensure correct callback execution order */
  212.     var tipPopupForm = defchat_settings.domroot.find('.tip_popup form');
  213.     tipPopupForm.submit(onFormSubmit);
  214.  
  215.     keepOpenCheckbox.css({
  216.         'margin-top': '10px'
  217.     });
  218.  
  219.     $('body').click(function(ev) {
  220.  
  221.         if ($('.tip_button').is(ev.target)) {
  222.             popupIsForcedOpen = false;
  223.             return;
  224.         }
  225.  
  226.         if (!popupIsForcedOpen || tipPopup.has(ev.target).length) {
  227.             return;
  228.         }
  229.  
  230.         if (tipPopup.is(':visible')) {
  231.             tipPopup.hide();
  232.         }
  233.  
  234.         popupIsForcedOpen = false;
  235.     });
  236.  
  237.     function onFormSubmit() {
  238.  
  239.         setPopupHeight('270px');
  240.  
  241.         if (!keepOpenCheckbox.is(':checked')) {
  242.             return;
  243.         }
  244.  
  245.         if (!tipPopup.is(':visible')) {
  246.             tipPopup.show();
  247.             popupIsForcedOpen = true;
  248.         }
  249.     }
  250.  
  251.     function setPopupHeight(value) {
  252.         $('.overlay_popup.tip_popup .formborder').css({
  253.             'height': value,
  254.         });
  255.     }
  256. }
  257.  
  258. function startTipping() {
  259.  
  260.     var err = verifyTipperFields();
  261.  
  262.     if (err) {
  263.         alert(err);
  264.         stopTipping();
  265.         return;
  266.     }
  267.  
  268.     saveCurrentSettings();
  269.  
  270.     $(HTML_IDS['START']).prop('disabled', true).css(CSS_GREY);
  271.     $(HTML_IDS['STOP']).prop('disabled', false).css(CSS_WHITE);
  272.     $(CLASS_INPUT).prop('disabled', true).css(CSS_GREY);
  273.  
  274.     tipsLeft = getTipCount();
  275.  
  276.     /* we really want to send the first one immediately */
  277.     sendTip();
  278.  
  279.     if (tipsLeft > 0) {
  280.         chainQueueTips();
  281.     }
  282. }
  283.  
  284. function verifyTipperFields() {
  285.  
  286.     function isInt(value) {
  287.         var regex = /^[0-9]+$/;
  288.         return regex.test(String(value));
  289.     }
  290.  
  291.     function isDuration(value) {
  292.         try {
  293.             juration.parse(value);
  294.             return true;
  295.         }
  296.         catch(ex) {
  297.             return false;
  298.         }
  299.     }
  300.  
  301.     function isDurationOrEmpty(value) {
  302.         return value === '' || isDuration(value);
  303.     }
  304.  
  305.     if (!isInt(getTipAmountRaw()) || getTipAmount() <= 0) {
  306.         return 'Tip amount field should be a positive integer.';
  307.     }
  308.  
  309.     if (!isInt(getTipCountRaw()) || getTipCount() <= 0) {
  310.         return 'Tip count field should be a positive integer.';
  311.     }
  312.  
  313.     if (!isDuration(getTipInterval())) {
  314.         return 'Tip interval should contain a duration. E.g.: "2.5s", "1", "2min"';
  315.     }
  316.  
  317.     if (!isDurationOrEmpty(getVarianceLowerRaw()) || !isDurationOrEmpty(getVarianceUpperRaw())) {
  318.         return 'Variance fields should contain durations, or be left blank. E.g.: "", "2.5s"';
  319.     }
  320. }
  321.  
  322. function getSleepInterval() {
  323.  
  324.     var interval = juration.parse(getTipInterval());
  325.     var lower_bound = interval - getVarianceLower();
  326.     var upper_bound = interval + getVarianceUpper();
  327.  
  328.     return getRandomNumber(lower_bound, upper_bound) * 1000;
  329. }
  330.  
  331. function getRandomNumber(min, max) {
  332.  
  333.     return Math.random() * (max - min) + min;
  334. }
  335.  
  336. function chainQueueTips() {
  337.  
  338.     var sleepTime = getSleepInterval();
  339.  
  340.     tipFunctionTimeout = setTimeout(function() {
  341.         sendTip(chainQueueTips);
  342.     }, sleepTime);
  343. }
  344.  
  345. function sendTip(queueNextTipFn) {
  346.  
  347.     var queryUrl = $('.tip_popup form').attr('action');
  348.  
  349.     var queryParams = $.param({
  350.         'csrfmiddlewaretoken': $.cookie('csrftoken'),
  351.         'tip_amount': getTipAmount(),
  352.         'message': '',
  353.         'tip_room_type': $('#id_tip_room_type').val(),
  354.         'tip_v': defchat_settings.v_tip_vol,
  355.     });
  356.  
  357.     $.ajax({
  358.         url: queryUrl,
  359.         data: queryParams,
  360.         dataType: 'json',
  361.         type: 'post',
  362.         success: function(response) {
  363.             if (response.error) {
  364.                 alert(response.error);
  365.                 stopTipping();
  366.             }
  367.         }
  368.     });
  369.  
  370.     updateTipsLeft();
  371.  
  372.     if (tipsLeft === 0) {
  373.         stopTipping();
  374.     }
  375.     else if (queueNextTipFn) {
  376.         queueNextTipFn();
  377.     }
  378. }
  379.  
  380. function updateTipsLeft() {
  381.  
  382.     tipsLeft--;
  383.     updateTipperButton();
  384. }
  385.  
  386. function stopTipping() {
  387.  
  388.     clearTimeout(tipFunctionTimeout);
  389.     tipFunctionTimeout = null;
  390.  
  391.     tipsLeft = 0;
  392.     updateTipperButton();
  393.  
  394.     $(HTML_IDS['STOP']).prop('disabled', true).css(CSS_GREY);
  395.     $(HTML_IDS['START']).prop('disabled', false).css(CSS_WHITE);
  396.     $(CLASS_INPUT).prop('disabled', false).css(CSS_BLACK);
  397. }
  398.  
  399. function initializeButtonCallbacks() {
  400.  
  401.     var popup = $(HTML_IDS['POPUP']);
  402.     var button = $(HTML_IDS['BUTTON']);
  403.  
  404.     button.click(function(ev) {
  405.         if (popup.is(':visible')) {
  406.             popup.hide();
  407.         }
  408.         else {
  409.             popup.show();
  410.         }
  411.     });
  412.  
  413.     popup.click(function(ev) {
  414.         ev.stopPropagation();
  415.     });
  416.  
  417.     $(HTML_IDS['START']).click(function() {
  418.         startTipping();
  419.         $(HTML_IDS['POPUP']).hide();
  420.     });
  421.  
  422.     $(HTML_IDS['STOP']).click(function() {
  423.         stopTipping();
  424.     });
  425.  
  426.     $('body').click(function(ev) {
  427.         if (ev.target.id != button.prop('id')) {
  428.             $(HTML_IDS['POPUP']).hide();
  429.         }
  430.     });
  431.  
  432.     $(CLASS_INPUT).change(function() {
  433.         calculateAndSetTotalTip();
  434.         calculateAndSetETA();
  435.     });
  436. }
  437.  
  438. function calculateAndSetTotalTip() {
  439.  
  440.     var value = $(HTML_IDS['AMOUNT']).val() * $(HTML_IDS['COUNT']).val();
  441.     $(HTML_IDS['TOTAL']).html(value + ' tokens');
  442. }
  443.  
  444. function calculateAndSetETA() {
  445.  
  446.     var interval = juration.parse($(HTML_IDS['INTERVAL']).val());
  447.  
  448.     /* we're not counting the first tip */
  449.     var count = getTipCount() - 1;
  450.  
  451.     var variance_lower = getVarianceLower();
  452.     var variance_upper = getVarianceUpper();
  453.  
  454.     var eta = (interval + variance_upper - variance_lower) * count;
  455.     $(HTML_IDS['ETA']).html(juration.stringify(eta, {'format': 'long', 'units': 2}));
  456. }
  457.  
  458. function getTipAmount() {
  459.  
  460.     return parseInt(getTipAmountRaw());
  461. }
  462.  
  463. function getTipAmountRaw() {
  464.  
  465.     return $(HTML_IDS['AMOUNT']).val();
  466. }
  467.  
  468. function getTipInterval() {
  469.  
  470.     return $(HTML_IDS['INTERVAL']).val();
  471. }
  472.  
  473. function getTipCount() {
  474.  
  475.     return parseInt(getTipCountRaw());
  476. }
  477.  
  478. function getTipCountRaw() {
  479.  
  480.     return $(HTML_IDS['COUNT']).val();
  481. }
  482.  
  483. function getVarianceLower() {
  484.  
  485.     return parseVariance(getVarianceLowerRaw());
  486. }
  487.  
  488. function getVarianceLowerRaw() {
  489.  
  490.     return $(HTML_IDS['VARIANCE_LOWER']).val();
  491. }
  492.  
  493.  
  494. function getVarianceUpper() {
  495.  
  496.     return parseVariance(getVarianceUpperRaw());
  497. }
  498.  
  499. function getVarianceUpperRaw() {
  500.  
  501.     return $(HTML_IDS['VARIANCE_UPPER']).val();
  502. }
  503.  
  504. function parseVariance(variance) {
  505.  
  506.     if (variance == '0') {
  507.         variance = 0;
  508.     }
  509.  
  510.     variance = variance || 0;
  511.  
  512.     if (variance != 0) {
  513.         variance = juration.parse(variance);
  514.     }
  515.  
  516.     return variance;
  517. }
  518.  
  519. function saveCurrentSettings() {
  520.  
  521.     GM_setValue('amount', getTipAmount());
  522.     GM_setValue('interval', getTipInterval());
  523.     GM_setValue('count', getTipCount());
  524.     GM_setValue('variance_lower', getVarianceLower());
  525.     GM_setValue('variance_upper', getVarianceUpper());
  526. }
  527.  
  528. function loadPreviousSettings() {
  529.  
  530.     var amount = GM_getValue('amount', 1);
  531.     $(HTML_IDS['AMOUNT']).val(amount);
  532.  
  533.     var count = GM_getValue('count', 10);
  534.     $(HTML_IDS['COUNT']).val(count);
  535.  
  536.     var interval = GM_getValue('interval', '1s');
  537.     $(HTML_IDS['INTERVAL']).val(interval);
  538.  
  539.     var variance_lower = GM_getValue('variance_lower', '');
  540.     $(HTML_IDS['VARIANCE_LOWER']).val(variance_lower);
  541.  
  542.     var variance_upper = GM_getValue('variance_upper', '');
  543.     $(HTML_IDS['VARIANCE_UPPER']).val(variance_upper);
  544.  
  545.     calculateAndSetTotalTip();
  546.     calculateAndSetETA();
  547. }
  548.  
  549.  
  550. // Script ends here
  551. // Libs included because they're not on a popular cdn
  552.  
  553.  
  554. /*
  555.  * juration - a natural language duration parser
  556.  * https://github.com/domchristie/juration
  557.  *
  558.  * Copyright 2011, Dom Christie
  559.  * Licenced under the MIT licence
  560.  *
  561.  */
  562.  
  563. function loadJuration() {
  564.  
  565.   var UNITS = {
  566.     seconds: {
  567.       patterns: ['second', 'sec', 's'],
  568.       value: 1,
  569.       formats: {
  570.         'chrono': '',
  571.         'micro':  's',
  572.         'short':  'sec',
  573.         'long':   'second'
  574.       }
  575.     },
  576.     minutes: {
  577.       patterns: ['minute', 'min', 'm(?!s)'],
  578.       value: 60,
  579.       formats: {
  580.         'chrono': ':',
  581.         'micro':  'm',
  582.         'short':  'min',
  583.         'long':   'minute'
  584.       }
  585.     },
  586.     hours: {
  587.       patterns: ['hour', 'hr', 'h'],
  588.       value: 3600,
  589.       formats: {
  590.         'chrono': ':',
  591.         'micro':  'h',
  592.         'short':  'hr',
  593.         'long':   'hour'
  594.       }
  595.     },
  596.     days: {
  597.       patterns: ['day', 'dy', 'd'],
  598.       value: 86400,
  599.       formats: {
  600.         'chrono': ':',
  601.         'micro':  'd',
  602.         'short':  'day',
  603.         'long':   'day'
  604.       }
  605.     },
  606.     weeks: {
  607.       patterns: ['week', 'wk', 'w'],
  608.       value: 604800,
  609.       formats: {
  610.         'chrono': ':',
  611.         'micro':  'w',
  612.         'short':  'wk',
  613.         'long':   'week'
  614.       }
  615.     },
  616.     months: {
  617.       patterns: ['month', 'mon', 'mo', 'mth'],
  618.       value: 2628000,
  619.       formats: {
  620.         'chrono': ':',
  621.         'micro':  'm',
  622.         'short':  'mth',
  623.         'long':   'month'
  624.       }
  625.     },
  626.     years: {
  627.       patterns: ['year', 'yr', 'y'],
  628.       value: 31536000,
  629.       formats: {
  630.         'chrono': ':',
  631.         'micro':  'y',
  632.         'short':  'yr',
  633.         'long':   'year'
  634.       }
  635.     }
  636.   };
  637.  
  638.   var stringify = function(seconds, options) {
  639.  
  640.     if(!_isNumeric(seconds)) {
  641.       throw "juration.stringify(): Unable to stringify a non-numeric value";
  642.     }
  643.  
  644.     if((typeof options === 'object' && options.format !== undefined) && (options.format !== 'micro' && options.format !== 'short' && options.format !== 'long' && options.format !== 'chrono')) {
  645.       throw "juration.stringify(): format cannot be '" + options.format + "', and must be either 'micro', 'short', or 'long'";
  646.     }
  647.  
  648.     var defaults = {
  649.       format: 'short',
  650.       units: undefined
  651.     };
  652.  
  653.     var opts = _extend(defaults, options);
  654.  
  655.     var units = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'], values = [];
  656.     var remaining = seconds;
  657.     var activeUnits = 0;
  658.     for(var i = 0, len = units.length;
  659.         i < len && (opts.units == undefined || activeUnits < opts.units);
  660.         i++) {
  661.       var unit = UNITS[units[i]];
  662.       values[i] = Math.floor(remaining / unit.value);
  663.       if (values[i] > 0 || activeUnits > 0)
  664.         activeUnits++;
  665.  
  666.       if(opts.format === 'micro' || opts.format === 'chrono') {
  667.         values[i] += unit.formats[opts.format];
  668.       }
  669.       else {
  670.         values[i] += ' ' + _pluralize(values[i], unit.formats[opts.format]);
  671.       }
  672.       remaining = remaining % unit.value;
  673.     }
  674.     var output = '';
  675.     for(i = 0, len = values.length; i < len; i++) {
  676.       if(values[i].charAt(0) !== "0" && opts.format != 'chrono') {
  677.         output += values[i] + ' ';
  678.       }
  679.       else if (opts.format == 'chrono') {
  680.         output += _padLeft(values[i]+'', '0', i==values.length-1 ? 2 : 3);
  681.       }
  682.     }
  683.     return output.replace(/\s+$/, '').replace(/^(00:)+/g, '').replace(/^0/, '');
  684.   };
  685.  
  686.   var parse = function(string) {
  687.  
  688.     // returns calculated values separated by spaces
  689.     for(var unit in UNITS) {
  690.       for(var i = 0, mLen = UNITS[unit].patterns.length; i < mLen; i++) {
  691.         var regex = new RegExp("((?:\\d+\\.\\d+)|\\d+)\\s?(" + UNITS[unit].patterns[i] + "s?(?=\\s|\\d|\\b))", 'gi');
  692.         string = string.replace(regex, function(str, p1, p2) {
  693.           return " " + (p1 * UNITS[unit].value).toString() + " ";
  694.         });
  695.       }
  696.     }
  697.  
  698.     var sum = 0,
  699.         numbers = string
  700.                     .replace(/(?!\.)\W+/g, ' ')                       // replaces non-word chars (excluding '.') with whitespace
  701.                     .replace(/^\s+|\s+$|(?:and|plus|with)\s?/g, '')   // trim L/R whitespace, replace known join words with ''
  702.                     .split(' ');
  703.  
  704.     for(var j = 0, nLen = numbers.length; j < nLen; j++) {
  705.       if(numbers[j] && isFinite(numbers[j])) {
  706.          sum += parseFloat(numbers[j]);
  707.       } else if(!numbers[j]) {
  708.         throw "juration.parse(): Unable to parse: a falsey value";
  709.       } else {
  710.         // throw an exception if it's not a valid word/unit
  711.         throw "juration.parse(): Unable to parse: " + numbers[j].replace(/^\d+/g, '');
  712.       }
  713.     }
  714.     return sum;
  715.   };
  716.  
  717.   // _padLeft('5', '0', 2); // 05
  718.   var _padLeft = function(s, c, n) {
  719.       if (! s || ! c || s.length >= n) {
  720.         return s;
  721.       }
  722.  
  723.       var max = (n - s.length)/c.length;
  724.       for (var i = 0; i < max; i++) {
  725.         s = c + s;
  726.       }
  727.  
  728.       return s;
  729.   };
  730.  
  731.   var _pluralize = function(count, singular) {
  732.     return count == 1 ? singular : singular + "s";
  733.   };
  734.  
  735.   var _isNumeric = function(n) {
  736.     return !isNaN(parseFloat(n)) && isFinite(n);
  737.   };
  738.  
  739.   var _extend = function(obj, extObj) {
  740.     for (var i in extObj) {
  741.       if(extObj[i] !== undefined) {
  742.         obj[i] = extObj[i];
  743.       }
  744.     }
  745.     return obj;
  746.   };
  747.  
  748.   var juration = {
  749.     parse: parse,
  750.     stringify: stringify,
  751.     humanize: stringify
  752.   };
  753.  
  754.   return juration;
  755. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement