//################################################################################################
/** @file OOP Inheritance mixin for ish.js
* @mixin ish.oop.inherit
* @author Nick Campbell
* @license MIT
* @copyright 2014-2023, Nick Campbell
*/ //############################################################################################
/*global module, define */ //# Enable Node globals for JSHint
/*jshint maxcomplexity:9 */ //# Enable max complexity warnings for JSHint
(function () {
'use strict'; //<MIXIN>
function init(core) {
//################################################################################################
/** Collection of Multiple Inheritance-based functionality.
* @namespace ish.oop.inherit
* @ignore
*/ //############################################################################################
core.oop.partial(core.oop, function (/*oProtected*/) {
var _this = this,
oOopData = _this.oopData
;
//# add(the)OopDataType d(erivedFrom), defaulting to []
//# NOTE: Setting up a .watch for the .event isn't necessary as the added data type will be defaulted to [] automajicially
_this.addOopDataType("d", []);
//core.io.event.watch("ish.oop._setOopEntry", function (/*vTarget, oProtected*/) {
// oOopData.d.push([]);
//});
return {
inherit: function () {
//# Safely returns the d(erivedFrom) array stored in oopData for the vTarget
function derivedFrom(vTarget) {
return oOopData.d[
oOopData.i.indexOf(vTarget)
] || [];
} //# derivedFrom
return core.extend(
//#########
/** Inherits the passed hierarchy into the passed value.
* @function ish.oop.inherit.!
* @param {object[]} a_oHierarchy Value representing the following options: TODO
* @param {object|function} vTarget Value representing the object to inherit into.
*/ //#####
function (a_oHierarchy, vTarget) {
var oProtected, i,
a_oProtected = [{}] //# Pre-populate a_oProtected with a blank object to receive vTarget's oProtected interfaces
;
//# If the passed a_oHierarchy .is an .arr and vTarget is a valid .extend target
if (core.type.arr.is(a_oHierarchy) && core.type.obj.is(vTarget, { allowFn: true })) {
//# Traverse the a_oHierarchy, .push'ing each .p(rotected) reference (if any) into a_oProtected
//# NOTE: We traverse the a_oHierarchy in reverse because .extend works as right-most wins, while a_oHierarchy is left-most wins
for (i = a_oHierarchy.length - 1; i > -1; i--) {
oProtected = oOopData.p[oOopData.i.indexOf(a_oHierarchy[i])];
if (core.type.obj.is(oProtected, { nonEmpty: true })) {
a_oProtected.push(oProtected);
}
}
//#
_this.setOopEntry(vTarget, core.extend.apply(null, a_oProtected), { d: a_oHierarchy });
}
//#
else {
throw "ish.oop.inherit: `a_oHierarchy` must be an array and `vTarget` must be an object or function.";
}
}, { //# core.oop.inherit
//#########
/** Determines if the passed value has been the subject of multiple inheritance.
* @function ish.oop.inherit.is
* @param {object|function} vTarget Value representing the object to test.
* @returns {boolean} Value representing if the passed value has been the subject of multiple inheritance.
*/ //#####
is: function (vTarget) {
return core.type.arr.is(derivedFrom(vTarget), true);
}, //# core.oop.inherit.is
//#########
/** Determines if the passed value is an instance of the passed reference value.
* @function ish.oop.inherit.instanceOf
* @param {object|function} vTarget Value representing the object to test.
* @param {object|function} vReference Value representing the reference object.
* @returns {boolean} Value representing if the passed value is an instance of the passed reference value.
*/ //#####
instanceOf: function (vTarget, vReference) {
return (derivedFrom(vTarget).indexOf(vReference) > -1);
}, //# core.oop.inherit.instanceOf
//#########
/** Determines the base values of the passed reference value.
* @function ish.oop.inherit.derivedFrom
* @param {object|function} vReference Value representing the reference value.
* @returns {boolean} Value representing the base values of the passed reference value.
*/ //#####
derivedFrom: function (vReference) {
return derivedFrom(vReference).slice(0); //# core.type.arr.clone(derivedFrom(vReference));
}
}
);
}() //# oop.inherit
};
}); //# core.oop.inherit
//# .fire the plugin's loaded event
core.io.event.fire("ish.oop.inherit");
//# Return core to allow for chaining
return core;
} //# init
//# If we are running server-side
//# NOTE: Compliant with UMD, see: https://github.com/umdjs/umd/blob/master/templates/returnExports.js
//# NOTE: Does not work with strict CommonJS, but only CommonJS-like environments that support module.exports, like Node.
if (typeof module === 'object' && module.exports) { //if (typeof module !== 'undefined' && this.module !== module && module.exports) {
module.exports = init;
}
//# Else if we are running in an .amd environment, register as an anonymous module
else if (typeof define === 'function' && define.amd) {
define([], init);
}
//# Else we are running in the browser, so we need to setup the _document-based features
else {
return init(window.head.ish || document.querySelector("SCRIPT[ish]").ish);
}
//</MIXIN>
}());