Skip to content

Instantly share code, notes, and snippets.

@JeremyJaydan
Last active February 15, 2019 07:34
Show Gist options
  • Save JeremyJaydan/cd1473ff97cb653c219d3cc17de389e2 to your computer and use it in GitHub Desktop.
Save JeremyJaydan/cd1473ff97cb653c219d3cc17de389e2 to your computer and use it in GitHub Desktop.
Node.js/JavaScript utility library with a focus on object manipulation and components

jModifier is a JavaScript utility library focused on the ability to easily query and manipulate Objects.


const $ = jModifier.getAlts();
const myElement = $.q("#my-element", {
    uls: "ul",
    items: "ul li"
});

$.aa(myElement.uls, {
    style: {
        transform: [16, 0, 24, 0].map(function(val) {
            return "translateY(" + val + "px)"
        })
    }
}, {
    interval: 80,
    loop: Infinity,
    dupe: 4
});

$.aa(myElement.items, {
    innerText: ["Hello,", "world", "this", "is", "jModifier!"],
    style: {
        background: ["#7986CB", "#64B5F6", "#4DB6AC", "#FFD54F", "#FF8A65"],
        textIndent: [32, 64, 16, 88, 0].map(function(val) {
            return val + "px"
        })
    }
}, {
    loop: Infinity,
    interval: 100,
    dupe: 5
});

Question Answer
What's the current version? v0.1
jModifier stable? Not yet!
What's the purpose? Minimal methods with broad uses.
Is this a replacement for jQuery? It's not, however it really depends on what you need done (it can be).
Can I get help? Feel free to join my Discord server for help or general conversation: https://discord.gg/fHKgFSF

Basic Concept

Most methods in jModifier are categorized and can be utilized under the following paths:

  • jModifier.dom
  • jModifier.string
  • jModifier.object
  • jModifier.array
  • jModifier.function

Installing

  1. Download/Copy the jModifier library into a file in your project with the extension .js
  2. Reference the library with a script tag: <script type="text/javascript" src="/path/to/jModifier.js">

Note: There is also an experimental version of jModifier under the /dev directory.


Table of Contents

Method Jump to or Fiddle
jModifier.getAlts() #getalts x3bh6055
jModifier.alts #alts
jModifier.for() #for cjpo7krj
jModifier.dom.query() #domquery e65rk4mj
jModifier.dom.on() #domon 7de3fp35
jModifier.dom.create() #domcreate ufqf8ery
jModifier.dom.createElement() #domcreateelement 4rzam1nc
jModifier.dom.createElements() #domcreateelements s0z3cbvx
jModifier.dom.insertInto() #dominsertinto gnr5q6y9
jModifier.string.toNestedArray() #stringtonestedarray 7m031cvb
jModifier.string.splitFromXOutsideY() #stringsplitfromxoutsidey ovs7Lh3u
jModifier.object.assign() #objectassign 7udvLmyz
jModifier.object.isType() #objectistype 2jm5jwrs
jModifier.object.pathValue() #objectpathvalue zct148bu
jModifier.object.NumStringBool #objectnumstringbool
jModifier.array.assign() #arrayassign gm58pyns
jModifier.array.reverse() #arrayreverse p9n36zL0
jModifier.array.shuffle() #arrayshuffle nsa4h11x
jModifier.array.sum() #arraysum o5L8gvjv
jModifier.array.fill() #arrayfill gbr7s0jv
jModifier.array.wrap() #arraywrap qmj4c4Lm
jModifier.array.getIndex() #arraygetindex aeq1ybsf
jModifier.array.listy #arraylisty
jModifier.function.argumentEvaluator() #functionargumentevaluator 1hynpfhp
jModifier.function.getArguments() #functiongetarguments 8v2hLur9

Documentation


.getAlts

Returns Object of specified or default alternate method paths.

jModifier.getAlts(<Object(Method Paths)>)

Utilizes: jModifier.alts, jModifier.object.pathValue

// Default alternate paths
const $ = jModifier.getAlts();

console.log("Default: ", $);

// Custom alternate paths
const c = jModifier.getAlts({
    query: "dom.query",
    create: "dom.create"
});

console.log("Custom: ", c);

View on JSFiddle



.alts

Default alternate paths for jModifier.getAlts().

jModifier.alts


.for

Similar to the native for loop. Has options argument for more control.

jModifier.for(<Array|Number(Items)>*, <Function(Callback)>*, <Object(Options)>)

Utilizes: jModifier.array.fill, jModifier.array.reverse, jModifier.array.shuffle, jModifier.array.sum

/* Example with number */
jModifier.for(10, function(item, index) {
    console.log(item + 1); // Counting down from 10
}, {
    reverse: true, // Starts in reverse since we're counting down
    interval: 1000, // 1000ms between each execution
    done: function() { // Executes after the loop completes
        console.log("O");
    }
});

/* Example with elements */
const myElements = jModifier.dom.query("li");
jModifier.for(myElements, function(item, index) {
    item.style.textIndent = "32px";
}, {
    interval: 2000
});

View on JSFiddle

Current Options Type Default
interval Number (ms) 0
reverse Boolean false
shuffle Boolean false
dupe Number 0
delay Number (ms) 0
loop Number (including Infinity) 0
done Function null


.dom.query

You can easily query elements with this one however it works differently depending on how you use it.

jModifier.dom.query(<Element|Array|String(Target|Parent)>*, <String(Child Target)>, <Boolean(Force Array)>)

Utilizes: jModifier.for, jModifier.array.wrap

// Simple query
const myElement = jModifier.dom.query("#my-element");

// Query children of element
const childrenUL = jModifier.dom.query(myElement, "ul");

// Query multiple children of multiple elements and return in single Array
const childrenLI = jModifier.dom.query(childrenUL, "li");

// Query children and assign to returning object 
const childrenObj = jModifier.dom.query(myElement, {
    UL: "ul",
    LI: "ul li"
});

View on JSFiddle



.dom.on

Similar to <Element>.addEventListener however you can add multiple listeners to multiple elements with one simple function.

jModifier.dom.on(<String|Element|Array(Target Element(s))>*, <Function(Callback & Events)>*, <Boolean(useCapture)>)

Utilizes: jModifier.function.getArguments, jModifier.dom.query, jModifier.for

// First argument utilizes the .dom.query method therefore you can specify element(s)
// via a string, variable, array, etc.
jModifier.dom.on("#my-element ul li", function(element, mouseenter, click) {

    // First argument of the callback function returns an object that consists
    // of the elements, target index, and target element
    // {elements, index, node}

    // Specify the events after the first argument
    // (You can add as many events as you like)

    // Confused on how to handle multiple events?
    // That's super easy with the || operator
    let event = mouseenter || click;

    let rand = Math.floor(Math.random() * 255);
    element.node.style.background = "rgb(" + rand + ", " + rand + ", " + rand + ")";

});

View on JSFiddle



.dom.create

Create multiple elements with a jModifier Nested Array String (div[ul[li*6]]).

jModifier.dom.create(<String(jModifier Nested Array String)>*)

Utilizes: jModifier.string.toNestedArray, jModifier.dom.createElements

// The below method will create the reference html
// structure using a jModifier Nested Array String.
const myElement = jModifier.dom.create("div[ul*2[li*3]]");
console.log(myElement);
// You can use other methods of jModifier such as array.assign
// to assign data to the elements once created.

// You can also use Regular Expression Objects. Because why not right?
console.log(jModifier.dom.create(/div*1000/));

View on JSFiddle



.dom.createElement

Create one or more elements easily.

jModifier.dom.createElement(<String(Tag Name)>*, <Number(Amount)>)
// This one is for creating multiple elements but only of the same tag type.
const div2 = jModifier.dom.createElement("div", 2);
console.log(div2);

// Leave the second argument blank for only 1 element to be created & returned.
const small = jModifier.dom.createElement("small");
console.log(small);

// Note: This method always returns an Array

View on JSFiddle



.dom.createElements

Create multiple elements with a jModifier Nested Array ([["div",[["ul",[["li*3"]]]]]]).

jModifier.dom.createElements(<Array(jModifier Nested Array String)>)

Utilizes: jModifier.dom.createElement

// .dom.createElements essentially works exactly the same way as .dom.create
// however it requires a "jModifier Nested Array" (NOT "jModifier Nested Array String")

// This one should be your go-to if you want even better performance.

const myElement = jModifier.dom.createElements([["div",[["ul*2",[["li*3"]]]]]]);
console.log(myElement[0]);

// [["div",[["ul*2",[["li*3"]]]]]]
// the above "jModifier Nested Array" is the 
// equivilent to the below "jModifier Nested Array String"
// div[ul*2[li*3]]

View on JSFiddle



.dom.insertInto

Similar to the native <Element>.insertBefore() however it works with multiple elements.

jModifier.dom.insertInto(<String|Element(Target Parent)>*, <Element|Array(Target Element(s))>*, <Number(Position)>)

Utilizes: jModifier.array.wrap, jModifier.dom.query

// Creating element to be inserted into the 1st UL
const newLI = document.createElement("li");
newLI.innerText = "Inserted Element #1";

// Inserting element #1
// The first argument utilizes the .dom.query method
jModifier.dom.insertInto("#my-element ul:nth-child(1)", newLI);
// if no position is specified, the element will be appended to the bottom.

// Creating element to be inserted into the 2nd UL
const newLI2 = document.createElement("li");
newLI2.innerText = "Inserted Element #2";

// You can specify a position with the third argument
jModifier.dom.insertInto("#my-element ul:nth-child(2)", newLI2, 1);
// 0 = before 1st item
// 1 = before 2nd item
// etc..

// Note: You can insert multiple elements and specify the position

View on JSFiddle



.string.toNestedArray

This is the backbone of the dom element creation but it has many data structure uses.

jModifier.string.toNestedArray(<String(jModifier Nested Array String)>*)

Utilizes: jModifier.string.splitFromXOutsideY

