Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Chaturbate Easy Tipping Fixed Version
- // @namespace madTipper
- // @version 0.11
- // @author omgmikey - fixed on 1/21/2018 by tblopgreg
- // @match https://*.chaturbate.com/*
- // @grant GM_getValue
- // @grant GM_setValue
- // @license MIT
- // @run-at document-idle
- // @description Adds a new tipping popup and modifies the existing one
- // ==/UserScript==
- var CB2_TipButtonText = "TRINKGELD SENDEN";
- var CB2_TipPopupHeaderText = "Trinkgeld senden"
- var CSS_GREY = {'color': 'rgb(88,141,61)'};
- var CSS_WHITE = {'color': '#FFFFFF'};
- var CSS_BLACK = {'color': '#000000'};
- var ID_PREFIX = 'madTipper'
- var CLASS_PREFIX = 'madTipper'
- var CLASS_INPUT = CLASS_PREFIX + '_input';
- var BROADCASTER = "";
- var TippingUrl;
- var isLegacy;
- var HTML_IDS = {
- 'BUTTON': 'button',
- 'POPUP': 'popup',
- 'AMOUNT': 'amount',
- 'COUNT': 'count',
- 'INTERVAL': 'interval',
- 'VARIANCE_LOWER': 'variance_lower',
- 'VARIANCE_UPPER': 'variance_upper',
- 'START': 'start',
- 'STOP': 'stop',
- 'TOTAL': 'total',
- 'ETA': 'eta'
- };
- for (var key in HTML_IDS) {
- HTML_IDS[key] = ID_PREFIX + '_' + HTML_IDS[key];
- }
- function dragElement(elmnt, grabElement) {
- var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
- if (grabElement) {
- // if present, the header is where you move the DIV from:
- grabElement.onmousedown = dragMouseDown;
- } else {
- // otherwise, move the DIV from anywhere inside the DIV:
- elmnt.onmousedown = dragMouseDown;
- }
- function dragMouseDown(e) {
- e = e || window.event;
- e.preventDefault();
- // get the mouse cursor position at startup:
- pos3 = e.clientX;
- pos4 = e.clientY;
- document.onmouseup = closeDragElement;
- // call a function whenever the cursor moves:
- document.onmousemove = elementDrag;
- }
- function elementDrag(e) {
- e = e || window.event;
- e.preventDefault();
- // calculate the new cursor position:
- pos1 = pos3 - e.clientX;
- pos2 = pos4 - e.clientY;
- pos3 = e.clientX;
- pos4 = e.clientY;
- // set the element's new position:
- elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
- elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
- }
- function closeDragElement() {
- // stop moving when mouse button is released:
- document.onmouseup = null;
- document.onmousemove = null;
- }
- }
- function getCookie(cname) {
- var name = cname + "=";
- var decodedCookie = decodeURIComponent(document.cookie);
- var ca = decodedCookie.split(';');
- for(var i = 0; i <ca.length; i++) {
- var c = ca[i];
- while (c.charAt(0) == ' ') {
- c = c.substring(1);
- }
- if (c.indexOf(name) == 0) {
- return c.substring(name.length, c.length);
- }
- }
- return "";
- }
- function setCookie(cname, cvalue, exdays) {
- var d = new Date();
- d.setTime(d.getTime() + (exdays*24*60*60*1000));
- var expires = "expires="+ d.toUTCString();
- document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
- }
- function applyCSSobjectToElement(element, cssObject) {
- for (let key in cssObject) {
- element.style[key] = cssObject[key];
- }
- }
- var tipPopup = "";
- var tipButton = "";
- var buttonContainer = "nix";
- var tipsLeft = 0;
- var tipFunctionTimeout = null;
- var juration = loadJuration();
- setTimeout(function initialize() {
- isLegacy = getCookie("cb_legacy") === "1"; // new Beta website of CB, with interactive fullscreen and that jazz
- if (isLegacy) {
- tipButton = document.querySelector("a.tip_button").parentElement;
- buttonContainer = document.querySelector("div.tip_shell");
- TippingUrl = document.querySelector('.tip_popup form').action
- tipPopup = document.querySelector('.overlay_popup.tip_popup');
- tipPopupHeader = document.querySelector("div.tip_popup div.title")
- }
- else {
- tipButton = document.querySelector(`[title="${CB2_TipButtonText}"]`);
- buttonContainer = tipButton.parentElement;
- buttonContainer.parentElement.style.width = "430px";
- var broadcaster = JSON.parse(initialRoomDossier).broadcaster_username;
- TippingUrl = "/tipping/send_tip/" + broadcaster + "/";
- var divTags = document.getElementsByTagName("div");
- var tipPopupHeader;
- for (var i = 0; i < divTags.length; i++) {
- if (divTags[i].textContent == CB2_TipPopupHeaderText) {
- tipPopupHeader = divTags[i];
- break;
- }
- }
- if (tipPopupHeader) {
- tipPopup = tipPopupHeader.parentElement
- }
- }
- dragElement(tipPopup, tipPopupHeader);
- createTipperButton();
- createTipperPopup();
- injectCSS();
- loadPreviousSettings();
- initializeButtonCallbacks();
- updateTipperButton();
- }, 400);
- function createTipperButton() {
- buttonContainer.insertAdjacentHTML("beforeend", '<span id="madTipper_button" >MADTIPPER</span>');
- }
- function updateTipperButton() {
- if (tipsLeft == 0) {
- document.getElementById(HTML_IDS['BUTTON']).innerHTML = 'MAD TIPPER';
- document.getElementById(HTML_IDS['BUTTON']).style.width = "80px";
- }
- else {
- document.getElementById(HTML_IDS['BUTTON']).innerHTML = 'MAD TIPPER (' + tipsLeft + ')' ;
- document.getElementById(HTML_IDS['BUTTON']).style.width = "120px";
- }
- }
- function createTipperPopup() {
- buttonContainer.insertAdjacentHTML("beforeend",
- '<div class="overlay_popup" id="madTipper_popup">' +
- '<div id="madTipper_popup_header" style="color: rgb(11, 93, 129); background-color: rgb(224, 224, 224); font-size: 15px; font-family: UbuntuBold, Helvetica, Arial, sans-serif; padding: 6px;">Mad Tipper</div>'+
- '<table width="100%" border="0" cellspacing="0" cellpadding="0">' +
- '<tbody>' +
- '<tr>' +
- '<div class="body">' +
- '<form>' +
- '<label>Amount per tip:</label><br >' +
- '<input type="text" id="madTipper_amount" class="madTipper_input">' +
- '<br />' +
- '<label>Number of tips:</label><br >' +
- '<input type="text" id="madTipper_count" class="madTipper_input">' +
- '<br /><hr />' +
- '<label>Interval:</label><br >' +
- '<input type="text" id="madTipper_interval" class="madTipper_input">' +
- '<br />' +
- '<label>Interval variance lower (optional):</label><br >' +
- '<input type="text" id="madTipper_variance_lower" class="madTipper_input">' +
- '<br />' +
- '<label>Interval variance upper (optional):</label><br >' +
- '<input type="text" id="madTipper_variance_upper" class="madTipper_input">' +
- '<br /><hr />' +
- 'Total tip: ' + '<a id="madTipper_total"></a>' +
- '<br />' +
- 'Estimated duration: ' + '<a id="madTipper_eta"></a>' +
- '</form>' +
- '<hr />' +
- '<button id="madTipper_start">Start</button>' +
- '<button id="madTipper_stop" disabled="disabled">Stop</button>' +
- '</div>' +
- '</td>' +
- '</tr>' +
- '</tbody>' +
- '</table>' +
- '</div>'
- );
- }
- function injectCSS() {
- var buttonBackgroundUrl =
- 'url("https://ssl-ccstatic.highwebmedia.com/images/btn-sprites2.gif?ac5eba7d5cf3") no-repeat right';
- var buttonFontFamily =
- 'UbuntuMedium,Arial,Helvetica,sans-serif';
- var genericButtonCSS = {
- 'height':'21px',
- 'width':'100px',
- 'padding-left':'10px',
- 'marginRight':'10px',
- 'fontSize':'12px',
- 'textShadow':'1px 1px 0 #588d3d',
- 'color': '#FFFFFF'
- };
- genericButtonCSS['font-family'] = buttonFontFamily;
- genericButtonCSS['background'] = buttonBackgroundUrl + ' -84px';
- var mainButtonCSS = {
- position: "absolute",
- marginRight: "10px",
- fontSize: "12px",
- textShadow: "rgb(88, 141, 61) 1px 1px 0px",
- color: "rgb(255, 255, 255)",
- }
- for (let key in genericButtonCSS) {
- if (mainButtonCSS[key] === undefined) {
- mainButtonCSS[key] = genericButtonCSS[key];
- }
- }
- console.log("Hallo");
- if (isLegacy) {
- document.getElementById(HTML_IDS['BUTTON']).classList.add(tipButton.classList[0])
- document.getElementById(HTML_IDS['BUTTON']).style.left = parseInt(getComputedStyle(tipButton).left, 10) + parseInt(getComputedStyle(tipButton).width, 10) + "px";
- document.getElementById(HTML_IDS['BUTTON']).style.lineHeight = 1.7;
- document.getElementById(HTML_IDS['BUTTON']).style.color = "white";
- }
- else {
- document.getElementById(HTML_IDS['BUTTON']).style.cssText = tipButton.style.cssText
- }
- console.log("blablabla");
- for (const element of document.getElementsByClassName(CLASS_INPUT)) {
- element.style.width = "auto";
- element.style.marginBottom = "10px" ;
- };
- document.getElementById(HTML_IDS['POPUP']).style.position = "absolute" ;
- document.getElementById(HTML_IDS['POPUP']).style.zIndex = "auto" ;
- document.getElementById(HTML_IDS['POPUP']).style.width = "280px" ;
- document.getElementById(HTML_IDS['POPUP']).style.height = "367px";
- document.getElementById(HTML_IDS['POPUP']).style.backgroundColor = "rgb(255, 255, 255)";
- document.getElementById(HTML_IDS['POPUP']).style.border = "2px solid rgb(11, 93, 129)";
- document.getElementById(HTML_IDS['POPUP']).style.borderRadius = "4px";
- document.getElementById(HTML_IDS['POPUP']).style.color = "rgb(73, 73, 73)";
- document.getElementById(HTML_IDS['POPUP']).style.top = "-340" ;
- document.getElementById(HTML_IDS['POPUP']).style.left = "170" ;
- document.getElementById(HTML_IDS['POPUP']).style.display = "none" ;
- document.getElementById(HTML_IDS['POPUP']).style.fontFamily = "UbuntuRegular, Helvetica, Arial, sans-serif";
- dragElement(document.getElementById(HTML_IDS['POPUP']), document.getElementById("madTipper_popup_header"))
- applyCSSobjectToElement(document.getElementById(HTML_IDS['START']), genericButtonCSS)
- genericButtonCSS['background'] = buttonBackgroundUrl + ' -42px';
- delete genericButtonCSS['color'];
- applyCSSobjectToElement(document.getElementById(HTML_IDS['STOP']), genericButtonCSS)
- }
- function startTipping() {
- var err = verifyTipperFields();
- if (err) {
- alert(err);
- stopTipping();
- return;
- }
- saveCurrentSettings();
- document.getElementById(HTML_IDS['START']).disabled = true;
- applyCSSobjectToElement(document.getElementById(HTML_IDS['START']), CSS_GREY) ;
- document.getElementById(HTML_IDS['STOP']).disabled = false
- applyCSSobjectToElement(document.getElementById(HTML_IDS['STOP']), CSS_WHITE) ;
- document.getElementById(HTML_IDS['STOP']);
- for (const element of document.getElementsByClassName(CLASS_INPUT)) {
- element.disabled = true;
- applyCSSobjectToElement(element, CSS_GREY);
- };
- tipsLeft = getTipCount();
- /* we really want to send the first one immediately */
- sendTip();
- if (tipsLeft > 0) {
- chainQueueTips();
- }
- }
- function verifyTipperFields() {
- function isInt(value) {
- var regex = /^[0-9]+$/;
- return regex.test(String(value));
- }
- function isDuration(value) {
- try {
- juration.parse(value);
- return true;
- }
- catch(ex) {
- return false;
- }
- }
- function isDurationOrEmpty(value) {
- return value === '' || isDuration(value);
- }
- if (!isInt(getTipAmountRaw()) || getTipAmount() <= 0) {
- return 'Tip amount field should be a positive integer.';
- }
- if (!isInt(getTipCountRaw()) || getTipCount() <= 0) {
- return 'Tip count field should be a positive integer.';
- }
- if (!isDuration(getTipInterval())) {
- return 'Tip interval should contain a duration. E.g.: "2.5s", "1", "2min"';
- }
- if (!isDurationOrEmpty(getVarianceLowerRaw()) || !isDurationOrEmpty(getVarianceUpperRaw())) {
- return 'Variance fields should contain durations, or be left blank. E.g.: "", "2.5s"';
- }
- }
- function getSleepInterval() {
- var interval = juration.parse(getTipInterval());
- var lower_bound = interval - getVarianceLower();
- var upper_bound = interval + getVarianceUpper();
- return getRandomNumber(lower_bound, upper_bound) * 1000;
- }
- function getRandomNumber(min, max) {
- return Math.random() * (max - min) + min;
- }
- function chainQueueTips() {
- var sleepTime = getSleepInterval();
- tipFunctionTimeout = setTimeout(function() {
- sendTip(chainQueueTips);
- }, sleepTime);
- }
- function sendTip(queueNextTipFn) {
- var queryParams = {
- 'csrfmiddlewaretoken': getCookie('csrftoken'),
- 'tip_amount': getTipAmount(),
- 'source': 'theater',
- 'message': '',
- 'tip_room_type': 'public' // TODO: normally not static, used before was: document.getElementById('id_tip_room_type').value
- };
- fetch(TippingUrl,
- {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'X-Requested-With': 'XMLHttpRequest'
- },
- body: Object.keys(queryParams).map(function(k) {
- return encodeURIComponent(k) + '=' + encodeURIComponent(queryParams[k])
- }).join('&')
- })
- .then(function (response) {
- if (response.error) {
- alert(response.error);
- stopTipping();
- }
- })
- .catch(function (error) {
- alert(response.error);
- stopTipping();
- });
- updateTipsLeft();
- if (tipsLeft === 0) {
- stopTipping();
- }
- else if (queueNextTipFn) {
- queueNextTipFn();
- }
- }
- function updateTipsLeft() {
- tipsLeft--;
- updateTipperButton();
- }
- function stopTipping() {
- clearTimeout(tipFunctionTimeout);
- tipFunctionTimeout = null;
- tipsLeft = 0;
- updateTipperButton();
- document.getElementById(HTML_IDS['STOP']).disabled = true;
- applyCSSobjectToElement(document.getElementById(HTML_IDS['STOP']), CSS_GREY);
- document.getElementById(HTML_IDS['START']).disabled = false;
- applyCSSobjectToElement(document.getElementById(HTML_IDS['STOP']), CSS_WHITE);
- for (const element of document.getElementsByClassName(CLASS_INPUT)) {
- element.disabled = false;;
- applyCSSobjectToElement(element, CSS_BLACK);
- };
- }
- function initializeButtonCallbacks() {
- var popup = document.getElementById(HTML_IDS['POPUP'])
- var button = document.getElementById(HTML_IDS['BUTTON'])
- button.onclick = function(ev) {
- if (popup.style.display !=="none") {
- popup.style.display = "none";
- }
- else {
- popup.style.display = "block";
- }
- };
- popup.onclick = function(ev) {
- ev.stopPropagation();
- };
- document.getElementById(HTML_IDS['START']).onclick =function() {
- startTipping();
- document.getElementById(HTML_IDS['POPUP']).style.display = "none";
- };
- document.getElementById(HTML_IDS['STOP']).onclick = function() {
- stopTipping();
- };
- document.body.addEventListener("click", function(ev) {
- if (ev.target.id != button.id) {
- document.getElementById(HTML_IDS['POPUP']).style.display = "none";
- }
- });
- for (const element of document.getElementsByClassName(CLASS_INPUT)) {
- element.onChange = ()=> {
- calculateAndSetTotalTip();
- calculateAndSetETA();
- }
- };
- }
- function calculateAndSetTotalTip() {
- var value = document.getElementById(HTML_IDS['AMOUNT']).value * document.getElementById(HTML_IDS['COUNT']).value;
- document.getElementById(HTML_IDS['TOTAL']).innerHTML = value + ' tokens';
- }
- function calculateAndSetETA() {
- var interval = juration.parse(document.getElementById(HTML_IDS['INTERVAL']).value);
- /* we're not counting the first tip */
- var count = getTipCount() - 1;
- var variance_lower = getVarianceLower();
- var variance_upper = getVarianceUpper();
- var eta = (interval + variance_upper - variance_lower) * count;
- document.getElementById(HTML_IDS['ETA']).innerHTML = juration.stringify(eta, {'format': 'long', 'units': 2});
- }
- function getTipAmount() {
- return parseInt(getTipAmountRaw());
- }
- function getTipAmountRaw() {
- return document.getElementById(HTML_IDS['AMOUNT']).value;
- }
- function getTipInterval() {
- return document.getElementById(HTML_IDS['INTERVAL']).value;
- }
- function getTipCount() {
- return parseInt(getTipCountRaw());
- }
- function getTipCountRaw() {
- return document.getElementById(HTML_IDS['COUNT']).value;
- }
- function getVarianceLower() {
- return parseVariance(getVarianceLowerRaw());
- }
- function getVarianceLowerRaw() {
- return document.getElementById(HTML_IDS['VARIANCE_LOWER']).value;
- }
- function getVarianceUpper() {
- return parseVariance(getVarianceUpperRaw());
- }
- function getVarianceUpperRaw() {
- return document.getElementById(HTML_IDS['VARIANCE_UPPER']).value;
- }
- function parseVariance(variance) {
- if (variance == '0') {
- variance = 0;
- }
- variance = variance || 0;
- if (variance != 0) {
- variance = juration.parse(variance);
- }
- return variance;
- }
- function saveCurrentSettings() {
- GM_setValue('amount', getTipAmount());
- GM_setValue('interval', getTipInterval());
- GM_setValue('count', getTipCount());
- GM_setValue('variance_lower', getVarianceLower());
- GM_setValue('variance_upper', getVarianceUpper());
- }
- function loadPreviousSettings() {
- var amount = GM_getValue('amount', 1);
- document.getElementById(HTML_IDS['AMOUNT']).value = amount;
- var count = GM_getValue('count', 10);
- document.getElementById(HTML_IDS['COUNT']).value = count;
- var interval = GM_getValue('interval', '1s');
- document.getElementById(HTML_IDS['INTERVAL']).value = interval;
- var variance_lower = GM_getValue('variance_lower', '');
- document.getElementById(HTML_IDS['VARIANCE_LOWER']).value = variance_lower;
- var variance_upper = GM_getValue('variance_upper', '');
- document.getElementById(HTML_IDS['VARIANCE_UPPER']).value = variance_upper;
- calculateAndSetTotalTip();
- calculateAndSetETA();
- }
- // Script ends here
- // Libs included because they're not on a popular cdn
- /*
- * juration - a natural language duration parser
- * https://github.com/domchristie/juration
- *
- * Copyright 2011, Dom Christie
- * Licenced under the MIT licence
- *
- */
- function loadJuration() {
- var UNITS = {
- seconds: {
- patterns: ['second', 'sec', 's'],
- value: 1,
- formats: {
- 'chrono': '',
- 'micro': 's',
- 'short': 'sec',
- 'long': 'second'
- }
- },
- minutes: {
- patterns: ['minute', 'min', 'm(?!s)'],
- value: 60,
- formats: {
- 'chrono': ':',
- 'micro': 'm',
- 'short': 'min',
- 'long': 'minute'
- }
- },
- hours: {
- patterns: ['hour', 'hr', 'h'],
- value: 3600,
- formats: {
- 'chrono': ':',
- 'micro': 'h',
- 'short': 'hr',
- 'long': 'hour'
- }
- },
- days: {
- patterns: ['day', 'dy', 'd'],
- value: 86400,
- formats: {
- 'chrono': ':',
- 'micro': 'd',
- 'short': 'day',
- 'long': 'day'
- }
- },
- weeks: {
- patterns: ['week', 'wk', 'w'],
- value: 604800,
- formats: {
- 'chrono': ':',
- 'micro': 'w',
- 'short': 'wk',
- 'long': 'week'
- }
- },
- months: {
- patterns: ['month', 'mon', 'mo', 'mth'],
- value: 2628000,
- formats: {
- 'chrono': ':',
- 'micro': 'm',
- 'short': 'mth',
- 'long': 'month'
- }
- },
- years: {
- patterns: ['year', 'yr', 'y'],
- value: 31536000,
- formats: {
- 'chrono': ':',
- 'micro': 'y',
- 'short': 'yr',
- 'long': 'year'
- }
- }
- };
- var stringify = function(seconds, options) {
- if(!_isNumeric(seconds)) {
- throw "juration.stringify(): Unable to stringify a non-numeric value";
- }
- if((typeof options === 'object' && options.format !== undefined) && (options.format !== 'micro' && options.format !== 'short' && options.format !== 'long' && options.format !== 'chrono')) {
- throw "juration.stringify(): format cannot be '" + options.format + "', and must be either 'micro', 'short', or 'long'";
- }
- var defaults = {
- format: 'short',
- units: undefined
- };
- var opts = _extend(defaults, options);
- var units = ['years', 'months', 'days', 'hours', 'minutes', 'seconds'], values = [];
- var remaining = seconds;
- var activeUnits = 0;
- for(var i = 0, len = units.length;
- i < len && (opts.units == undefined || activeUnits < opts.units);
- i++) {
- var unit = UNITS[units[i]];
- values[i] = Math.floor(remaining / unit.value);
- if (values[i] > 0 || activeUnits > 0)
- activeUnits++;
- if(opts.format === 'micro' || opts.format === 'chrono') {
- values[i] += unit.formats[opts.format];
- }
- else {
- values[i] += ' ' + _pluralize(values[i], unit.formats[opts.format]);
- }
- remaining = remaining % unit.value;
- }
- var output = '';
- for(i = 0, len = values.length; i < len; i++) {
- if(values[i].charAt(0) !== "0" && opts.format != 'chrono') {
- output += values[i] + ' ';
- }
- else if (opts.format == 'chrono') {
- output += _padLeft(values[i]+'', '0', i==values.length-1 ? 2 : 3);
- }
- }
- return output.replace(/\s+$/, '').replace(/^(00:)+/g, '').replace(/^0/, '');
- };
- var parse = function(string) {
- // returns calculated values separated by spaces
- for(var unit in UNITS) {
- for(var i = 0, mLen = UNITS[unit].patterns.length; i < mLen; i++) {
- var regex = new RegExp("((?:\\d+\\.\\d+)|\\d+)\\s?(" + UNITS[unit].patterns[i] + "s?(?=\\s|\\d|\\b))", 'gi');
- string = string.replace(regex, function(str, p1, p2) {
- return " " + (p1 * UNITS[unit].value).toString() + " ";
- });
- }
- }
- var sum = 0,
- numbers = string
- .replace(/(?!\.)\W+/g, ' ') // replaces non-word chars (excluding '.') with whitespace
- .replace(/^\s+|\s+$|(?:and|plus|with)\s?/g, '') // trim L/R whitespace, replace known join words with ''
- .split(' ');
- for(var j = 0, nLen = numbers.length; j < nLen; j++) {
- if(numbers[j] && isFinite(numbers[j])) {
- sum += parseFloat(numbers[j]);
- } else if(!numbers[j]) {
- throw "juration.parse(): Unable to parse: a falsey value";
- } else {
- // throw an exception if it's not a valid word/unit
- throw "juration.parse(): Unable to parse: " + numbers[j].replace(/^\d+/g, '');
- }
- }
- return sum;
- };
- // _padLeft('5', '0', 2); // 05
- var _padLeft = function(s, c, n) {
- if (! s || ! c || s.length >= n) {
- return s;
- }
- var max = (n - s.length)/c.length;
- for (var i = 0; i < max; i++) {
- s = c + s;
- }
- return s;
- };
- var _pluralize = function(count, singular) {
- return count == 1 ? singular : singular + "s";
- };
- var _isNumeric = function(n) {
- return !isNaN(parseFloat(n)) && isFinite(n);
- };
- var _extend = function(obj, extObj) {
- for (var i in extObj) {
- if(extObj[i] !== undefined) {
- obj[i] = extObj[i];
- }
- }
- return obj;
- };
- var juration = {
- parse: parse,
- stringify: stringify,
- humanize: stringify
- };
- return juration;
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement