jQuery.extend( jQuery.fn.dataTableExt.oSort, {
/**
* European dates dd.mm(.yyyy) or dd/mm(/yyyy), will be detected automatically
*/
'date-eu-pre': function ( date ) {
var year = '', // year is optional
month, day,
character = '/';
if ( date.indexOf('.') > 0 ) {
character = '.'; // if found, use . as the separator.
} else if ( date.indexOf('-') > 0 ) {
character = '-'; // if found, use - as the separator, otherwise use /
}
date = date.replace( ' ', '' ).split( character );
if ( date[2] ) {
year = date[2];
}
month = date[1];
if ( 1 === month.length ) {
month = '0' + month;
}
day = date[0];
if ( 1 === day.length ) {
day = '0' + day;
}
return ( year + month + day ) * 1;
},
'date-eu-asc': function ( a, b ) {
return a - b;
},
'date-eu-desc': function ( a, b ) {
return b - a;
},
/**
* Formatted numbers, currency and percentage values, will be detected automatically
*/
'formatted-num-pre': function ( a ) {
a = ( '-' === a ) ? 0 : a.replace( /[^\d\-\.]/g, "" );
return parseFloat( a ) || 0;
},
'formatted-num-asc': function ( a, b ) {
return a - b;
},
'formatted-num-desc': function ( a, b ) {
return b - a;
},
/**
* Numeric Comma (numbers like 0,5), NOT detected automatically!
*/
'numeric-comma-pre': function ( a ) {
a = ( '-' === a ) ? 0 : a.replace( /[^\d\-\,]/g, "" ).replace( /,/, "." );
return parseFloat( a );
},
'numeric-comma-asc': function ( a, b ) {
return a - b;
},
'numeric-comma-desc': function ( a, b ) {
return b - a;
},
/**
* Numbers and text mixed in a column, text is treated as infinity
*/
'numbers+text-pre': function ( a ) {
if ( ! isNaN( parseFloat( a ) ) && isFinite( a ) ) {
return parseFloat(a);
} else {
return Number.MAX_VALUE;
}
},
'numbers+text-asc': function ( a, b ) {
return a - b;
},
'numbers+text-desc': function ( a, b ) {
return b - a;
},
/* Cell content like 1, 1a, 1b, 2, 3, 3a, 3b, 3c, etc. */
'numbers+letter-pre': function ( a ) {
const number = parseInt( a );
const letter = a.replace( number, '' );
if ( '' === letter ) {
return number;
}
return number + ( letter.toLowerCase().charCodeAt( 0 ) - 96 ) / 100;
},
'numbers+letter-asc': function ( a, b ) {
return a - b;
},
'numbers+letter-desc': function ( a, b ) {
return b - a;
},
} );
/**
* Type detection for currency and percentage values
*/
jQuery.fn.dataTableExt.aTypes.unshift( function ( data ) {
if ( typeof data !== 'string' ) {
return null;
}
if ( data.match( /^(0[1-9]|[12][0-9]|30|31)[\.\/-](0[1-9]|1[012])[\.\/-](19|20|21)\d\d$/ ) ) {
return 'date-eu';
}
return null;
} );
/**
* Type detection for currency and percentage values
*/
(function(){
var re = new RegExp( "[^\$£€%0-9\.,' -]" ); // Init the regex just once for speed
jQuery.fn.dataTableExt.aTypes.unshift( function ( data ) {
if ( typeof data !== 'string' || re.test( data ) ) {
return null;
}
return 'formatted-num';
} );
}());
/**
* Type detection for formatted numbers
*/
jQuery.fn.dataTableExt.aTypes.unshift( function ( data ) {
if ( typeof data !== 'string' ) {
return null;
}
var deformatted = data.replace(/[^\d\-\.\/a-zA-Z]/g,'');
// Replacement for the deprecated jQuery.isNumeric().
const isNumeric = ( obj ) => ( (obj - parseFloat( obj ) + 1) >= 0 );
if ( isNumeric( deformatted ) || '-' === deformatted ) {
return 'formatted-num';
}
return null;
} );
;
!function(e){"function"==typeof define&&define.amd?define(["jquery"],e):"object"==typeof exports?e(require("jquery")):e(jQuery)}(function(m){"use strict";var a;m.support.htmlMenuitem="HTMLMenuItemElement"in window,m.support.htmlCommand="HTMLCommandElement"in window,m.support.eventSelectstart="onselectstart"in document.documentElement,m.ui&&m.widget||(m.cleanData=(a=m.cleanData,function(e){var t,n,o;for(o=0;null!=e[o];o++){n=e[o];try{(t=m._data(n,"events"))&&t.remove&&m(n).triggerHandler("remove")}catch(e){}}a(e)}));var c=null,d=!1,p=m(window),f=0,h={},x={},v={},g={selector:null,appendTo:null,trigger:"right",autoHide:!1,delay:200,reposition:!0,hideOnSecondTrigger:!1,selectableSubMenu:!1,classNames:{hover:"context-menu-hover",disabled:"context-menu-disabled",visible:"context-menu-visible",notSelectable:"context-menu-not-selectable",icon:"context-menu-icon",iconEdit:"context-menu-icon-edit",iconCut:"context-menu-icon-cut",iconCopy:"context-menu-icon-copy",iconPaste:"context-menu-icon-paste",iconDelete:"context-menu-icon-delete",iconAdd:"context-menu-icon-add",iconQuit:"context-menu-icon-quit",iconLoadingClass:"context-menu-icon-loading"},determinePosition:function(e){if(m.ui&&m.ui.position)e.css("display","block").position({my:"center top",at:"center bottom",of:this,offset:"0 5",collision:"fit"}).css("display","none");else{var t=this.offset();t.top+=this.outerHeight(),t.left+=this.outerWidth()/2-e.outerWidth()/2,e.css(t)}},position:function(e,t,n){var o;if(t||n){if("maintain"===t&&"maintain"===n)o=e.$menu.position();else{var a=e.$menu.offsetParent().offset();o={top:n-a.top,left:t-a.left}}var s=p.scrollTop()+p.height(),i=p.scrollLeft()+p.width(),c=e.$menu.outerHeight(),l=e.$menu.outerWidth();o.top+c>s&&(o.top-=c),o.top<0&&(o.top=0),o.left+l>i&&(o.left-=l),o.left<0&&(o.left=0),e.$menu.css(o)}else e.determinePosition.call(this,e.$menu)},positionSubmenu:function(e){if(void 0!==e)if(m.ui&&m.ui.position)e.css("display","block").position({my:"left top-5",at:"right top",of:this,collision:"flipfit fit"}).css("display","");else{var t={top:-9,left:this.outerWidth()-5};e.css(t)}},zIndex:1,animation:{duration:50,show:"slideDown",hide:"slideUp"},events:{show:m.noop,hide:m.noop,activated:m.noop},callback:null,items:{}},s={timer:null,pageX:null,pageY:null},b={abortevent:function(e){e.preventDefault(),e.stopImmediatePropagation()},contextmenu:function(e){var t=m(this);if("right"===e.data.trigger&&(e.preventDefault(),e.stopImmediatePropagation()),!("right"!==e.data.trigger&&"demand"!==e.data.trigger&&e.originalEvent||!(void 0===e.mouseButton||!e.data||"left"===e.data.trigger&&0===e.mouseButton||"right"===e.data.trigger&&2===e.mouseButton)||t.hasClass("context-menu-active")||t.hasClass("context-menu-disabled"))){if(c=t,e.data.build){var n=e.data.build(c,e);if(!1===n)return;if(e.data=m.extend(!0,{},g,e.data,n||{}),!e.data.items||m.isEmptyObject(e.data.items))throw window.console&&(console.error||console.log).call(console,"No items specified to show in contextMenu"),new Error("No Items specified");e.data.$trigger=c,$.create(e.data)}$.show.call(t,e.data,e.pageX,e.pageY)}},click:function(e){e.preventDefault(),e.stopImmediatePropagation(),m(this).trigger(m.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))},mousedown:function(e){var t=m(this);c&&c.length&&!c.is(t)&&c.data("contextMenu").$menu.trigger("contextmenu:hide"),2===e.button&&(c=t.data("contextMenuActive",!0))},mouseup:function(e){var t=m(this);t.data("contextMenuActive")&&c&&c.length&&c.is(t)&&!t.hasClass("context-menu-disabled")&&(e.preventDefault(),e.stopImmediatePropagation(),(c=t).trigger(m.Event("contextmenu",{data:e.data,pageX:e.pageX,pageY:e.pageY}))),t.removeData("contextMenuActive")},mouseenter:function(e){var t=m(this),n=m(e.relatedTarget),o=m(document);n.is(".context-menu-list")||n.closest(".context-menu-list").length||c&&c.length||(s.pageX=e.pageX,s.pageY=e.pageY,s.data=e.data,o.on("mousemove.contextMenuShow",b.mousemove),s.timer=setTimeout(function(){s.timer=null,o.off("mousemove.contextMenuShow"),(c=t).trigger(m.Event("contextmenu",{data:s.data,pageX:s.pageX,pageY:s.pageY}))},e.data.delay))},mousemove:function(e){s.pageX=e.pageX,s.pageY=e.pageY},mouseleave:function(e){var t=m(e.relatedTarget);if(!t.is(".context-menu-list")&&!t.closest(".context-menu-list").length){try{clearTimeout(s.timer)}catch(e){}s.timer=null}},layerClick:function(a){var s,i,c=m(this).data("contextMenuRoot"),l=a.button,r=a.pageX,u=a.pageY,d=void 0===r;a.preventDefault(),setTimeout(function(){if(d)null!=c&&null!==c.$menu&&void 0!==c.$menu&&c.$menu.trigger("contextmenu:hide");else{var e,t="left"===c.trigger&&0===l||"right"===c.trigger&&2===l;if(document.elementFromPoint&&c.$layer){if(c.$layer.hide(),(s=document.elementFromPoint(r-p.scrollLeft(),u-p.scrollTop())).isContentEditable){var n=document.createRange(),o=window.getSelection();n.selectNode(s),n.collapse(!0),o.removeAllRanges(),o.addRange(n)}m(s).trigger(a),c.$layer.show()}if(c.hideOnSecondTrigger&&t&&null!==c.$menu&&void 0!==c.$menu)c.$menu.trigger("contextmenu:hide");else{if(c.reposition&&t)if(document.elementFromPoint){if(c.$trigger.is(s))return void c.position.call(c.$trigger,c,r,u)}else if(i=c.$trigger.offset(),e=m(window),i.top+=e.scrollTop(),i.top<=a.pageY&&(i.left+=e.scrollLeft(),i.left<=a.pageX&&(i.bottom=i.top+c.$trigger.outerHeight(),i.bottom>=a.pageY&&(i.right=i.left+c.$trigger.outerWidth(),i.right>=a.pageX))))return void c.position.call(c.$trigger,c,r,u);s&&t&&c.$trigger.one("contextmenu:hidden",function(){m(s).contextMenu({x:r,y:u,button:l})}),null!=c&&null!==c.$menu&&void 0!==c.$menu&&c.$menu.trigger("contextmenu:hide")}}},50)},keyStop:function(e,t){t.isInput||e.preventDefault(),e.stopPropagation()},key:function(e){var t={};c&&(t=c.data("contextMenu")||{}),void 0===t.zIndex&&(t.zIndex=0);var n=0,o=function(e){""!==e.style.zIndex?n=e.style.zIndex:null!==e.offsetParent&&void 0!==e.offsetParent?o(e.offsetParent):null!==e.parentElement&&void 0!==e.parentElement&&o(e.parentElement)};if(o(e.target),!(t.$menu&&parseInt(n,10)>parseInt(t.$menu.css("zIndex"),10))){switch(e.keyCode){case 9:case 38:if(b.keyStop(e,t),t.isInput){if(9===e.keyCode&&e.shiftKey)return e.preventDefault(),t.$selected&&t.$selected.find("input, textarea, select").blur(),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("prevcommand"));if(38===e.keyCode&&"checkbox"===t.$selected.find("input, textarea, select").prop("type"))return void e.preventDefault()}else if(9!==e.keyCode||e.shiftKey)return void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("prevcommand"));break;case 40:if(b.keyStop(e,t),!t.isInput)return void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("nextcommand"));if(9===e.keyCode)return e.preventDefault(),t.$selected&&t.$selected.find("input, textarea, select").blur(),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("nextcommand"));if(40===e.keyCode&&"checkbox"===t.$selected.find("input, textarea, select").prop("type"))return void e.preventDefault();break;case 37:if(b.keyStop(e,t),t.isInput||!t.$selected||!t.$selected.length)break;if(!t.$selected.parent().hasClass("context-menu-root")){var a=t.$selected.parent().parent();return t.$selected.trigger("contextmenu:blur"),void(t.$selected=a)}break;case 39:if(b.keyStop(e,t),t.isInput||!t.$selected||!t.$selected.length)break;var s=t.$selected.data("contextMenu")||{};if(s.$menu&&t.$selected.hasClass("context-menu-submenu"))return t.$selected=null,s.$selected=null,void s.$menu.trigger("nextcommand");break;case 35:case 36:return t.$selected&&t.$selected.find("input, textarea, select").length?void 0:((t.$selected&&t.$selected.parent()||t.$menu).children(":not(."+t.classNames.disabled+", ."+t.classNames.notSelectable+")")[36===e.keyCode?"first":"last"]().trigger("contextmenu:focus"),void e.preventDefault());case 13:if(b.keyStop(e,t),t.isInput){if(t.$selected&&!t.$selected.is("textarea, select"))return void e.preventDefault();break}return void(void 0!==t.$selected&&null!==t.$selected&&t.$selected.trigger("mouseup"));case 32:case 33:case 34:return void b.keyStop(e,t);case 27:return b.keyStop(e,t),void(null!==t.$menu&&void 0!==t.$menu&&t.$menu.trigger("contextmenu:hide"));default:var i=String.fromCharCode(e.keyCode).toUpperCase();if(t.accesskeys&&t.accesskeys[i])return void t.accesskeys[i].$node.trigger(t.accesskeys[i].$menu?"contextmenu:focus":"mouseup")}e.stopPropagation(),void 0!==t.$selected&&null!==t.$selected&&t.$selected.trigger(e)}},prevItem:function(e){e.stopPropagation();var t=m(this).data("contextMenu")||{},n=m(this).data("contextMenuRoot")||{};if(t.$selected){var o=t.$selected;(t=t.$selected.parent().data("contextMenu")||{}).$selected=o}for(var a=t.$menu.children(),s=t.$selected&&t.$selected.prev().length?t.$selected.prev():a.last(),i=s;s.hasClass(n.classNames.disabled)||s.hasClass(n.classNames.notSelectable)||s.is(":hidden");)if((s=s.prev().length?s.prev():a.last()).is(i))return;t.$selected&&b.itemMouseleave.call(t.$selected.get(0),e),b.itemMouseenter.call(s.get(0),e);var c=s.find("input, textarea, select");c.length&&c.focus()},nextItem:function(e){e.stopPropagation();var t=m(this).data("contextMenu")||{},n=m(this).data("contextMenuRoot")||{};if(t.$selected){var o=t.$selected;(t=t.$selected.parent().data("contextMenu")||{}).$selected=o}for(var a=t.$menu.children(),s=t.$selected&&t.$selected.next().length?t.$selected.next():a.first(),i=s;s.hasClass(n.classNames.disabled)||s.hasClass(n.classNames.notSelectable)||s.is(":hidden");)if((s=s.next().length?s.next():a.first()).is(i))return;t.$selected&&b.itemMouseleave.call(t.$selected.get(0),e),b.itemMouseenter.call(s.get(0),e);var c=s.find("input, textarea, select");c.length&&c.focus()},focusInput:function(){var e=m(this).closest(".context-menu-item"),t=e.data(),n=t.contextMenu,o=t.contextMenuRoot;o.$selected=n.$selected=e,o.isInput=n.isInput=!0},blurInput:function(){var e=m(this).closest(".context-menu-item").data(),t=e.contextMenu;e.contextMenuRoot.isInput=t.isInput=!1},menuMouseenter:function(){m(this).data().contextMenuRoot.hovering=!0},menuMouseleave:function(e){var t=m(this).data().contextMenuRoot;t.$layer&&t.$layer.is(e.relatedTarget)&&(t.hovering=!1)},itemMouseenter:function(e){var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;a.hovering=!0,e&&a.$layer&&a.$layer.is(e.relatedTarget)&&(e.preventDefault(),e.stopImmediatePropagation()),(o.$menu?o:a).$menu.children("."+a.classNames.hover).trigger("contextmenu:blur").children(".hover").trigger("contextmenu:blur"),t.hasClass(a.classNames.disabled)||t.hasClass(a.classNames.notSelectable)?o.$selected=null:t.trigger("contextmenu:focus")},itemMouseleave:function(e){var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;if(a!==o&&a.$layer&&a.$layer.is(e.relatedTarget))return void 0!==a.$selected&&null!==a.$selected&&a.$selected.trigger("contextmenu:blur"),e.preventDefault(),e.stopImmediatePropagation(),void(a.$selected=o.$selected=o.$node);o&&o.$menu&&o.$menu.hasClass("context-menu-visible")||t.trigger("contextmenu:blur")},itemClick:function(e){var t,n=m(this),o=n.data(),a=o.contextMenu,s=o.contextMenuRoot,i=o.contextMenuKey;if(!(!a.items[i]||n.is("."+s.classNames.disabled+", .context-menu-separator, ."+s.classNames.notSelectable)||n.is(".context-menu-submenu")&&!1===s.selectableSubMenu)){if(e.preventDefault(),e.stopImmediatePropagation(),m.isFunction(a.callbacks[i])&&Object.prototype.hasOwnProperty.call(a.callbacks,i))t=a.callbacks[i];else{if(!m.isFunction(s.callback))return;t=s.callback}!1!==t.call(s.$trigger,i,s,e)?s.$menu.trigger("contextmenu:hide"):s.$menu.parent().length&&$.update.call(s.$trigger,s)}},inputClick:function(e){e.stopImmediatePropagation()},hideMenu:function(e,t){var n=m(this).data("contextMenuRoot");$.hide.call(n.$trigger,n,t&&t.force)},focusItem:function(e){e.stopPropagation();var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;t.hasClass(a.classNames.disabled)||t.hasClass(a.classNames.notSelectable)||(t.addClass([a.classNames.hover,a.classNames.visible].join(" ")).parent().find(".context-menu-item").not(t).removeClass(a.classNames.visible).filter("."+a.classNames.hover).trigger("contextmenu:blur"),o.$selected=a.$selected=t,o&&o.$node&&o.$node.hasClass("context-menu-submenu")&&o.$node.addClass(a.classNames.hover),o.$node&&a.positionSubmenu.call(o.$node,o.$menu))},blurItem:function(e){e.stopPropagation();var t=m(this),n=t.data(),o=n.contextMenu,a=n.contextMenuRoot;o.autoHide&&t.removeClass(a.classNames.visible),t.removeClass(a.classNames.hover),o.$selected=null}},$={show:function(n,e,t){var o=m(this),a={};if(m("#context-menu-layer").trigger("mousedown"),n.$trigger=o,!1!==n.events.show.call(o,n))if(!1!==$.update.call(o,n)){if(n.position.call(o,n,e,t),n.zIndex){var s=n.zIndex;"function"==typeof n.zIndex&&(s=n.zIndex.call(o,n)),a.zIndex=function(e){for(var t=0,n=e;t=Math.max(t,parseInt(n.css("z-index"),10)||0),(n=n.parent())&&n.length&&!(-1<"html body".indexOf(n.prop("nodeName").toLowerCase())););return t}(o)+s}$.layer.call(n.$menu,n,a.zIndex),n.$menu.find("ul").css("zIndex",a.zIndex+1),n.$menu.css(a)[n.animation.show](n.animation.duration,function(){o.trigger("contextmenu:visible"),$.activated(n),n.events.activated(n)}),o.data("contextMenu",n).addClass("context-menu-active"),m(document).off("keydown.contextMenu").on("keydown.contextMenu",b.key),n.autoHide&&m(document).on("mousemove.contextMenuAutoHide",function(e){var t=o.offset();t.right=t.left+o.outerWidth(),t.bottom=t.top+o.outerHeight(),!n.$layer||n.hovering||e.pageX>=t.left&&e.pageX<=t.right&&e.pageY>=t.top&&e.pageY<=t.bottom||setTimeout(function(){n.hovering||null===n.$menu||void 0===n.$menu||n.$menu.trigger("contextmenu:hide")},50)})}else c=null;else c=null},hide:function(t,e){var n=m(this);if(t||(t=n.data("contextMenu")||{}),e||!t.events||!1!==t.events.hide.call(n,t)){if(n.removeData("contextMenu").removeClass("context-menu-active"),t.$layer){setTimeout((o=t.$layer,function(){o.remove()}),10);try{delete t.$layer}catch(e){t.$layer=null}}var o;c=null,t.$menu.find("."+t.classNames.hover).trigger("contextmenu:blur"),t.$selected=null,t.$menu.find("."+t.classNames.visible).removeClass(t.classNames.visible),m(document).off(".contextMenuAutoHide").off("keydown.contextMenu"),t.$menu&&t.$menu[t.animation.hide](t.animation.duration,function(){t.build&&(t.$menu.remove(),m.each(t,function(e){switch(e){case"ns":case"selector":case"build":case"trigger":return!0;default:t[e]=void 0;try{delete t[e]}catch(e){}return!0}})),setTimeout(function(){n.trigger("contextmenu:hidden")},10)})}},create:function(r,u){function d(e){var t=m("");if(e._accesskey)e._beforeAccesskey&&t.append(document.createTextNode(e._beforeAccesskey)),m("").addClass("context-menu-accesskey").text(e._accesskey).appendTo(t),e._afterAccesskey&&t.append(document.createTextNode(e._afterAccesskey));else if(e.isHtmlName){if(void 0!==e.accesskey)throw new Error("accesskeys are not compatible with HTML names and cannot be used together in the same item");t.html(e.name)}else t.text(e.name);return t}void 0===u&&(u=r),r.$menu=m('
').addClass(r.className||"").data({contextMenu:r,contextMenuRoot:u}),m.each(["callbacks","commands","inputs"],function(e,t){r[t]={},u[t]||(u[t]={})}),u.accesskeys||(u.accesskeys={}),m.each(r.items,function(n,o){var e=m('').addClass(o.className||""),t=null,a=null;if(e.on("click",m.noop),"string"!=typeof o&&"cm_separator"!==o.type||(o={type:"cm_seperator"}),o.$node=e.data({contextMenu:r,contextMenuRoot:u,contextMenuKey:n}),void 0!==o.accesskey)for(var s,i=function(e){for(var t,n=e.split(/\s+/),o=[],a=0;t=n[a];a++)t=t.charAt(0).toUpperCase(),o.push(t);return o}(o.accesskey),c=0;s=i[c];c++)if(!u.accesskeys[s]){var l=(u.accesskeys[s]=o).name.match(new RegExp("^(.*?)("+s+")(.*)$","i"));l&&(o._beforeAccesskey=l[1],o._accesskey=l[2],o._afterAccesskey=l[3]);break}if(o.type&&v[o.type])v[o.type].call(e,o,r,u),m.each([r,u],function(e,t){t.commands[n]=o,!m.isFunction(o.callback)||void 0!==t.callbacks[n]&&void 0!==r.type||(t.callbacks[n]=o.callback)});else{switch("cm_seperator"===o.type?e.addClass("context-menu-separator "+u.classNames.notSelectable):"html"===o.type?e.addClass("context-menu-html "+u.classNames.notSelectable):"sub"===o.type||(o.type?(t=m("").appendTo(e),d(o).appendTo(t),e.addClass("context-menu-input"),r.hasTypes=!0,m.each([r,u],function(e,t){t.commands[n]=o,t.inputs[n]=o})):o.items&&(o.type="sub")),o.type){case"cm_seperator":break;case"text":a=m('').attr("name","context-menu-input-"+n).val(o.value||"").appendTo(t);break;case"textarea":a=m('').attr("name","context-menu-input-"+n).val(o.value||"").appendTo(t),o.height&&a.height(o.height);break;case"checkbox":a=m('').attr("name","context-menu-input-"+n).val(o.value||"").prop("checked",!!o.selected).prependTo(t);break;case"radio":a=m('').attr("name","context-menu-input-"+o.radio).val(o.value||"").prop("checked",!!o.selected).prependTo(t);break;case"select":a=m('').attr("name","context-menu-input-"+n).appendTo(t),o.options&&(m.each(o.options,function(e,t){m("").val(e).text(t).appendTo(a)}),a.val(o.selected));break;case"sub":d(o).appendTo(e),o.appendTo=o.$node,e.data("contextMenu",o).addClass("context-menu-submenu"),o.callback=null,"function"==typeof o.items.then?$.processPromises(o,u,o.items):$.create(o,u);break;case"html":m(o.html).appendTo(e);break;default:m.each([r,u],function(e,t){t.commands[n]=o,!m.isFunction(o.callback)||void 0!==t.callbacks[n]&&void 0!==r.type||(t.callbacks[n]=o.callback)}),d(o).appendTo(e)}o.type&&"sub"!==o.type&&"html"!==o.type&&"cm_seperator"!==o.type&&(a.on("focus",b.focusInput).on("blur",b.blurInput),o.events&&a.on(o.events,r)),o.icon&&(m.isFunction(o.icon)?o._icon=o.icon.call(this,this,e,n,o):"string"==typeof o.icon&&"fa-"===o.icon.substring(0,3)?o._icon=u.classNames.icon+" "+u.classNames.icon+"--fa fa "+o.icon:o._icon=u.classNames.icon+" "+u.classNames.icon+"-"+o.icon,e.addClass(o._icon))}o.$input=a,o.$label=t,e.appendTo(r.$menu),!r.hasTypes&&m.support.eventSelectstart&&e.on("selectstart.disableTextSelect",b.abortevent)}),r.$node||r.$menu.css("display","none").addClass("context-menu-root"),r.$menu.appendTo(r.appendTo||document.body)},resize:function(e,t){var n;e.css({position:"absolute",display:"block"}),e.data("width",(n=e.get(0)).getBoundingClientRect?Math.ceil(n.getBoundingClientRect().width):e.outerWidth()+1),e.css({position:"static",minWidth:"0px",maxWidth:"100000px"}),e.find("> li > ul").each(function(){$.resize(m(this),!0)}),t||e.find("ul").addBack().css({position:"",display:"",minWidth:"",maxWidth:""}).outerWidth(function(){return m(this).data("width")})},update:function(s,i){var c=this;void 0===i&&(i=s,$.resize(s.$menu));var l=!1;return s.$menu.children().each(function(){var e,t=m(this),n=t.data("contextMenuKey"),o=s.items[n],a=m.isFunction(o.disabled)&&o.disabled.call(c,n,i)||!0===o.disabled;if((e=m.isFunction(o.visible)?o.visible.call(c,n,i):void 0===o.visible||!0===o.visible)&&(l=!0),t[e?"show":"hide"](),t[a?"addClass":"removeClass"](i.classNames.disabled),m.isFunction(o.icon)&&(t.removeClass(o._icon),o._icon=o.icon.call(this,c,t,n,o),t.addClass(o._icon)),o.type)switch(t.find("input, select, textarea").prop("disabled",a),o.type){case"text":case"textarea":o.$input.val(o.value||"");break;case"checkbox":case"radio":o.$input.val(o.value||"").prop("checked",!!o.selected);break;case"select":o.$input.val((0===o.selected?"0":o.selected)||"")}o.$menu&&($.update.call(c,o,i)&&(l=!0))}),l},layer:function(e,t){var n=e.$layer=m('').css({height:p.height(),width:p.width(),display:"block",position:"fixed","z-index":t,top:0,left:0,opacity:0,filter:"alpha(opacity=0)","background-color":"#000"}).data("contextMenuRoot",e).insertBefore(this).on("contextmenu",b.abortevent).on("mousedown",b.layerClick);return void 0===document.body.style.maxWidth&&n.css({position:"absolute",height:m(document).height()}),n},processPromises:function(e,t,n){function o(e,t,n){void 0===n?(n={error:{name:"No items and no error item",icon:"context-menu-icon context-menu-icon-quit"}},window.console&&(console.error||console.log).call(console,'When you reject a promise, provide an "items" object, equal to normal sub-menu items')):"string"==typeof n&&(n={error:{name:n}}),a(e,t,n)}function a(e,t,n){void 0!==t.$menu&&t.$menu.is(":visible")&&(e.$node.removeClass(t.classNames.iconLoadingClass),e.items=n,$.create(e,t,!0),$.update(e,t),t.positionSubmenu.call(e.$node,e.$menu))}e.$node.addClass(t.classNames.iconLoadingClass),n.then(function(e,t,n){void 0===n&&o(void 0),a(e,t,n)}.bind(this,e,t),o.bind(this,e,t))},activated:function(e){var t=e.$menu,n=t.offset(),o=m(window).height(),a=m(window).scrollTop(),s=t.height();oa+o)&&t.css({top:"0px"})}};function l(e){return e.id&&m('label[for="'+e.id+'"]').val()||e.name}m.fn.contextMenu=function(e){var t=this,n=e;if(0= 0) {
return url.replace(pattern, '$1' + paramValue + '$2');
}
return url + (url.indexOf('?') > 0 ? '&' : '?') + paramName + '=' + paramValue;
});
vendor[appName].getAllTableInstances = (function() {
return dataTableInstances;
});
vendor[appName].removeAllTableInstances = (function() {
dataTableInstances = [];
});
vendor[appName].setTableInstance = (function(instance) {
dataTableInstances.push(instance);
});
vendor[appName].getTableInstanceById = (function(id) {
var allTables = this.getAllTableInstances();
for (var i = 0; i < allTables.length; i++) {
if (allTables[i].table_id == id) {
return allTables[i];
}
}
return false;
});
vendor[appName].getTableInstanceByViewId = (function(viewId) {
var allTables = this.getAllTableInstances();
for (var i = 0; i < allTables.length; i++) {
if (allTables[i].table_view_id == viewId) {
return allTables[i];
}
}
return false;
});
vendor[appName].removeTableInstanceByViewId = (function(viewId) {
var allTables = this.getAllTableInstances();
for (var i = 0; i < allTables.length; i++) {
if (allTables[i].table_view_id == viewId) {
allTables.splice(i, 1);
return true;
}
}
return false;
});
vendor[appName].getAllRuleJSInstances = (function() {
return ruleJSInstances;
});
vendor[appName].setRuleJSInstance = (function(table) {
var rootElem = table.closest('.supsystic-tables-wrap'),
viewId = table.data('view-id');
ruleJSInstances[viewId] = new ruleJS(rootElem.attr('id'));
ruleJSInstances[viewId].instanceTable = table;
return ruleJSInstances[viewId];
});
vendor[appName].getRuleJSInstance = (function(table) {
var allRuleJS = this.getAllRuleJSInstances(),
viewId = table.data('view-id');
if (!allRuleJS[viewId]) {
this.setRuleJSInstance(table);
}
return allRuleJS[viewId];
});
vendor[appName].request = (function(route, data) {
if (!jQuery.isPlainObject(route) || !('module' in route) || !('action' in route)) {
throw new Error('Request route is not specified.');
}
if (!jQuery.isPlainObject(data)) {
data = {};
}
if ('action' in data) {
throw new Error('Reserved field "action" used.');
}
data.action = 'supsystic-tables';
var url = window.ajaxurl ? window.ajaxurl : ajax_obj.ajaxurl,
deferred = jQuery.Deferred();
jQuery.post(url, jQuery.extend({}, {
route: route
}, data))
.done(function(response, textStatus, jqXHR) {
if (response.success) {
deferred.resolve(response, textStatus, jqXHR);
} else {
if (data._maxIter) {
retryAjax(deferred, url, route, data, 1, data._maxIter);
} else {
var message = typeof response.message !== 'undefined' ? response.message : 'There are errors during the request.';
deferred.reject(message, textStatus, jqXHR);
}
}
}).fail(function(jqXHR, textStatus, errorThrown) {
if (data._maxIter) {
retryAjax(deferred, url, route, data, 1, data._maxIter);
} else {
deferred.reject(errorThrown, textStatus, jqXHR);
}
});
function retryAjax(def, url, route, data, curIter, maxIter) {
jQuery.post(url, jQuery.extend({}, {
route: route
}, data))
.done(function(response, textStatus, jqXHR) {
if (response.success) {
def.resolve(response, textStatus, jqXHR);
} else {
var message = typeof response.message !== 'undefined' ? response.message : 'There are errors during the request.';
retryErrorHandler(def, url, route, data, curIter, maxIter, message, textStatus, jqXHR);
}
}).fail(function(jqXHR, textStatus, errorThrown) {
retryErrorHandler(def, url, route, data, curIter, maxIter, errorThrown, textStatus, jqXHR);
});
}
function retryErrorHandler(def, url, route, data, curIter, maxIter, errorThrown, textStatus, jqXHR) {
curIter++;
if (curIter < maxIter) {
retryAjax(def, url, route, data, curIter, maxIter);
} else {
def.reject(errorThrown, textStatus, jqXHR);
}
}
return deferred.promise();
});
vendor[appName].setTableMobileWidth = (function(isMobile) {
jQuery('div .supsystic-tables-wrap').each(function() {
isMobile = (typeof(isMobile) == 'undefined' ? true : isMobile);
var ssDiv = jQuery(this),
widthAttr = ssDiv.data('table-width-' + (isMobile ? 'mobile' : 'fixed'));
if (typeof(widthAttr) != 'undefined') {
ssDiv.css('display', (widthAttr == 'auto' ? 'inline-block' : '')).css('width', widthAttr);
}
});
});
vendor[appName].initTablesOnPage = (function(id) {
this._initTablesOnPage(id);
});
vendor[appName]._initTablesOnPage = (function(id) {
var tables = jQuery(typeof id != 'undefined' ? '#supsystic-table-' + id + ':not(.dataTable)' : '.supsystic-table');
if (tables.length == 0) return;
if (typeof this._initTablesOnPageWoo === 'function') this._initTablesOnPageWoo(id);
var self = this,
firstTableId = '',
firstTableViewId = '',
firstTable = '',
firstTableWrapper = '',
firstTableFirstRow = '';
if (jQuery(window).width() <= 991) {
self.setTableMobileWidth();
}
tables.each(function() {
self.initializeTable(this, self.showTable, function(table) {
// This is used when table is hidden in tabs and can't calculate itself width to adjust on small screens
if (table.is(':visible')) {
// Fix bug in FF and IE which not supporting max-width 100% for images in td
self._calculateImages(table);
} else {
table.data('isVisible', setInterval(function() {
if (table.is(':visible')) {
clearInterval(table.data('isVisible'));
self._calculateImages(table);
}
}, 250));
}
// Align all tables on page by the columns width depending on the columns width of first table on page
if (table.data('align-by-first-table')) {
firstTableId = firstTableId || jQuery('.supsystic-table:first').data('id');
firstTable = firstTable || jQuery('#supsystic-table-' + firstTableId);
firstTableViewId = firstTable.data('view-id');
firstTableWrapper = firstTableWrapper || firstTable.parents('#supsystic-table-' + firstTableViewId);
firstTableFirstRow = firstTable.data('head') ? firstTable.find('thead tr:first-child th') : firstTable.find('tbody tr:first-child td');
if (firstTableViewId != table.data('view-id')) {
var currentTableWrapper = table.parents('#supsystic-table-' + table.data('view-id'));
currentTableWrapper.css({
width: firstTableWrapper.get(0).style.width
});
table.css({
width: firstTable.get(0).style.width
});
currentTableWrapper.find('.supsystic-table').each(function() {
var curTable = jQuery(this),
curTableFirstRow = curTable.data('head') ? curTable.find('thead tr:first-child th') : curTable.find('tbody tr:first-child td');
jQuery.each(curTableFirstRow, function(index, element) {
if (firstTableFirstRow[index]) {
jQuery(this).width(jQuery(firstTableFirstRow[index]).get(0).style.width);
}
});
});
}
}
//if row has merged cells no need place header there
if (table.data('merged') && table.hasClass('ColWithMergeCellsAlign')) {
var mergedData = table.data('merged');
jQuery.each(mergedData, function(index, value) {
var rowNumWithMergeCell = value.row;
var numForEq = Number(rowNumWithMergeCell) - 1;
table.find('tbody tr:eq(' + numForEq + ')').closest('tr').addClass('haveMergedCell');
});
self.setCellAttributes(table.parents('.supsystic-tables-wrap:first').find('.DTFC_LeftWrapper, DTFC_RightWrapper, .dataTables_scrollHead, .dataTables_scrollFoot').find('th, td'));
}
if (typeof self.getTableInstanceById(table.data('id')).fnAdjustColumnSizing == 'function') {
table.trigger('responsive-resize.dt');
setTimeout(function() {
table.trigger('responsive-resize.dt');
self.getTableInstanceById(table.data('id')).fnAdjustColumnSizing(false);
}, 500);
}
self.initShortcodesInTable(table);
});
//self.initShortcodesInTable(jQuery(this));
});
});
vendor[appName].initShortcodesInTable = (function(table) {
var tableViewId = table.data('view-id');
//google-maps-easy
if (typeof(gmpAllMapsInfo) !== 'undefined' && gmpAllMapsInfo && gmpAllMapsInfo.length) {
for (var i = 0; i < gmpAllMapsInfo.length; i++) {
var mapData = gmpAllMapsInfo[i],
map = jQuery('#' + mapData.view_html_id);
if (map.length && map.closest('#supsystic-table-' + tableViewId).length) {
var mapViewId = mapData.view_id;
setTimeout(function(mapData, mapViewId) {
g_gmpAllMaps = jQuery.grep(g_gmpAllMaps, function(value) {
if (value.getViewId() == mapViewId) {
if (mapData.heatmap && mapData.heatmap.coords) {
var coord = [],
oldCoord = mapData.heatmap.coords;
for (var c = 0; c < oldCoord.length; c++) {
var data = oldCoord[c];
coord.push(typeof data == 'object' ? data.join(',') : data);
}
mapData.heatmap.coords = coord;
}
if (value._mapParams.simple_slider_id) {
jQuery('#' + value._mapParams.simple_slider_id).html(value._mapParams.original_slider_html);
}
}
return value.getViewId() != mapViewId;
});
gmpInitMapOnPage(mapData);
}, 50, mapData, mapViewId);
}
}
jQuery(document).trigger('gmpAmiVarInited');
}
//ultimate-maps
if (typeof(umsAllMapsInfo) !== 'undefined' && umsAllMapsInfo && umsAllMapsInfo.length) {
for (var i = 0; i < umsAllMapsInfo.length; i++) {
var mapData = umsAllMapsInfo[i],
map = jQuery('#' + mapData.view_html_id);
if (map.length && map.closest('#supsystic-table-' + tableViewId).length) {
var mapViewId = mapData.view_id;
setTimeout(function(mapData, mapViewId) {
g_umsAllMaps = jQuery.grep(g_umsAllMaps, function(value) {
if (value.getViewId() == mapViewId) {
value._mapObj.remove();
}
return value.getViewId() != mapViewId;
});
umsInitMapOnPage(mapData);
}, 600, mapData, mapViewId);
}
}
jQuery(document).trigger('umsAmiVarInited');
}
});
vendor[appName]._getOriginalImageSizes = (function(img) {
var tempImage = new Image(),
width,
height;
if ('naturalWidth' in tempImage && 'naturalHeight' in tempImage) {
width = img.naturalWidth;
height = img.naturalHeight;
} else {
tempImage.src = img.src;
width = tempImage.width;
height = tempImage.height;
}
return {
width: width,
height: height
};
});
vendor[appName]._calculateImages = (function($table) {
var self = this,
$images = $table.find('img');
if ($images.length > 0 && /firefox|trident|msie/i.test(navigator.userAgent)) {
$images.hide();
jQuery.each($images, function(index, el) {
var $img = jQuery(this),
originalSizes = self._getOriginalImageSizes(this);
if ($img.closest('td, th').width() < originalSizes.width) {
$img.css('width', '100%');
}
});
$images.show();
}
});
vendor[appName].createSpinner = (function(elem) {
elem = typeof(elem) != 'undefined' ? elem : false;
if (elem) {
var icon = elem.attr('disabled', true).find('.fa');
if (icon) {
icon.data('icon', icon.attr('class'));
icon.attr('class', 'fa fa-spinner fa-spin');
}
} else {
return jQuery('', {
class: 'fa fa-spinner fa-spin'
});
}
});
vendor[appName].deleteSpinner = (function(elem) {
var icon = elem.attr('disabled', false).find('.fa');
if (icon) {
icon.attr('class', icon.data('icon'));
icon.data('icon', '');
}
});
vendor[appName].initializeTable = (function(table, callback, finalCallback, reinit, addInstance) {
if (typeof jQuery.fn.dataTable.moment == "undefined" && typeof moment !== "undefined") {
jQuery.fn.dataTable.moment = function ( format, locale, reverseEmpties ) {
var types = jQuery.fn.dataTable.ext.type;
// Add type detection
types.detect.unshift( function ( d ) {
if ( d ) {
// Strip HTML tags and newline characters if possible
if ( d.replace ) {
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
}
// Strip out surrounding white space
d = jQuery.trim( d );
}
// Null and empty values are acceptable
if ( d === '' || d === null ) {
return 'moment-'+format;
}
return moment( d, format, locale, true ).isValid() ?
'moment-'+format :
null;
} );
// Add sorting method - use an integer for the sorting
types.order[ 'moment-'+format+'-pre' ] = function ( d ) {
if ( d ) {
// Strip HTML tags and newline characters if possible
if ( d.replace ) {
d = d.replace(/(<.*?>)|(\r?\n|\r)/g, '');
}
// Strip out surrounding white space
d = jQuery.trim( d );
}
return !moment(d, format, locale, true).isValid() ?
(reverseEmpties ? -Infinity : Infinity) :
parseInt( moment( d, format, locale, true ).format( 'x' ), 10 );
};
};
}
if (typeof jQuery.fn.dataTable.ext.order.intl == "undefined" && typeof window.Intl !== "undefined") {
jQuery.fn.dataTable.ext.order.intl = function ( locales, options ) {
if ( window.Intl ) {
var collator = new Intl.Collator( locales, options );
var types = jQuery.fn.dataTable.ext.type;
delete types.order['string-pre'];
types.order['string-asc'] = collator.compare;
types.order['string-desc'] = function ( a, b ) {
return collator.compare( a, b ) * -1;
};
}
};
}
if (typeof naturalSort == "undefined") {
function naturalSort (a, b, html) {
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?%?$|^0x[0-9a-f]+$|[0-9]+)/gi,
sre = /(^[ ]*|[ ]*$)/g,
dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/,
hre = /^0x[0-9a-f]+$/i,
ore = /^0/,
htmre = /(<([^>]+)>)/ig,
// convert all to strings and trim()
x = a.toString().replace(sre, '') || '',
y = b.toString().replace(sre, '') || '';
// remove html from strings if desired
if (!html) {
x = x.replace(htmre, '');
y = y.replace(htmre, '');
}
// chunk/tokenize
var xN = x.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
yN = y.replace(re, '\0$1\0').replace(/\0$/,'').replace(/^\0/,'').split('\0'),
// numeric, hex or date detection
xD = parseInt(x.match(hre), 10) || (xN.length !== 1 && x.match(dre) && Date.parse(x)),
yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
// first try and sort Hex codes or Dates
if (yD) {
if ( xD < yD ) {
return -1;
}
else if ( xD > yD ) {
return 1;
}
}
// natural sorting through split numeric strings and default strings
for(var cLoc=0, numS=Math.max(xN.length, yN.length); cLoc < numS; cLoc++) {
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
/*supsystic*/
//var oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc], 10) || xN[cLoc] || 0;
//var oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc], 10) || yN[cLoc] || 0;
var oFxNcL = parseFloat(xN[cLoc], 10) || xN[cLoc] || undefined;
var oFyNcL = parseFloat(yN[cLoc], 10) || yN[cLoc] || undefined;
/*****/
// handle numeric vs string comparison - number < string - (Kyle Adams)
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
return (isNaN(oFxNcL)) ? 1 : -1;
}
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
else if (typeof oFxNcL !== typeof oFyNcL) {
oFxNcL += '';
oFyNcL += '';
}
if (oFxNcL < oFyNcL) {
return -1;
}
if (oFxNcL > oFyNcL) {
return 1;
}
}
return 0;
}
}
if (typeof jQuery.fn.dataTableExt.oApi.fnFakeRowspan == "undefined") {
jQuery.fn.dataTableExt.oApi.fnFakeRowspan = function (oSettings) {
if(oSettings) {
var cells;
jQuery.each(oSettings.aoData, function(index, rowData) {
vendor[appName].setCellAttributes(rowData.anCells);
});
if (oSettings.aoHeader.length) {
cells = [];
jQuery.each(oSettings.aoHeader, function(index, rowData) {
jQuery.each(rowData, function(index, cellData) {
cells.push(cellData.cell);
});
});
vendor[appName].setCellAttributes(cells);
}
if (oSettings.aoFooter.length) {
cells = [];
jQuery.each(oSettings.aoFooter, function(index, rowData) {
jQuery.each(rowData, function(index, cellData) {
cells.push(cellData.cell);
});
});
vendor[appName].setCellAttributes(cells);
}
}
return this;
};
}
if (typeof jQuery.fn.dataTableExt.oApi.fnResetFakeRowspan == "undefined") {
jQuery.fn.dataTableExt.oApi.fnResetFakeRowspan = function (oSettings) {
if(oSettings) {
var displayRows = oSettings.aiDisplay,
mergedData = jQuery(oSettings.nTable).data('merged');
if(!mergedData || mergedData.length == 0 || displayRows.length == 0) return this;
var rows = oSettings.aoData,
table = jQuery(oSettings.nTable),
autoHiding = table.attr('data-auto-hiding'),
rowNums = {},
first = table.attr('data-auto-index') == 'new' ? 1 : 0;
autoHiding = (typeof(autoHiding) != 'undefined' && autoHiding.length > 0) ? autoHiding.split(',').map(Number) : [];
jQuery.each(displayRows, function(index, rowNum) {
var cells = rows[rowNum].anCells;
rowNums[cells[first].getAttribute('data-y')] = rowNum;
for(var i = 0; i < cells.length; i++) {
if(cells[i].getAttribute('data-hide') == "true" && (autoHiding.length <= i || autoHiding[i] == 1)) {
jQuery(cells[i]).css('display', '');
}
cells[i].setAttribute('rowspan', 1);
cells[i].setAttribute('colspan', 1);
}
});
jQuery.each(mergedData, function(index, value) {
var firstRow = Number(value.row) + 1,
lastRow = firstRow + Number(value.rowspan) - 1,
colspan = Number(value.colspan),
firstCol = Number(value.col) + first,
lastCol = firstCol + colspan - 1,
rowspan = 0;
for(var r = firstRow; r <= lastRow; r++) {
if(r in rowNums) {
if(rowspan == 0) {
firstRow = r;
}
for(var c = firstCol + (firstRow == r ? 1 : 0); c <= lastCol; c++) {
var cell = rows[rowNums[r]].anCells[c];
if (typeof cell !== "undefined" && typeof cell.style !== "undefined" && typeof cell.style.display !== "undefined") {
cell.style.display = 'none';
}
if(autoHiding[c] === 0) {
colspan--;
}
}
rowspan++;
}
}
if(rowspan > 0) {
var mergedCell = rows[rowNums[firstRow]].anCells[firstCol];
if(rowspan > 1) {
mergedCell.setAttribute('rowspan', rowspan);
}
if(colspan > 1) {
mergedCell.setAttribute('colspan', colspan);
}
}
});
}
return this;
};
}
if (typeof jQuery.fn.dataTableExt.oSort !== "undefined") {
jQuery.extend( jQuery.fn.dataTableExt.oSort, {
"natural-asc": function ( a, b ) {
return naturalSort(a,b,true);
},
"natural-desc": function ( a, b ) {
return naturalSort(a,b,true) * -1;
},
"natural-nohtml-asc": function( a, b ) {
return naturalSort(a,b,false);
},
"natural-nohtml-desc": function( a, b ) {
return naturalSort(a,b,false) * -1;
},
"natural-ci-asc": function( a, b ) {
a = a.toString().toLowerCase();
b = b.toString().toLowerCase();
return naturalSort(a,b,true);
},
"natural-ci-desc": function( a, b ) {
a = a.toString().toLowerCase();
b = b.toString().toLowerCase();
return naturalSort(a,b,true) * -1;
},
"natural-nohtml-ci-asc": function( a, b ) {
a = a.toString().toLowerCase();
b = b.toString().toLowerCase();
return naturalSort(a,b,false);
},
"natural-nohtml-ci-desc": function( a, b ) {
a = a.toString().toLowerCase();
b = b.toString().toLowerCase();
return naturalSort(a,b,false) * -1;
}
} );
}
reinit = typeof reinit != 'undefined' ? reinit : {};
addInstance = typeof addInstance != 'undefined' ? addInstance : true;
var self = this,
$table = (table instanceof $ ? table : jQuery(table)),
features = $table.data('features'),
config = {},
responsiveMode = $table.data('responsive-mode'),
searchingSettings = $table.data('searching-settings'),
tableInstance = {},
defaultFeatures = {
autoWidth: false,
info: false,
ordering: false,
paging: false,
responsive: false,
searching: false,
stateSave: false,
bJQueryUI: true,
api: true,
retrieve: true,
processing: true,
initComplete: callback,
headerCallback: function(thead, data, start, end, display) {
jQuery(thead).closest('thead').find('th').each(function() {
self.setStylesToCell(this);
});
},
footerCallback: function(tfoot, data, start, end, display) {
jQuery(tfoot).closest('tfoot').find('th').each(function() {
self.setStylesToCell(this);
});
},
// order param disable the default table sorting.
// it should be here because of Woocommerce addon:
// it has no hidden header for tables without header
// and in triggers an error during initializing.
// order param should be disabled later during sorting activation
order: []
};
g_stbServerSideProcessing = $table.data('server-side-processing') && $table.data('server-side-processing') == 'on';
// Fix for searching by merged cells
$table.find('tbody td[data-colspan], tbody td[data-rowspan]').each(function(index, item) {
var cell = jQuery(item),
cellData = cell.html();
// prevent of copy cell data if it contains tags with id attribute - it must be unique on page
if (!cellData.toString().match(/<.*?id=['|"].*?['|"].*?>/g)) {
var cellOrValue = cell.data('original-value'),
cellFormula = cell.data('formula'),
cellOrder = cell.data('order'),
table = cell.parents('table:first'),
colIndex = cell.index(),
rowIndex = cell.parents('tr:first').index(),
colspan = cell.data('colspan'),
rowspan = cell.data('rowspan');
for (var i = rowIndex + 1; i <= rowIndex + rowspan; i++) {
for (var j = colIndex + 1; j <= colIndex + colspan; j++) {
var hiddenCell = table.find('tbody tr:nth-child(' + i + ') td:nth-child(' + j + ')');
if (hiddenCell.data('hide') && !$table.data('merged')) {
hiddenCell.html(cellData);
hiddenCell.data('original-value', cellOrValue);
hiddenCell.attr('data-original-value', cellOrValue);
hiddenCell.data('order', cellOrder);
hiddenCell.attr('data-order', cellOrder);
if (cellFormula) {
hiddenCell.data('formula', cellFormula);
hiddenCell.attr('data-formula', cellFormula);
}
}
}
}
}
});
// Set features
jQuery.each(features, function() {
var featureName = this.replace(/[-_]([a-z])/g, function(g) {
return g[1].toUpperCase();
});
config[featureName] = true;
});
if ($table.data('search-value') && !config['searching']) {
config['searching'] = true;
}
if (!config['searching'] && (typeof this.setTableAddSearching === 'function')) {
config['searching'] = this.setTableAddSearching($table);
}
if (toeInArray('searching', features) != -1 && searchingSettings) {
if (searchingSettings.minChars > 0 ||
searchingSettings.resultOnly ||
searchingSettings.strictMatching
) {
jQuery.fn.dataTable.ext.search.push(function(settings, data) {
var $searchInput = jQuery(settings.nTableWrapper).find('.dataTables_filter input'),
searchValue = $searchInput.val();
if (searchingSettings.resultOnly && searchValue.length === 0) {
if (searchingSettings.showTable) {
return false;
}
return false;
}
if (searchingSettings.strictMatching) {
searchValue = jQuery.fn.dataTable.util.escapeRegex(searchValue);
var regExp = new RegExp('^' + searchValue, 'i');
for (var i = 0; i < data.length; i++) {
var words = data[i].replace(/\s\s+/g, ' ').split(' ');
for (var j = 0; j < words.length; j++) {
if (words[j].match(regExp)) {
return true;
}
}
}
return false;
} else {
return data.join(' ').toLowerCase().indexOf(searchValue.toLowerCase()) !== -1
}
});
$table.on('init.dt', function(event, settings) {
if (!settings) {
return;
}
var $tableWrapper = jQuery(settings.nTableWrapper),
$tableSearchInput = $tableWrapper.find('.dataTables_filter input'),
$customInput = $tableSearchInput.clone();
$tableSearchInput.replaceWith($customInput);
$customInput.on('input change', function() {
if (!searchingSettings.showTable) {
if (searchingSettings.resultOnly && searchingSettings.minChars && (this.value.length < searchingSettings.minChars || !this.value.length)) {
$table.hide();
$table.parent().find('.dataTables_paginate').hide();
} else {
$table.show();
$table.parent().find('.dataTables_paginate').show();
}
}
if (searchingSettings.minChars && (this.value.length < searchingSettings.minChars && this.value.length !== 0)) {
event.preventDefault();
return false;
}
$table.api().draw();
});
if (searchingSettings.resultOnly && !searchingSettings.showTable) {
$table.hide();
$table.parent().find('.dataTables_paginate').hide();
}
});
}
if (searchingSettings.columnSearch) {
var inputTop = (searchingSettings.columnSearchPosition && searchingSettings.columnSearchPosition == 'top'),
tPosition = inputTop ? 'thead' : 'tfoot';
if (!$table.find('.stbColumnsSearchWrapper').length) {
var headerRow = $table.find('thead tr:first').find('th');
if (headerRow.length) {
var searchRow = '
',
func = inputTop ? 'prepend' : 'append';
for (var i = 0; i < headerRow.length; i++) {
var cellItem = jQuery(headerRow[i]),
cellClass = '',
cellStyle = '';
if (!g_stbServerSideProcessing) {
cellStyle = cellItem.is(':visible') ? '' : 'style="display: none;"';
}
if (cellItem.hasClass('invisibleCell')) {
cellClass = ' class="invisibleCell"'
}
searchRow += '
')
.addClass('collapsed-cell-holder')
.attr('data-cell-row', col.rowIndex)
.attr('data-cell-column', col.columnIndex)
.hide()
);
$subTable.append(jQuery(markup).append($cell.addClass('collapsed').show()));
}
});
return $subTable.is(':empty') ? false : $subTable;
}
}
};
$table.on('responsive-resize.dt', function(event, api, columns) {
if (typeof api == 'undefined' || typeof columns == 'undefined') {
var tbl = jQuery(this),
instance = vendor[appName].getTableInstanceById(tbl.data('id'));
if (instance) {
api = typeof api != 'undefined' ? api : instance.api();
columns = typeof columns != 'undefined' ? columns : instance.api().columns();
}
}
var autoHiding = [],
searchColumn = $table.find('.stbColumnsSearchWrapper input.search-column');
for (var i = 0, len = columns.length; i < len; i++) {
autoHiding[i] = columns[i] ? 1 : 0;
}
$table.find('th input.search-column').each(function() {
var th = jQuery(this).parents('th:first'),
i = th.index();
if (columns.length > i) {
th.css('display', columns[i] ? '' : 'none');
}
});
if (typeof columns[0] == 'boolean') {
$table.attr('data-auto-hiding', autoHiding.join());
}
if ($table.width() > $table.parent().width()) {
$table.css('width', '100%');
$table.css('max-width', '100%');
api.responsive.recalc();
return;
}
for (var i = 0, len = columns.length; i < len; i++) {
if (columns[i]) {
$table.find('tr > td.collapsed-cell-holder[data-cell-column="' + i + '"]').each(function(index, el) {
var $this = jQuery(this);
var $cell = jQuery(api.cell(
$this.data('cell-row'),
$this.data('cell-column')
).node());
if ($cell.hasClass('collapsed')) {
$cell.removeClass('collapsed');
$this.replaceWith($cell);
}
});
}
}
if ($table.data('merged')) {
// if has merged cells remove them, with autohidding they not working
$table.find('td[data-hide]').show();
$table.find('td[data-rowspan]').attr({
'data-rowspan': 1,
rowspan: 1,
'data-colspan': 1,
colspan: 1
});
}
});
} else if (responsiveMode === 2) {
// Responsive Mode: Horizontal Scroll
config.scrollX = true;
config.bAutoWidth = false;
var firstRow = $table.find('tbody tr:first-child td');
if (firstRow.length) {
var cntCols = firstRow.length;
$table.find('thead tr:first-child th').each(function(i, th) {
if (cntCols > i && jQuery(th).css('width')) {
firstRow.eq(i).css('width', jQuery(th).css('width'));
}
});
}
}
if (responsiveMode === 2 || responsiveMode === 3) {
// Responsive Mode: 2 - Horizontal Scroll, 3 - Disable Responsivity
var fixedHead = $table.data('head') && $table.data('fixed-head'),
fixedFoot = $table.data('foot') && $table.data('fixed-foot'),
fixedLeft = $table.data('fixed-left'),
fixedRight = $table.data('fixed-right');
// TODO: correct the code to set fixed header and fixed footer in the standard way
// TODO: https://datatables.net/extensions/fixedheader/#Features
//config.fixedHeader = {
// header: false,
// footer: false
//};
//if (fixedHead) {
// config.fixedHeader.header = true;
//}
//if (fixedFoot) {
// config.fixedHeader.footer = true;
//}
if (fixedHead || fixedFoot) {
config.scrollY = $table.data('fixed-height');
config.scrollCollapse = true;
}
if ($table.data('fixed-cols')) {
config.fixedColumns = {
leftColumns: fixedLeft ? parseInt(fixedLeft) : 0,
rightColumns: fixedRight ? parseInt(fixedRight) : 0
};
config.scrollX = true;
}
}
//$table.find('.invisibleCell').siblings('td').addClass('invisibleCell');
// Add translation
var langData = typeof g_stbTblLangData != 'undefined' ? JSON.parse(g_stbTblLangData) : $table.data('translation'),
translation = langData || {},
override = $table.data('override');
if (typeof translation != 'object') {
translation = {}; // for just to be sure that it is object
}
jQuery.each(override, function(key, value) {
if (value.length) {
if (key == 'previous' || key == 'next') {
if (typeof translation['paginate'] === "undefined") {
translation['paginate'] = {};
}
translation['paginate'][key] = value;
}
translation[key] = value;
// We need to support old DT format, cuz some languages use it
translation['s' + key.charAt(0).toUpperCase() + key.substr(1)] = value;
}
});
config.language = translation;
var ajaxSource = {};
if (g_stbServerSideProcessing) {
var nonce = (typeof DTGS_NONCE !== "undefined") ? DTGS_NONCE : DTGS_NONCE_FRONTEND;
var route = {
"action": "getPageRows",
"module": "tables",
"nonce": nonce
},
loadedRows = [],
loadedCells = [],
headerRowsCount = ($table.data('head') == 'on' ? $table.data('head-rows-count') : 0),
footerRowsCount = ($table.data('foot') == 'on' ? $table.data('foot-custom-rows-count') : 0);
ajaxSource = {
processing: true,
serverSide: true,
ajax: {
url: window.ajaxurl ? window.ajaxurl : ajax_obj.ajaxurl,
type: 'POST',
data: {
action: "supsystic-tables",
route: route,
id: $table.data('id'),
searchParams: searchingSettings,
searchValue: function() {
var input = jQuery('#' + $table.attr('id') + '_filter.dataTables_filter').find('input');
return (input.length ? input.val() : '');
},
header: headerRowsCount,
footer: footerRowsCount,
beforeSend: function() {
g_stbServerSideProcessingIsActive = true;
}
},
dataFilter: function(data) {
var json = jQuery.parseJSON(data),
rows = jQuery(json.rows).find('tr'),
aData = [];
loadedRows = [];
loadedCells = [];
for (var i = 0; i < rows.length; i++) {
var row = rows[i];
loadedRows.push(row.attributes);
var cells = jQuery(row).find('td'),
attrs = [],
vals = [];
for (var j = 0; j < cells.length; j++) {
var cell = cells[j];
attrs.push(cell.attributes);
vals.push(cell.innerHTML);
}
loadedCells.push(attrs);
aData.push(vals);
}
json.rows = '';
json.data = aData;
g_stbServerSideProcessingIsActive = false;
return JSON.stringify(json);
}
},
createdRow: function(row, data, dataIndex) {
if (typeof(loadedRows[dataIndex]) != 'undefined') {
jQuery(loadedRows[dataIndex]).each(function() {
jQuery(row).attr(this.name, this.value);
});
}
}
};
if (typeof(config.aoColumnDefs) == 'undefined' || jQuery.isEmptyObject(config.aoColumnDefs)) {
config.aoColumnDefs = [];
}
config.aoColumnDefs.push({
targets: '_all',
cellType: 'td',
createdCell: function(td, cellData, rowData, row, col) {
if (typeof(loadedCells[row][col]) != 'undefined') {
var rowspan = 1,
colspan = 1;
jQuery(loadedCells[row][col]).each(function() {
if (this.name == 'data-rowspan' && this.value > 1) {
rowspan = this.value;
}
if (this.name == 'data-colspan' && this.value > 1) {
colspan = this.value;
}
});
if (rowspan > 1 || colspan > 1) {
var stopRow = row + parseInt(rowspan),
stopCol = col + parseInt(colspan),
startRow = colspan > 1 ? row : row + 1,
hide;
if (stopRow >= loadedCells.length) {
stopRow = loadedCells.length;
}
if (stopCol >= loadedCells[row].length) {
stopCol = loadedCells[row].length;
}
for (i = startRow; i < stopRow; i++) {
if (i > row) {
hide = document.createAttribute('data-hide');
hide.value = 'true';
loadedCells[i][col].setNamedItem(hide);
}
for (j = col + 1; j < stopCol; j++) {
hide = document.createAttribute('data-hide');
hide.value = 'true';
loadedCells[i][j].setNamedItem(hide);
}
}
}
jQuery(loadedCells[row][col]).each(function() {
//if(this.name != 'data-formula') {
jQuery(td).attr(this.name, this.value);
//}
});
}
}
});
}
window.table = $table;
$table.trigger('beforeInitializeTable', $table);
var dateFormat = $table.data('date-format');
// if (typeof $table.dataTable.moment !== "undefined") {
$table.dataTable.moment(dateFormat);
// }
// if (typeof jQuery.fn.dataTable.ext.order.intl !== "undefined") {
jQuery.fn.dataTable.ext.order.intl();
// }
tableInstance = $table.dataTable(jQuery.extend({}, defaultFeatures, config, extraConfig, ajaxSource, reinit));
tableInstance.table_id = $table.data('id');
tableInstance.table_view_id = $table.data('view-id');
if (typeof tableInstance.fnFakeRowspan !== "undefined") {
tableInstance.fnFakeRowspan();
}
self._checkOnClickPopups($table);
window.table = $table;
if ($table.data('remove-rows')) {
jQuery(function() {
jQuery.contextMenu({
selector: '.dataTable td',
animation: {
duration: 250,
show: 'fadeIn',
hide: 'fadeOut'
},
callback: function(key, options) {
var m = "clicked: " + key;
},
items: {
"remove_row": {
name: "Remove row",
callback: function(itemKey, opt, e) {
contextMenuAction(this, 'remove_row');
}
},
"add_row_before": {
name: "Add row before",
callback: function(itemKey, opt, e) {
contextMenuAction(this, 'add_row', 'before');
}
},
"add_row_after": {
name: "Add row after",
callback: function(itemKey, opt, e) {
contextMenuAction(this, 'add_row', 'after');
}
},
"sep1": "---------",
"quit": {
name: "Quit"
}
}
});
function contextMenuAction(e, action, second) {
var coltext = e.text();
var colvindex = e.parent().children().index(e);
var colindex = jQuery('table.dataTable thead tr th:eq(' + colvindex + ')').data('column-index');
/* Global var for counter */
var giCount = 1;
switch (action) {
case "remove_row":
$table.fnDeleteRow(e.parent('tr'));
$table.fnUpdate();
break;
case "add_row":
var tr = e.parent('tr').clone(true, true);
tr.find('td').html('').addClass('menu-injected').addClass('editable').addClass('justCloned');
tr.find('td').data('original-value', '').attr('data-original-value', '');
var order = tr.find('td').data('order');
if (second == 'before') {
order = order - 1;
tr.find('td').data('order', order).attr('data-order', order);
} else {
order = order + 1;
tr.find('td').data('order', order).attr('data-order', order);
}
tr.find('td').data('cell-type', 'text').attr('data-cell-type', 'text');
tr.find('td').data('cell-format-type', '').attr('data-cell-format-type', '');
$table.append(tr);
$table.fnAddData(tr, true);
tr.find('td.justCloned').data('y', '9999').attr('data-y', '9999').removeClass('justCloned');
// $table.fnUpdate();
// $table.trigger('draw.dt');
break;
}
}
});
}
if (g_stbServerSideProcessing) {
jQuery('.dataTables_processing').css('z-index', '10');
} else {
self.setColumnSearch($table);
}
$table.on('draw.dt', function() {
var searching = $table.data('searching-settings');
if (searching && ('columnSearch' in searching) && searching.columnSearch == 'on') {
self.setColumnSearch($table);
}
if (!g_stbServerSideProcessing && $table.data('merged')) {
tableInstance.fnResetFakeRowspan();
}
self.initShortcodesInTable($table);
});
if (responsiveMode === 1) {
$table.on('responsive-resize.dt', function(event, api, columns) {
if (!g_stbServerSideProcessing && $table.data('merged')) {
tableInstance.fnResetFakeRowspan();
}
});
}
if (typeof $table.data('fixed-cols') !== 'undefined') {
tableInstance.api().fixedColumns().update();
}
if (addInstance) {
this.setTableInstance(tableInstance);
}
return typeof finalCallback == "function" ? finalCallback(tableInstance) : tableInstance;
});
/** Callback for displaying table after initializing
* @param {object} settings - DataTables settings object
* @param {object} json - JSON data retrieved from the server if the ajax option was set. Otherwise undefined.
*/
vendor[appName].showTable = (function(settings, json) {
var self = vendor[appName], // it is callback so "this" does not equal vendor[appName] object
$table = this instanceof $ ? this : settings, // for compatibility with old pro versions
$tableWrap = $table.closest('.supsystic-tables-wrap'),
tableSelector = '#supsystic-table-' + $table.data('view-id') + ' #supsystic-table-' + $table.data('id'),
afterTableLoadedScriptString = $table.attr('data-after-table-loaded-script'),
_ruleJS = self.setRuleJSInstance($table),
responsiveMode = $table.data('responsive-mode'),
fixedHeader = $table.data('fixed-head') == 'on',
fixedFooter = $table.data('fixed-foot') == 'on',
fixedColumns = $table.data('fixed-right') > 0 || $table.data('fixed-left') > 0,
viewId = $table.data('view-id');
// Apply custom CSS styles, which have been set through the table editor
$table.find('th, td').each(function() {
self.setStylesToCell(this);
});
$table.bind('column-visibility.dt draw.dt', function(e) {
jQuery(this).find('th, td').each(function() {
self.setStylesToCell(this);
});
});
// Remove sorting visual elements from the tags if there is no header on table
if (!$table.data('head')) {
$table.find('th').removeClass('sorting sorting_asc sorting_desc sorting_disabled');
}
// Calculate formulas
_ruleJS.init();
// Set formats
self.formatDataAtTable($table, true);
// Apply shortcode param "search"
if ($table.data('search-value')) {
$table.api().search($table.data('search-value')).draw();
}
// Show comments on tap
if ('ontouchstart' in window || navigator.msMaxTouchPoints) {
$table.parents('.supsystic-tables-wrap:first').find('td, th').on('click', self.applyMobileTableComments);
}
// Prepare Contact Form by Supsystic buttons
$table.parents('.supsystic-tables-wrap:first').find('th, td').each(self._contactFormBtnCellClb);
// Page change callback
$table.on('page.dt', function() {
if (g_stbServerSideProcessing) {
g_stbServerSideProcessingIsActive = true;
}
var table = jQuery(this),
tableSelector = '#supsystic-table-' + table.data('view-id') + ' #supsystic-table-' + table.data('id');
self.applyTableEventClb(self.pageEvent, 50, tableSelector);
if ($table.data('pagination-scroll') == 'on') {
jQuery('html, body').animate({
scrollTop: table.closest('.dataTables_wrapper').offset().top
}, 100);
}
if (typeof(self.setImgLightbox) == 'function') {
self.setImgLightbox($table);
}
});
// Frontend fields
if (typeof(self.createEditableFields) == 'function') { // for compatibility with old pro versions
var $editableFields = $tableWrap.find('.editable'),
$editfileFields = $tableWrap.find('.editfile'),
$selectableFields = $tableWrap.find('.selectable'),
$tableId = $table.data('id'),
useEditableFields = typeof(useEdit) != 'undefined' && typeof(useEdit[$tableId]) != 'undefined' ?
useEdit[$tableId] :
false;
if (useEditableFields || (SDT_DATA.isAdmin && SDT_DATA.isPro)) {
if (typeof(self.setFrontendFields) == 'function') {
self.setFrontendFields($table);
} else if (typeof(self.setAllFields) == 'function') {
self.setAllFields($table, $editableFields, $selectableFields);
} else {
self.createEditableFields($table, $editableFields);
self.createEditableFileFields($table, $editfileFields);
}
$table.on('init.dt', function() {
$table.on('responsive-resize.dt responsive-display.dt draw.dt', function() {
$editableFields.off('click.sup'); // for compatibility with old pro versions
$editfileFields.off('click.sup');
self.updateAfterRedraw($table);
});
});
}
}
if (typeof(self.setImgLightbox) == 'function') {
self.setImgLightbox($table);
}
// apply page.dt event by change table pagination via select
var paginationSelect = $tableWrap.find('.dataTables_length select');
if (paginationSelect.length) {
paginationSelect.on('change', function() {
$table.trigger('page.dt');
});
}
self.applyTableEventClb(self.fixHeaderOfHiddenColumns, 50, tableSelector);
$table.trigger('beforeShowTable', $table);
// Show table
$tableWrap.prev('.supsystic-table-loader').hide();
$tableWrap.css('visibility', 'visible');
self.fixSortingForMultipleHeader($table);
if (responsiveMode === 2 || fixedHeader || fixedFooter) {
// Responsive Mode: Horizontal Scroll
jQuery(window).on('load resize orientationchange', $table, function(event) {
var tBody = $tableWrap.find('.dataTables_scrollBody'),
tBodyTable = tBody.find('.supsystic-table');
if (tBody.width() > tBodyTable.width() || $tableWrap.width() > tBodyTable.width()) {
tBody.width(tBodyTable.width());
$tableWrap.find('.dataTables_scrollHead, .dataTables_scrollFoot, .dataTables_scrollBody').width(tBodyTable.width() + 1);
/*
var scrollTables = $tableWrap.find('.dataTables_scrollHead, .dataTables_scrollFoot');
scrollTables.width(tBodyTable.width() + 1);
scrollTables.find('table').width(tBodyTable.width() + 1);*/
}
if (tBody.isHorizontallyScrollable()) {
tBody.css({
'border-bottom': 'none'
});
} else {
tBody.removeStyle('border-bottom');
}
var table = self.getTableInstanceById($table.data('id'));
if (typeof table.fnAdjustColumnSizing == 'function') {
setTimeout(function() {
table.fnAdjustColumnSizing(false);
}, 350);
}
});
// need resize twice to get better frontend view
var tBody = $tableWrap.find('.dataTables_scrollBody'),
tBodyTable = tBody.find('.supsystic-table');
if (tBodyTable.is(":visible")) {
setTimeout(function() {
jQuery(window).trigger('load');
}, 200);
}
var $tHeadTable = $tableWrap.find('.dataTables_scrollHead .supsystic-table');
if ($tHeadTable.length) {
self.formatDataAtTable($tHeadTable, true);
}
var $tFootTable = $tableWrap.find('.dataTables_scrollFoot .supsystic-table');
if ($tFootTable.length) {
self.formatDataAtTable($tFootTable, true);
}
}
// Correct width of fixed header / footer
if (fixedHeader || fixedFooter) {
$table.api().fixedHeader.adjust();
var i = 1;
setTimeout(function() {
var flag = fixedHeader,
el = fixedHeader ?
$tableWrap.find('.dataTables_scrollHead table thead tr:first-child th') :
$tableWrap.find('.dataTables_scrollFoot table tfoot tr:first-child th');
el.each(function() {
var thWidth = $tableWrap.find('.dataTables_scrollBody table tbody tr:first-child td:nth-child(' + i + ')');
jQuery(this).css({
'width': thWidth.outerWidth(),
'min-width': thWidth.outerWidth(),
'box-sizing': 'border-box'
});
if (fixedFooter && flag) {
var footerEl = $tableWrap.find('.dataTables_scrollFoot table tfoot tr:first-child th:nth-child(' + i + ')');
footerEl.css({
'width': thWidth.outerWidth(),
'min-width': thWidth.outerWidth(),
'box-sizing': 'border-box'
});
}
i++;
});
}, 200);
}
// Correct width of fixed columns
if (fixedColumns) {
$table.api().fixedColumns().relayout();
//var tableCaption = jQuery('.dataTables_scrollHead caption');
//
//if(tableCaption.length) {
//self._fixTableCaption(tableCaption.height(), viewId, 10);
//}
}
/* Fix for Horizontal scroll responsive mode if table has different width for one column in header and body */
if (!fixedHeader && !fixedFooter && responsiveMode === 2 && toeInArray('auto_width', $table.data('features')) == -1) {
$tableWrap.find('.dataTables_scrollBody table thead tr:first-child th').each(function() {
var tableWidth = $table.width(),
tableWrapWidth = $tableWrap.width();
if (tableWrapWidth > tableWidth) {
$tableWrap
.find('.dataTables_scrollHeadInner, .dataTables_scrollBody, .dataTables_scrollFootInner')
.addClass('fit-content');
}
});
}
// Load user custom scripts
if (afterTableLoadedScriptString !== undefined) {
afterTableLoadedScriptString = afterTableLoadedScriptString.substring(1, afterTableLoadedScriptString.length - 1);
var afterTableLoadedScript = b64DecodeUnicode(afterTableLoadedScriptString).replace(/"/g, "'"),
executeScript = new Function(afterTableLoadedScript);
if (typeof executeScript === "function") {
setTimeout(function() {
executeScript();
}, 1000);
}
}
if (g_stbServerSideProcessing) {
$table.on('draw.dt', function(e) {
var searching = $table.data('searching-settings');
if (searching && ('columnSearch' in searching) && searching.columnSearch == 'on') {
self.setColumnSearch($table);
}
self.getTableInstanceByViewId(viewId).fnFakeRowspan();
if (responsiveMode === 0 || responsiveMode === 2) {
jQuery(window).trigger('load');
}
}).trigger('draw.dt');
}
var tblEditLink = 'g_stbTblEditLink_' + $table.data('id'),
showTblEditLink = eval("typeof " + tblEditLink) !== 'undefined' ? jQuery(window.atob(eval(tblEditLink))) : false;
if (showTblEditLink && jQuery(tableSelector).closest('.supsystic-tables-wrap').find('.tblEditLink').length === 0) {
jQuery(tableSelector).closest('.supsystic-tables-wrap').append(showTblEditLink);
}
function b64DecodeUnicode(str) {
return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) {
return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);
}).join(''));
}
});
vendor[appName].applyTableEventClb = (function(clb, timeout) {
// Callback for applying events' actions and other functions to tables with server side processing (SSP)
timeout = timeout ? timeout : 0;
var self = this,
args = Array.from(arguments);
if (g_stbServerSideProcessing && g_stbServerSideProcessingIsActive) {
setTimeout(function() {
self.applyTableEventClb.apply(self, args);
}, 50);
} else {
if (typeof clb == 'function') {
args = args.slice(2);
setTimeout(function() {
clb.apply(self, args);
}, timeout);
}
}
});
vendor[appName].pageEvent = (function(tableSelector) {
var table = jQuery(tableSelector),
tableWrapper = table.parents('.supsystic-tables-wrap:first');
this.getRuleJSInstance(table).init();
this.formatDataAtTable(table, true);
this.fixHeaderOfHiddenColumns(table);
if ('ontouchstart' in window || navigator.msMaxTouchPoints) {
tableWrapper.find('td, th').on('click', this.applyMobileTableComments);
}
tableWrapper.find('td, th').each(this._contactFormBtnCellClb);
this.initShortcodesInTable(table);
});
vendor[appName].fixHeaderOfHiddenColumns = (function($table) {
$table = $table instanceof $ ? $table : jQuery($table);
var tableWrapper = $table.parents('.supsystic-tables-wrap:first');
if (!$table.data('head')) {
tableWrapper.find('thead').each(function() {
var thead = jQuery(this);
thead.find('th').each(function(iter, item) {
var th = jQuery(this),
itemIndex = iter + 1,
columnAllTd = thead.parents('table:first').find('tbody td:nth-child(' + itemIndex + ')'),
columnInvTd = columnAllTd.filter('.invisibleCell'),
hidden = columnAllTd.length > 0 && columnAllTd.length == columnInvTd.length;
if (hidden) {
// Fix of correct displaying of tables with hidden rows / columns for tables without headers
th.addClass('invisibleCell');
}
});
});
}
});
vendor[appName].applyMobileTableComments = (function(e) {
var $elem = jQuery(this),
title = $elem.attr('title');
if (title) {
var tableViewId = $elem.parents('table.supsystic-table:first').data('view-id'),
cellId = $elem.data('cell-id'),
comment = jQuery('.stbMobileComment[data-table="' + tableViewId + '"][data-cell="' + cellId + '"]');
if (!comment.length) {
comment = jQuery('');
comment.text(title)
.data('table', tableViewId)
.attr('data-table', tableViewId)
.data('cell', cellId)
.attr('data-cell', cellId)
.appendTo('body');
}
comment.css({
top: (e.pageY - 70) + 'px',
left: (e.pageX + 20) + 'px'
}).fadeIn('slow');
setTimeout(function() {
comment.fadeOut('slow');
}, 2500);
}
});
vendor[appName]._contactFormBtnCellClb = (function(e) {
var cell = jQuery(this),
y = cell.data('y'),
pair,
valueCell;
if (cell.html().indexOf('cfsPreFill') != -1) {
var cellHtml = cell.html().replace(/href=["|']([^"]*?)["|']/g, function(a, b) {
if (b.indexOf('cfsPreFill') != -1) {
var newB = b.split('&');
if (newB.length) {
for (var i = 0; i < newB.length; i++) {
pair = newB[i].split('=');
if (pair.length && pair[1].match(/[A-Za-z]/)) {
valueCell = cell.parents('tr:first').find('[data-cell-id="' + pair[1] + y + '"]');
if (valueCell.length) {
pair[1] = jQuery.trim(valueCell.html());
}
}
newB[i] = pair.join('=');
}
newB = newB.join('&');
a = a.replace(b, newB);
}
return a;
}
});
cell.html(cellHtml);
}
});
vendor[appName].setColumnSearch = (function(table) {
if (typeof this.setTableAddFilters === 'function') this.setTableAddFilters(table);
var self = this,
searchingSettings = table.data('searching-settings'),
inputs = table.parents('.dataTables_wrapper:first').find('.stbColumnsSearchWrapper .search-column');
if (inputs.length == 0) {
return;
}
//jQuery(document).off('keyup change', ".dataTables_wrapper:first .stbColumnsSearchWrapper .search-column")
// .on('keyup change', ".dataTables_wrapper:first .stbColumnsSearchWrapper .search-column",function () {
inputs.off('keyup.dtg change.dtg').on('keyup.dtg change.dtg', function() {
var input = jQuery(this),
position = input.parents('th:first').index(),
value = this.value,
column = table.api().column(position);
if (typeof self.resetTableAddFilters === 'function') self.resetTableAddFilters(table);
if (column.search() !== value) {
column.search(value.replace(/;/g, "|"), true, false).draw();
setTimeout(function() {
column.draw();
}, 50);
}
});
});
vendor[appName].setCopyEvents = (function(obj, events) {
jQuery.each(events, function(event, handlers) {
jQuery.each(handlers, function(j, handler) {
jQuery(obj).unbind(event).bind(event, handler);
});
});
});
// Callback for executing script after table is initialized
vendor[appName].executeScript = (function(table) {
var $table = (table instanceof $ ? table : jQuery(table)),
$tableWrap = $table.closest('.supsystic-tables-wrap');
this.getRuleJSInstance($table).init();
$tableWrap.prev('.supsystic-table-loader').hide();
$tableWrap.css('visibility', 'visible');
});
vendor[appName].fixSortingForMultipleHeader = (function(table) {
if (table.data('head-rows-count') > 1 && table.data('sort-order')) {
var thead = table.find('thead tr').get().reverse();
// Fix of sorting for table with multiple header (when header has more than 1 row)
if (table.data('head')) {
jQuery.each(table.find('thead tr:last-child th'), function(index, element) {
var th = jQuery(element),
nthChild = index + 1;
if (th.data('hide')) {
jQuery(thead).each(function() {
var item = jQuery(this).find('th:nth-child(' + nthChild + ')');
if (!item.data('hide')) {
item.addClass('sorting');
item.click(function() {
th.trigger('click');
if (th.hasClass('sorting')) {
item.removeClass('sorting_asc');
item.removeClass('sorting_desc');
item.addClass('sorting');
} else if (th.hasClass('sorting_asc')) {
item.removeClass('sorting');
item.removeClass('sorting_desc');
item.addClass('sorting_asc');
} else if (th.hasClass('sorting_desc')) {
item.removeClass('sorting');
item.removeClass('sorting_asc');
item.addClass('sorting_desc');
}
});
return false; // stop .each() function
}
});
}
});
}
}
});
vendor[appName].formatDataAtTable = (function(table, correctSorting) {
correctSorting = correctSorting ? correctSorting : false;
var self = this,
numberFormat = table.data('number-format'),
generalCurrencyFormat = table.data('currency-format'),
generalPercentFormat = table.data('percent-format'),
generalDateFormat = table.data('date-format'),
generalTimeFormat = table.data('time-format');
table.find('th, td').each(function(index, el) {
var $this = jQuery(this);
if ((table.data('auto-index') != 'off' && $this.is(':first-child')) ||
(table.data('responsive-mode') == 1 && table.hasClass('collapsed') && $this.hasClass('child')) ||
$this.find('.search-column').length ||
$this.hasClass('tooltipCell') ||
$this.data('hide')
) {
// Break current .each iteration
return;
}
var languageData = numeral.languageData(),
format = $this.data('cell-format'),
formatType = $this.data('cell-format-type'),
preparedFormat,
delimiters,
value = jQuery.trim($this.html()),
noFormat = false;
// function checkIfDate(parts) {
// var newDate = new Date(parts[0], parts[1]-1, parts[2]);
// if (newDate.getTime() === newDate.getTime()) {
// $this.attr('data-cell-format-type', 'date');
// $this.data('cell-format-type', 'date');
// formatType = $this.data('cell-format-type');
// console.log(parts);
// }
// }
// var parts = value.split('.');
// if (parts.length > 0) {
// checkIfDate(parts);
// }
// var parts = value.split('-');
// if (parts.length > 0) {
// checkIfDate(parts);
// }
// var parts = value.split('/');
// if (parts.length > 0) {
// checkIfDate(parts);
// }
// Fix data params for cells which use formulas, which depended on cells with shortcodes inside
if (correctSorting && toeInArray(formatType, ['date', 'time_duration']) == -1) {
var dataTableInstance = typeof table.api == 'function' ? table : self.getTableInstanceById(table.data('id'));
if ($this.data('original-value') != value) {
$this.data('original-value', value);
$this.attr('data-original-value', value);
}
if ($this.data('data-order') != value) {
$this.data('order');
$this.attr('data-order', value);
if (dataTableInstance) {
dataTableInstance.api().cell($this).invalidate();
}
}
}
if (value) {
if ($this.data('cell-reformat')) {
switch (formatType) {
case 'date':
var newDate = moment(value, format);
if (newDate.isValid()) {
value = newDate.format(generalDateFormat);
$this.data('cell-format', generalDateFormat);
$this.attr('data-cell-format', generalDateFormat);
$this.data('original-value', value);
$this.attr('data-original-value', value);
$this.data('order', value);
$this.attr('data-order', value);
if (!g_stbServerSideProcessing) {
$this.data('cell-reformat', false);
$this.attr('data-cell-reformat', 0);
}
}
break;
case 'time_duration':
var newTime = moment(value, format),
isValid = false;
// console.log(newTime);
if (newTime.isValid()) {
value = newTime.format(generalTimeFormat);
isValid = true;
} else {
newTime = moment.duration(value);
if (newTime._milliseconds || value == 0) {
value = newTime.format(generalTimeFormat);
isValid = true;
}
}
if (isValid) {
$this.data('cell-format', generalTimeFormat);
$this.attr('data-cell-format', generalTimeFormat);
$this.data('original-value', value);
$this.attr('data-original-value', value);
$this.data('order', value);
$this.attr('data-order', value);
if (!g_stbServerSideProcessing) {
$this.data('cell-reformat', false);
$this.attr('data-cell-reformat', 0);
}
}
break;
default:
break;
}
} else if (self.isNumber(value) && !isNaN(value)) {
numberFormat = numberFormat ? numberFormat.toString() : '';
switch (formatType) {
case 'percent':
format = format ? format : generalPercentFormat;
if (format) {
format = format.toString();
var clearFormat = format.indexOf('%') > -1 ? format.replace('%', '') : format;
value = value.indexOf('%') > -1 ? $this.data('original-value') : value;
delimiters = (clearFormat.match(/[^\d]/g) || [',', '.']).reverse();
languageData.delimiters = {
decimal: delimiters[0],
thousands: delimiters[1]
};
// We need to use dafault delimiters for format string
preparedFormat = format.replace(clearFormat, clearFormat.replace(delimiters[0], '.').replace(delimiters[1], ','));
} else {
noFormat = true;
}
break;
case 'currency':
format = format ? format : generalCurrencyFormat;
if (format) {
format = format.toString();
var formatWithoutCurrency = format.match(/\d.?\d*.?\d*/)[0],
currencySymbol = format.replace(formatWithoutCurrency, '') || '$'; // We need to set currency symbol in any case for normal work of numeraljs
delimiters = (formatWithoutCurrency.match(/[^\d]/g) || [',', '.']).reverse();
languageData.delimiters = {
decimal: delimiters[0],
thousands: delimiters[1]
};
languageData.currency.symbol = currencySymbol;
// We need to use dafault delimiters for format string
preparedFormat = format
.replace(formatWithoutCurrency, formatWithoutCurrency
.replace(delimiters[0], '.')
.replace(delimiters[1], ','))
.replace(currencySymbol, '$');
} else {
noFormat = true;
}
break;
case 'date':
case 'time_duration':
noFormat = true;
break;
default:
if (numberFormat) {
format = numberFormat;
delimiters = (format.match(/[^\d]/g) || [',', '.']).reverse();
languageData.delimiters = {
decimal: delimiters[0],
thousands: delimiters[1]
};
// We need to use dafault delimiters for format string
preparedFormat = format.replace(format, format.replace(delimiters[0], '.').replace(delimiters[1], ','));
break;
} else {
noFormat = true;
}
break;
}
if (noFormat) {
noFormat = false;
} else {
numeral.language('en', languageData);
value = numeral(value).format(preparedFormat);
}
}
}
$this.html(value);
});
});
vendor[appName].isNumber = (function(value) {
if (value) {
if (value.toString().match(/^-{0,1}\d+\.{0,1}\d*$/)) {
return true;
}
}
return false;
});
vendor[appName].prepareFormulaToParse = (function(value) {
var stringsInFormula = value.match(/".+?"|'.+?'/g);
if (stringsInFormula && stringsInFormula.length) {
var clearValue = value.replace(/".+?"|'.+?'/g, '%STR%'),
index = 0;
clearValue = clearValue.toUpperCase();
value = clearValue.replace(/%STR%/g, function(match) {
var val = match;
if (index < stringsInFormula.length) {
val = stringsInFormula[index];
index++;
}
return val;
});
} else {
value = value.toUpperCase();
}
return value;
});
vendor[appName].Base64 = {
_keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
encode: function(input) {
var self = vendor[appName].Base64,
output = "",
i = 0,
chr1, chr2, chr3, enc1, enc2, enc3, enc4;
input = self._utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output = output +
self._keyStr.charAt(enc1) + self._keyStr.charAt(enc2) +
self._keyStr.charAt(enc3) + self._keyStr.charAt(enc4);
}
return output;
},
// private method for UTF-8 encoding
_utf8_encode: function(string) {
string = string.replace(/\r\n/g, "\n");
var utftext = "";
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if ((c > 127) && (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
}
};
vendor[appName].getClassesRegexp = (function() {
return {
color: /color\-([0-9a-f]{6})/,
background: /bg\-([0-9a-f]{6})/,
fontFamily: /ffamily\-([a-z_]+)/i,
fontSize: /fsize\-([0-9]+)/
}
});
vendor[appName].setStylesToCell = (function(cell) {
var $cell = cell instanceof jQuery ? cell : jQuery(cell),
viewId = $cell.parents('.supsystic-table:first').data('view-id'),
classes = this.getClassesRegexp(),
cellClassNames = $cell.get(0).className,
color = classes.color.exec(cellClassNames),
background = classes.background.exec(cellClassNames),
fontFamily = classes.fontFamily.exec(cellClassNames),
fontSize = classes.fontSize.exec(cellClassNames);
if (null !== color) {
$cell.css({
color: '#' + color[1]
});
}
if (null !== background) {
$cell.css({
backgroundColor: '#' + background[1]
});
}
if (null !== fontFamily) {
var family = fontFamily[1].replace(/_/g, ' '),
familyName = fontFamily[1].replace(/_/g, '+'),
familyString = '@import url("//fonts.googleapis.com/css?family=' + familyName + '");';
if (g_stbStandartFontsList &&
toeInArray(family, g_stbStandartFontsList) == -1 &&
g_stbAllFontsList &&
toeInArray(family, g_stbAllFontsList) != -1
) {
var style = this.getFrontendCellStylesElem(viewId);
if (style.text().indexOf(familyString) == -1) {
style.text(familyString + '\n' + style.text());
}
}
$cell.css({
fontFamily: family
});
}
if (null !== fontSize) {
var lineHeight = +fontSize[1] + 6;
$cell.css({
fontSize: fontSize[1] + 'px',
lineHeight: lineHeight + 'px'
});
}
});
vendor[appName].getAdminCellStylesElem = (function() {
var $style = jQuery('#supsystic-tables-style');
if (!$style.length) {
$style = jQuery('', {
id: 'supsystic-tables-style'
});
jQuery('head').append($style);
}
return $style;
});
vendor[appName].getFrontendCellStylesElem = (function(viewId) {
var $style = jQuery('#supsystic-table-' + viewId + '-css');
if (!$style.length) {
$style = jQuery('', {
id: 'supsystic-table-' + viewId + '-css'
});
jQuery('head').append($style);
}
return $style;
});
vendor[appName]._fixTableCaption = (function(captionHeight, viewId, counter) {
if (counter < 0) return false;
// Fix for displaying of caption for tables with fixed columns
var self = this,
tableViewHtmlId = '#supsystic-table-' + viewId,
fixedColumnsWrapper = jQuery(tableViewHtmlId + ' .DTFC_LeftWrapper, ' + tableViewHtmlId + ' .DTFC_RightWrapper');
if (fixedColumnsWrapper.length) {
fixedColumnsWrapper.find('caption').css({
display: 'none'
});
fixedColumnsWrapper.css({
top: captionHeight + 'px'
});
} else {
counter--;
setTimeout(function() {
self._fixTableCaption(captionHeight, viewId, counter);
}, 50);
}
});
vendor[appName]._getChunksArray = (function(arr, len) {
var chunks = [],
i = 0,
n = arr.length;
while (i < n) {
chunks.push(arr.slice(i, i += len));
}
return chunks;
});
vendor[appName]._checkOnClickPopups = (function($table) {
// Integration with our PopUp plugin
// Only after table was inited - we can do this, and only in that way it will work
if (typeof(_ppsBindOnElementClickPopups) !== 'undefined' && $table && $table.size()) {
var $bindedLinks = $table.find('[href*="#ppsShowPopUp_"].ppsClickBinded');
if ($bindedLinks && $bindedLinks.size()) {
$bindedLinks.removeClass('ppsClickBinded').unbind('click');
}
_ppsBindOnElementClickPopups();
}
});
vendor[appName].setCellAttributes = function(cells) {
var colspan, rowspan;
for (var i = 0; i < cells.length; i++) {
if (cells[i].getAttribute('data-hide')) {
cells[i].style.display = 'none';
}
if (colspan = cells[i].getAttribute('data-colspan')) {
if (colspan > 1) {
cells[i].setAttribute('colspan', colspan);
jQuery(cells[i]).attr('colspan', colspan);
}
}
if (rowspan = cells[i].getAttribute('data-rowspan')) {
if (rowspan > 1) {
cells[i].setAttribute('rowspan', rowspan);
}
}
}
};
}
}(window.supsystic = window.supsystic || {}, window.jQuery, window));
// For compatibility to old PRO versions
function classesRegexp() {
return window.supsystic.Tables.getClassesRegexp();
}
function getAdminCellStylesElem() {
return window.supsystic.Tables.getAdminCellStylesElem();
}
/**
* We will not use just jQUery.inArray because it is work incorrect for objects
* @return mixed - key that was found element or -1 if not
*/
function toeInArray(needle, haystack) {
if (typeof(haystack) == 'object') {
for (var k in haystack) {
if (haystack[k] == needle)
return k;
}
} else if (typeof(haystack) == 'array') {
return jQuery.inArray(needle, haystack);
}
return -1;
}
(function($) {
/**
* Detects whether element can be scrolled vertically.
* @this jQuery
* @return {boolean}
*/
jQuery.fn.isVerticallyScrollable = function() {
if (this.scrollTop()) {
// Element is already scrolled, so it is scrollable
return true;
} else {
// Test by actually scrolling
this.scrollTop(1);
if (this.scrollTop()) {
// Scroll back
this.scrollTop(0);
return true;
}
}
return false;
};
/**
* Detects whether element can be scrolled horizontally.
* @this jQuery
* @return {boolean}
*/
jQuery.fn.isHorizontallyScrollable = function() {
if (this.scrollLeft()) {
// Element is already scrolled, so it is scrollable
return true;
} else {
// Test by actually scrolling
this.scrollLeft(1);
if (this.scrollLeft()) {
// Scroll back
this.scrollLeft(0);
return true;
}
}
return false;
};
jQuery.extend(jQuery.expr.pseudos || jQuery.expr[":"], {
"vertically-scrollable": function(a, i, m) {
return jQuery(a).isVerticallyScrollable();
},
"horizontally-scrollable": function(a, i, m) {
return jQuery(a).isHorizontallyScrollable();
}
});
jQuery.fn.removeStyle = function(style) {
var search = new RegExp(style + '[^;]+;?', 'g');
return this.each(function() {
jQuery(this).attr('style', function(i, style) {
return style && style.replace(search, '');
});
});
};
if (!Array.from) {
// Fix of compatibility with IE browser to use ES6 feature
Array.from = (function() {
var toStr = Object.prototype.toString;
var isCallable = function(fn) {
return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
};
var toInteger = function(value) {
var number = Number(value);
if (isNaN(number)) {
return 0;
}
if (number === 0 || !isFinite(number)) {
return number;
}
return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
};
var maxSafeInteger = Math.pow(2, 53) - 1;
var toLength = function(value) {
var len = toInteger(value);
return Math.min(Math.max(len, 0), maxSafeInteger);
};
// The length property of the from method is 1.
return function from(arrayLike /*, mapFn, thisArg */ ) {
// 1. Let C be the this value.
var C = this;
// 2. Let items be ToObject(arrayLike).
var items = Object(arrayLike);
// 3. ReturnIfAbrupt(items).
if (arrayLike == null) {
throw new TypeError('Array.from requires an array-like object - not null or undefined');
}
// 4. If mapfn is undefined, then let mapping be false.
var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
var T;
if (typeof mapFn !== 'undefined') {
// 5. else
// 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
if (!isCallable(mapFn)) {
throw new TypeError('Array.from: when provided, the second argument must be a function');
}
// 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (arguments.length > 2) {
T = arguments[2];
}
}
// 10. Let lenValue be Get(items, "length").
// 11. Let len be ToLength(lenValue).
var len = toLength(items.length);
// 13. If IsConstructor(C) is true, then
// 13. a. Let A be the result of calling the [[Construct]] internal method
// of C with an argument list containing the single item len.
// 14. a. Else, Let A be ArrayCreate(len).
var A = isCallable(C) ? Object(new C(len)) : new Array(len);
// 16. Let k be 0.
var k = 0;
// 17. Repeat, while k < len… (also steps a - h)
var kValue;
while (k < len) {
kValue = items[k];
if (mapFn) {
A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
} else {
A[k] = kValue;
}
k += 1;
}
// 18. Let putStatus be Put(A, "length", len, true).
A.length = len;
// 20. Return A.
return A;
};
}());
}
}(jQuery));
;
// underscore no conflict
_u = typeof _ == 'function' && _.noConflict();
/**
* @license
* Lo-Dash 2.4.1 (Custom Build)
* Build: `lodash modern -o ./dist/lodash.js`
* Copyright 2012-2013 The Dojo Foundation
* Based on Underscore.js 1.5.2
* Copyright 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
* Available under MIT license
*/
;(function() {
/** Used as a safe reference for `undefined` in pre ES5 environments */
var undefined;
/** Used to pool arrays and objects used internally */
var arrayPool = [],
objectPool = [];
/** Used to generate unique IDs */
var idCounter = 0;
/** Used to prefix keys to avoid issues with `__proto__` and properties on `Object.prototype` */
var keyPrefix = +new Date + '';
/** Used as the size when optimizations are enabled for large arrays */
var largeArraySize = 75;
/** Used as the max size of the `arrayPool` and `objectPool` */
var maxPoolSize = 40;
/** Used to detect and test whitespace */
var whitespace = (
// whitespace
' \t\x0B\f\xA0\ufeff' +
// line terminators
'\n\r\u2028\u2029' +
// unicode category "Zs" space separators
'\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000'
);
/** Used to match empty string literals in compiled template source */
var reEmptyStringLeading = /\b__p \+= '';/g,
reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
/**
* Used to match ES6 template delimiters
* http://people.mozilla.org/~jorendorff/es6-draft.html#sec-literals-string-literals
*/
var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
/** Used to match regexp flags from their coerced string values */
var reFlags = /\w*$/;
/** Used to detected named functions */
var reFuncName = /^\s*function[ \n\r\t]+\w/;
/** Used to match "interpolate" template delimiters */
var reInterpolate = /<%=([\s\S]+?)%>/g;
/** Used to match leading whitespace and zeros to be removed */
var reLeadingSpacesAndZeros = RegExp('^[' + whitespace + ']*0+(?=.$)');
/** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/;
/** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/;
/** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to assign default `context` object properties */
var contextProps = [
'Array', 'Boolean', 'Date', 'Function', 'Math', 'Number', 'Object',
'RegExp', 'String', '_', 'attachEvent', 'clearTimeout', 'isFinite', 'isNaN',
'parseInt', 'setTimeout'
];
/** Used to make template sourceURLs easier to identify */
var templateCounter = 0;
/** `Object#toString` result shortcuts */
var argsClass = '[object Arguments]',
arrayClass = '[object Array]',
boolClass = '[object Boolean]',
dateClass = '[object Date]',
funcClass = '[object Function]',
numberClass = '[object Number]',
objectClass = '[object Object]',
regexpClass = '[object RegExp]',
stringClass = '[object String]';
/** Used to identify object classifications that `_.clone` supports */
var cloneableClasses = {};
cloneableClasses[funcClass] = false;
cloneableClasses[argsClass] = cloneableClasses[arrayClass] =
cloneableClasses[boolClass] = cloneableClasses[dateClass] =
cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used as an internal `_.debounce` options object */
var debounceOptions = {
'leading': false,
'maxWait': 0,
'trailing': false
};
/** Used as the property descriptor for `__bindData__` */
var descriptor = {
'configurable': false,
'enumerable': false,
'value': null,
'writable': false
};
/** Used to determine if values are of the language type Object */
var objectTypes = {
'boolean': false,
'function': true,
'object': true,
'number': false,
'string': false,
'undefined': false
};
/** Used to escape characters for inclusion in compiled string literals */
var stringEscapes = {
'\\': '\\',
"'": "'",
'\n': 'n',
'\r': 'r',
'\t': 't',
'\u2028': 'u2028',
'\u2029': 'u2029'
};
/** Used as a reference to the global object */
var root = (objectTypes[typeof window] && window) || this;
/** Detect free variable `exports` */
var freeExports = objectTypes[typeof exports] && exports && !exports.nodeType && exports;
/** Detect free variable `module` */
var freeModule = objectTypes[typeof module] && module && !module.nodeType && module;
/** Detect the popular CommonJS extension `module.exports` */
var moduleExports = freeModule && freeModule.exports === freeExports && freeExports;
/** Detect free variable `global` from Node.js or Browserified code and use it as `root` */
var freeGlobal = objectTypes[typeof global] && global;
if (freeGlobal && (freeGlobal.global === freeGlobal || freeGlobal.window === freeGlobal)) {
root = freeGlobal;
}
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.indexOf` without support for binary searches
* or `fromIndex` constraints.
*
* @private
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
*/
function baseIndexOf(array, value, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0;
while (++index < length) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* An implementation of `_.contains` for cache objects that mimics the return
* signature of `_.indexOf` by returning `0` if the value is found, else `-1`.
*
* @private
* @param {Object} cache The cache object to inspect.
* @param {*} value The value to search for.
* @returns {number} Returns `0` if `value` is found, else `-1`.
*/
function cacheIndexOf(cache, value) {
var type = typeof value;
cache = cache.cache;
if (type == 'boolean' || value == null) {
return cache[value] ? 0 : -1;
}
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value;
cache = (cache = cache[type]) && cache[key];
return type == 'object'
? (cache && baseIndexOf(cache, value) > -1 ? 0 : -1)
: (cache ? 0 : -1);
}
/**
* Adds a given value to the corresponding cache object.
*
* @private
* @param {*} value The value to add to the cache.
*/
function cachePush(value) {
var cache = this.cache,
type = typeof value;
if (type == 'boolean' || value == null) {
cache[value] = true;
} else {
if (type != 'number' && type != 'string') {
type = 'object';
}
var key = type == 'number' ? value : keyPrefix + value,
typeCache = cache[type] || (cache[type] = {});
if (type == 'object') {
(typeCache[key] || (typeCache[key] = [])).push(value);
} else {
typeCache[key] = true;
}
}
}
/**
* Used by `_.max` and `_.min` as the default callback when a given
* collection is a string value.
*
* @private
* @param {string} value The character to inspect.
* @returns {number} Returns the code unit of given character.
*/
function charAtCallback(value) {
return value.charCodeAt(0);
}
/**
* Used by `sortBy` to compare transformed `collection` elements, stable sorting
* them in ascending order.
*
* @private
* @param {Object} a The object to compare to `b`.
* @param {Object} b The object to compare to `a`.
* @returns {number} Returns the sort order indicator of `1` or `-1`.
*/
function compareAscending(a, b) {
var ac = a.criteria,
bc = b.criteria,
index = -1,
length = ac.length;
while (++index < length) {
var value = ac[index],
other = bc[index];
if (value !== other) {
if (value > other || typeof value == 'undefined') {
return 1;
}
if (value < other || typeof other == 'undefined') {
return -1;
}
}
}
// Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
// that causes it, under certain circumstances, to return the same value for
// `a` and `b`. See https://github.com/jashkenas/underscore/pull/1247
//
// This also ensures a stable sort in V8 and other engines.
// See http://code.google.com/p/v8/issues/detail?id=90
return a.index - b.index;
}
/**
* Creates a cache object to optimize linear searches of large arrays.
*
* @private
* @param {Array} [array=[]] The array to search.
* @returns {null|Object} Returns the cache object or `null` if caching should not be used.
*/
function createCache(array) {
var index = -1,
length = array.length,
first = array[0],
mid = array[(length / 2) | 0],
last = array[length - 1];
if (first && typeof first == 'object' &&
mid && typeof mid == 'object' && last && typeof last == 'object') {
return false;
}
var cache = getObject();
cache['false'] = cache['null'] = cache['true'] = cache['undefined'] = false;
var result = getObject();
result.array = array;
result.cache = cache;
result.push = cachePush;
while (++index < length) {
result.push(array[index]);
}
return result;
}
/**
* Used by `template` to escape characters for inclusion in compiled
* string literals.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeStringChar(match) {
return '\\' + stringEscapes[match];
}
/**
* Gets an array from the array pool or creates a new one if the pool is empty.
*
* @private
* @returns {Array} The array from the pool.
*/
function getArray() {
return arrayPool.pop() || [];
}
/**
* Gets an object from the object pool or creates a new one if the pool is empty.
*
* @private
* @returns {Object} The object from the pool.
*/
function getObject() {
return objectPool.pop() || {
'array': null,
'cache': null,
'criteria': null,
'false': false,
'index': 0,
'null': false,
'number': null,
'object': null,
'push': null,
'string': null,
'true': false,
'undefined': false,
'value': null
};
}
/**
* Releases the given array back to the array pool.
*
* @private
* @param {Array} [array] The array to release.
*/
function releaseArray(array) {
array.length = 0;
if (arrayPool.length < maxPoolSize) {
arrayPool.push(array);
}
}
/**
* Releases the given object back to the object pool.
*
* @private
* @param {Object} [object] The object to release.
*/
function releaseObject(object) {
var cache = object.cache;
if (cache) {
releaseObject(cache);
}
object.array = object.cache = object.criteria = object.object = object.number = object.string = object.value = null;
if (objectPool.length < maxPoolSize) {
objectPool.push(object);
}
}
/**
* Slices the `collection` from the `start` index up to, but not including,
* the `end` index.
*
* Note: This function is used instead of `Array#slice` to support node lists
* in IE < 9 and to ensure dense arrays are returned.
*
* @private
* @param {Array|Object|string} collection The collection to slice.
* @param {number} start The start index.
* @param {number} end The end index.
* @returns {Array} Returns the new array.
*/
function slice(array, start, end) {
start || (start = 0);
if (typeof end == 'undefined') {
end = array ? array.length : 0;
}
var index = -1,
length = end - start || 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = array[start + index];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Create a new `lodash` function using the given context object.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} [context=root] The context object.
* @returns {Function} Returns the `lodash` function.
*/
function runInContext(context) {
// Avoid issues with some ES3 environments that attempt to use values, named
// after built-in constructors like `Object`, for the creation of literals.
// ES5 clears this up by stating that literals must use built-in constructors.
// See http://es5.github.io/#x11.1.5.
context = context ? _.defaults(root.Object(), context, _.pick(root, contextProps)) : root;
/** Native constructor references */
var Array = context.Array,
Boolean = context.Boolean,
Date = context.Date,
Function = context.Function,
Math = context.Math,
Number = context.Number,
Object = context.Object,
RegExp = context.RegExp,
String = context.String,
TypeError = context.TypeError;
/**
* Used for `Array` method references.
*
* Normally `Array.prototype` would suffice, however, using an array literal
* avoids issues in Narwhal.
*/
var arrayRef = [];
/** Used for native method references */
var objectProto = Object.prototype;
/** Used to restore the original `_` reference in `noConflict` */
var oldDash = context._;
/** Used to resolve the internal [[Class]] of values */
var toString = objectProto.toString;
/** Used to detect if a method is native */
var reNative = RegExp('^' +
String(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
.replace(/toString| for [^\]]+/g, '.*?') + '$'
);
/** Native method shortcuts */
var ceil = Math.ceil,
clearTimeout = context.clearTimeout,
floor = Math.floor,
fnToString = Function.prototype.toString,
getPrototypeOf = isNative(getPrototypeOf = Object.getPrototypeOf) && getPrototypeOf,
hasOwnProperty = objectProto.hasOwnProperty,
push = arrayRef.push,
setTimeout = context.setTimeout,
splice = arrayRef.splice,
unshift = arrayRef.unshift;
/** Used to set meta data on functions */
var defineProperty = (function() {
// IE 8 only accepts DOM elements
try {
var o = {},
func = isNative(func = Object.defineProperty) && func,
result = func(o, o, o) && func;
} catch(e) { }
return result;
}());
/* Native method shortcuts for methods with the same name as other `lodash` methods */
var nativeCreate = isNative(nativeCreate = Object.create) && nativeCreate,
nativeIsArray = isNative(nativeIsArray = Array.isArray) && nativeIsArray,
nativeIsFinite = context.isFinite,
nativeIsNaN = context.isNaN,
nativeKeys = isNative(nativeKeys = Object.keys) && nativeKeys,
nativeMax = Math.max,
nativeMin = Math.min,
nativeParseInt = context.parseInt,
nativeRandom = Math.random;
/** Used to lookup a built-in constructor by [[Class]] */
var ctorByClass = {};
ctorByClass[arrayClass] = Array;
ctorByClass[boolClass] = Boolean;
ctorByClass[dateClass] = Date;
ctorByClass[funcClass] = Function;
ctorByClass[objectClass] = Object;
ctorByClass[numberClass] = Number;
ctorByClass[regexpClass] = RegExp;
ctorByClass[stringClass] = String;
/*--------------------------------------------------------------------------*/
/**
* Creates a `lodash` object which wraps the given value to enable intuitive
* method chaining.
*
* In addition to Lo-Dash methods, wrappers also have the following `Array` methods:
* `concat`, `join`, `pop`, `push`, `reverse`, `shift`, `slice`, `sort`, `splice`,
* and `unshift`
*
* Chaining is supported in custom builds as long as the `value` method is
* implicitly or explicitly included in the build.
*
* The chainable wrapper functions are:
* `after`, `assign`, `bind`, `bindAll`, `bindKey`, `chain`, `compact`,
* `compose`, `concat`, `countBy`, `create`, `createCallback`, `curry`,
* `debounce`, `defaults`, `defer`, `delay`, `difference`, `filter`, `flatten`,
* `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`, `forOwnRight`,
* `functions`, `groupBy`, `indexBy`, `initial`, `intersection`, `invert`,
* `invoke`, `keys`, `map`, `max`, `memoize`, `merge`, `min`, `object`, `omit`,
* `once`, `pairs`, `partial`, `partialRight`, `pick`, `pluck`, `pull`, `push`,
* `range`, `reject`, `remove`, `rest`, `reverse`, `shuffle`, `slice`, `sort`,
* `sortBy`, `splice`, `tap`, `throttle`, `times`, `toArray`, `transform`,
* `union`, `uniq`, `unshift`, `unzip`, `values`, `where`, `without`, `wrap`,
* and `zip`
*
* The non-chainable wrapper functions are:
* `clone`, `cloneDeep`, `contains`, `escape`, `every`, `find`, `findIndex`,
* `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `has`, `identity`,
* `indexOf`, `isArguments`, `isArray`, `isBoolean`, `isDate`, `isElement`,
* `isEmpty`, `isEqual`, `isFinite`, `isFunction`, `isNaN`, `isNull`, `isNumber`,
* `isObject`, `isPlainObject`, `isRegExp`, `isString`, `isUndefined`, `join`,
* `lastIndexOf`, `mixin`, `noConflict`, `parseInt`, `pop`, `random`, `reduce`,
* `reduceRight`, `result`, `shift`, `size`, `some`, `sortedIndex`, `runInContext`,
* `template`, `unescape`, `uniqueId`, and `value`
*
* The wrapper functions `first` and `last` return wrapped values when `n` is
* provided, otherwise they return unwrapped values.
*
* Explicit chaining can be enabled by using the `_.chain` method.
*
* @name _
* @constructor
* @category Chaining
* @param {*} value The value to wrap in a `lodash` instance.
* @returns {Object} Returns a `lodash` instance.
* @example
*
* var wrapped = _([1, 2, 3]);
*
* // returns an unwrapped value
* wrapped.reduce(function(sum, num) {
* return sum + num;
* });
* // => 6
*
* // returns a wrapped value
* var squares = wrapped.map(function(num) {
* return num * num;
* });
*
* _.isArray(squares);
* // => false
*
* _.isArray(squares.value());
* // => true
*/
function lodash(value) {
// don't wrap if already wrapped, even if wrapped by a different `lodash` constructor
return (value && typeof value == 'object' && !isArray(value) && hasOwnProperty.call(value, '__wrapped__'))
? value
: new lodashWrapper(value);
}
/**
* A fast path for creating `lodash` wrapper objects.
*
* @private
* @param {*} value The value to wrap in a `lodash` instance.
* @param {boolean} chainAll A flag to enable chaining for all methods
* @returns {Object} Returns a `lodash` instance.
*/
function lodashWrapper(value, chainAll) {
this.__chain__ = !!chainAll;
this.__wrapped__ = value;
}
// ensure `new lodashWrapper` is an instance of `lodash`
lodashWrapper.prototype = lodash.prototype;
/**
* An object used to flag environments features.
*
* @static
* @memberOf _
* @type Object
*/
var support = lodash.support = {};
/**
* Detect if functions can be decompiled by `Function#toString`
* (all but PS3 and older Opera mobile browsers & avoided in Windows 8 apps).
*
* @memberOf _.support
* @type boolean
*/
support.funcDecomp = !isNative(context.WinRTError) && reThis.test(runInContext);
/**
* Detect if `Function#name` is supported (all but IE).
*
* @memberOf _.support
* @type boolean
*/
support.funcNames = typeof Function.name == 'string';
/**
* By default, the template delimiters used by Lo-Dash are similar to those in
* embedded Ruby (ERB). Change the following template settings to use alternative
* delimiters.
*
* @static
* @memberOf _
* @type Object
*/
lodash.templateSettings = {
/**
* Used to detect `data` property values to be HTML-escaped.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'escape': /<%-([\s\S]+?)%>/g,
/**
* Used to detect code to be evaluated.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'evaluate': /<%([\s\S]+?)%>/g,
/**
* Used to detect `data` property values to inject.
*
* @memberOf _.templateSettings
* @type RegExp
*/
'interpolate': reInterpolate,
/**
* Used to reference the data object in the template text.
*
* @memberOf _.templateSettings
* @type string
*/
'variable': '',
/**
* Used to import variables into the compiled template.
*
* @memberOf _.templateSettings
* @type Object
*/
'imports': {
/**
* A reference to the `lodash` function.
*
* @memberOf _.templateSettings.imports
* @type Function
*/
'_': lodash
}
};
/*--------------------------------------------------------------------------*/
/**
* The base implementation of `_.bind` that creates the bound function and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new bound function.
*/
function baseBind(bindData) {
var func = bindData[0],
partialArgs = bindData[2],
thisArg = bindData[4];
function bound() {
// `Function#bind` spec
// http://es5.github.io/#x15.3.4.5
if (partialArgs) {
// avoid `arguments` object deoptimizations by using `slice` instead
// of `Array.prototype.slice.call` and not assigning `arguments` to a
// variable as a ternary expression
var args = slice(partialArgs);
push.apply(args, arguments);
}
// mimic the constructor's `return` behavior
// http://es5.github.io/#x13.2.2
if (this instanceof bound) {
// ensure `new bound` is an instance of `func`
var thisBinding = baseCreate(func.prototype),
result = func.apply(thisBinding, args || arguments);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisArg, args || arguments);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.clone` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates clones with source counterparts.
* @returns {*} Returns the cloned value.
*/
function baseClone(value, isDeep, callback, stackA, stackB) {
if (callback) {
var result = callback(value);
if (typeof result != 'undefined') {
return result;
}
}
// inspect [[Class]]
var isObj = isObject(value);
if (isObj) {
var className = toString.call(value);
if (!cloneableClasses[className]) {
return value;
}
var ctor = ctorByClass[className];
switch (className) {
case boolClass:
case dateClass:
return new ctor(+value);
case numberClass:
case stringClass:
return new ctor(value);
case regexpClass:
result = ctor(value.source, reFlags.exec(value));
result.lastIndex = value.lastIndex;
return result;
}
} else {
return value;
}
var isArr = isArray(value);
if (isDeep) {
// check for circular references and return corresponding clone
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == value) {
return stackB[length];
}
}
result = isArr ? ctor(value.length) : {};
}
else {
result = isArr ? slice(value) : assign({}, value);
}
// add array properties assigned by `RegExp#exec`
if (isArr) {
if (hasOwnProperty.call(value, 'index')) {
result.index = value.index;
}
if (hasOwnProperty.call(value, 'input')) {
result.input = value.input;
}
}
// exit for shallow clone
if (!isDeep) {
return result;
}
// add the source value to the stack of traversed objects
// and associate it with its clone
stackA.push(value);
stackB.push(result);
// recursively populate clone (susceptible to call stack limits)
(isArr ? forEach : forOwn)(value, function(objValue, key) {
result[key] = baseClone(objValue, isDeep, callback, stackA, stackB);
});
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.create` without support for assigning
* properties to the created object.
*
* @private
* @param {Object} prototype The object to inherit from.
* @returns {Object} Returns the new object.
*/
function baseCreate(prototype, properties) {
return isObject(prototype) ? nativeCreate(prototype) : {};
}
// fallback for browsers without `Object.create`
if (!nativeCreate) {
baseCreate = (function() {
function Object() {}
return function(prototype) {
if (isObject(prototype)) {
Object.prototype = prototype;
var result = new Object;
Object.prototype = null;
}
return result || context.Object();
};
}());
}
/**
* The base implementation of `_.createCallback` without support for creating
* "_.pluck" or "_.where" style callbacks.
*
* @private
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
*/
function baseCreateCallback(func, thisArg, argCount) {
if (typeof func != 'function') {
return identity;
}
// exit early for no `thisArg` or already bound by `Function#bind`
if (typeof thisArg == 'undefined' || !('prototype' in func)) {
return func;
}
var bindData = func.__bindData__;
if (typeof bindData == 'undefined') {
if (support.funcNames) {
bindData = !func.name;
}
bindData = bindData || !support.funcDecomp;
if (!bindData) {
var source = fnToString.call(func);
if (!support.funcNames) {
bindData = !reFuncName.test(source);
}
if (!bindData) {
// checks if `func` references the `this` keyword and stores the result
bindData = reThis.test(source);
setBindData(func, bindData);
}
}
}
// exit early if there are no `this` references or `func` is bound
if (bindData === false || (bindData !== true && bindData[1] & 1)) {
return func;
}
switch (argCount) {
case 1: return function(value) {
return func.call(thisArg, value);
};
case 2: return function(a, b) {
return func.call(thisArg, a, b);
};
case 3: return function(value, index, collection) {
return func.call(thisArg, value, index, collection);
};
case 4: return function(accumulator, value, index, collection) {
return func.call(thisArg, accumulator, value, index, collection);
};
}
return bind(func, thisArg);
}
/**
* The base implementation of `createWrapper` that creates the wrapper and
* sets its meta data.
*
* @private
* @param {Array} bindData The bind data array.
* @returns {Function} Returns the new function.
*/
function baseCreateWrapper(bindData) {
var func = bindData[0],
bitmask = bindData[1],
partialArgs = bindData[2],
partialRightArgs = bindData[3],
thisArg = bindData[4],
arity = bindData[5];
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
key = func;
function bound() {
var thisBinding = isBind ? thisArg : this;
if (partialArgs) {
var args = slice(partialArgs);
push.apply(args, arguments);
}
if (partialRightArgs || isCurry) {
args || (args = slice(arguments));
if (partialRightArgs) {
push.apply(args, partialRightArgs);
}
if (isCurry && args.length < arity) {
bitmask |= 16 & ~32;
return baseCreateWrapper([func, (isCurryBound ? bitmask : bitmask & ~3), args, null, thisArg, arity]);
}
}
args || (args = arguments);
if (isBindKey) {
func = thisBinding[key];
}
if (this instanceof bound) {
thisBinding = baseCreate(func.prototype);
var result = func.apply(thisBinding, args);
return isObject(result) ? result : thisBinding;
}
return func.apply(thisBinding, args);
}
setBindData(bound, bindData);
return bound;
}
/**
* The base implementation of `_.difference` that accepts a single array
* of values to exclude.
*
* @private
* @param {Array} array The array to process.
* @param {Array} [values] The array of values to exclude.
* @returns {Array} Returns a new array of filtered values.
*/
function baseDifference(array, values) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
isLarge = length >= largeArraySize && indexOf === baseIndexOf,
result = [];
if (isLarge) {
var cache = createCache(values);
if (cache) {
indexOf = cacheIndexOf;
values = cache;
} else {
isLarge = false;
}
}
while (++index < length) {
var value = array[index];
if (indexOf(values, value) < 0) {
result.push(value);
}
}
if (isLarge) {
releaseObject(values);
}
return result;
}
/**
* The base implementation of `_.flatten` without support for callback
* shorthands or `thisArg` binding.
*
* @private
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {boolean} [isStrict=false] A flag to restrict flattening to arrays and `arguments` objects.
* @param {number} [fromIndex=0] The index to start from.
* @returns {Array} Returns a new flattened array.
*/
function baseFlatten(array, isShallow, isStrict, fromIndex) {
var index = (fromIndex || 0) - 1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value && typeof value == 'object' && typeof value.length == 'number'
&& (isArray(value) || isArguments(value))) {
// recursively flatten arrays (susceptible to call stack limits)
if (!isShallow) {
value = baseFlatten(value, isShallow, isStrict);
}
var valIndex = -1,
valLength = value.length,
resIndex = result.length;
result.length += valLength;
while (++valIndex < valLength) {
result[resIndex++] = value[valIndex];
}
} else if (!isStrict) {
result.push(value);
}
}
return result;
}
/**
* The base implementation of `_.isEqual`, without support for `thisArg` binding,
* that allows partial "_.where" style comparisons.
*
* @private
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {Function} [isWhere=false] A flag to indicate performing partial comparisons.
* @param {Array} [stackA=[]] Tracks traversed `a` objects.
* @param {Array} [stackB=[]] Tracks traversed `b` objects.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
*/
function baseIsEqual(a, b, callback, isWhere, stackA, stackB) {
// used to indicate that when comparing objects, `a` has at least the properties of `b`
if (callback) {
var result = callback(a, b);
if (typeof result != 'undefined') {
return !!result;
}
}
// exit early for identical values
if (a === b) {
// treat `+0` vs. `-0` as not equal
return a !== 0 || (1 / a == 1 / b);
}
var type = typeof a,
otherType = typeof b;
// exit early for unlike primitive values
if (a === a &&
!(a && objectTypes[type]) &&
!(b && objectTypes[otherType])) {
return false;
}
// exit early for `null` and `undefined` avoiding ES3's Function#call behavior
// http://es5.github.io/#x15.3.4.4
if (a == null || b == null) {
return a === b;
}
// compare [[Class]] names
var className = toString.call(a),
otherClass = toString.call(b);
if (className == argsClass) {
className = objectClass;
}
if (otherClass == argsClass) {
otherClass = objectClass;
}
if (className != otherClass) {
return false;
}
switch (className) {
case boolClass:
case dateClass:
// coerce dates and booleans to numbers, dates to milliseconds and booleans
// to `1` or `0` treating invalid dates coerced to `NaN` as not equal
return +a == +b;
case numberClass:
// treat `NaN` vs. `NaN` as equal
return (a != +a)
? b != +b
// but treat `+0` vs. `-0` as not equal
: (a == 0 ? (1 / a == 1 / b) : a == +b);
case regexpClass:
case stringClass:
// coerce regexes to strings (http://es5.github.io/#x15.10.6.4)
// treat string primitives and their corresponding object instances as equal
return a == String(b);
}
var isArr = className == arrayClass;
if (!isArr) {
// unwrap any `lodash` wrapped values
var aWrapped = hasOwnProperty.call(a, '__wrapped__'),
bWrapped = hasOwnProperty.call(b, '__wrapped__');
if (aWrapped || bWrapped) {
return baseIsEqual(aWrapped ? a.__wrapped__ : a, bWrapped ? b.__wrapped__ : b, callback, isWhere, stackA, stackB);
}
// exit for functions and DOM nodes
if (className != objectClass) {
return false;
}
// in older versions of Opera, `arguments` objects have `Array` constructors
var ctorA = a.constructor,
ctorB = b.constructor;
// non `Object` object instances with different constructors are not equal
if (ctorA != ctorB &&
!(isFunction(ctorA) && ctorA instanceof ctorA && isFunction(ctorB) && ctorB instanceof ctorB) &&
('constructor' in a && 'constructor' in b)
) {
return false;
}
}
// assume cyclic structures are equal
// the algorithm for detecting cyclic structures is adapted from ES 5.1
// section 15.12.3, abstract operation `JO` (http://es5.github.io/#x15.12.3)
var initedStack = !stackA;
stackA || (stackA = getArray());
stackB || (stackB = getArray());
var length = stackA.length;
while (length--) {
if (stackA[length] == a) {
return stackB[length] == b;
}
}
var size = 0;
result = true;
// add `a` and `b` to the stack of traversed objects
stackA.push(a);
stackB.push(b);
// recursively compare objects and arrays (susceptible to call stack limits)
if (isArr) {
// compare lengths to determine if a deep comparison is necessary
length = a.length;
size = b.length;
result = size == length;
if (result || isWhere) {
// deep compare the contents, ignoring non-numeric properties
while (size--) {
var index = length,
value = b[size];
if (isWhere) {
while (index--) {
if ((result = baseIsEqual(a[index], value, callback, isWhere, stackA, stackB))) {
break;
}
}
} else if (!(result = baseIsEqual(a[size], value, callback, isWhere, stackA, stackB))) {
break;
}
}
}
}
else {
// deep compare objects using `forIn`, instead of `forOwn`, to avoid `Object.keys`
// which, in this case, is more costly
forIn(b, function(value, key, b) {
if (hasOwnProperty.call(b, key)) {
// count the number of properties.
size++;
// deep compare each property value.
return (result = hasOwnProperty.call(a, key) && baseIsEqual(a[key], value, callback, isWhere, stackA, stackB));
}
});
if (result && !isWhere) {
// ensure both objects have the same number of properties
forIn(a, function(value, key, a) {
if (hasOwnProperty.call(a, key)) {
// `size` will be `-1` if `a` has more properties than `b`
return (result = --size > -1);
}
});
}
}
stackA.pop();
stackB.pop();
if (initedStack) {
releaseArray(stackA);
releaseArray(stackB);
}
return result;
}
/**
* The base implementation of `_.merge` without argument juggling or support
* for `thisArg` binding.
*
* @private
* @param {Object} object The destination object.
* @param {Object} source The source object.
* @param {Function} [callback] The function to customize merging properties.
* @param {Array} [stackA=[]] Tracks traversed source objects.
* @param {Array} [stackB=[]] Associates values with source counterparts.
*/
function baseMerge(object, source, callback, stackA, stackB) {
(isArray(source) ? forEach : forOwn)(source, function(source, key) {
var found,
isArr,
result = source,
value = object[key];
if (source && ((isArr = isArray(source)) || isPlainObject(source))) {
// avoid merging previously merged cyclic sources
var stackLength = stackA.length;
while (stackLength--) {
if ((found = stackA[stackLength] == source)) {
value = stackB[stackLength];
break;
}
}
if (!found) {
var isShallow;
if (callback) {
result = callback(value, source);
if ((isShallow = typeof result != 'undefined')) {
value = result;
}
}
if (!isShallow) {
value = isArr
? (isArray(value) ? value : [])
: (isPlainObject(value) ? value : {});
}
// add `source` and associated `value` to the stack of traversed objects
stackA.push(source);
stackB.push(value);
// recursively merge objects and arrays (susceptible to call stack limits)
if (!isShallow) {
baseMerge(value, source, callback, stackA, stackB);
}
}
}
else {
if (callback) {
result = callback(value, source);
if (typeof result == 'undefined') {
result = source;
}
}
if (typeof result != 'undefined') {
value = result;
}
}
object[key] = value;
});
}
/**
* The base implementation of `_.random` without argument juggling or support
* for returning floating-point numbers.
*
* @private
* @param {number} min The minimum possible value.
* @param {number} max The maximum possible value.
* @returns {number} Returns a random number.
*/
function baseRandom(min, max) {
return min + floor(nativeRandom() * (max - min + 1));
}
/**
* The base implementation of `_.uniq` without support for callback shorthands
* or `thisArg` binding.
*
* @private
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function} [callback] The function called per iteration.
* @returns {Array} Returns a duplicate-value-free array.
*/
function baseUniq(array, isSorted, callback) {
var index = -1,
indexOf = getIndexOf(),
length = array ? array.length : 0,
result = [];
var isLarge = !isSorted && length >= largeArraySize && indexOf === baseIndexOf,
seen = (callback || isLarge) ? getArray() : result;
if (isLarge) {
var cache = createCache(seen);
indexOf = cacheIndexOf;
seen = cache;
}
while (++index < length) {
var value = array[index],
computed = callback ? callback(value, index, array) : value;
if (isSorted
? !index || seen[seen.length - 1] !== computed
: indexOf(seen, computed) < 0
) {
if (callback || isLarge) {
seen.push(computed);
}
result.push(value);
}
}
if (isLarge) {
releaseArray(seen.array);
releaseObject(seen);
} else if (callback) {
releaseArray(seen);
}
return result;
}
/**
* Creates a function that aggregates a collection, creating an object composed
* of keys generated from the results of running each element of the collection
* through a callback. The given `setter` function sets the keys and values
* of the composed object.
*
* @private
* @param {Function} setter The setter function.
* @returns {Function} Returns the new aggregator function.
*/
function createAggregator(setter) {
return function(collection, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
setter(result, value, callback(value, index, collection), collection);
}
} else {
forOwn(collection, function(value, key, collection) {
setter(result, value, callback(value, key, collection), collection);
});
}
return result;
};
}
/**
* Creates a function that, when called, either curries or invokes `func`
* with an optional `this` binding and partially applied arguments.
*
* @private
* @param {Function|string} func The function or method name to reference.
* @param {number} bitmask The bitmask of method flags to compose.
* The bitmask may be composed of the following flags:
* 1 - `_.bind`
* 2 - `_.bindKey`
* 4 - `_.curry`
* 8 - `_.curry` (bound)
* 16 - `_.partial`
* 32 - `_.partialRight`
* @param {Array} [partialArgs] An array of arguments to prepend to those
* provided to the new function.
* @param {Array} [partialRightArgs] An array of arguments to append to those
* provided to the new function.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {number} [arity] The arity of `func`.
* @returns {Function} Returns the new function.
*/
function createWrapper(func, bitmask, partialArgs, partialRightArgs, thisArg, arity) {
var isBind = bitmask & 1,
isBindKey = bitmask & 2,
isCurry = bitmask & 4,
isCurryBound = bitmask & 8,
isPartial = bitmask & 16,
isPartialRight = bitmask & 32;
if (!isBindKey && !isFunction(func)) {
throw new TypeError;
}
if (isPartial && !partialArgs.length) {
bitmask &= ~16;
isPartial = partialArgs = false;
}
if (isPartialRight && !partialRightArgs.length) {
bitmask &= ~32;
isPartialRight = partialRightArgs = false;
}
var bindData = func && func.__bindData__;
if (bindData && bindData !== true) {
// clone `bindData`
bindData = slice(bindData);
if (bindData[2]) {
bindData[2] = slice(bindData[2]);
}
if (bindData[3]) {
bindData[3] = slice(bindData[3]);
}
// set `thisBinding` is not previously bound
if (isBind && !(bindData[1] & 1)) {
bindData[4] = thisArg;
}
// set if previously bound but not currently (subsequent curried functions)
if (!isBind && bindData[1] & 1) {
bitmask |= 8;
}
// set curried arity if not yet set
if (isCurry && !(bindData[1] & 4)) {
bindData[5] = arity;
}
// append partial left arguments
if (isPartial) {
push.apply(bindData[2] || (bindData[2] = []), partialArgs);
}
// append partial right arguments
if (isPartialRight) {
unshift.apply(bindData[3] || (bindData[3] = []), partialRightArgs);
}
// merge flags
bindData[1] |= bitmask;
return createWrapper.apply(null, bindData);
}
// fast path for `_.bind`
var creater = (bitmask == 1 || bitmask === 17) ? baseBind : baseCreateWrapper;
return creater([func, bitmask, partialArgs, partialRightArgs, thisArg, arity]);
}
/**
* Used by `escape` to convert characters to HTML entities.
*
* @private
* @param {string} match The matched character to escape.
* @returns {string} Returns the escaped character.
*/
function escapeHtmlChar(match) {
return htmlEscapes[match];
}
/**
* Gets the appropriate "indexOf" function. If the `_.indexOf` method is
* customized, this method returns the custom method, otherwise it returns
* the `baseIndexOf` function.
*
* @private
* @returns {Function} Returns the "indexOf" function.
*/
function getIndexOf() {
var result = (result = lodash.indexOf) === indexOf ? baseIndexOf : result;
return result;
}
/**
* Checks if `value` is a native function.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a native function, else `false`.
*/
function isNative(value) {
return typeof value == 'function' && reNative.test(value);
}
/**
* Sets `this` binding data on a given function.
*
* @private
* @param {Function} func The function to set data on.
* @param {Array} value The data array to set.
*/
var setBindData = !defineProperty ? noop : function(func, value) {
descriptor.value = value;
defineProperty(func, '__bindData__', descriptor);
};
/**
* A fallback implementation of `isPlainObject` which checks if a given value
* is an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that
* there are no `Object.prototype` extensions.
*
* @private
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
*/
function shimIsPlainObject(value) {
var ctor,
result;
// avoid non Object objects, `arguments` objects, and DOM elements
if (!(value && toString.call(value) == objectClass) ||
(ctor = value.constructor, isFunction(ctor) && !(ctor instanceof ctor))) {
return false;
}
// In most environments an object's own properties are iterated before
// its inherited properties. If the last iterated property is an object's
// own property then there are no inherited enumerable properties.
forIn(value, function(value, key) {
result = key;
});
return typeof result == 'undefined' || hasOwnProperty.call(value, result);
}
/**
* Used by `unescape` to convert HTML entities to characters.
*
* @private
* @param {string} match The matched character to unescape.
* @returns {string} Returns the unescaped character.
*/
function unescapeHtmlChar(match) {
return htmlUnescapes[match];
}
/*--------------------------------------------------------------------------*/
/**
* Checks if `value` is an `arguments` object.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an `arguments` object, else `false`.
* @example
*
* (function() { return _.isArguments(arguments); })(1, 2, 3);
* // => true
*
* _.isArguments([1, 2, 3]);
* // => false
*/
function isArguments(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == argsClass || false;
}
/**
* Checks if `value` is an array.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an array, else `false`.
* @example
*
* (function() { return _.isArray(arguments); })();
* // => false
*
* _.isArray([1, 2, 3]);
* // => true
*/
var isArray = nativeIsArray || function(value) {
return value && typeof value == 'object' && typeof value.length == 'number' &&
toString.call(value) == arrayClass || false;
};
/**
* A fallback implementation of `Object.keys` which produces an array of the
* given object's own enumerable property names.
*
* @private
* @type Function
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
*/
var shimKeys = function(object) {
var index, iterable = object, result = [];
if (!iterable) return result;
if (!(objectTypes[typeof object])) return result;
for (index in iterable) {
if (hasOwnProperty.call(iterable, index)) {
result.push(index);
}
}
return result
};
/**
* Creates an array composed of the own enumerable property names of an object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names.
* @example
*
* _.keys({ 'one': 1, 'two': 2, 'three': 3 });
* // => ['one', 'two', 'three'] (property order is not guaranteed across environments)
*/
var keys = !nativeKeys ? shimKeys : function(object) {
if (!isObject(object)) {
return [];
}
return nativeKeys(object);
};
/**
* Used to convert characters to HTML entities:
*
* Though the `>` character is escaped for symmetry, characters like `>` and `/`
* don't require escaping in HTML and have no special meaning unless they're part
* of a tag or an unquoted attribute value.
* http://mathiasbynens.be/notes/ambiguous-ampersands (under "semi-related fun fact")
*/
var htmlEscapes = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
};
/** Used to convert HTML entities to characters */
var htmlUnescapes = invert(htmlEscapes);
/** Used to match HTML entities and HTML characters */
var reEscapedHtml = RegExp('(' + keys(htmlUnescapes).join('|') + ')', 'g'),
reUnescapedHtml = RegExp('[' + keys(htmlEscapes).join('') + ']', 'g');
/*--------------------------------------------------------------------------*/
/**
* Assigns own enumerable properties of source object(s) to the destination
* object. Subsequent sources will overwrite property assignments of previous
* sources. If a callback is provided it will be executed to produce the
* assigned values. The callback is bound to `thisArg` and invoked with two
* arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @type Function
* @alias extend
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize assigning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* _.assign({ 'name': 'fred' }, { 'employer': 'slate' });
* // => { 'name': 'fred', 'employer': 'slate' }
*
* var defaults = _.partialRight(_.assign, function(a, b) {
* return typeof a == 'undefined' ? b : a;
* });
*
* var object = { 'name': 'barney' };
* defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var assign = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
if (argsLength > 3 && typeof args[argsLength - 2] == 'function') {
var callback = baseCreateCallback(args[--argsLength - 1], args[argsLength--], 2);
} else if (argsLength > 2 && typeof args[argsLength - 1] == 'function') {
callback = args[--argsLength];
}
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
result[index] = callback ? callback(result[index], iterable[index]) : iterable[index];
}
}
}
return result
};
/**
* Creates a clone of `value`. If `isDeep` is `true` nested objects will also
* be cloned, otherwise they will be assigned by reference. If a callback
* is provided it will be executed to produce the cloned values. If the
* callback returns `undefined` cloning will be handled by the method instead.
* The callback is bound to `thisArg` and invoked with one argument; (value).
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to clone.
* @param {boolean} [isDeep=false] Specify a deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var shallow = _.clone(characters);
* shallow[0] === characters[0];
* // => true
*
* var deep = _.clone(characters, true);
* deep[0] === characters[0];
* // => false
*
* _.mixin({
* 'clone': _.partialRight(_.clone, function(value) {
* return _.isElement(value) ? value.cloneNode(false) : undefined;
* })
* });
*
* var clone = _.clone(document.body);
* clone.childNodes.length;
* // => 0
*/
function clone(value, isDeep, callback, thisArg) {
// allows working with "Collections" methods without using their `index`
// and `collection` arguments for `isDeep` and `callback`
if (typeof isDeep != 'boolean' && isDeep != null) {
thisArg = callback;
callback = isDeep;
isDeep = false;
}
return baseClone(value, isDeep, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
/**
* Creates a deep clone of `value`. If a callback is provided it will be
* executed to produce the cloned values. If the callback returns `undefined`
* cloning will be handled by the method instead. The callback is bound to
* `thisArg` and invoked with one argument; (value).
*
* Note: This method is loosely based on the structured clone algorithm. Functions
* and DOM nodes are **not** cloned. The enumerable properties of `arguments` objects and
* objects created by constructors other than `Object` are cloned to plain `Object` objects.
* See http://www.w3.org/TR/html5/infrastructure.html#internal-structured-cloning-algorithm.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to deep clone.
* @param {Function} [callback] The function to customize cloning values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the deep cloned value.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* var deep = _.cloneDeep(characters);
* deep[0] === characters[0];
* // => false
*
* var view = {
* 'label': 'docs',
* 'node': element
* };
*
* var clone = _.cloneDeep(view, function(value) {
* return _.isElement(value) ? value.cloneNode(true) : undefined;
* });
*
* clone.node == view.node;
* // => false
*/
function cloneDeep(value, callback, thisArg) {
return baseClone(value, true, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 1));
}
/**
* Creates an object that inherits from the given `prototype` object. If a
* `properties` object is provided its own enumerable properties are assigned
* to the created object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} prototype The object to inherit from.
* @param {Object} [properties] The properties to assign to the object.
* @returns {Object} Returns the new object.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* function Circle() {
* Shape.call(this);
* }
*
* Circle.prototype = _.create(Shape.prototype, { 'constructor': Circle });
*
* var circle = new Circle;
* circle instanceof Circle;
* // => true
*
* circle instanceof Shape;
* // => true
*/
function create(prototype, properties) {
var result = baseCreate(prototype);
return properties ? assign(result, properties) : result;
}
/**
* Assigns own enumerable properties of source object(s) to the destination
* object for all destination properties that resolve to `undefined`. Once a
* property is set, additional defaults of the same property will be ignored.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param- {Object} [guard] Allows working with `_.reduce` without using its
* `key` and `object` arguments as sources.
* @returns {Object} Returns the destination object.
* @example
*
* var object = { 'name': 'barney' };
* _.defaults(object, { 'name': 'fred', 'employer': 'slate' });
* // => { 'name': 'barney', 'employer': 'slate' }
*/
var defaults = function(object, source, guard) {
var index, iterable = object, result = iterable;
if (!iterable) return result;
var args = arguments,
argsIndex = 0,
argsLength = typeof guard == 'number' ? 2 : args.length;
while (++argsIndex < argsLength) {
iterable = args[argsIndex];
if (iterable && objectTypes[typeof iterable]) {
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (typeof result[index] == 'undefined') result[index] = iterable[index];
}
}
}
return result
};
/**
* This method is like `_.findIndex` except that it returns the key of the
* first element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': false },
* 'fred': { 'age': 40, 'blocked': true },
* 'pebbles': { 'age': 1, 'blocked': false }
* };
*
* _.findKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => 'barney' (property order is not guaranteed across environments)
*
* // using "_.where" callback shorthand
* _.findKey(characters, { 'age': 1 });
* // => 'pebbles'
*
* // using "_.pluck" callback shorthand
* _.findKey(characters, 'blocked');
* // => 'fred'
*/
function findKey(object, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
/**
* This method is like `_.findKey` except that it iterates over elements
* of a `collection` in the opposite order.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per
* iteration. If a property name or object is provided it will be used to
* create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example
*
* var characters = {
* 'barney': { 'age': 36, 'blocked': true },
* 'fred': { 'age': 40, 'blocked': false },
* 'pebbles': { 'age': 1, 'blocked': true }
* };
*
* _.findLastKey(characters, function(chr) {
* return chr.age < 40;
* });
* // => returns `pebbles`, assuming `_.findKey` returns `barney`
*
* // using "_.where" callback shorthand
* _.findLastKey(characters, { 'age': 40 });
* // => 'fred'
*
* // using "_.pluck" callback shorthand
* _.findLastKey(characters, 'blocked');
* // => 'pebbles'
*/
function findLastKey(object, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forOwnRight(object, function(value, key, object) {
if (callback(value, key, object)) {
result = key;
return false;
}
});
return result;
}
/**
* Iterates over own and inherited enumerable properties of an object,
* executing the callback for each property. The callback is bound to `thisArg`
* and invoked with three arguments; (value, key, object). Callbacks may exit
* iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forIn(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'x', 'y', and 'move' (property order is not guaranteed across environments)
*/
var forIn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
for (index in iterable) {
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* This method is like `_.forIn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* Shape.prototype.move = function(x, y) {
* this.x += x;
* this.y += y;
* };
*
* _.forInRight(new Shape, function(value, key) {
* console.log(key);
* });
* // => logs 'move', 'y', and 'x' assuming `_.forIn ` logs 'x', 'y', and 'move'
*/
function forInRight(object, callback, thisArg) {
var pairs = [];
forIn(object, function(value, key) {
pairs.push(key, value);
});
var length = pairs.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
if (callback(pairs[length--], pairs[length], object) === false) {
break;
}
}
return object;
}
/**
* Iterates over own enumerable properties of an object, executing the callback
* for each property. The callback is bound to `thisArg` and invoked with three
* arguments; (value, key, object). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* @static
* @memberOf _
* @type Function
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwn({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs '0', '1', and 'length' (property order is not guaranteed across environments)
*/
var forOwn = function(collection, callback, thisArg) {
var index, iterable = collection, result = iterable;
if (!iterable) return result;
if (!objectTypes[typeof iterable]) return result;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
var ownIndex = -1,
ownProps = objectTypes[typeof iterable] && keys(iterable),
length = ownProps ? ownProps.length : 0;
while (++ownIndex < length) {
index = ownProps[ownIndex];
if (callback(iterable[index], index, collection) === false) return result;
}
return result
};
/**
* This method is like `_.forOwn` except that it iterates over elements
* of a `collection` in the opposite order.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns `object`.
* @example
*
* _.forOwnRight({ '0': 'zero', '1': 'one', 'length': 2 }, function(num, key) {
* console.log(key);
* });
* // => logs 'length', '1', and '0' assuming `_.forOwn` logs '0', '1', and 'length'
*/
function forOwnRight(object, callback, thisArg) {
var props = keys(object),
length = props.length;
callback = baseCreateCallback(callback, thisArg, 3);
while (length--) {
var key = props[length];
if (callback(object[key], key, object) === false) {
break;
}
}
return object;
}
/**
* Creates a sorted array of property names of all enumerable properties,
* own and inherited, of `object` that have function values.
*
* @static
* @memberOf _
* @alias methods
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property names that have function values.
* @example
*
* _.functions(_);
* // => ['all', 'any', 'bind', 'bindAll', 'clone', 'compact', 'compose', ...]
*/
function functions(object) {
var result = [];
forIn(object, function(value, key) {
if (isFunction(value)) {
result.push(key);
}
});
return result.sort();
}
/**
* Checks if the specified property name exists as a direct property of `object`,
* instead of an inherited property.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to check.
* @returns {boolean} Returns `true` if key is a direct property, else `false`.
* @example
*
* _.has({ 'a': 1, 'b': 2, 'c': 3 }, 'b');
* // => true
*/
function has(object, key) {
return object ? hasOwnProperty.call(object, key) : false;
}
/**
* Creates an object composed of the inverted keys and values of the given object.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to invert.
* @returns {Object} Returns the created inverted object.
* @example
*
* _.invert({ 'first': 'fred', 'second': 'barney' });
* // => { 'fred': 'first', 'barney': 'second' }
*/
function invert(object) {
var index = -1,
props = keys(object),
length = props.length,
result = {};
while (++index < length) {
var key = props[index];
result[object[key]] = key;
}
return result;
}
/**
* Checks if `value` is a boolean value.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a boolean value, else `false`.
* @example
*
* _.isBoolean(null);
* // => false
*/
function isBoolean(value) {
return value === true || value === false ||
value && typeof value == 'object' && toString.call(value) == boolClass || false;
}
/**
* Checks if `value` is a date.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a date, else `false`.
* @example
*
* _.isDate(new Date);
* // => true
*/
function isDate(value) {
return value && typeof value == 'object' && toString.call(value) == dateClass || false;
}
/**
* Checks if `value` is a DOM element.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a DOM element, else `false`.
* @example
*
* _.isElement(document.body);
* // => true
*/
function isElement(value) {
return value && value.nodeType === 1 || false;
}
/**
* Checks if `value` is empty. Arrays, strings, or `arguments` objects with a
* length of `0` and objects with no own enumerable properties are considered
* "empty".
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object|string} value The value to inspect.
* @returns {boolean} Returns `true` if the `value` is empty, else `false`.
* @example
*
* _.isEmpty([1, 2, 3]);
* // => false
*
* _.isEmpty({});
* // => true
*
* _.isEmpty('');
* // => true
*/
function isEmpty(value) {
var result = true;
if (!value) {
return result;
}
var className = toString.call(value),
length = value.length;
if ((className == arrayClass || className == stringClass || className == argsClass ) ||
(className == objectClass && typeof length == 'number' && isFunction(value.splice))) {
return !length;
}
forOwn(value, function() {
return (result = false);
});
return result;
}
/**
* Performs a deep comparison between two values to determine if they are
* equivalent to each other. If a callback is provided it will be executed
* to compare values. If the callback returns `undefined` comparisons will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (a, b).
*
* @static
* @memberOf _
* @category Objects
* @param {*} a The value to compare.
* @param {*} b The other value to compare.
* @param {Function} [callback] The function to customize comparing values.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if the values are equivalent, else `false`.
* @example
*
* var object = { 'name': 'fred' };
* var copy = { 'name': 'fred' };
*
* object == copy;
* // => false
*
* _.isEqual(object, copy);
* // => true
*
* var words = ['hello', 'goodbye'];
* var otherWords = ['hi', 'goodbye'];
*
* _.isEqual(words, otherWords, function(a, b) {
* var reGreet = /^(?:hello|hi)$/i,
* aGreet = _.isString(a) && reGreet.test(a),
* bGreet = _.isString(b) && reGreet.test(b);
*
* return (aGreet || bGreet) ? (aGreet == bGreet) : undefined;
* });
* // => true
*/
function isEqual(a, b, callback, thisArg) {
return baseIsEqual(a, b, typeof callback == 'function' && baseCreateCallback(callback, thisArg, 2));
}
/**
* Checks if `value` is, or can be coerced to, a finite number.
*
* Note: This is not the same as native `isFinite` which will return true for
* booleans and empty strings. See http://es5.github.io/#x15.1.2.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is finite, else `false`.
* @example
*
* _.isFinite(-101);
* // => true
*
* _.isFinite('10');
* // => true
*
* _.isFinite(true);
* // => false
*
* _.isFinite('');
* // => false
*
* _.isFinite(Infinity);
* // => false
*/
function isFinite(value) {
return nativeIsFinite(value) && !nativeIsNaN(parseFloat(value));
}
/**
* Checks if `value` is a function.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a function, else `false`.
* @example
*
* _.isFunction(_);
* // => true
*/
function isFunction(value) {
return typeof value == 'function';
}
/**
* Checks if `value` is the language type of Object.
* (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is an object, else `false`.
* @example
*
* _.isObject({});
* // => true
*
* _.isObject([1, 2, 3]);
* // => true
*
* _.isObject(1);
* // => false
*/
function isObject(value) {
// check if the value is the ECMAScript language type of Object
// http://es5.github.io/#x8
// and avoid a V8 bug
// http://code.google.com/p/v8/issues/detail?id=2291
return !!(value && objectTypes[typeof value]);
}
/**
* Checks if `value` is `NaN`.
*
* Note: This is not the same as native `isNaN` which will return `true` for
* `undefined` and other non-numeric values. See http://es5.github.io/#x15.1.2.4.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `NaN`, else `false`.
* @example
*
* _.isNaN(NaN);
* // => true
*
* _.isNaN(new Number(NaN));
* // => true
*
* isNaN(undefined);
* // => true
*
* _.isNaN(undefined);
* // => false
*/
function isNaN(value) {
// `NaN` as a primitive is the only value that is not equal to itself
// (perform the [[Class]] check first to avoid errors with some host objects in IE)
return isNumber(value) && value != +value;
}
/**
* Checks if `value` is `null`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `null`, else `false`.
* @example
*
* _.isNull(null);
* // => true
*
* _.isNull(undefined);
* // => false
*/
function isNull(value) {
return value === null;
}
/**
* Checks if `value` is a number.
*
* Note: `NaN` is considered a number. See http://es5.github.io/#x8.5.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a number, else `false`.
* @example
*
* _.isNumber(8.4 * 5);
* // => true
*/
function isNumber(value) {
return typeof value == 'number' ||
value && typeof value == 'object' && toString.call(value) == numberClass || false;
}
/**
* Checks if `value` is an object created by the `Object` constructor.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
* @example
*
* function Shape() {
* this.x = 0;
* this.y = 0;
* }
*
* _.isPlainObject(new Shape);
* // => false
*
* _.isPlainObject([1, 2, 3]);
* // => false
*
* _.isPlainObject({ 'x': 0, 'y': 0 });
* // => true
*/
var isPlainObject = !getPrototypeOf ? shimIsPlainObject : function(value) {
if (!(value && toString.call(value) == objectClass)) {
return false;
}
var valueOf = value.valueOf,
objProto = isNative(valueOf) && (objProto = getPrototypeOf(valueOf)) && getPrototypeOf(objProto);
return objProto
? (value == objProto || getPrototypeOf(value) == objProto)
: shimIsPlainObject(value);
};
/**
* Checks if `value` is a regular expression.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a regular expression, else `false`.
* @example
*
* _.isRegExp(/fred/);
* // => true
*/
function isRegExp(value) {
return value && typeof value == 'object' && toString.call(value) == regexpClass || false;
}
/**
* Checks if `value` is a string.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is a string, else `false`.
* @example
*
* _.isString('fred');
* // => true
*/
function isString(value) {
return typeof value == 'string' ||
value && typeof value == 'object' && toString.call(value) == stringClass || false;
}
/**
* Checks if `value` is `undefined`.
*
* @static
* @memberOf _
* @category Objects
* @param {*} value The value to check.
* @returns {boolean} Returns `true` if the `value` is `undefined`, else `false`.
* @example
*
* _.isUndefined(void 0);
* // => true
*/
function isUndefined(value) {
return typeof value == 'undefined';
}
/**
* Creates an object with the same keys as `object` and values generated by
* running each own enumerable property of `object` through the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new object with values of the results of each `callback` execution.
* @example
*
* _.mapValues({ 'a': 1, 'b': 2, 'c': 3} , function(num) { return num * 3; });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*
* var characters = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // using "_.pluck" callback shorthand
* _.mapValues(characters, 'age');
* // => { 'fred': 40, 'pebbles': 1 }
*/
function mapValues(object, callback, thisArg) {
var result = {};
callback = lodash.createCallback(callback, thisArg, 3);
forOwn(object, function(value, key, object) {
result[key] = callback(value, key, object);
});
return result;
}
/**
* Recursively merges own enumerable properties of the source object(s), that
* don't resolve to `undefined` into the destination object. Subsequent sources
* will overwrite property assignments of previous sources. If a callback is
* provided it will be executed to produce the merged values of the destination
* and source properties. If the callback returns `undefined` merging will
* be handled by the method instead. The callback is bound to `thisArg` and
* invoked with two arguments; (objectValue, sourceValue).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The destination object.
* @param {...Object} [source] The source objects.
* @param {Function} [callback] The function to customize merging properties.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the destination object.
* @example
*
* var names = {
* 'characters': [
* { 'name': 'barney' },
* { 'name': 'fred' }
* ]
* };
*
* var ages = {
* 'characters': [
* { 'age': 36 },
* { 'age': 40 }
* ]
* };
*
* _.merge(names, ages);
* // => { 'characters': [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }] }
*
* var food = {
* 'fruits': ['apple'],
* 'vegetables': ['beet']
* };
*
* var otherFood = {
* 'fruits': ['banana'],
* 'vegetables': ['carrot']
* };
*
* _.merge(food, otherFood, function(a, b) {
* return _.isArray(a) ? a.concat(b) : undefined;
* });
* // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot] }
*/
function merge(object) {
var args = arguments,
length = 2;
if (!isObject(object)) {
return object;
}
// allows working with `_.reduce` and `_.reduceRight` without using
// their `index` and `collection` arguments
if (typeof args[2] != 'number') {
length = args.length;
}
if (length > 3 && typeof args[length - 2] == 'function') {
var callback = baseCreateCallback(args[--length - 1], args[length--], 2);
} else if (length > 2 && typeof args[length - 1] == 'function') {
callback = args[--length];
}
var sources = slice(arguments, 1, length),
index = -1,
stackA = getArray(),
stackB = getArray();
while (++index < length) {
baseMerge(object, sources[index], callback, stackA, stackB);
}
releaseArray(stackA);
releaseArray(stackB);
return object;
}
/**
* Creates a shallow clone of `object` excluding the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` omitting the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The properties to omit or the
* function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object without the omitted properties.
* @example
*
* _.omit({ 'name': 'fred', 'age': 40 }, 'age');
* // => { 'name': 'fred' }
*
* _.omit({ 'name': 'fred', 'age': 40 }, function(value) {
* return typeof value == 'number';
* });
* // => { 'name': 'fred' }
*/
function omit(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var props = [];
forIn(object, function(value, key) {
props.push(key);
});
props = baseDifference(props, baseFlatten(arguments, true, false, 1));
var index = -1,
length = props.length;
while (++index < length) {
var key = props[index];
result[key] = object[key];
}
} else {
callback = lodash.createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (!callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
/**
* Creates a two dimensional array of an object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns new array of key-value pairs.
* @example
*
* _.pairs({ 'barney': 36, 'fred': 40 });
* // => [['barney', 36], ['fred', 40]] (property order is not guaranteed across environments)
*/
function pairs(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
var key = props[index];
result[index] = [key, object[key]];
}
return result;
}
/**
* Creates a shallow clone of `object` composed of the specified properties.
* Property names may be specified as individual arguments or as arrays of
* property names. If a callback is provided it will be executed for each
* property of `object` picking the properties the callback returns truey
* for. The callback is bound to `thisArg` and invoked with three arguments;
* (value, key, object).
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The source object.
* @param {Function|...string|string[]} [callback] The function called per
* iteration or property names to pick, specified as individual property
* names or arrays of property names.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns an object composed of the picked properties.
* @example
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, 'name');
* // => { 'name': 'fred' }
*
* _.pick({ 'name': 'fred', '_userid': 'fred1' }, function(value, key) {
* return key.charAt(0) != '_';
* });
* // => { 'name': 'fred' }
*/
function pick(object, callback, thisArg) {
var result = {};
if (typeof callback != 'function') {
var index = -1,
props = baseFlatten(arguments, true, false, 1),
length = isObject(object) ? props.length : 0;
while (++index < length) {
var key = props[index];
if (key in object) {
result[key] = object[key];
}
}
} else {
callback = lodash.createCallback(callback, thisArg, 3);
forIn(object, function(value, key, object) {
if (callback(value, key, object)) {
result[key] = value;
}
});
}
return result;
}
/**
* An alternative to `_.reduce` this method transforms `object` to a new
* `accumulator` object which is the result of running each of its own
* enumerable properties through a callback, with each callback execution
* potentially mutating the `accumulator` object. The callback is bound to
* `thisArg` and invoked with four arguments; (accumulator, value, key, object).
* Callbacks may exit iteration early by explicitly returning `false`.
*
* @static
* @memberOf _
* @category Objects
* @param {Array|Object} object The object to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] The custom accumulator value.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var squares = _.transform([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], function(result, num) {
* num *= num;
* if (num % 2) {
* return result.push(num) < 3;
* }
* });
* // => [1, 9, 25]
*
* var mapped = _.transform({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* });
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function transform(object, callback, accumulator, thisArg) {
var isArr = isArray(object);
if (accumulator == null) {
if (isArr) {
accumulator = [];
} else {
var ctor = object && object.constructor,
proto = ctor && ctor.prototype;
accumulator = baseCreate(proto);
}
}
if (callback) {
callback = lodash.createCallback(callback, thisArg, 4);
(isArr ? forEach : forOwn)(object, function(value, index, object) {
return callback(accumulator, value, index, object);
});
}
return accumulator;
}
/**
* Creates an array composed of the own enumerable property values of `object`.
*
* @static
* @memberOf _
* @category Objects
* @param {Object} object The object to inspect.
* @returns {Array} Returns an array of property values.
* @example
*
* _.values({ 'one': 1, 'two': 2, 'three': 3 });
* // => [1, 2, 3] (property order is not guaranteed across environments)
*/
function values(object) {
var index = -1,
props = keys(object),
length = props.length,
result = Array(length);
while (++index < length) {
result[index] = object[props[index]];
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Creates an array of elements from the specified indexes, or keys, of the
* `collection`. Indexes may be specified as individual arguments or as arrays
* of indexes.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {...(number|number[]|string|string[])} [index] The indexes of `collection`
* to retrieve, specified as individual indexes or arrays of indexes.
* @returns {Array} Returns a new array of elements corresponding to the
* provided indexes.
* @example
*
* _.at(['a', 'b', 'c', 'd', 'e'], [0, 2, 4]);
* // => ['a', 'c', 'e']
*
* _.at(['fred', 'barney', 'pebbles'], 0, 2);
* // => ['fred', 'pebbles']
*/
function at(collection) {
var args = arguments,
index = -1,
props = baseFlatten(args, true, false, 1),
length = (args[2] && args[2][args[1]] === collection) ? 1 : props.length,
result = Array(length);
while(++index < length) {
result[index] = collection[props[index]];
}
return result;
}
/**
* Checks if a given value is present in a collection using strict equality
* for comparisons, i.e. `===`. If `fromIndex` is negative, it is used as the
* offset from the end of the collection.
*
* @static
* @memberOf _
* @alias include
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {*} target The value to check for.
* @param {number} [fromIndex=0] The index to search from.
* @returns {boolean} Returns `true` if the `target` element is found, else `false`.
* @example
*
* _.contains([1, 2, 3], 1);
* // => true
*
* _.contains([1, 2, 3], 1, 2);
* // => false
*
* _.contains({ 'name': 'fred', 'age': 40 }, 'fred');
* // => true
*
* _.contains('pebbles', 'eb');
* // => true
*/
function contains(collection, target, fromIndex) {
var index = -1,
indexOf = getIndexOf(),
length = collection ? collection.length : 0,
result = false;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex) || 0;
if (isArray(collection)) {
result = indexOf(collection, target, fromIndex) > -1;
} else if (typeof length == 'number') {
result = (isString(collection) ? collection.indexOf(target, fromIndex) : indexOf(collection, target, fromIndex)) > -1;
} else {
forOwn(collection, function(value) {
if (++index >= fromIndex) {
return !(result = value === target);
}
});
}
return result;
}
/**
* Creates an object composed of keys generated from the results of running
* each element of `collection` through the callback. The corresponding value
* of each key is the number of times the key was returned by the callback.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': 1, '6': 2 }
*
* _.countBy([4.3, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': 1, '6': 2 }
*
* _.countBy(['one', 'two', 'three'], 'length');
* // => { '3': 2, '5': 1 }
*/
var countBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key]++ : result[key] = 1);
});
/**
* Checks if the given callback returns truey value for **all** elements of
* a collection. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias all
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if all elements passed the callback check,
* else `false`.
* @example
*
* _.every([true, 1, null, 'yes']);
* // => false
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.every(characters, 'age');
* // => true
*
* // using "_.where" callback shorthand
* _.every(characters, { 'age': 36 });
* // => false
*/
function every(collection, callback, thisArg) {
var result = true;
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if (!(result = !!callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return (result = !!callback(value, index, collection));
});
}
return result;
}
/**
* Iterates over elements of a collection, returning an array of all elements
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias select
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that passed the callback check.
* @example
*
* var evens = _.filter([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [2, 4, 6]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.filter(characters, 'blocked');
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*
* // using "_.where" callback shorthand
* _.filter(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*/
function filter(collection, callback, thisArg) {
var result = [];
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
result.push(value);
}
}
} else {
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result.push(value);
}
});
}
return result;
}
/**
* Iterates over elements of a collection, returning the first element that
* the callback returns truey for. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias detect, findWhere
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.find(characters, function(chr) {
* return chr.age < 40;
* });
* // => { 'name': 'barney', 'age': 36, 'blocked': false }
*
* // using "_.where" callback shorthand
* _.find(characters, { 'age': 1 });
* // => { 'name': 'pebbles', 'age': 1, 'blocked': false }
*
* // using "_.pluck" callback shorthand
* _.find(characters, 'blocked');
* // => { 'name': 'fred', 'age': 40, 'blocked': true }
*/
function find(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
var value = collection[index];
if (callback(value, index, collection)) {
return value;
}
}
} else {
var result;
forOwn(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
}
/**
* This method is like `_.find` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the found element, else `undefined`.
* @example
*
* _.findLast([1, 2, 3, 4], function(num) {
* return num % 2 == 1;
* });
* // => 3
*/
function findLast(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
forEachRight(collection, function(value, index, collection) {
if (callback(value, index, collection)) {
result = value;
return false;
}
});
return result;
}
/**
* Iterates over elements of a collection, executing the callback for each
* element. The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection). Callbacks may exit iteration early by
* explicitly returning `false`.
*
* Note: As with other "Collections" methods, objects with a `length` property
* are iterated like arrays. To avoid this behavior `_.forIn` or `_.forOwn`
* may be used for object iteration.
*
* @static
* @memberOf _
* @alias each
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEach(function(num) { console.log(num); }).join(',');
* // => logs each number and returns '1,2,3'
*
* _.forEach({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { console.log(num); });
* // => logs each number and returns the object (property order is not guaranteed across environments)
*/
function forEach(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
if (typeof length == 'number') {
while (++index < length) {
if (callback(collection[index], index, collection) === false) {
break;
}
}
} else {
forOwn(collection, callback);
}
return collection;
}
/**
* This method is like `_.forEach` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias eachRight
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array|Object|string} Returns `collection`.
* @example
*
* _([1, 2, 3]).forEachRight(function(num) { console.log(num); }).join(',');
* // => logs each number from right to left and returns '3,2,1'
*/
function forEachRight(collection, callback, thisArg) {
var length = collection ? collection.length : 0;
callback = callback && typeof thisArg == 'undefined' ? callback : baseCreateCallback(callback, thisArg, 3);
if (typeof length == 'number') {
while (length--) {
if (callback(collection[length], length, collection) === false) {
break;
}
}
} else {
var props = keys(collection);
length = props.length;
forOwn(collection, function(value, key, collection) {
key = props ? props[--length] : --length;
return callback(collection[key], key, collection);
});
}
return collection;
}
/**
* Creates an object composed of keys generated from the results of running
* each element of a collection through the callback. The corresponding value
* of each key is an array of the elements responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return Math.floor(num); });
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* _.groupBy([4.2, 6.1, 6.4], function(num) { return this.floor(num); }, Math);
* // => { '4': [4.2], '6': [6.1, 6.4] }
*
* // using "_.pluck" callback shorthand
* _.groupBy(['one', 'two', 'three'], 'length');
* // => { '3': ['one', 'two'], '5': ['three'] }
*/
var groupBy = createAggregator(function(result, value, key) {
(hasOwnProperty.call(result, key) ? result[key] : result[key] = []).push(value);
});
/**
* Creates an object composed of keys generated from the results of running
* each element of the collection through the given callback. The corresponding
* value of each key is the last element responsible for generating the key.
* The callback is bound to `thisArg` and invoked with three arguments;
* (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Object} Returns the composed aggregate object.
* @example
*
* var keys = [
* { 'dir': 'left', 'code': 97 },
* { 'dir': 'right', 'code': 100 }
* ];
*
* _.indexBy(keys, 'dir');
* // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(keys, function(key) { return String.fromCharCode(key.code); });
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*
* _.indexBy(characters, function(key) { this.fromCharCode(key.code); }, String);
* // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
*/
var indexBy = createAggregator(function(result, value, key) {
result[key] = value;
});
/**
* Invokes the method named by `methodName` on each element in the `collection`
* returning an array of the results of each invoked method. Additional arguments
* will be provided to each invoked method. If `methodName` is a function it
* will be invoked for, and `this` bound to, each element in the `collection`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|string} methodName The name of the method to invoke or
* the function invoked per iteration.
* @param {...*} [arg] Arguments to invoke the method with.
* @returns {Array} Returns a new array of the results of each invoked method.
* @example
*
* _.invoke([[5, 1, 7], [3, 2, 1]], 'sort');
* // => [[1, 5, 7], [1, 2, 3]]
*
* _.invoke([123, 456], String.prototype.split, '');
* // => [['1', '2', '3'], ['4', '5', '6']]
*/
function invoke(collection, methodName) {
var args = slice(arguments, 2),
index = -1,
isFunc = typeof methodName == 'function',
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
result[++index] = (isFunc ? methodName : value[methodName]).apply(value, args);
});
return result;
}
/**
* Creates an array of values by running each element in the collection
* through the callback. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias collect
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of the results of each `callback` execution.
* @example
*
* _.map([1, 2, 3], function(num) { return num * 3; });
* // => [3, 6, 9]
*
* _.map({ 'one': 1, 'two': 2, 'three': 3 }, function(num) { return num * 3; });
* // => [3, 6, 9] (property order is not guaranteed across environments)
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(characters, 'name');
* // => ['barney', 'fred']
*/
function map(collection, callback, thisArg) {
var index = -1,
length = collection ? collection.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
if (typeof length == 'number') {
var result = Array(length);
while (++index < length) {
result[index] = callback(collection[index], index, collection);
}
} else {
result = [];
forOwn(collection, function(value, key, collection) {
result[++index] = callback(value, key, collection);
});
}
return result;
}
/**
* Retrieves the maximum value of a collection. If the collection is empty or
* falsey `-Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the maximum value.
* @example
*
* _.max([4, 2, 8, 6]);
* // => 8
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.max(characters, function(chr) { return chr.age; });
* // => { 'name': 'fred', 'age': 40 };
*
* // using "_.pluck" callback shorthand
* _.max(characters, 'age');
* // => { 'name': 'fred', 'age': 40 };
*/
function max(collection, callback, thisArg) {
var computed = -Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value > result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current > computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the minimum value of a collection. If the collection is empty or
* falsey `Infinity` is returned. If a callback is provided it will be executed
* for each value in the collection to generate the criterion by which the value
* is ranked. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the minimum value.
* @example
*
* _.min([4, 2, 8, 6]);
* // => 2
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.min(characters, function(chr) { return chr.age; });
* // => { 'name': 'barney', 'age': 36 };
*
* // using "_.pluck" callback shorthand
* _.min(characters, 'age');
* // => { 'name': 'barney', 'age': 36 };
*/
function min(collection, callback, thisArg) {
var computed = Infinity,
result = computed;
// allows working with functions like `_.map` without using
// their `index` argument as a callback
if (typeof callback != 'function' && thisArg && thisArg[callback] === collection) {
callback = null;
}
if (callback == null && isArray(collection)) {
var index = -1,
length = collection.length;
while (++index < length) {
var value = collection[index];
if (value < result) {
result = value;
}
}
} else {
callback = (callback == null && isString(collection))
? charAtCallback
: lodash.createCallback(callback, thisArg, 3);
forEach(collection, function(value, index, collection) {
var current = callback(value, index, collection);
if (current < computed) {
computed = current;
result = value;
}
});
}
return result;
}
/**
* Retrieves the value of a specified property from all elements in the collection.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {string} property The name of the property to pluck.
* @returns {Array} Returns a new array of property values.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* _.pluck(characters, 'name');
* // => ['barney', 'fred']
*/
var pluck = map;
/**
* Reduces a collection to a value which is the accumulated result of running
* each element in the collection through the callback, where each successive
* callback execution consumes the return value of the previous execution. If
* `accumulator` is not provided the first element of the collection will be
* used as the initial `accumulator` value. The callback is bound to `thisArg`
* and invoked with four arguments; (accumulator, value, index|key, collection).
*
* @static
* @memberOf _
* @alias foldl, inject
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var sum = _.reduce([1, 2, 3], function(sum, num) {
* return sum + num;
* });
* // => 6
*
* var mapped = _.reduce({ 'a': 1, 'b': 2, 'c': 3 }, function(result, num, key) {
* result[key] = num * 3;
* return result;
* }, {});
* // => { 'a': 3, 'b': 6, 'c': 9 }
*/
function reduce(collection, callback, accumulator, thisArg) {
if (!collection) return accumulator;
var noaccum = arguments.length < 3;
callback = lodash.createCallback(callback, thisArg, 4);
var index = -1,
length = collection.length;
if (typeof length == 'number') {
if (noaccum) {
accumulator = collection[++index];
}
while (++index < length) {
accumulator = callback(accumulator, collection[index], index, collection);
}
} else {
forOwn(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection)
});
}
return accumulator;
}
/**
* This method is like `_.reduce` except that it iterates over elements
* of a `collection` from right to left.
*
* @static
* @memberOf _
* @alias foldr
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function} [callback=identity] The function called per iteration.
* @param {*} [accumulator] Initial value of the accumulator.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the accumulated value.
* @example
*
* var list = [[0, 1], [2, 3], [4, 5]];
* var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
* // => [4, 5, 2, 3, 0, 1]
*/
function reduceRight(collection, callback, accumulator, thisArg) {
var noaccum = arguments.length < 3;
callback = lodash.createCallback(callback, thisArg, 4);
forEachRight(collection, function(value, index, collection) {
accumulator = noaccum
? (noaccum = false, value)
: callback(accumulator, value, index, collection);
});
return accumulator;
}
/**
* The opposite of `_.filter` this method returns the elements of a
* collection that the callback does **not** return truey for.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of elements that failed the callback check.
* @example
*
* var odds = _.reject([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
* // => [1, 3, 5]
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.reject(characters, 'blocked');
* // => [{ 'name': 'barney', 'age': 36, 'blocked': false }]
*
* // using "_.where" callback shorthand
* _.reject(characters, { 'age': 36 });
* // => [{ 'name': 'fred', 'age': 40, 'blocked': true }]
*/
function reject(collection, callback, thisArg) {
callback = lodash.createCallback(callback, thisArg, 3);
return filter(collection, function(value, index, collection) {
return !callback(value, index, collection);
});
}
/**
* Retrieves a random element or `n` random elements from a collection.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to sample.
* @param {number} [n] The number of elements to sample.
* @param- {Object} [guard] Allows working with functions like `_.map`
* without using their `index` arguments as `n`.
* @returns {Array} Returns the random sample(s) of `collection`.
* @example
*
* _.sample([1, 2, 3, 4]);
* // => 2
*
* _.sample([1, 2, 3, 4], 2);
* // => [3, 1]
*/
function sample(collection, n, guard) {
if (collection && typeof collection.length != 'number') {
collection = values(collection);
}
if (n == null || guard) {
return collection ? collection[baseRandom(0, collection.length - 1)] : undefined;
}
var result = shuffle(collection);
result.length = nativeMin(nativeMax(0, n), result.length);
return result;
}
/**
* Creates an array of shuffled values, using a version of the Fisher-Yates
* shuffle. See http://en.wikipedia.org/wiki/Fisher-Yates_shuffle.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to shuffle.
* @returns {Array} Returns a new shuffled collection.
* @example
*
* _.shuffle([1, 2, 3, 4, 5, 6]);
* // => [4, 1, 6, 3, 5, 2]
*/
function shuffle(collection) {
var index = -1,
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
forEach(collection, function(value) {
var rand = baseRandom(0, ++index);
result[index] = result[rand];
result[rand] = value;
});
return result;
}
/**
* Gets the size of the `collection` by returning `collection.length` for arrays
* and array-like objects or the number of own enumerable properties for objects.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to inspect.
* @returns {number} Returns `collection.length` or number of own enumerable properties.
* @example
*
* _.size([1, 2]);
* // => 2
*
* _.size({ 'one': 1, 'two': 2, 'three': 3 });
* // => 3
*
* _.size('pebbles');
* // => 7
*/
function size(collection) {
var length = collection ? collection.length : 0;
return typeof length == 'number' ? length : keys(collection).length;
}
/**
* Checks if the callback returns a truey value for **any** element of a
* collection. The function returns as soon as it finds a passing value and
* does not iterate over the entire collection. The callback is bound to
* `thisArg` and invoked with three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias any
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {boolean} Returns `true` if any element passed the callback check,
* else `false`.
* @example
*
* _.some([null, 0, 'yes', false], Boolean);
* // => true
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true }
* ];
*
* // using "_.pluck" callback shorthand
* _.some(characters, 'blocked');
* // => true
*
* // using "_.where" callback shorthand
* _.some(characters, { 'age': 1 });
* // => false
*/
function some(collection, callback, thisArg) {
var result;
callback = lodash.createCallback(callback, thisArg, 3);
var index = -1,
length = collection ? collection.length : 0;
if (typeof length == 'number') {
while (++index < length) {
if ((result = callback(collection[index], index, collection))) {
break;
}
}
} else {
forOwn(collection, function(value, index, collection) {
return !(result = callback(value, index, collection));
});
}
return !!result;
}
/**
* Creates an array of elements, sorted in ascending order by the results of
* running each element in a collection through the callback. This method
* performs a stable sort, that is, it will preserve the original sort order
* of equal elements. The callback is bound to `thisArg` and invoked with
* three arguments; (value, index|key, collection).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an array of property names is provided for `callback` the collection
* will be sorted by each property value.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Array|Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of sorted elements.
* @example
*
* _.sortBy([1, 2, 3], function(num) { return Math.sin(num); });
* // => [3, 1, 2]
*
* _.sortBy([1, 2, 3], function(num) { return this.sin(num); }, Math);
* // => [3, 1, 2]
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 26 },
* { 'name': 'fred', 'age': 30 }
* ];
*
* // using "_.pluck" callback shorthand
* _.map(_.sortBy(characters, 'age'), _.values);
* // => [['barney', 26], ['fred', 30], ['barney', 36], ['fred', 40]]
*
* // sorting by multiple properties
* _.map(_.sortBy(characters, ['name', 'age']), _.values);
* // = > [['barney', 26], ['barney', 36], ['fred', 30], ['fred', 40]]
*/
function sortBy(collection, callback, thisArg) {
var index = -1,
isArr = isArray(callback),
length = collection ? collection.length : 0,
result = Array(typeof length == 'number' ? length : 0);
if (!isArr) {
callback = lodash.createCallback(callback, thisArg, 3);
}
forEach(collection, function(value, key, collection) {
var object = result[++index] = getObject();
if (isArr) {
object.criteria = map(callback, function(key) { return value[key]; });
} else {
(object.criteria = getArray())[0] = callback(value, key, collection);
}
object.index = index;
object.value = value;
});
length = result.length;
result.sort(compareAscending);
while (length--) {
var object = result[length];
result[length] = object.value;
if (!isArr) {
releaseArray(object.criteria);
}
releaseObject(object);
}
return result;
}
/**
* Converts the `collection` to an array.
*
* @static
* @memberOf _
* @category Collections
* @param {Array|Object|string} collection The collection to convert.
* @returns {Array} Returns the new converted array.
* @example
*
* (function() { return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
* // => [2, 3, 4]
*/
function toArray(collection) {
if (collection && typeof collection.length == 'number') {
return slice(collection);
}
return values(collection);
}
/**
* Performs a deep comparison of each element in a `collection` to the given
* `properties` object, returning an array of all elements that have equivalent
* property values.
*
* @static
* @memberOf _
* @type Function
* @category Collections
* @param {Array|Object|string} collection The collection to iterate over.
* @param {Object} props The object of property values to filter by.
* @returns {Array} Returns a new array of elements that have the given properties.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* _.where(characters, { 'age': 36 });
* // => [{ 'name': 'barney', 'age': 36, 'pets': ['hoppy'] }]
*
* _.where(characters, { 'pets': ['dino'] });
* // => [{ 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }]
*/
var where = filter;
/*--------------------------------------------------------------------------*/
/**
* Creates an array with all falsey values removed. The values `false`, `null`,
* `0`, `""`, `undefined`, and `NaN` are all falsey.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to compact.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.compact([0, 1, false, 2, '', 3]);
* // => [1, 2, 3]
*/
function compact(array) {
var index = -1,
length = array ? array.length : 0,
result = [];
while (++index < length) {
var value = array[index];
if (value) {
result.push(value);
}
}
return result;
}
/**
* Creates an array excluding all values of the provided arrays using strict
* equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to process.
* @param {...Array} [values] The arrays of values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.difference([1, 2, 3, 4, 5], [5, 2, 10]);
* // => [1, 3, 4]
*/
function difference(array) {
return baseDifference(array, baseFlatten(arguments, true, true, 1));
}
/**
* This method is like `_.find` except that it returns the index of the first
* element that passes the callback check, instead of the element itself.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': false },
* { 'name': 'fred', 'age': 40, 'blocked': true },
* { 'name': 'pebbles', 'age': 1, 'blocked': false }
* ];
*
* _.findIndex(characters, function(chr) {
* return chr.age < 20;
* });
* // => 2
*
* // using "_.where" callback shorthand
* _.findIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findIndex(characters, 'blocked');
* // => 1
*/
function findIndex(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
if (callback(array[index], index, array)) {
return index;
}
}
return -1;
}
/**
* This method is like `_.findIndex` except that it iterates over elements
* of a `collection` from right to left.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index of the found element, else `-1`.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36, 'blocked': true },
* { 'name': 'fred', 'age': 40, 'blocked': false },
* { 'name': 'pebbles', 'age': 1, 'blocked': true }
* ];
*
* _.findLastIndex(characters, function(chr) {
* return chr.age > 30;
* });
* // => 1
*
* // using "_.where" callback shorthand
* _.findLastIndex(characters, { 'age': 36 });
* // => 0
*
* // using "_.pluck" callback shorthand
* _.findLastIndex(characters, 'blocked');
* // => 2
*/
function findLastIndex(array, callback, thisArg) {
var length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (length--) {
if (callback(array[length], length, array)) {
return length;
}
}
return -1;
}
/**
* Gets the first element or first `n` elements of an array. If a callback
* is provided elements at the beginning of the array are returned as long
* as the callback returns truey. The callback is bound to `thisArg` and
* invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias head, take
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the first element(s) of `array`.
* @example
*
* _.first([1, 2, 3]);
* // => 1
*
* _.first([1, 2, 3], 2);
* // => [1, 2]
*
* _.first([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [1, 2]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.first(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': true, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.first(characters, { 'employer': 'slate' }), 'name');
* // => ['barney', 'fred']
*/
function first(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = -1;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[0] : undefined;
}
}
return slice(array, 0, nativeMin(nativeMax(0, n), length));
}
/**
* Flattens a nested array (the nesting can be to any depth). If `isShallow`
* is truey, the array will only be flattened a single level. If a callback
* is provided each element of the array is passed through the callback before
* flattening. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array.
* @example
*
* _.flatten([1, [2], [3, [[4]]]]);
* // => [1, 2, 3, 4];
*
* _.flatten([1, [2], [3, [[4]]]], true);
* // => [1, 2, 3, [[4]]];
*
* var characters = [
* { 'name': 'barney', 'age': 30, 'pets': ['hoppy'] },
* { 'name': 'fred', 'age': 40, 'pets': ['baby puss', 'dino'] }
* ];
*
* // using "_.pluck" callback shorthand
* _.flatten(characters, 'pets');
* // => ['hoppy', 'baby puss', 'dino']
*/
function flatten(array, isShallow, callback, thisArg) {
// juggle arguments
if (typeof isShallow != 'boolean' && isShallow != null) {
thisArg = callback;
callback = (typeof isShallow != 'function' && thisArg && thisArg[isShallow] === array) ? null : isShallow;
isShallow = false;
}
if (callback != null) {
array = map(array, callback, thisArg);
}
return baseFlatten(array, isShallow);
}
/**
* Gets the index at which the first occurrence of `value` is found using
* strict equality for comparisons, i.e. `===`. If the array is already sorted
* providing `true` for `fromIndex` will run a faster binary search.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {boolean|number} [fromIndex=0] The index to search from or `true`
* to perform a binary search on a sorted array.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2);
* // => 1
*
* _.indexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 4
*
* _.indexOf([1, 1, 2, 2, 3, 3], 2, true);
* // => 2
*/
function indexOf(array, value, fromIndex) {
if (typeof fromIndex == 'number') {
var length = array ? array.length : 0;
fromIndex = (fromIndex < 0 ? nativeMax(0, length + fromIndex) : fromIndex || 0);
} else if (fromIndex) {
var index = sortedIndex(array, value);
return array[index] === value ? index : -1;
}
return baseIndexOf(array, value, fromIndex);
}
/**
* Gets all but the last element or last `n` elements of an array. If a
* callback is provided elements at the end of the array are excluded from
* the result as long as the callback returns truey. The callback is bound
* to `thisArg` and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.initial([1, 2, 3]);
* // => [1, 2]
*
* _.initial([1, 2, 3], 2);
* // => [1]
*
* _.initial([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [1]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.initial(characters, 'blocked');
* // => [{ 'name': 'barney', 'blocked': false, 'employer': 'slate' }]
*
* // using "_.where" callback shorthand
* _.pluck(_.initial(characters, { 'employer': 'na' }), 'name');
* // => ['barney', 'fred']
*/
function initial(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : callback || n;
}
return slice(array, 0, nativeMin(nativeMax(0, length - n), length));
}
/**
* Creates an array of unique values present in all provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of shared values.
* @example
*
* _.intersection([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2]
*/
function intersection() {
var args = [],
argsIndex = -1,
argsLength = arguments.length,
caches = getArray(),
indexOf = getIndexOf(),
trustIndexOf = indexOf === baseIndexOf,
seen = getArray();
while (++argsIndex < argsLength) {
var value = arguments[argsIndex];
if (isArray(value) || isArguments(value)) {
args.push(value);
caches.push(trustIndexOf && value.length >= largeArraySize &&
createCache(argsIndex ? args[argsIndex] : seen));
}
}
var array = args[0],
index = -1,
length = array ? array.length : 0,
result = [];
outer:
while (++index < length) {
var cache = caches[0];
value = array[index];
if ((cache ? cacheIndexOf(cache, value) : indexOf(seen, value)) < 0) {
argsIndex = argsLength;
(cache || seen).push(value);
while (--argsIndex) {
cache = caches[argsIndex];
if ((cache ? cacheIndexOf(cache, value) : indexOf(args[argsIndex], value)) < 0) {
continue outer;
}
}
result.push(value);
}
}
while (argsLength--) {
cache = caches[argsLength];
if (cache) {
releaseObject(cache);
}
}
releaseArray(caches);
releaseArray(seen);
return result;
}
/**
* Gets the last element or last `n` elements of an array. If a callback is
* provided elements at the end of the array are returned as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback] The function called
* per element or the number of elements to return. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the last element(s) of `array`.
* @example
*
* _.last([1, 2, 3]);
* // => 3
*
* _.last([1, 2, 3], 2);
* // => [2, 3]
*
* _.last([1, 2, 3], function(num) {
* return num > 1;
* });
* // => [2, 3]
*
* var characters = [
* { 'name': 'barney', 'blocked': false, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': true, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.last(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.last(characters, { 'employer': 'na' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function last(array, callback, thisArg) {
var n = 0,
length = array ? array.length : 0;
if (typeof callback != 'number' && callback != null) {
var index = length;
callback = lodash.createCallback(callback, thisArg, 3);
while (index-- && callback(array[index], index, array)) {
n++;
}
} else {
n = callback;
if (n == null || thisArg) {
return array ? array[length - 1] : undefined;
}
}
return slice(array, nativeMax(0, length - n));
}
/**
* Gets the index at which the last occurrence of `value` is found using strict
* equality for comparisons, i.e. `===`. If `fromIndex` is negative, it is used
* as the offset from the end of the collection.
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to search.
* @param {*} value The value to search for.
* @param {number} [fromIndex=array.length-1] The index to search from.
* @returns {number} Returns the index of the matched value or `-1`.
* @example
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2);
* // => 4
*
* _.lastIndexOf([1, 2, 3, 1, 2, 3], 2, 3);
* // => 1
*/
function lastIndexOf(array, value, fromIndex) {
var index = array ? array.length : 0;
if (typeof fromIndex == 'number') {
index = (fromIndex < 0 ? nativeMax(0, index + fromIndex) : nativeMin(fromIndex, index - 1)) + 1;
}
while (index--) {
if (array[index] === value) {
return index;
}
}
return -1;
}
/**
* Removes all provided values from the given array using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {...*} [value] The values to remove.
* @returns {Array} Returns `array`.
* @example
*
* var array = [1, 2, 3, 1, 2, 3];
* _.pull(array, 2, 3);
* console.log(array);
* // => [1, 1]
*/
function pull(array) {
var args = arguments,
argsIndex = 0,
argsLength = args.length,
length = array ? array.length : 0;
while (++argsIndex < argsLength) {
var index = -1,
value = args[argsIndex];
while (++index < length) {
if (array[index] === value) {
splice.call(array, index--, 1);
length--;
}
}
}
return array;
}
/**
* Creates an array of numbers (positive and/or negative) progressing from
* `start` up to but not including `end`. If `start` is less than `stop` a
* zero-length range is created unless a negative `step` is specified.
*
* @static
* @memberOf _
* @category Arrays
* @param {number} [start=0] The start of the range.
* @param {number} end The end of the range.
* @param {number} [step=1] The value to increment or decrement by.
* @returns {Array} Returns a new range array.
* @example
*
* _.range(4);
* // => [0, 1, 2, 3]
*
* _.range(1, 5);
* // => [1, 2, 3, 4]
*
* _.range(0, 20, 5);
* // => [0, 5, 10, 15]
*
* _.range(0, -4, -1);
* // => [0, -1, -2, -3]
*
* _.range(1, 4, 0);
* // => [1, 1, 1]
*
* _.range(0);
* // => []
*/
function range(start, end, step) {
start = +start || 0;
step = typeof step == 'number' ? step : (+step || 1);
if (end == null) {
end = start;
start = 0;
}
// use `Array(length)` so engines like Chakra and V8 avoid slower modes
// http://youtu.be/XAqIpGU8ZZk#t=17m25s
var index = -1,
length = nativeMax(0, ceil((end - start) / (step || 1))),
result = Array(length);
while (++index < length) {
result[index] = start;
start += step;
}
return result;
}
/**
* Removes all elements from an array that the callback returns truey for
* and returns an array of removed elements. The callback is bound to `thisArg`
* and invoked with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to modify.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of removed elements.
* @example
*
* var array = [1, 2, 3, 4, 5, 6];
* var evens = _.remove(array, function(num) { return num % 2 == 0; });
*
* console.log(array);
* // => [1, 3, 5]
*
* console.log(evens);
* // => [2, 4, 6]
*/
function remove(array, callback, thisArg) {
var index = -1,
length = array ? array.length : 0,
result = [];
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length) {
var value = array[index];
if (callback(value, index, array)) {
result.push(value);
splice.call(array, index--, 1);
length--;
}
}
return result;
}
/**
* The opposite of `_.initial` this method gets all but the first element or
* first `n` elements of an array. If a callback function is provided elements
* at the beginning of the array are excluded from the result as long as the
* callback returns truey. The callback is bound to `thisArg` and invoked
* with three arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias drop, tail
* @category Arrays
* @param {Array} array The array to query.
* @param {Function|Object|number|string} [callback=1] The function called
* per element or the number of elements to exclude. If a property name or
* object is provided it will be used to create a "_.pluck" or "_.where"
* style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a slice of `array`.
* @example
*
* _.rest([1, 2, 3]);
* // => [2, 3]
*
* _.rest([1, 2, 3], 2);
* // => [3]
*
* _.rest([1, 2, 3], function(num) {
* return num < 3;
* });
* // => [3]
*
* var characters = [
* { 'name': 'barney', 'blocked': true, 'employer': 'slate' },
* { 'name': 'fred', 'blocked': false, 'employer': 'slate' },
* { 'name': 'pebbles', 'blocked': true, 'employer': 'na' }
* ];
*
* // using "_.pluck" callback shorthand
* _.pluck(_.rest(characters, 'blocked'), 'name');
* // => ['fred', 'pebbles']
*
* // using "_.where" callback shorthand
* _.rest(characters, { 'employer': 'slate' });
* // => [{ 'name': 'pebbles', 'blocked': true, 'employer': 'na' }]
*/
function rest(array, callback, thisArg) {
if (typeof callback != 'number' && callback != null) {
var n = 0,
index = -1,
length = array ? array.length : 0;
callback = lodash.createCallback(callback, thisArg, 3);
while (++index < length && callback(array[index], index, array)) {
n++;
}
} else {
n = (callback == null || thisArg) ? 1 : nativeMax(0, callback);
}
return slice(array, n);
}
/**
* Uses a binary search to determine the smallest index at which a value
* should be inserted into a given sorted array in order to maintain the sort
* order of the array. If a callback is provided it will be executed for
* `value` and each element of `array` to compute their sort ranking. The
* callback is bound to `thisArg` and invoked with one argument; (value).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to inspect.
* @param {*} value The value to evaluate.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {number} Returns the index at which `value` should be inserted
* into `array`.
* @example
*
* _.sortedIndex([20, 30, 50], 40);
* // => 2
*
* // using "_.pluck" callback shorthand
* _.sortedIndex([{ 'x': 20 }, { 'x': 30 }, { 'x': 50 }], { 'x': 40 }, 'x');
* // => 2
*
* var dict = {
* 'wordToNumber': { 'twenty': 20, 'thirty': 30, 'fourty': 40, 'fifty': 50 }
* };
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return dict.wordToNumber[word];
* });
* // => 2
*
* _.sortedIndex(['twenty', 'thirty', 'fifty'], 'fourty', function(word) {
* return this.wordToNumber[word];
* }, dict);
* // => 2
*/
function sortedIndex(array, value, callback, thisArg) {
var low = 0,
high = array ? array.length : low;
// explicitly reference `identity` for better inlining in Firefox
callback = callback ? lodash.createCallback(callback, thisArg, 1) : identity;
value = callback(value);
while (low < high) {
var mid = (low + high) >>> 1;
(callback(array[mid]) < value)
? low = mid + 1
: high = mid;
}
return low;
}
/**
* Creates an array of unique values, in order, of the provided arrays using
* strict equality for comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of combined values.
* @example
*
* _.union([1, 2, 3], [5, 2, 1, 4], [2, 1]);
* // => [1, 2, 3, 5, 4]
*/
function union() {
return baseUniq(baseFlatten(arguments, true, true));
}
/**
* Creates a duplicate-value-free version of an array using strict equality
* for comparisons, i.e. `===`. If the array is sorted, providing
* `true` for `isSorted` will use a faster algorithm. If a callback is provided
* each element of `array` is passed through the callback before uniqueness
* is computed. The callback is bound to `thisArg` and invoked with three
* arguments; (value, index, array).
*
* If a property name is provided for `callback` the created "_.pluck" style
* callback will return the property value of the given element.
*
* If an object is provided for `callback` the created "_.where" style callback
* will return `true` for elements that have the properties of the given object,
* else `false`.
*
* @static
* @memberOf _
* @alias unique
* @category Arrays
* @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array.
* @example
*
* _.uniq([1, 2, 1, 3, 1]);
* // => [1, 2, 3]
*
* _.uniq([1, 1, 2, 2, 3], true);
* // => [1, 2, 3]
*
* _.uniq(['A', 'b', 'C', 'a', 'B', 'c'], function(letter) { return letter.toLowerCase(); });
* // => ['A', 'b', 'C']
*
* _.uniq([1, 2.5, 3, 1.5, 2, 3.5], function(num) { return this.floor(num); }, Math);
* // => [1, 2.5, 3]
*
* // using "_.pluck" callback shorthand
* _.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
function uniq(array, isSorted, callback, thisArg) {
// juggle arguments
if (typeof isSorted != 'boolean' && isSorted != null) {
thisArg = callback;
callback = (typeof isSorted != 'function' && thisArg && thisArg[isSorted] === array) ? null : isSorted;
isSorted = false;
}
if (callback != null) {
callback = lodash.createCallback(callback, thisArg, 3);
}
return baseUniq(array, isSorted, callback);
}
/**
* Creates an array excluding all provided values using strict equality for
* comparisons, i.e. `===`.
*
* @static
* @memberOf _
* @category Arrays
* @param {Array} array The array to filter.
* @param {...*} [value] The values to exclude.
* @returns {Array} Returns a new array of filtered values.
* @example
*
* _.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
* // => [2, 3, 4]
*/
function without(array) {
return baseDifference(array, slice(arguments, 1));
}
/**
* Creates an array that is the symmetric difference of the provided arrays.
* See http://en.wikipedia.org/wiki/Symmetric_difference.
*
* @static
* @memberOf _
* @category Arrays
* @param {...Array} [array] The arrays to inspect.
* @returns {Array} Returns an array of values.
* @example
*
* _.xor([1, 2, 3], [5, 2, 1, 4]);
* // => [3, 5, 4]
*
* _.xor([1, 2, 5], [2, 3, 5], [3, 4, 5]);
* // => [1, 4, 5]
*/
function xor() {
var index = -1,
length = arguments.length;
while (++index < length) {
var array = arguments[index];
if (isArray(array) || isArguments(array)) {
var result = result
? baseUniq(baseDifference(result, array).concat(baseDifference(array, result)))
: array;
}
}
return result || [];
}
/**
* Creates an array of grouped elements, the first of which contains the first
* elements of the given arrays, the second of which contains the second
* elements of the given arrays, and so on.
*
* @static
* @memberOf _
* @alias unzip
* @category Arrays
* @param {...Array} [array] Arrays to process.
* @returns {Array} Returns a new array of grouped elements.
* @example
*
* _.zip(['fred', 'barney'], [30, 40], [true, false]);
* // => [['fred', 30, true], ['barney', 40, false]]
*/
function zip() {
var array = arguments.length > 1 ? arguments : arguments[0],
index = -1,
length = array ? max(pluck(array, 'length')) : 0,
result = Array(length < 0 ? 0 : length);
while (++index < length) {
result[index] = pluck(array, index);
}
return result;
}
/**
* Creates an object composed from arrays of `keys` and `values`. Provide
* either a single two dimensional array, i.e. `[[key1, value1], [key2, value2]]`
* or two arrays, one of `keys` and one of corresponding `values`.
*
* @static
* @memberOf _
* @alias object
* @category Arrays
* @param {Array} keys The array of keys.
* @param {Array} [values=[]] The array of values.
* @returns {Object} Returns an object composed of the given keys and
* corresponding values.
* @example
*
* _.zipObject(['fred', 'barney'], [30, 40]);
* // => { 'fred': 30, 'barney': 40 }
*/
function zipObject(keys, values) {
var index = -1,
length = keys ? keys.length : 0,
result = {};
if (!values && length && !isArray(keys[0])) {
values = [];
}
while (++index < length) {
var key = keys[index];
if (values) {
result[key] = values[index];
} else if (key) {
result[key[0]] = key[1];
}
}
return result;
}
/*--------------------------------------------------------------------------*/
/**
* Creates a function that executes `func`, with the `this` binding and
* arguments of the created function, only after being called `n` times.
*
* @static
* @memberOf _
* @category Functions
* @param {number} n The number of times the function must be called before
* `func` is executed.
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var saves = ['profile', 'settings'];
*
* var done = _.after(saves.length, function() {
* console.log('Done saving!');
* });
*
* _.forEach(saves, function(type) {
* asyncSave({ 'type': type, 'complete': done });
* });
* // => logs 'Done saving!', after all saves have completed
*/
function after(n, func) {
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (--n < 1) {
return func.apply(this, arguments);
}
};
}
/**
* Creates a function that, when called, invokes `func` with the `this`
* binding of `thisArg` and prepends any additional `bind` arguments to those
* provided to the bound function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to bind.
* @param {*} [thisArg] The `this` binding of `func`.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var func = function(greeting) {
* return greeting + ' ' + this.name;
* };
*
* func = _.bind(func, { 'name': 'fred' }, 'hi');
* func();
* // => 'hi fred'
*/
function bind(func, thisArg) {
return arguments.length > 2
? createWrapper(func, 17, slice(arguments, 2), null, thisArg)
: createWrapper(func, 1, null, null, thisArg);
}
/**
* Binds methods of an object to the object itself, overwriting the existing
* method. Method names may be specified as individual arguments or as arrays
* of method names. If no method names are provided all the function properties
* of `object` will be bound.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object to bind and assign the bound methods to.
* @param {...string} [methodName] The object method names to
* bind, specified as individual method names or arrays of method names.
* @returns {Object} Returns `object`.
* @example
*
* var view = {
* 'label': 'docs',
* 'onClick': function() { console.log('clicked ' + this.label); }
* };
*
* _.bindAll(view);
* jQuery('#docs').on('click', view.onClick);
* // => logs 'clicked docs', when the button is clicked
*/
function bindAll(object) {
var funcs = arguments.length > 1 ? baseFlatten(arguments, true, false, 1) : functions(object),
index = -1,
length = funcs.length;
while (++index < length) {
var key = funcs[index];
object[key] = createWrapper(object[key], 1, null, null, object);
}
return object;
}
/**
* Creates a function that, when called, invokes the method at `object[key]`
* and prepends any additional `bindKey` arguments to those provided to the bound
* function. This method differs from `_.bind` by allowing bound functions to
* reference methods that will be redefined or don't yet exist.
* See http://michaux.ca/articles/lazy-function-definition-pattern.
*
* @static
* @memberOf _
* @category Functions
* @param {Object} object The object the method belongs to.
* @param {string} key The key of the method.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new bound function.
* @example
*
* var object = {
* 'name': 'fred',
* 'greet': function(greeting) {
* return greeting + ' ' + this.name;
* }
* };
*
* var func = _.bindKey(object, 'greet', 'hi');
* func();
* // => 'hi fred'
*
* object.greet = function(greeting) {
* return greeting + 'ya ' + this.name + '!';
* };
*
* func();
* // => 'hiya fred!'
*/
function bindKey(object, key) {
return arguments.length > 2
? createWrapper(key, 19, slice(arguments, 2), null, object)
: createWrapper(key, 3, null, null, object);
}
/**
* Creates a function that is the composition of the provided functions,
* where each function consumes the return value of the function that follows.
* For example, composing the functions `f()`, `g()`, and `h()` produces `f(g(h()))`.
* Each function is executed with the `this` binding of the composed function.
*
* @static
* @memberOf _
* @category Functions
* @param {...Function} [func] Functions to compose.
* @returns {Function} Returns the new composed function.
* @example
*
* var realNameMap = {
* 'pebbles': 'penelope'
* };
*
* var format = function(name) {
* name = realNameMap[name.toLowerCase()] || name;
* return name.charAt(0).toUpperCase() + name.slice(1).toLowerCase();
* };
*
* var greet = function(formatted) {
* return 'Hiya ' + formatted + '!';
* };
*
* var welcome = _.compose(greet, format);
* welcome('pebbles');
* // => 'Hiya Penelope!'
*/
function compose() {
var funcs = arguments,
length = funcs.length;
while (length--) {
if (!isFunction(funcs[length])) {
throw new TypeError;
}
}
return function() {
var args = arguments,
length = funcs.length;
while (length--) {
args = [funcs[length].apply(this, args)];
}
return args[0];
};
}
/**
* Creates a function which accepts one or more arguments of `func` that when
* invoked either executes `func` returning its result, if all `func` arguments
* have been provided, or returns a function that accepts one or more of the
* remaining `func` arguments, and so on. The arity of `func` can be specified
* if `func.length` is not sufficient.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to curry.
* @param {number} [arity=func.length] The arity of `func`.
* @returns {Function} Returns the new curried function.
* @example
*
* var curried = _.curry(function(a, b, c) {
* console.log(a + b + c);
* });
*
* curried(1)(2)(3);
* // => 6
*
* curried(1, 2)(3);
* // => 6
*
* curried(1, 2, 3);
* // => 6
*/
function curry(func, arity) {
arity = typeof arity == 'number' ? arity : (+arity || func.length);
return createWrapper(func, 4, null, null, null, arity);
}
/**
* Creates a function that will delay the execution of `func` until after
* `wait` milliseconds have elapsed since the last time it was invoked.
* Provide an options object to indicate that `func` should be invoked on
* the leading and/or trailing edge of the `wait` timeout. Subsequent calls
* to the debounced function will return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the debounced function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to debounce.
* @param {number} wait The number of milliseconds to delay.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=false] Specify execution on the leading edge of the timeout.
* @param {number} [options.maxWait] The maximum time `func` is allowed to be delayed before it's called.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new debounced function.
* @example
*
* // avoid costly calculations while the window size is in flux
* var lazyLayout = _.debounce(calculateLayout, 150);
* jQuery(window).on('resize', lazyLayout);
*
* // execute `sendMail` when the click event is fired, debouncing subsequent calls
* jQuery('#postbox').on('click', _.debounce(sendMail, 300, {
* 'leading': true,
* 'trailing': false
* });
*
* // ensure `batchLog` is executed once after 1 second of debounced calls
* var source = new EventSource('/stream');
* source.addEventListener('message', _.debounce(batchLog, 250, {
* 'maxWait': 1000
* }, false);
*/
function debounce(func, wait, options) {
var args,
maxTimeoutId,
result,
stamp,
thisArg,
timeoutId,
trailingCall,
lastCalled = 0,
maxWait = false,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
wait = nativeMax(0, wait) || 0;
if (options === true) {
var leading = true;
trailing = false;
} else if (isObject(options)) {
leading = options.leading;
maxWait = 'maxWait' in options && (nativeMax(wait, options.maxWait) || 0);
trailing = 'trailing' in options ? options.trailing : trailing;
}
var delayed = function() {
var remaining = wait - (now() - stamp);
if (remaining <= 0) {
if (maxTimeoutId) {
clearTimeout(maxTimeoutId);
}
var isCalled = trailingCall;
maxTimeoutId = timeoutId = trailingCall = undefined;
if (isCalled) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
} else {
timeoutId = setTimeout(delayed, remaining);
}
};
var maxDelayed = function() {
if (timeoutId) {
clearTimeout(timeoutId);
}
maxTimeoutId = timeoutId = trailingCall = undefined;
if (trailing || (maxWait !== wait)) {
lastCalled = now();
result = func.apply(thisArg, args);
if (!timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
}
};
return function() {
args = arguments;
stamp = now();
thisArg = this;
trailingCall = trailing && (timeoutId || !leading);
if (maxWait === false) {
var leadingCall = leading && !timeoutId;
} else {
if (!maxTimeoutId && !leading) {
lastCalled = stamp;
}
var remaining = maxWait - (stamp - lastCalled),
isCalled = remaining <= 0;
if (isCalled) {
if (maxTimeoutId) {
maxTimeoutId = clearTimeout(maxTimeoutId);
}
lastCalled = stamp;
result = func.apply(thisArg, args);
}
else if (!maxTimeoutId) {
maxTimeoutId = setTimeout(maxDelayed, remaining);
}
}
if (isCalled && timeoutId) {
timeoutId = clearTimeout(timeoutId);
}
else if (!timeoutId && wait !== maxWait) {
timeoutId = setTimeout(delayed, wait);
}
if (leadingCall) {
isCalled = true;
result = func.apply(thisArg, args);
}
if (isCalled && !timeoutId && !maxTimeoutId) {
args = thisArg = null;
}
return result;
};
}
/**
* Defers executing the `func` function until the current call stack has cleared.
* Additional arguments will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to defer.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.defer(function(text) { console.log(text); }, 'deferred');
* // logs 'deferred' after one or more milliseconds
*/
function defer(func) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 1);
return setTimeout(function() { func.apply(undefined, args); }, 1);
}
/**
* Executes the `func` function after `wait` milliseconds. Additional arguments
* will be provided to `func` when it is invoked.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to delay.
* @param {number} wait The number of milliseconds to delay execution.
* @param {...*} [arg] Arguments to invoke the function with.
* @returns {number} Returns the timer id.
* @example
*
* _.delay(function(text) { console.log(text); }, 1000, 'later');
* // => logs 'later' after one second
*/
function delay(func, wait) {
if (!isFunction(func)) {
throw new TypeError;
}
var args = slice(arguments, 2);
return setTimeout(function() { func.apply(undefined, args); }, wait);
}
/**
* Creates a function that memoizes the result of `func`. If `resolver` is
* provided it will be used to determine the cache key for storing the result
* based on the arguments provided to the memoized function. By default, the
* first argument provided to the memoized function is used as the cache key.
* The `func` is executed with the `this` binding of the memoized function.
* The result cache is exposed as the `cache` property on the memoized function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to have its output memoized.
* @param {Function} [resolver] A function used to resolve the cache key.
* @returns {Function} Returns the new memoizing function.
* @example
*
* var fibonacci = _.memoize(function(n) {
* return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
* });
*
* fibonacci(9)
* // => 34
*
* var data = {
* 'fred': { 'name': 'fred', 'age': 40 },
* 'pebbles': { 'name': 'pebbles', 'age': 1 }
* };
*
* // modifying the result cache
* var get = _.memoize(function(name) { return data[name]; }, _.identity);
* get('pebbles');
* // => { 'name': 'pebbles', 'age': 1 }
*
* get.cache.pebbles.name = 'penelope';
* get('pebbles');
* // => { 'name': 'penelope', 'age': 1 }
*/
function memoize(func, resolver) {
if (!isFunction(func)) {
throw new TypeError;
}
var memoized = function() {
var cache = memoized.cache,
key = resolver ? resolver.apply(this, arguments) : keyPrefix + arguments[0];
return hasOwnProperty.call(cache, key)
? cache[key]
: (cache[key] = func.apply(this, arguments));
}
memoized.cache = {};
return memoized;
}
/**
* Creates a function that is restricted to execute `func` once. Repeat calls to
* the function will return the value of the first call. The `func` is executed
* with the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to restrict.
* @returns {Function} Returns the new restricted function.
* @example
*
* var initialize = _.once(createApplication);
* initialize();
* initialize();
* // `initialize` executes `createApplication` once
*/
function once(func) {
var ran,
result;
if (!isFunction(func)) {
throw new TypeError;
}
return function() {
if (ran) {
return result;
}
ran = true;
result = func.apply(this, arguments);
// clear the `func` variable so the function may be garbage collected
func = null;
return result;
};
}
/**
* Creates a function that, when called, invokes `func` with any additional
* `partial` arguments prepended to those provided to the new function. This
* method is similar to `_.bind` except it does **not** alter the `this` binding.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var greet = function(greeting, name) { return greeting + ' ' + name; };
* var hi = _.partial(greet, 'hi');
* hi('fred');
* // => 'hi fred'
*/
function partial(func) {
return createWrapper(func, 16, slice(arguments, 1));
}
/**
* This method is like `_.partial` except that `partial` arguments are
* appended to those provided to the new function.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to partially apply arguments to.
* @param {...*} [arg] Arguments to be partially applied.
* @returns {Function} Returns the new partially applied function.
* @example
*
* var defaultsDeep = _.partialRight(_.merge, _.defaults);
*
* var options = {
* 'variable': 'data',
* 'imports': { 'jq': $ }
* };
*
* defaultsDeep(options, _.templateSettings);
*
* options.variable
* // => 'data'
*
* options.imports
* // => { '_': _, 'jq': $ }
*/
function partialRight(func) {
return createWrapper(func, 32, null, slice(arguments, 1));
}
/**
* Creates a function that, when executed, will only call the `func` function
* at most once per every `wait` milliseconds. Provide an options object to
* indicate that `func` should be invoked on the leading and/or trailing edge
* of the `wait` timeout. Subsequent calls to the throttled function will
* return the result of the last `func` call.
*
* Note: If `leading` and `trailing` options are `true` `func` will be called
* on the trailing edge of the timeout only if the the throttled function is
* invoked more than once during the `wait` timeout.
*
* @static
* @memberOf _
* @category Functions
* @param {Function} func The function to throttle.
* @param {number} wait The number of milliseconds to throttle executions to.
* @param {Object} [options] The options object.
* @param {boolean} [options.leading=true] Specify execution on the leading edge of the timeout.
* @param {boolean} [options.trailing=true] Specify execution on the trailing edge of the timeout.
* @returns {Function} Returns the new throttled function.
* @example
*
* // avoid excessively updating the position while scrolling
* var throttled = _.throttle(updatePosition, 100);
* jQuery(window).on('scroll', throttled);
*
* // execute `renewToken` when the click event is fired, but not more than once every 5 minutes
* jQuery('.interactive').on('click', _.throttle(renewToken, 300000, {
* 'trailing': false
* }));
*/
function throttle(func, wait, options) {
var leading = true,
trailing = true;
if (!isFunction(func)) {
throw new TypeError;
}
if (options === false) {
leading = false;
} else if (isObject(options)) {
leading = 'leading' in options ? options.leading : leading;
trailing = 'trailing' in options ? options.trailing : trailing;
}
debounceOptions.leading = leading;
debounceOptions.maxWait = wait;
debounceOptions.trailing = trailing;
return debounce(func, wait, debounceOptions);
}
/**
* Creates a function that provides `value` to the wrapper function as its
* first argument. Additional arguments provided to the function are appended
* to those provided to the wrapper function. The wrapper is executed with
* the `this` binding of the created function.
*
* @static
* @memberOf _
* @category Functions
* @param {*} value The value to wrap.
* @param {Function} wrapper The wrapper function.
* @returns {Function} Returns the new function.
* @example
*
* var p = _.wrap(_.escape, function(func, text) {
* return '
'
*/
function wrap(value, wrapper) {
return createWrapper(wrapper, 16, [value]);
}
/*--------------------------------------------------------------------------*/
/**
* Creates a function that returns `value`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value The value to return from the new function.
* @returns {Function} Returns the new function.
* @example
*
* var object = { 'name': 'fred' };
* var getter = _.constant(object);
* getter() === object;
* // => true
*/
function constant(value) {
return function() {
return value;
};
}
/**
* Produces a callback bound to an optional `thisArg`. If `func` is a property
* name the created callback will return the property value for a given element.
* If `func` is an object the created callback will return `true` for elements
* that contain the equivalent object properties, otherwise it will return `false`.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} [func=identity] The value to convert to a callback.
* @param {*} [thisArg] The `this` binding of the created callback.
* @param {number} [argCount] The number of arguments the callback accepts.
* @returns {Function} Returns a callback function.
* @example
*
* var characters = [
* { 'name': 'barney', 'age': 36 },
* { 'name': 'fred', 'age': 40 }
* ];
*
* // wrap to create custom callback shorthands
* _.createCallback = _.wrap(_.createCallback, function(func, callback, thisArg) {
* var match = /^(.+?)__([gl]t)(.+)$/.exec(callback);
* return !match ? func(callback, thisArg) : function(object) {
* return match[2] == 'gt' ? object[match[1]] > match[3] : object[match[1]] < match[3];
* };
* });
*
* _.filter(characters, 'age__gt38');
* // => [{ 'name': 'fred', 'age': 40 }]
*/
function createCallback(func, thisArg, argCount) {
var type = typeof func;
if (func == null || type == 'function') {
return baseCreateCallback(func, thisArg, argCount);
}
// handle "_.pluck" style callback shorthands
if (type != 'object') {
return property(func);
}
var props = keys(func),
key = props[0],
a = func[key];
// handle "_.where" style callback shorthands
if (props.length == 1 && a === a && !isObject(a)) {
// fast path the common case of providing an object with a single
// property containing a primitive value
return function(object) {
var b = object[key];
return a === b && (a !== 0 || (1 / a == 1 / b));
};
}
return function(object) {
var length = props.length,
result = false;
while (length--) {
if (!(result = baseIsEqual(object[props[length]], func[props[length]], null, true))) {
break;
}
}
return result;
};
}
/**
* Converts the characters `&`, `<`, `>`, `"`, and `'` in `string` to their
* corresponding HTML entities.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} string The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escape('Fred, Wilma, & Pebbles');
* // => 'Fred, Wilma, & Pebbles'
*/
function escape(string) {
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
}
/**
* This method returns the first argument provided to it.
*
* @static
* @memberOf _
* @category Utilities
* @param {*} value Any value.
* @returns {*} Returns `value`.
* @example
*
* var object = { 'name': 'fred' };
* _.identity(object) === object;
* // => true
*/
function identity(value) {
return value;
}
/**
* Adds function properties of a source object to the destination object.
* If `object` is a function methods will be added to its prototype as well.
*
* @static
* @memberOf _
* @category Utilities
* @param {Function|Object} [object=lodash] object The destination object.
* @param {Object} source The object of functions to add.
* @param {Object} [options] The options object.
* @param {boolean} [options.chain=true] Specify whether the functions added are chainable.
* @example
*
* function capitalize(string) {
* return string.charAt(0).toUpperCase() + string.slice(1).toLowerCase();
* }
*
* _.mixin({ 'capitalize': capitalize });
* _.capitalize('fred');
* // => 'Fred'
*
* _('fred').capitalize().value();
* // => 'Fred'
*
* _.mixin({ 'capitalize': capitalize }, { 'chain': false });
* _('fred').capitalize();
* // => 'Fred'
*/
function mixin(object, source, options) {
var chain = true,
methodNames = source && functions(source);
if (!source || (!options && !methodNames.length)) {
if (options == null) {
options = source;
}
ctor = lodashWrapper;
source = object;
object = lodash;
methodNames = functions(source);
}
if (options === false) {
chain = false;
} else if (isObject(options) && 'chain' in options) {
chain = options.chain;
}
var ctor = object,
isFunc = isFunction(ctor);
forEach(methodNames, function(methodName) {
var func = object[methodName] = source[methodName];
if (isFunc) {
ctor.prototype[methodName] = function() {
var chainAll = this.__chain__,
value = this.__wrapped__,
args = [value];
push.apply(args, arguments);
var result = func.apply(object, args);
if (chain || chainAll) {
if (value === result && isObject(result)) {
return this;
}
result = new ctor(result);
result.__chain__ = chainAll;
}
return result;
};
}
});
}
/**
* Reverts the '_' variable to its previous value and returns a reference to
* the `lodash` function.
*
* @static
* @memberOf _
* @category Utilities
* @returns {Function} Returns the `lodash` function.
* @example
*
* var lodash = _.noConflict();
*/
function noConflict() {
context._ = oldDash;
return this;
}
/**
* A no-operation function.
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var object = { 'name': 'fred' };
* _.noop(object) === undefined;
* // => true
*/
function noop() {
// no operation performed
}
/**
* Gets the number of milliseconds that have elapsed since the Unix epoch
* (1 January 1970 00:00:00 UTC).
*
* @static
* @memberOf _
* @category Utilities
* @example
*
* var stamp = _.now();
* _.defer(function() { console.log(_.now() - stamp); });
* // => logs the number of milliseconds it took for the deferred function to be called
*/
var now = isNative(now = Date.now) && now || function() {
return new Date().getTime();
};
/**
* Converts the given value into an integer of the specified radix.
* If `radix` is `undefined` or `0` a `radix` of `10` is used unless the
* `value` is a hexadecimal, in which case a `radix` of `16` is used.
*
* Note: This method avoids differences in native ES3 and ES5 `parseInt`
* implementations. See http://es5.github.io/#E.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} value The value to parse.
* @param {number} [radix] The radix used to interpret the value to parse.
* @returns {number} Returns the new integer value.
* @example
*
* _.parseInt('08');
* // => 8
*/
var parseInt = nativeParseInt(whitespace + '08') == 8 ? nativeParseInt : function(value, radix) {
// Firefox < 21 and Opera < 15 follow the ES3 specified implementation of `parseInt`
return nativeParseInt(isString(value) ? value.replace(reLeadingSpacesAndZeros, '') : value, radix || 0);
};
/**
* Creates a "_.pluck" style function, which returns the `key` value of a
* given object.
*
* @static
* @memberOf _
* @category Utilities
* @param {string} key The name of the property to retrieve.
* @returns {Function} Returns the new function.
* @example
*
* var characters = [
* { 'name': 'fred', 'age': 40 },
* { 'name': 'barney', 'age': 36 }
* ];
*
* var getName = _.property('name');
*
* _.map(characters, getName);
* // => ['barney', 'fred']
*
* _.sortBy(characters, getName);
* // => [{ 'name': 'barney', 'age': 36 }, { 'name': 'fred', 'age': 40 }]
*/
function property(key) {
return function(object) {
return object[key];
};
}
/**
* Produces a random number between `min` and `max` (inclusive). If only one
* argument is provided a number between `0` and the given number will be
* returned. If `floating` is truey or either `min` or `max` are floats a
* floating-point number will be returned instead of an integer.
*
* @static
* @memberOf _
* @category Utilities
* @param {number} [min=0] The minimum possible value.
* @param {number} [max=1] The maximum possible value.
* @param {boolean} [floating=false] Specify returning a floating-point number.
* @returns {number} Returns a random number.
* @example
*
* _.random(0, 5);
* // => an integer between 0 and 5
*
* _.random(5);
* // => also an integer between 0 and 5
*
* _.random(5, true);
* // => a floating-point number between 0 and 5
*
* _.random(1.2, 5.2);
* // => a floating-point number between 1.2 and 5.2
*/
function random(min, max, floating) {
var noMin = min == null,
noMax = max == null;
if (floating == null) {
if (typeof min == 'boolean' && noMax) {
floating = min;
min = 1;
}
else if (!noMax && typeof max == 'boolean') {
floating = max;
noMax = true;
}
}
if (noMin && noMax) {
max = 1;
}
min = +min || 0;
if (noMax) {
max = min;
min = 0;
} else {
max = +max || 0;
}
if (floating || min % 1 || max % 1) {
var rand = nativeRandom();
return nativeMin(min + (rand * (max - min + parseFloat('1e-' + ((rand +'').length - 1)))), max);
}
return baseRandom(min, max);
}
/**
* Resolves the value of property `key` on `object`. If `key` is a function
* it will be invoked with the `this` binding of `object` and its result returned,
* else the property value is returned. If `object` is falsey then `undefined`
* is returned.
*
* @static
* @memberOf _
* @category Utilities
* @param {Object} object The object to inspect.
* @param {string} key The name of the property to resolve.
* @returns {*} Returns the resolved value.
* @example
*
* var object = {
* 'cheese': 'crumpets',
* 'stuff': function() {
* return 'nonsense';
* }
* };
*
* _.result(object, 'cheese');
* // => 'crumpets'
*
* _.result(object, 'stuff');
* // => 'nonsense'
*/
function result(object, key) {
if (object) {
var value = object[key];
return isFunction(value) ? object[key]() : value;
}
}
/**
* A micro-templating method that handles arbitrary delimiters, preserves
* whitespace, and correctly escapes quotes within interpolated code.
*
* Note: In the development build, `_.template` utilizes sourceURLs for easier
* debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
*
* For more information on precompiling templates see:
* http://lodash.com/custom-builds
*
* For more information on Chrome extension sandboxes see:
* http://developer.chrome.com/stable/extensions/sandboxingEval.html
*
* @static
* @memberOf _
* @category Utilities
* @param {string} text The template text.
* @param {Object} data The data object used to populate the text.
* @param {Object} [options] The options object.
* @param {RegExp} [options.escape] The "escape" delimiter.
* @param {RegExp} [options.evaluate] The "evaluate" delimiter.
* @param {Object} [options.imports] An object to import into the template as local variables.
* @param {RegExp} [options.interpolate] The "interpolate" delimiter.
* @param {string} [sourceURL] The sourceURL of the template's compiled source.
* @param {string} [variable] The data object variable name.
* @returns {Function|string} Returns a compiled function when no `data` object
* is given, else it returns the interpolated text.
* @example
*
* // using the "interpolate" delimiter to create a compiled template
* var compiled = _.template('hello <%= name %>');
* compiled({ 'name': 'fred' });
* // => 'hello fred'
*
* // using the "escape" delimiter to escape HTML in data property values
* _.template('<%- value %>', { 'value': '