// Alright this one may be a little confusing to understand.
// Bare with me!

// The best way I can explain this is to use element creation as an example.

// When creating multiple, nested elements, you want to specify the parent tag
// and the child tags and the child tags of the child tags. 

// So say if we want to create a div, a h1 inside that div,
// then another div a ul inside that with a li inside the ul..

console.log("Example: ",
    jModifier.string.toNestedArray("div[h1], div[ul[li]]")
); // output: [["div",[["h1"]]],["div",[["ul",[["li"]]]]]]

// You can use the output of this to create elements even faster with the 
// jModifier.dom.createElements() method

/* OUTPUT Explanation below */

// The way this works is that the jModifier Nested Array consists of two
// types of Arrays: "Tag Array" and "Child Array"

// The "Tag Array" holds 2 items: [tag, childArray]
// The "Child Array" holds infinite Tag Arrays: [ tagArray, tagArray, tagArray ]

// It starts with a Child Array
const nestedArray = [ // Start of Child Array
    [ // Start of Tag Array
        "Tag Array without children"
    ],
    [ // Start of Tag Array
        "Tag Array with children", [ // Start of Child Array
            [ // Start of Tag Array
                "Another tag array without children"
            ]
        ]
    ]
];

// Same example below as above (Might be easier to understand):
// [  [  "T1"  ], [  "T2", [  [  "C1"  ]  ]  ]  ]
// ^  ^           ^        ^  ^       
// ^  ^           ^        ^  Start of Tag Array 
// ^  ^           ^        ^
// ^  ^           ^        Start of Child Array
// ^  ^           ^        
// ^  ^           Start of Tag Array
// ^  ^           
// ^  Start of Tag Array
// ^
// Start of Child Array

// Disclaimer: "jModifier Nested Array" is just a name for convienient reference. I do not claim to be the first person to create this type of data structure.

View on JSFiddle



.string.splitFromXOutsideY

Splits from x but not if x is within y.

jModifier.string.splitFromXOutsideY(<String(Target)>*, <String(X)>*, <String(Y)>*, <Boolean(removeWhitespace)>)
// Similar to the native <String>.split() method
// however you can control where the split happens.
// (Specifically where the split does not happen)

// So for example if you wanted to split the below
// string by commas but not within the parentheses
const str = "ONE, TWO, THREE (1, 2, 3)";

// Your first argument would be your string, then the comma.
// Then for the third argument, you add the starting character
// and the ending character in the same string.
console.log(
    jModifier.string.splitFromXOutsideY(str, ",", "()")
); // output: ["ONE", " TWO", " THREE (1, 2, 3)"]

// If the fourth argument is true, the whitespace will be removed before returning
console.log(
    jModifier.string.splitFromXOutsideY(str, ",", "()", true)
); // output: ["ONE", "TWO", "THREE(1,2,3)"]

View on JSFiddle



.object.assign

Object assignment. Similar to the native mehod Object.assign().

jModifier.object.assign(<Object(Target)>*, <Object(Assignment)>*)

Utilizes: jModifier.object.NumStringBool, jModifier.array.listy

const myElement = jModifier.dom.query("#my-element");

// This method works similar to the native Object.assign() although
// it does not assign in "one hit", it assigns recursively.

jModifier.object.assign(myElement, {
    style: {
        background: "red"
    }
});

// In the above, jModifier gets the style property of myElement
// then recursively assigns to the property.


/* Example with plain Object */
const myObject = {
    one: 1,
    two: 2,
    three: {
        four: {
            five: 5
        }
    }
};

jModifier.object.assign(myObject, {
    one: 100,
    three: {
        four: {
            five: 500
        },
        addedKey: "hello, world"
    }
});

console.log(
    myObject
);

/* output: 
{
    "one": 100,
    "two": 2,
    "three": {
        "four": {
            "five": 500
        },
        "addedKey": "hello, world"
    }
}
 */

View on JSFiddle



.object.isType

Check target if target is of a certain types.

jModifier.object.isType(<Any(Target)>*, <Array(Types)>*)
// This method uses the constructor of the specified first
// argument against each specified item in the 2nd argument Array

console.log("Is Object, String, or function: ",
    jModifier.object.isType({}, [Object, String, Function])
); // output: true

console.log("Is String or Object: ",
    jModifier.object.isType([], [String, Object])
); // output: false

// If the specified item matches the type of any of the specified items in the Array, it will result in true.

View on JSFiddle



.object.pathValue

Target and return the value of an Object path.

jModifier.object.pathValue(<Object(Target)>*, <String(Path)>*)
// Pretty simple one
const myObject = {
    this: {
        is: {
            a: "Object!"
        }
    }
};

console.log("Returns path value: ",
    jModifier.object.pathValue(myObject, "this.is.a")
); // output: "Object!"

View on JSFiddle



.object.NumStringBool

Simply an Object that consists of {Number, String, Boolean}.

jModifier.object.NumStringBool


.array.assign

Assignment for Object(s) within Array(s) (Inherits .for options).

jModifier.array.assign(<Array(Target Array)>*, <Object(Assignment)>*, <Object(Options)>)

Utilizes: jModifier.dom.query, jModifier.for, jModifier.array.wrap, jModifier.object.assign

// .array.assign is basically .for & .object.assign combined.

// Works great with elements:
const listItems = jModifier.dom.query("#my-element ul li");
jModifier.array.assign(listItems, {
    innerText: "hello, world"
}, {
    delay: 1000
});

/* Property Assignment With $ Functions */
// If a function name within an array assignment is equal to "$"
// the function will evaluate and return with "originalValue, index, and item"
// (Make sure to return inside the $ functions)
jModifier.array.assign(listItems, {
    innerText: function $(originalValue, index, item) {
        return originalValue + " " + (index + 1)
    }
}, {
    delay: 2000,
    interval: 300
});

/* Property Assignment With Arrays */
// Instead of using $ functions, you can also use Arrays
// The each item in the Array will assign to the relative index
jModifier.array.assign(listItems, {
    innerText: ["one", "two", null, "four", "five", null]
        // use "null" to skip item assignment
        // (however the interval still counts the skipped time)
}, {
    delay: 3800,
    interval: 300
});

/* Property Assignment With Arrays + Duplication */
// With duplication, the property Array assigns the first item
// to each of the elements then 2nd Array item, 3rd, etc.. (to the dupe number)
jModifier.array.assign(listItems, {
    innerText: ["THREE", "TWO", "ONE", "HAPPY NEW YEAR!!"]
}, {
    delay: 5000,
    interval: 100,
    dupe: 4
});

/* Using loop option */
jModifier.array.assign(listItems, {
    style: {
        textIndent: ["32px", "0px", "64px", "0px"]
    }
}, {
    delay: 7000,
    interval: 30,
    dupe: 4,
    loop: Infinity
})

View on JSFiddle



.array.reverse

Returns given Array backwards.

jModifier.array.reverse(<Array(Target)>*)
const myArray = [1, 2, 3];
console.log(
    jModifier.array.reverse(myArray)
); // output: [3, 2, 1]

View on JSFiddle



.array.shuffle

Returns given Array shuffled.

jModifier.array.shuffle(<Array(Target)>*)
const myArray = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(
    jModifier.array.shuffle(myArray)
); // output: (view console on jsfiddle)

View on JSFiddle



.array.sum

Sums up given array to stop point and returns result.

jModifier.array.sum(<Array(Target)>*, <Number(Stop Point)>*)
const myArray = [1, 2, 3];

console.log("Without stop point: ",
    jModifier.array.sum(myArray)
); // output: 6

console.log("With stop point: ",
    jModifier.array.sum(myArray, 2)
); // output: 3

View on JSFiddle



.array.fill

Fills and returns given Array with specified content.

jModifier.array.fill(<Array(Target)>*, <Any(Content)>*)
// If no content is specified (2nd argument), it will return with
// each item as a number starting from 0
console.log(
    jModifier.array.fill(new Array(5))
); // output: [0, 1, 2, 3, 4]

// With content:
console.log(
    jModifier.array.fill(new Array(3), "foo")
); // output: ["foo", "foo", "foo"]

// Keep in mind, the above does not assign, only returns!

View on JSFiddle



.array.wrap

Wraps given argument in Array if not Array already.

jModifier.array.wrap(<Any(Target)>*)

Utilizes: jModifier.array.listy

// .array.wrap is useful for when you don't know whether
// an incoming variable is an Array or not

const notArray = "foo";
const isArray = ["bar"];

console.log(
    jModifier.array.wrap(notArray)
); // output: ["foo"]

console.log(
    jModifier.array.wrap(isArray)
); // output: ["bar"]

// (Always returns as array)

View on JSFiddle



.array.getIndex

Gets index of item within given Array.

jModifier.array.getIndex(<Array(Target)>*, <Any(Item)>*)
// Useful for getting the index of an element within an Array
const listItems = jModifier.dom.query("#my-element ul li");
const listItem = jModifier.dom.query("#my-element ul:nth-child(1) li:nth-child(3)");

console.log(
    jModifier.array.getIndex(listItems, listItem) // (3rd item)
); // output: 2

View on JSFiddle



.array.listy

Simply an Object that consists of list style type Objects. Add your custom Array to this Object for other jModifier method compatibility.

jModifier.listy


.function.argumentEvaluator

Create a table of functions that get evaluated when executed depending on the manipulation function

jModifier.function.argumentEvaluator(<Object(Table)>*, <Function(Manipulation)>)
// The argumentEvaluator method is a great way
// to avoid using multiple if else statements
const evaluator = jModifier.function.argumentEvaluator({
    "1:2:3": function() { // make sure to add the colon to seperate arguments
        return "123!";
    },
    "4:5:6": function() {
        return "456!";
    }
});

console.log(
    evaluator(1, 2, 3)
); // output: "123!"

console.log(
    evaluator(4, 5, 6)
); // output: "456!"

/* Example with argument manipulation */
const evaluatorWAM = jModifier.function.argumentEvaluator({
    "Number:String:Number": function() {
        return "Number String Number!";
    },
    "Object:Object:Object": function() {
        return "3x Object!";
    }
}, function(value) {
    // The below returns the constructor name which if 
    // matches a function in the above table,
    // it will execute said function
    return value.constructor.name
});

console.log(
    evaluatorWAM(1, "o", 1)
); // output: "Number String Number!"

console.log(
    evaluatorWAM({}, {}, {})
) // output: "3x Object!"

View on JSFiddle



.function.getArguments

Returns arguments of given Function

jModifier.function.getArguments(<Function(Target)>)
function foo(one, two, three) {}

console.log(
    jModifier.function.getArguments(foo)
); // output: ["one", "two", "three"]

View on JSFiddle



var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
// jModifier [Mon May 28 2018 03:14:45 GMT+0800 (W. Australia Standard Time)] - Written by Jeremy J Parmenter a.k.a. @JeremyJaydan
const jModifier = function () {
function domClassList(target, classNames, opts, targetProp){
if(this != jMethods.dom){
opts = classNames;
classNames = target;
target = this;
}
let elements = jMethods.dom.query(target);
classNames.split(" ").forEach(function(className){
elements.forEach(function(element){
element.classList[targetProp](className);
}, opts);
});
}
var jMethods = {
"for": function _for(arr, cb, opts) {
if (this != jMethods) {
opts = cb;
cb = arr;
arr = this;
}
if (arr) {
if (arr.constructor === Number) arr = jMethods.array.fill(new Array(arr));
if (typeof cb === "function") {
opts = opts || {};
arr = opts.reverse ? arr.reverse() : opts.shuffle ? jMethods.array.shuffle(arr) : arr;
if (opts.dupe && !opts.dupeInit) {
var dArr = [],
rep = opts.dupe;
for (var i = 0; i < rep; i++) {
for (var a = 0; a < arr.length; a++) {
dArr.push(arr[a]);
}
}
arr = dArr;
}
var init = function init() {
for (var _i = 0; _i < arr.length; _i++) {
if (opts.interval) {
var timeout = _i === 0 ? 0 : opts.interval.constructor === Array ? jMethods.array.sum(opts.interval, _i) : opts.interval * _i;
setTimeout(cb, timeout, arr[_i], _i);
} else {
cb(arr[_i], _i);
}
}
};
opts.delay ? setTimeout(init, opts.delay) : init();
setTimeout(function () {
if (opts.done && opts.done.constructor === Function) opts.delay ? setTimeout(opts.done, opts.delay) : opts.done();
if (opts.loop) {
opts.loop--;
opts.dupeInit = true;
jMethods.for(arr, cb, opts);
}
}, opts.interval ? opts.interval.constructor === Array ? jMethods.array.sum(opts.interval) : opts.interval * arr.length : 0);
}
}
},
"dom": {
query: function query(primary, reference, Constructor) {
if (this != jMethods.dom) {
reference = primary;
primary = this;
}
let isList = primary.isList || primary.constructor === Array || primary.constructor === NodeList;
var _parent = isList ? primary : jMethods.dom.querySelectorAll(document, primary, Constructor);
if (reference) {
if (reference.constructor === String) {
var elements = [];
jMethods.array.wrap(reference).forEach(function (ref) {
_parent.forEach(function (item) {
return item.querySelectorAll(ref).forEach(function (element) {
return elements.push(element);
});
});
});
return new jMethods.dom.ElementCollection(elements);
} else if (reference.constructor === Object) {
var elementReference = {};
jMethods.object.forEachProperty(reference, function (key, val, path) {
if (val && val.constructor != Object) jMethods.object.pathSet(elementReference, path.join("."), jMethods.dom.query(_parent, val));
});
_parent.set(elementReference);
}
}
return _parent;
},
querySelectorAll: function querySelectorAll(_parent, primary, Constructor) {
var elements = [];
Constructor = Constructor || jModifier.dom.ElementCollection;
primary = jMethods.array.wrap(primary);
primary.forEach(function (target) {
var result = jMethods.array.wrap(target && (typeof target === "undefined" ? "undefined" : _typeof(target)) === "object" ? target : _parent.querySelectorAll(target));
for (var i = 0; i < result.length; i++) {
elements.push(result[i]);
}
});
return new Constructor(elements, null, true);
},
on: function on(arg1, arg2, arg3, arg4, arg5) {
if (this != jMethods.dom) {
arg5 = arg4;
arg4 = arg3;
arg3 = arg2;
arg2 = arg1;
arg1 = this;
}
var elements = jModifier.dom.query(arg1);
var events = arg2;
var args = arg4;
var ucap = arg5;
var apply = function apply(eventStr, cb) {
eventStr.replace(/ /g, "").split(",").forEach(function (evt) {
elements.forEach(function (element, index) {
var callback = function callback(event) {
var obj = { node: element, index: index, collection: elements, event };
if(args){
var argKeys = Object.keys(args);
argKeys.forEach(function(key){
obj[key] = args[key];
});
}
return cb.call(elements.component && elements.component.top ? elements.component.top : this, obj);
};
element.addEventListener(evt, callback, ucap);
});
});
};
jMethods.array.wrap(events).forEach(function (event) {
event.constructor === String ? apply(event, arg3) : jMethods.object.forEachProperty(event, function (evtStr, cb) {
return apply(evtStr, cb);
});
});
},
addClass: function(target, classNames, opts){
domClassList.call(this, target, classNames, opts, "add");
return this;
},
removeClass: function(target, classNames, opts){
domClassList.call(this, target, classNames, opts, "remove");
return this;
},
create: function create(str, reference) {
if (str) {
var target = void 0;
if (this != jMethods.dom) target = this;
var nestedArray = str.constructor === String ? jMethods.string.toNestedArray(str) : str;
return jMethods.dom.createElements(nestedArray, reference, null, target);
}
},
createElement: function createElement(tagName, amt) {
var elements = [];
for (var i = 0, amount = amt || 1; i < amount; i++) {
elements.push(document.createElement(tagName));
}return elements;
},
createElements: function createElements(nestedArray, reference, collectionRec, target) {
var collection = target || new jMethods.dom.ElementCollection();
nestedArray.forEach(function (item) {
var key = jMethods.string.getDelimiters(item[0], ".#*+");
var tag = key.tag;
var dels = key.dels;
var amount = dels['*'];
var id = dels["#"];
var classes = dels["."];
var attributes = dels["+"];
var children = item[1];
var elements = jMethods.dom.createElement(tag, amount ? amount[0] : 1);
elements.forEach(function (element) {
collection.push(element);
if (classes) classes.forEach(function (className) {
return element.classList.add(className);
});
if (id) element.id = id[0];
if (attributes) {
attributes.forEach(function (attr) {
var aSplit = attr.split("=");
var aKey = aSplit[0];
var aVal = aSplit[1] || "";
element.setAttribute(aKey, aVal);
});
}
if (children) jMethods.dom.createElements(children, reference, collection).forEach(function (childElement) {
return element.appendChild(childElement);
});
});
});
if (!collectionRec && reference) collection.query(reference);
return collection;
},
insertInto: function insertInto(target, e, position) {
if (this != jMethods.dom) {
position = e;
e = this;
}
e = e.constructor === Function && e.name === "handler" ? e[0] : e;
target = target.constructor === Function && target.name === "handler" ? target.$ : target;
var elements = jMethods.array.wrap(e);
target = jMethods.dom.query(target, null, true)[0];
position = target.children[position] || null;
for (var i = 0, length = elements.length; i < length; i++) {
target.insertBefore(elements[i], position);
}return elements;
},
replaceChildren: function replaceChildren(target, replacement) {
if (this != jMethods.dom) {
replacement = target;
target = this;
}
Array.from(target[0].children).forEach(child => target[0].removeChild(child));
jMethods.dom.insertInto(target, replacement);
},
component: function(comp, prototypes){
prototypes = prototypes || {};
prototypes.component = {parent: null};
let Component = jMethods.class.extend(
jMethods.dom.Component,
function Component(i, r, isc){
isc ? jMethods.dom.Component.call(this, i, r) : comp.apply(this, arguments);
this.component.top = this;
}, prototypes
);
return Component;
},
components: function(compsObj){
jMethods.object.forEachProperty(compsObj, function(key, val){
return jMethods.dom.component(val);
});
return compsObj;
}
},
"string": {
toNestedArray: function toNestedArray(str) {
str = str.constructor === RegExp ? str.source : str;
str = str.replace(/\s/g, "");
var seperate = function seperate(node) {
var nl = node.length,
io = node.indexOf("["),
tag = io >= 0 ? node.substring(0, io) : node,
children = void 0;
if (io >= 0) children = node.substring(io + 1, nl - 1);
return children ? [tag, children] : [tag];
},
recursive = function recursive(str) {
var ns = jMethods.string.splitFromXOutsideY(str, ",", "[]", true),
nodes = [];
for (var i = 0, nsl = ns.length; i < nsl; i++) {
var sep = seperate(ns[i]),
children = sep[1];
if (children) {
sep[1] = recursive(children);
}
nodes.push(sep);
}
return nodes;
};
return recursive(str);
},
splitFromXOutsideY: function splitFromXOutsideY(str, X, Y, removeWhitespace) {
if (removeWhitespace) str = str.replace(/\s/g, "");
var commas = [],
nestPos = 0,
split = [];
for (var i = 0, sLength = str.length; i < sLength; i++) {
nestPos += str[i] === Y[0] ? 1 : str[i] === Y[1] ? -1 : 0;
if (str[i] === X && nestPos === 0) commas.push(i);
}
var cLength = commas.length ? commas.length + 1 : 1;
for (var _i2 = 0; _i2 < cLength; _i2++) {
var pos = commas[_i2],
last = commas[_i2 - 1] || 0;
split.push(str.substring(last === 0 ? last : last + 1, pos));
}
return split;
},
getDelimiters: function getDelimiters(str, delimiterString) {
var dels = {};
var delimiters = delimiterString.split("").map(function (del, index) {
return "\\" + del + (index < delimiterString.length - 1 ? "|" : "");
});
var regex = new RegExp("(?=" + delimiters.join("") + ")", "g");
var split = str.split(regex);
var tag = split[0];
split.shift();
split.forEach(function (del) {
var delimiter = del[0];
if (!dels[delimiter]) dels[delimiter] = [];
var target = dels[delimiter];
target.push(del.substring(1, del.length));
});
return { tag: tag, dels: dels };
}
},
"object": {
assign: function assign(obj, assignment, index, top, dupeIndex, arrayLength) {
if (this != jMethods.object) {
assignment = obj;
obj = this;
}
if (!top) top = obj;
var keys = Object.keys(assignment);
for (var i = 0, length = keys.length; i < length; i++) {
var key = keys[i],
val = assignment[key],
cCon = val ? val.constructor : val,
constName = cCon ? cCon.name : cCon,
indx = !isNaN(index);
if (jMethods.object.NumStringBool[constName] || val === null || val === undefined) {
if (val !== undefined) obj[key] = val;
} else {
if (indx && jMethods.array.listy[constName]) {
index = dupeIndex !== undefined ? dupeIndex : index;
if (val[index]) obj[key] = val[index];
} else if (indx && cCon === Function && val.name === "$") {
if (dupeIndex) index = index - dupeIndex * arrayLength;
var returned = val(obj[key], index, top);
if (returned || !isNaN(returned)) obj[key] = returned;
} else if (cCon === Object) {
if (!obj[key]) obj[key] = {};
jMethods.object.assign(obj[key], val, index, top, dupeIndex, arrayLength);
} else {
obj[key] = val;
}
}
}
return obj;
},
isType: function isType(trgt, type) {
for (var s = 0, length = type.length; s < length; s++) {
if (trgt.constructor.name === type[s]) return true;
}return false;
},
pathValue: function pathValue(target, path) {
if (this != jMethods.object) {
path = target;
target = this;
}
path = path.constructor === Array ? path : path.split(".");
var current = void 0;
for (var i = 0; i < path.length; i++) {
current = current ? current[path[i]] : target[path[i]];
if (current === undefined) return null;
}
return current;
},
pathSet: function pathSet(target, path, value) {
if (path) {
path = jMethods.array.wrap(path.split("."));
var prop = path[path.length - 1];
path.pop();
if (path.length > 0) {
for (var i = 0; i < path.length; i++) {
var current = path.slice(0, i + 1);
var currentKey = current[current.length - 1];
var node = current.join(".");
var pathValue = jMethods.object.pathValue(target, node);
var _parent = jMethods.object.pathValue(target, path.slice(0, i)) || target;
if (!pathValue) {
if (_parent) _parent[currentKey] = {};
}
if (i === path.length - 1) {
_parent[currentKey][prop] = value;
}
}
} else {
target[prop] = value;
}
}
},
NumStringBool: { Number: Number, String: String, Boolean: Boolean },
findPathIndex: function findPathIndex(target, path) {
if (path) {
var split = path.split(".");
for (var i = split.length - 1; i > -1; i--) {
if (jModifier.object.pathValue(target, split) != undefined) return i;
split.pop();
}
}
},
forEachProperty: function forEachProperty(obj, cb) {
var path = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var top = arguments[3];
if (!top) top = obj;
var keys = Object.keys(obj);
keys.forEach(function (key) {
var val = obj[key];
path.push(key);
var callback = cb(key, obj[key], path);
if (callback) obj[key] = callback;
var pathIndex = jMethods.object.findPathIndex(top, path.join("."));
if (val.constructor === Object) jMethods.object.forEachProperty(obj[key], cb, path, top);
path.splice(pathIndex, path.length + 1);
});
}
},
"class": {
create: function create() {
var target = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () {};
var prototypes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
Object.assign(target.prototype, prototypes);
return target;
},
extend: function extend(target, extension) {
var prototypes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
Object.assign(extension.prototype, target.prototype);
Object.assign(extension.prototype, prototypes);
return extension;
}
},
"array": {
assign: function assign(array, assignment, opts) {
if (this != jMethods.array) {
opts = assignment;
assignment = array;
array = this;
}
array = array.constructor === String ? jMethods.dom.query(array, null, true) : array;
jMethods.for(jMethods.array.wrap(array), function (item, index) {
jMethods.object.assign(item, assignment, index, null, opts && opts.dupe ? Math.floor(index / array.length) : undefined, array.length);
}, opts);
return array;
},
shuffle: function shuffle(arr) {
arr = this === jMethods.array ? arr : this;
var a = [];
arr.forEach(function (item) {
return a.push(item);
});
var length = a.length,
shuffled = new arr.constructor();
for (var i = 0; i < length; i++) {
var rand = Math.floor(Math.random() * a.length);
shuffled.push(a[rand]);
a.splice(a.indexOf(a[rand]), 1);
}
return shuffled;
},
sum: function sum(arr, stopPoint) {
var a = arr.slice(0, stopPoint || arr.length);
return a.reduce(function (a, b) {
return a + b;
});
},
fill: function fill(arr, content) {
return arr.fill(undefined).map(function (a, b) {
return content || b;
});
},
wrap: function wrap(trgt) {
if(trgt) return typeof trgt === "string" ? [trgt] : trgt.length ? trgt : [trgt];
// if (trgt) return jMethods.array.listy[trgt.constructor.name] ? trgt : new Array(typeof trgt === "number" ? trgt.toString() : trgt);
},
getIndex: function getIndex(arr, trgt) {
var length = arr.length;
for (var i = 0; i < length; i++) {
if (arr[i] === trgt) return i;
}
},
listy: {
Array: Array,
Int8Array: Int8Array,
Uint8ClampedArray: Uint8ClampedArray,
Int16Array: Int16Array,
Uint16Array: Uint16Array,
Int32Array: Int32Array,
Uint32Array: Uint32Array,
Float32Array: Float32Array,
Float64Array: Float64Array,
NodeList: NodeList
}
},
"function": {
argumentEvaluator: function argumentEvaluator(table, func) {
return function argumentEvaluator() {
var length = arguments.length,
result = [];
for (var i = 0; i < length; i++) {
var arg = arguments[i];
var argReturn = func ? func(arg) : arg;
if (argReturn && argReturn != "undefined") result.push(argReturn);
}
var endResult = result.join(":");
var target = table[endResult] || table.else;
if (table.log_output) console.info("Argument Evaluator Result: ", endResult);
if (target) return target.apply(null, arguments);
};
},
getArguments: function getArguments(func) {
var funcStr = JSON.stringify("" + func);
var open = funcStr.indexOf("(");
var close = funcStr.indexOf(")");
var refined = funcStr.substring(open + 1, close).replace(/\s/g, "").split(",");
return refined;
},
Validator: function(validations){
return function(validationChecks){
return new Promise(function(resolve, reject){
jMethods.object.forEachProperty(validations, function(key, validate){
let validationCheckProp = validationChecks[key];
if(validationCheckProp){
jMethods.array.wrap(validationCheckProp).forEach(function(validationCheck){
let check = validate(validationCheck);
if(check.invalid) reject(check);
});
}
});
resolve();
});
};
}
}
};
/* Collection */
jMethods.Collection = jMethods.class.create(function Collection(items, reference) {
var _this = this;
items = jMethods.array.wrap(items) || [];
items.forEach(function (item, index) {
return _this[index] = item;
});
if (reference && reference.constructor === Object) this.set(reference);
Object.defineProperty(this, "length", { value: items.length, writable: true });
}, {
get: jMethods.object.pathValue,
set: function set(path, val) {
var _this2 = this;
if (path && path.constructor === Object) {
var reference = path;
var refKeys = Object.keys(reference);
refKeys.forEach(function (key) {
var item = reference[key];
if (item) {
val = item;
var subReference = {};
if (item.constructor === Object) {
val = item.self;
subReference = item;
delete subReference.self;
}
_this2[key] = new _this2.constructor(val, subReference, true);
}
});
} else {
var collection = val.constructor === this.constructor ? val : new this.constructor(val);
return this;
}
},
toArray: function toArray() {
var arr = [];
this.forEach(function (item) {
return arr.push(item);
});
return arr;
},
isList: true,
self: function(obj){
jMethods.object.assign(this, obj);
},
forEach: jMethods.for,
assign: jMethods.array.assign,
shuffle: jMethods.array.shuffle,
push: Array.prototype.push,
reverse: Array.prototype.reverse,
splice: Array.prototype.splice,
pop: Array.prototype.pop,
shift: Array.prototype.shift,
unshift: Array.prototype.unshift
});
/* Element Collection */
jMethods.dom.ElementCollection = jMethods.class.extend(jMethods.Collection, function ElementCollection(items, reference) {
jMethods.Collection.call(this, items, reference);
}, {
query: jMethods.dom.query,
querySelectorAll: jMethods.dom.querySelectorAll,
insertInto: jMethods.dom.insertInto,
on: jMethods.dom.on,
addClass: jMethods.dom.addClass,
removeClass: jMethods.dom.removeClass
});
/* Listy types */
Object.assign(jMethods.array.listy, {
Collection: true,
ElementCollection: true,
ComponentCollection: true
});
/* DOM Component */
jMethods.dom.Component = jMethods.class.extend(jMethods.dom.ElementCollection, function Component(items, reference){
jMethods.Collection.call(this, items, reference);
}, {
use: function(a, b){
let collection = jMethods.dom.query(a, b, this.constructor);
let self = this;
collection.forEach(function(element){
self.push(element);
});
Object.assign(this, collection);
},
create: jMethods.dom.create
});
return jMethods;
}();
module.exports = jModifier;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment