/*
Software License Agreement (BSD License)
http://taffydb.com
Copyright (c) 2008
All rights reserved.
Version 1.6
Redistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following condition is met:
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
SUMMARY:
TAFFY takes a JavaScript object and returns a set of methods
to search, modify, and manipulate that object.
*/
// Setup TAFFY Function (nameSpace) to return an object with methods.
if (typeof TAFFY=="undefined"||!TAFFY) {
var TAFFY = function (obj) {
var conf = {
template:null
}, T = TAFFY, raw = (T.isString(obj)) ? T.JSON.parse(obj) : obj, TOb = raw, TIA = [], t = true, f=false;
// ****************************************
// *
// * Create prvate mergeTemp function
// * Loop over set of indexes and apply a template to the record
// *
// ****************************************
var mergeTemp = function (rows,tmpl) {
var tmpl = (TAFFY.isUndefined(tmpl)) ? conf.template : tmpl;
if (!TAFFY.isNull(tmpl))
{
for(var x = 0; x < rows.length; x++) {
TOb[rows[x]] = TAFFY.mergeObj(TOb[rows[x]],tmpl);
}
}
}
// ****************************************
// *
// * Create prvate bTIA function
// * Loop over every index within the Taffy Object TOb
// * and populate the Taffy Index Array TIA with the indexes
// *
// ****************************************
var bTIA = function () {
TIA = [];
for(var x = 0; x < TOb.length; x++) {
TIA[TIA.length] = x;
}
}
bTIA();
// ****************************************
// *
// * Create prvate findTests Object
// * Collect all possible true/false expression used when
// * doing lookups via the public find method.
// * Purpose: Used to house and document all of the
// * possible ways to match a value to a field with the
// * TAFFY Object. Each of the contained functions does an
// * evaluation against a value from the TAFFY Obj and a test
// * provided by the caller of the find method. If this
// * evaluation is true then the find method will add
// * the TAFFY Object record to the results set.
// *
// ****************************************
var findTests = {
pickTest:function(Tt)
{
var m = (Tt.indexOf("!") === 0) ? f : t;
if (!m)
{
Tt = Tt.substring(1,Tt.length);
}
return {test:(Tt == 'equal') ? 'is' :
(Tt == 'notequal') ? 'not' :
(Tt == 'startswith') ? 'starts' :
(Tt == 'endswith') ? 'ends' :
(Tt == 'greaterthan') ? 'gt' :
(Tt == 'lessthan') ? 'lt' :
(Tt == 'regexppass') ? 'regex' : Tt,mode:(m) ? {s:t,f:f} : {s:f,f:t}};
},
run:function(s,mvalue,mtest,b) {
return ((s=="regex") ? (mtest.test(mvalue)) :
(s=="lt") ? (mvalue < mtest) :
(s=="gt") ? (mvalue > mtest) :
(s=="starts") ? (mvalue.indexOf(mtest) === 0) :
(s=="ends") ? (mvalue.substring((mvalue.length - mtest.length)) == mtest) :
(s=="like") ? (mvalue.indexOf(mtest) >= 0) :
(s=="is") ? (mvalue == mtest) :
(s=="has") ? (T.has(mvalue,mtest)) :
(s=="hasAll") ? (T.hasAll(mvalue,mtest)) :
(s=="length") ? (findTests.length(mvalue,mtest,b)) :
findTests[s](mvalue,mtest)) ? b.s : b.f;
},
length:function (mvalue,mtest,b)
{
// If a value length exits and meets filter criteria
var rlen = (!T.isUndefined(mvalue.length)) ? mvalue.length : (!T.isUndefined(mvalue.getLength)) ? mvalue.getLength() : 0;
if (T.isObject(mtest)) {
for(var kt in mtest)
{
if (mtest.hasOwnProperty(kt))
{
var pt = findTests.pickTest(kt);
return findTests.run(pt.test,rlen,mtest[kt],pt.mode) ? t : f;
}
}
}
// default return
return rlen == mtest ? b.s : b.f;
}
};
// Add in isObjectType checks
(function () {
for(var z in TAFFY)
{
if (TAFFY.hasOwnProperty(z) && z.indexOf("is") === 0)
{
(function (y) {
findTests["is" + y] = function (mvalue,mtest,b) {
return (TAFFY["is" + y](mvalue) == mtest) ? t : f;
}
}(z.substring(2,z.length)))
}
}
} ());
// ****************************************
// *
// * Create prvate bDexArray method
// * Return an array of indexes
// * Purpose: Used to create a variable that is an
// * array that contains the indexes of the records
// * that an action should be taken on. If a single
// * number is passed then an array is created with that
// * number being in postion 0. If an array is passed
// * in then that array is returned. If no value is
// * passed in then an array containing every index
// * in the TAFFY Obj is returned. If an object is passed
// * then a call to the find function is made and the
// * resulting array of indexes returned.
// *
// ****************************************
var bDexArray = function (iA,f) {
var rA = [];
if (!T.isArray(iA) && TAFFY.isNumber(iA))
{
rA[rA.length] = iA;
}
else if (T.isArray(iA))
{
rA = iA;
}
else if (T.isObject(iA))
{
rA = f(iA);
}
else if (!T.isArray(iA) && !T.isNumber(iA))
{
rA = TIA;
}
return rA;
};
// ****************************************
// *
// * Create private toLogicalArray method
// * return custom array for use in array.sort based on sort obj
// * argument
// * Purpose: This is used by the buildSortFunction function in the case
// * of logical and logicaldesc sort types. This function splits a complex
// * value into an array so that each array item can be compared against
// * the item at the index in each value.
// *
// ****************************************
var toLogicalArray = function (value) {
var rArray = [0],type = "none";
if (!T.isNull(value) && !T.isUndefined(value)) {
for(var n = 0;n<value.length;n++)
{
var c = value.slice(n,(n+1));
if (T.isNumeric(c)) {
if (type != 'number') {
rArray[rArray.length] = c;
type = 'number';
} else {
rArray[(rArray.length-1)] = rArray[(rArray.length-1)] + "" + c;
}
} else {
if (type != 'string') {
rArray[rArray.length] = c;
type = 'string';
} else {
rArray[(rArray.length-1)] = rArray[(rArray.length-1)] + c;
}
}
}
for(var n = 0;n<rArray.length;n++)
{
if (T.isNumeric(rArray[n])) {
rArray[n] = parseFloat(rArray[n]);
}
}
} else {
rArray[rArray.length] = null;
}
return rArray;
};
// ****************************************
// *
// * Create private buildSortFunction method
// * return custom sort function for use in array.sort based on sort obj
// * argument
// * Purpose: This is used by the orderBy method to create a custom sort
// * function for use with array.sort(). This sort function will be unique
// * based on the field list supplied in the sortobj argument.
// *
// ****************************************
var buildSortFunction = function (sortobj) {
var custO = [],localO = [];
if (T.isString(sortobj))
{
localO[0] = sortobj;
} else if (T.isObject(sortobj)) {
localO = [sortobj];
} else {
localO = sortobj;
}
// create the custO which contains instructions
// for the returned sort function
if (T.isArray(localO)) {
for(var sa = 0; sa < localO.length; sa++) {
if (T.isString(localO[sa]))
{
if (T.isString(TOb[0][localO[sa]]))
{
custO[custO.length] = {sortCol : localO[sa], sortDir : "asc", type : "string"};
} else {
custO[custO.length] = {sortCol : localO[sa], sortDir : "asc", type : "number"};
}
} else if (T.isObject(localO[sa])) {
for(var sc in localO[sa])
{
if (localO[sa].hasOwnProperty(sc))
{
if (T.isString(TOb[0][localO[sa].sortCol]))
{
custO[custO.length] = {sortCol : sc, sortDir : localO[sa][sc], type : "string"};
} else {
custO[custO.length] = {sortCol : sc, sortDir : localO[sa][sc], type : "number"};
}
}
}
}
}
};
// Return the sort function to the calling object.
return function (a,b) {
var returnvar = 0,r1=a,r2=b,x,y;
// loop over the custO and test each sort
// instruction set against records x and y to see which
// should appear first in the final array sort
for(var sa = 0; sa < custO.length; sa++) {
if (returnvar === 0) {
x = r1[custO[sa]["sortCol"]];
y = r2[custO[sa]["sortCol"]];
if (custO[sa].type == 'string'){
x = (T.isString(x)) ? x.toLowerCase() : x;
y = (T.isString(y)) ? y.toLowerCase() : y;
}
if (custO[sa].sortDir == 'desc')
{
if (T.isNull(y) || T.isUndefined(y) || y < x) {
returnvar = -1;
} else if (T.isNull(x) || T.isUndefined(x) || x < y){
returnvar = 1;
}
} else if (custO[sa].sortDir == 'logical') {
x = toLogicalArray(x);
y = toLogicalArray(y);
for(var z = 0;z<y.length;z++)
{
if (x[z] < y[z] && z < x.length) {
returnvar = -1;
break;
} else if (x[z] > y[z]){
returnvar = 1;
break;
}
}
if (x.length < y.length && returnvar==0)
{
returnvar = -1;
} else if (x.length > y.length && returnvar==0) {
returnvar = 1;
}
} else if (custO[sa].sortDir == 'logicaldesc') {
x = toLogicalArray(x);
y = toLogicalArray(y);
for(var z = 0;z<y.length;z++)
{
if (x[z] > y[z] && z < x.length) {
returnvar = -1;
break;
} else if (x[z] < y[z]){
returnvar = 1;
break;
}
}
if (x.length < y.length && returnvar==0)
{
returnvar = 1;
} else if (x.length > y.length && returnvar==0) {
returnvar = -1;
}
} else {
if (T.isNull(x) || T.isUndefined(x) || x < y) {
returnvar = -1;
} else if (T.isNull(y) || T.isUndefined(y) || x > y){
returnvar = 1;
}
}
}
};
return returnvar;
};
};
// ****************************************
// *
// * Return Obj containing Methods
// *
// ****************************************
return {
// ****************************************
// *
// * This is a simple true flag to identify
// * the returned collection as being created by
// * TAFFY()
// *
// ****************************************
TAFFY:true,
// ****************************************
// *
// * Get the length of the TAFFY collection.
// *
// ****************************************
getLength:function () {
return TOb.length;
},
// ****************************************
// *
// * This is the date of the last change
// * to the TAFFY object.
// *
// ****************************************
lastModifyDate:new Date(),
// ****************************************
// *
// * Create public find method
// * Returns array of index numbers for matching array values
// * Purpose: This takes an obj that defines a set of match
// * cases for use against the TOb. Matching indexes are
// * added to an array and then returned to the user. This is the
// * primary "lookup" feature of TAFFY and is how you find individual
// * or sets of records for use in update, remove, get, etc.
// *
// ****************************************
find : function (matchObj,findFilter) {
// define findMatches array and findMatchesLoaded flag
var findIndex = 0;
// if findFilter is provided use findFilter to start findMatches array
// otherwise use TIA which contains all indexes of the TOb
if (T.isArray(findFilter)) {
var findMatches = findFilter;
} else {
var findMatches = TIA;
}
// if matchObject is a function run it against every item in findMatches
if (T.isFunction(matchObj))
{
var thisMatchArray = [];
// loop over every element in the findMatches
for(var d = 0; d < findMatches.length; d++) {
// add to matched item list if function returns true
if (matchObj(TOb[d],d)) {
thisMatchArray[thisMatchArray.length] = findMatches[d];
}
}
findMatches = thisMatchArray;
}
else {
// loop over attributes in matchObj
for (var mi in matchObj){
// default matchType, matchValue, matchField
var matchType = 'is',matchValue = '',matchField = mi,matchMode = {s:t,f:f},pt = {};
// If the matchObj attribute is an object
if (T.isObject(matchObj[mi]))
{
// loop over match field attributes
for (var fi in matchObj[mi]){
// switch over attributes, extract data
pt = findTests.pickTest(fi);
matchType = pt.test;
matchMode = pt.mode;
matchValue = matchObj[mi][fi];
}
}
// If the matchObj attribute is not an object
else
{
// set the match value to the value provided
matchValue = matchObj[mi];
}
//define thisMatchArray for this find method
var thisMatchArray = [];
// loop over every element in the findMatches
for(var d = 0; d < findMatches.length; d++) {
// if the value is an array of values, loop rather than do 1 to 1
if (T.isArray(matchValue) && matchType != 'isSameArray' && matchType != 'hasAll')
{
// call the correct filter based on matchType and add the record if the filter returns true
for(var md = 0; md < matchValue.length; md++) {
if (findTests.run(matchType,TOb[findMatches[d]][matchField],matchValue[md],matchMode)) {
thisMatchArray[thisMatchArray.length] = findMatches[d];
}
}
}
// if the value is a function call function and append index if it returns true
else if (T.isFunction(matchValue) && matchValue(TOb[findMatches[d]][matchField],d)) {
thisMatchArray[thisMatchArray.length] = findMatches[d];
}
// if the value is not an array but a single value
// If an exact match is found then add it to the array
else if (findTests.run(matchType,TOb[findMatches[d]][matchField],matchValue,matchMode))
{
thisMatchArray[thisMatchArray.length] = findMatches[d];
}
}
findMatches = thisMatchArray;
};
}
// Garther only unique finds
findMatches = T.gatherUniques(findMatches);
return findMatches;
},
// ****************************************
// *
// * Create public remove method
// * Purpose: This is used to remove a record from
// * the TOb by an index or an array of indexes.
// *
// ****************************************
remove : function (dex) {
var removeIndex = bDexArray(dex,this.find);
// loop over removeIndex and set each record to remove
// this is done so all records are flagged for remove
// before the size of the array changes do to the splice
// function below
for(var di = 0; di < removeIndex.length; di++) {
if (this.onRemove != null)
{
this.onRemove(TOb[removeIndex[di]]);
}
TOb[removeIndex[di]] = 'remove';
}
// nested function find delete
var removeRemaining = function () {
for(var tdi = 0; tdi < TOb.length; tdi++) {
if (TOb[tdi] === 'remove') {
return t;
}
}
return f;
};
// loop over TOb and remove all rows set to remove
while (removeRemaining()) {
for(var tdi = 0; tdi < TOb.length; tdi++) {
if (TOb[tdi] === 'remove') {
TOb.splice(tdi,1);
// update lastModifyDate
this.lastModifyDate = new Date();
}
}
}
// populate TIA
bTIA();
return removeIndex;
} ,
// ****************************************
// *
// * Create public insert method
// * Purpose: this takes an obj and inserts it into
// * the TAFFY Obj array
// *
// ****************************************
insert : function (newRecordObj) {
if (this.onInsert != null)
{
this.onInsert(newRecordObj);
}
// Do insert
TOb[TOb.length] = (TAFFY.isNull(conf.template)) ? newRecordObj : TAFFY.mergeObj(conf.template,newRecordObj);;
// update lastModifyDate
this.lastModifyDate = new Date();
// populate TIA
TIA[TIA.length] = TOb.length-1;
return [TOb.length-1];
} ,
// ****************************************
// *
// * Create public update method
// * Purpose: This takes an obj of name/value
// * pairs and then a set of 1 or more indexes
// * and updates those records with in the TOb
// *
// ****************************************
update : function (updateObj,dex) {
var updateIndex = bDexArray(dex,this.find), updateCount=0;
for(var d = 0; d < updateIndex.length; d++) {
// set the updatedex
var updateDex = updateIndex[d];
if (this.onUpdate != null)
{
this.onUpdate(updateObj,TOb[updateDex]);
}
// Merge Objects
TOb[updateDex] = T.mergeObj(TOb[updateDex],updateObj);
// add the updaecount
updateCount++;
}
return updateIndex;
} ,
// ****************************************
// *
// * Create public get method
// * Purpose: This return an array containing
// * the rows for a set of indexes. Used to get
// * a record set with the help of the find
// * function. Returns an empty array if
// * no records are found.
// *
// ****************************************
get : function (dex) {
var nT = [];
var getIndex = bDexArray(dex,this.find);
// loop over all of the indexes
for(var d = 0; d < getIndex.length; d++) {
// add the TOb to the newTAFFYArray array
nT[nT.length] = TOb[getIndex[d]];
}
return nT;
},
// ****************************************
// *
// * Create public first method
// * Purpose: This returns the first row
// * from a set of indexes. Used to get
// * a record with the help of the find
// * function. Returns false if no records
// * are found.
// *
// ****************************************
first : function (dex) {
var getIndex = bDexArray(dex,this.find);
return (getIndex.length > 0) ? TOb[getIndex[0]] : false;
},
// ****************************************
// *
// * Create public last method
// * Purpose: This returns the last row
// * from a set of indexes. Used to get
// * a record with the help of the find
// * function. Returns false if no records
// * are found.
// *
// ****************************************
last : function (dex) {
var getIndex = bDexArray(dex,this.find);
return (getIndex.length > 0) ? TOb[getIndex[(getIndex.length - 1)]] : false;
},
// ****************************************
// *
// * Create public stringify method
// * Purpose: This returns a string JSON array
// * from a set of indexes. Used to get records
// * for handling by AJAX or other langauges.
// *
// ****************************************
stringify : function (dex) {
return T.JSON.stringify(this.get(dex));
},
// ****************************************
// *
// * Create public orderBy method
// * Purpose: Reorder the array according
// * to a list of fields. Very useful for
// * ordering tables or other types of
// * sorting.
// *
// ****************************************
orderBy : function (Obj) {
// Only attempt to sort if there is a length
// to the TAFFY array
if (TOb.length > 0) {
// Use the private buildSortFunction method
// to create a custom sort function
var customSort = buildSortFunction(Obj);
// Call JavaScript's array.sort with the custom
// sort function
TOb.sort(customSort);
// update lastModifyDate
this.lastModifyDate = new Date();
}
},
// ****************************************
// *
// * Create public forEach method
// * Purpose: Loop over every item in a TOb
// * (or at least the ones passed in the forIndex)
// * and call the provided user created function.
// *
// ****************************************
forEach : function (func2call,dex) {
var forIndex = bDexArray(dex,this.find);
var row;
// loop over all of the indexes
for(var fe = 0; fe < forIndex.length; fe++) {
// get this row from the TOb
row = TOb[forIndex[fe]];
// call the function passed in to the method
var nr = func2call(row,forIndex[fe]);
// If nr is an object then set the row equal to the new object
if (T.isObject(nr))
{
if (TAFFY.isSameObject(nr,TAFFY.EXIT)) {
break;
} else {
this.update(nr,forIndex[fe])
}
}
};
},
// ****************************************
// *
// * config variable object
// *
// ****************************************
config:{
// ****************************************
// *
// * Create public set method
// * Purpose: Set a config value
// *
// ****************************************
set:function (n,v) {
conf[n] = v;
if (n == 'template' && !TAFFY.isNull(v)) {
mergeTemp(TIA,v);
}
},
// ****************************************
// *
// * Create public get method
// * Purpose: Get a config value
// *
// ****************************************
get:function (n) {
return conf[n];
}
},
// ****************************************
// *
// * Create public stringify method
// * Purpose: This returns a string JSON array
// * from a set of indexes. Used to get records
// * for handling by AJAX or other langauges.
// *
// ****************************************
applyTemplate : function (tmp,dex) {
var getIndex = bDexArray(dex,this.find);
mergeTemp(getIndex,tmp);
},
// ****************************************
// *
// * Empty On Update Event - This can be replaced with a function
// * to call a custom action as each record is updated.
// *
// ****************************************
onUpdate:null,
// ****************************************
// *
// * Empty On Remove Event - This can be replaced with a function
// * to call a custom action as each record is removed.
// *
// ****************************************
onRemove:null,
// ****************************************
// *
// * Empty On Insert Event - This can be replaced with a function
// * to call a custom action as each record is inserted.
// *
// ****************************************
onInsert:null
};
};
// ****************************************
// *
// * TAFFY Public Utilities
// * Accessed via TAFFY[methodname]()
// *
// ****************************************
// ****************************************
// *
// * typeOf Fixed in JavaScript as public utility
// *
// ****************************************
TAFFY.typeOf = function (v) {
var s = typeof v;
if (s === 'object') {
if (v) {
if (typeof v.length === 'number' &&
!(v.propertyIsEnumerable('length')) &&
typeof v.splice === 'function') {
s = 'array';
}
} else {
s = 'null';
}
}
return s;
};
// ****************************************
// *
// * JSON Object Handler / public utility
// * See http://www.JSON.org/js.html
// * The following JSON Object is Public Domain
// * No warranty expressed or implied. Use at your own risk.
// *
// ****************************************
TAFFY.JSON = function () {
function f(n) {
return n < 10 ? '0' + n : n;
}
Date.prototype.toJSON = function () {
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
var m = {
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
function stringify(value, whitelist) {
var a,i,k,l, r = /["\\\x00-\x1f\x7f-\x9f]/g,v;
switch (typeof value) {
case 'string':
return r.test(value) ?
'"' + value.replace(r, function (a) {
var c = m[a];
if (c) {
return c;
}
c = a.charCodeAt();
return '\\u00' + Math.floor(c / 16).toString(16) +
(c % 16).toString(16);
}) + '"' :
'"' + value + '"';
case 'number':
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
return String(value);
case 'object':
if (!value) {
return 'null';
}
if (typeof value.toJSON === 'function') {
return stringify(value.toJSON());
}
a = [];
if (typeof value.length === 'number' &&
!(value.propertyIsEnumerable('length'))) {
l = value.length;
for (i = 0; i < l; i += 1) {
a.push(stringify(value[i], whitelist) || 'null');
}
return '[' + a.join(',') + ']';
}
if (whitelist) {
l = whitelist.length;
for (i = 0; i < l; i += 1) {
k = whitelist[i];
if (typeof k === 'string') {
v = stringify(value[k], whitelist);
if (v) {
a.push(stringify(k) + ':' + v);
}
}
}
} else {
for (k in value) {
if (typeof k === 'string') {
v = stringify(value[k], whitelist);
if (v) {
a.push(stringify(k) + ':' + v);
}
}
}
}
return '{' + a.join(',') + '}';
}
return "";
}
return {
stringify: stringify,
parse: function (text, filter) {
var j;
function walk(k, v) {
var i, n;
if (v && typeof v === 'object') {
for (i in v) {
if (Object.prototype.hasOwnProperty.apply(v, [i])) {
n = walk(i, v[i]);
if (n !== undefined) {
v[i] = n;
} else {
delete v[i];
}
}
}
}
return filter(k, v);
}
if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
j = eval('(' + text + ')');
return typeof filter === 'function' ? walk('', j) : j;
}
throw new SyntaxError('parseJSON');
}
};
}();
// ****************************************
// *
// * End JSON Code Object Handler
// *
// ****************************************
// ****************************************
// *
// * Create public utility mergeObj method
// * Return a new object where items from obj2
// * have replaced or been added to the items in
// * obj1
// * Purpose: Used to combine objs
// *
// ****************************************
TAFFY.mergeObj = function (ob1,ob2) {
for(var n in ob2)
{
if (ob2.hasOwnProperty(n))
ob1[n] = ob2[n];
}
return ob1;
};
// ****************************************
// *
// * Create public utility getObjectKeys method
// * Returns an array of an objects keys
// * Purpose: Used to get the keys for an object
// *
// ****************************************
TAFFY.getObjectKeys = function (ob) {
var kA = [];
for(var n in ob)
{
if (ob.hasOwnProperty(n))
{
kA[kA.length] = n;
}
}
kA.sort();
return kA;
};
// ****************************************
// *
// * Create public utility isSameArray
// * Returns an array of an objects keys
// * Purpose: Used to get the keys for an object
// *
// ****************************************
TAFFY.isSameArray = function (ar1,ar2) {
return (TAFFY.isArray(ar1) && TAFFY.isArray(ar2) && ar1.join(",") == ar2.join(",")) ? true : false;
};
// ****************************************
// *
// * Create public utility isSameObject method
// * Returns true if objects contain the same
// * material or false if they do not
// * Purpose: Used to comare objects
// *
// ****************************************
TAFFY.isSameObject = function (ob1,ob2) {
var T = TAFFY;
if (T.isObject(ob1) && T.isObject(ob2)) {
if (T.isSameArray(T.getObjectKeys(ob1),T.getObjectKeys(ob2))) {
for(var n in ob1)
{
if (ob1.hasOwnProperty(n))
{
if ((T.isObject(ob1[n]) && T.isObject(ob2[n]) && T.isSameObject(ob1[n],ob2[n]))
|| (T.isArray(ob1[n]) && T.isArray(ob2[n]) && T.isSameArray(ob1[n],ob2[n]))
|| (ob1[n] == ob2[n])) {
} else {
return false;
}
}
}
} else {
return false;
}
} else {
return false;
}
return true;
};
// ****************************************
// *
// * Create public utility has method
// * Returns true if a complex object, array
// * or taffy collection contains the material
// * provided in the second argument
// * Purpose: Used to comare objects
// *
// ****************************************
TAFFY.has = function(var1, var2){
var T = TAFFY;
var re = true;
if (T.isTAFFY(var1)) {
re = var1.find(var2);
if (re.length > 0)
{
return true;
} else {
return false;
}
}
else {
switch (T.typeOf(var1)) {
case "object":
if (T.isObject(var2)) {
for (var x in var2) {
if (re == true && var2.hasOwnProperty(x) && !T.isUndefined(var1[x]) && var1.hasOwnProperty(x)) {
re = T.has(var1[x], var2[x]);
} else {
return false;
}
}
return re;
}
else
if (T.isArray(var2)) {
for (var x = 0; x < var2.length; x++) {
re = T.has(var1, var2[x]);
if (re == true) {
return true;
}
}
}
else
if (T.isString(var2) && var1[var2] != undefined) {
return true;
}
break;
case "array":
if (T.isObject(var2)) {
for (var n = 0; n < var1.length; n++) {
re = T.has(var1[n], var2);
if (re == true) {
return true;
}
}
}
else
if (T.isArray(var2)) {
for (var x = 0; x < var2.length; x++) {
for (var n = 0; n < var1.length; n++) {
re = T.has(var1[n], var2[x]);
if (re == true) {
return true;
}
} }
}
else
if (T.isString(var2)) {
for (var n = 0; n < var1.length; n++) {
re = T.has(var1[n], var2);
if (re == true) {
return true;
}
}
}
break;
case "string":
if (T.isString(var2) && var2 == var1) {
return true;
}
break;
default:
if (T.typeOf(var1) == T.typeOf(var2) && var1 == var2) {
return true;
}
break;
}
}
return false;
}
// ****************************************
// *
// * Create public utility hasAll method
// * Returns true if a complex object, array
// * or taffy collection contains the material
// * provided in the call - for arrays it must
// * contain all the material in each array item
// * Purpose: Used to comare objects
// *
// ****************************************
TAFFY.hasAll = function (var1,var2) {
var T = TAFFY;
if (T.isArray(var2)) {
var ar = true;
for(var i = 0;i<var2.length;i++)
{
ar = T.has(var1,var2[i]);
if(ar == false)
{
return ar;
}
}
return true;
} else {
return T.has(var1,var2);
}
}
// ****************************************
// *
// * Create public utility gatherUniques method
// * Return a new array with only unique
// * values from the passed array
// * Purpose: Used to get unique indexes for find
// *
// ****************************************
TAFFY.gatherUniques = function(a){
var uniques = [];
for (var z = 0; z < a.length; z++) {
var d = true;
for (var c = 0; c < uniques.length; c++) {
if (uniques[c] == a[z])
d = false;
}
if (d == true)
uniques[uniques.length] = a[z];
}
return uniques;
};
// ****************************************
// *
// * Create public utility is[DataType] methods
// * Return true if obj is datatype, false otherwise
// * Purpose: Used to determine if arguments are of certain data type
// *
// ****************************************
(function(ts){
for (var z = 0; z < ts.length; z++) {
(function(y){
TAFFY["is" + y] = function(c){
return (TAFFY.typeOf(c) == y.toLowerCase()) ? true : false;
}
}
(ts[z]))
}
}
(["String", "Number", "Object", "Array", "Boolean", "Null", "Function", "Undefined"]));
// ****************************************
// *
// * Create public utility isNumeric method
// * Return ture if text of sT is made up solely of numbers, false otherwise
// * Purpose: Used to determine if arguments are numbers
// *
// ****************************************
TAFFY.isNumeric = function(sT){
var vC = "0123456789";
var IsN = true;
for (var i = 0; i < sT.length && IsN == true; i++) {
if (vC.indexOf(sT.charAt(i)) == -1)
return false;
}
return IsN;
};
// ****************************************
// *
// * Create public utility isTAFFY method
// * Return ture if obj is created by TAFFY()
// * Purpose: Used to change behavior if oB is a TAFFY collection
// *
// ****************************************
TAFFY.isTAFFY = function(oB){
return (TAFFY.isObject(oB) && oB.TAFFY) ? true : false;
};
// ****************************************
// *
// * Create public utility EXIT object
// * Static value
// * Purpose: Return in a forEach function to break out of the loop
// *
// ****************************************
TAFFY.EXIT = {EXIT:true};
}
分享到:
相关推荐
RiPr0主题的全新V5版本(原RiPr0-V2的升级版)是一款功能卓越、性能优越且速度极快的WordPress虚拟资源商城主题。它具备首页模块化布局和WP原生小工具的自由拖拽设置,以提高网站设计便捷性。此外,该主题还支持高级筛选、内置会员生态系统和多种支付接口,使网站无需依赖任何附加插件即可实现众多功能。同时,主题也支持卡密、充值和站内币等多种功能,为您的网站提供全面而有效的解决方案。
扫地机器人是一种智能家居电器,主要用于地面清洁。它通常具备自主导航、避障、清扫和吸尘等功能,部分高级产品还增加了拖地、消毒等附加功能。扫地机器人通过内置的传感器和智能算法,能够自主规划清扫路径,识别并避开障碍物,实现高效的地面清洁。 据QYResearch调研团队最新报告“全球扫地机器人市场报告2024-2030”显示,预计2030年全球扫地机器人市场规模将达到87.8亿美元,未来几年年复合增长率CAGR为7.2%。
该项目包含完整的前后端代码、数据库脚本和相关工具,简单部署即可运行。功能完善、界面美观、操作简单,具有很高的实际应用价值,非常适合作为Java毕业设计或Java课程设计使用。 所有项目均经过严格调试,确保可运行!下载后即可快速部署和使用。 1 适用场景: 毕业设计 期末大作业 课程设计 2 项目特点: 代码完整:详细代码注释,适合新手学习和使用 功能强大:涵盖常见的核心功能,满足大部分课程设计需求 部署简单:有基础的人,只需按照教程操作,轻松完成本地或服务器部署 高质量代码:经过严格测试,确保无错误,稳定运行 3 技术栈和工具 前端:HTML + Vue.js 后端框架:Spring Boot 开发环境:IntelliJ IDEA 数据库:MySQL(建议使用 5.7 版本,更稳定) 数据库可视化工具:Navicat 部署环境:Tomcat(推荐 7.x 或 8.x 版本),Maven
VM17的密钥,亲测有效的,用的多了可能就没了
easy-interceptor修改请求头和响应头.zip
matlab机械臂关节空间轨迹规划,3-5-3分段多项式插值法,六自由度机械臂,该算法可运用到仿真建模机械臂上实时运动,可视化轨迹,有角度,速度,加速度仿真曲线。 也可以有单独角度,速度,加速度仿真曲线。 可自行更程序中机械臂与点的参数。 谢谢大家 (程序中均为弧度制参数)353混合多项式插值
pt100温度变送器,支持k型热电偶 4-20mA输出全套方案资料 2线、3线、隔离型。 (样板是2线电流 0-10V输出) 0-5V 0-10V输出 国产24位ADC精度0.01度,国产12位DAC千分之一线性价格便宜成熟方案。 485通信到串口示波器看温度电流曲线 2.4寸tft液晶屏,有串口屏接口。 外壳采用abs+透明上盖触摸按键组成。 2点仪表标定校准方式。
燕山大学数字电子技术实验报告1-5
2024年心灵状态全球报告-Six Seconds-2024-49页.pdf
Teamcenter清理缓存脚本,双击此bat,即可清理Teamcenter缓存
该项目包含完整的前后端代码、数据库脚本和相关工具,简单部署即可运行。功能完善、界面美观、操作简单,具有很高的实际应用价值,非常适合作为Java毕业设计或Java课程设计使用。 所有项目均经过严格调试,确保可运行!下载后即可快速部署和使用。 1 适用场景: 毕业设计 期末大作业 课程设计 2 项目特点: 代码完整:详细代码注释,适合新手学习和使用 功能强大:涵盖常见的核心功能,满足大部分课程设计需求 部署简单:有基础的人,只需按照教程操作,轻松完成本地或服务器部署 高质量代码:经过严格测试,确保无错误,稳定运行 3 技术栈和工具 前端:HTML + Vue.js 后端框架:Spring Boot 开发环境:IntelliJ IDEA 数据库:MySQL(建议使用 5.7 版本,更稳定) 数据库可视化工具:Navicat 部署环境:Tomcat(推荐 7.x 或 8.x 版本),Maven
72619971-63e9-4b20-aae7-d6ce002ace9-1.zip
该课件是给人工智能专业本科生上课用ppt,自己编写的,不是教材自带的ppt(一般教材自带的ppt全是文字,根本无法授课使用)。有需要的教师可以下载使用。也适合有想要学习opencv计算机视觉的学生使用。或作为期末考试复习专用。除了需要ppt,还需要教案和讲稿的教师可以私信我留言。 内容目录如下: 第1章 OpenCV起步 OpenCV简介、配置开发环境、使用OpenCV文档和示例 第2章 图像处理基础 NumPy简介、图像基础操作、图像运算 第3章 图形用户界面 窗口控制、绘图、响应鼠标事件、使用跟踪栏 第4章 图像变换 色彩空间变换、几何变换、图像模糊、阈值处理、形态变换 第5章 边缘和轮廓 边缘检测、图像轮廓、霍夫变换 第6章 直方图 直方图基础、直方图均衡化、二维直方图 第7章 模板匹配和图像分割 模板匹配、图像分割、交互式前景提取 第8章 特征检测 角检测、特征点检测、特征匹配、对象查找 第9章 人脸检测和识别 人脸检测、人脸识别 第10章 机器学习和深度学习 机器学习、深度学习
钢材门户企业站共12个页面,整套企业站,使用html+javascript+css实现,动态网页。各页面链接已经添加。 首页预览图片:https://a.ladshow.com/other/csdn/WX20250107-150141%402x%20%281%29.png 行业咨询预览图片:https://a.ladshow.com/other/csdn/WX20250107-150153%402x%20%281%29.png
大数据lzo压缩库,jar包格式
项目建设考核评价模板.xlsx
升压变压器市场前景分析:预计2030年市场规模将达到112亿美元,潜力无限 在电力传输的广阔舞台上,升压变压器以其独特的功能和广泛的应用场景,成为了确保电能高效、安全传输的关键角色。随着全球电力需求的持续增长和新能源发电的快速发展,升压变压器市场正迎来前所未有的发展机遇。然而,面对复杂多变的市场环境和日益激烈的竞争态势,如何精准把握市场脉搏,成为每一位市场参与者关注的焦点。本文将深入探讨升压变压器市场的现状、趋势、竞争格局及咨询服务的重要性,为您揭示市场的无限潜力。 市场概况: 据QYResearch(恒州博智)统计及预测,2023年全球升压变压器市场销售额达到了67亿美元,预计2030年将达到112亿美元,年复合增长率(CAGR)为7.5%。这一数据不仅彰显了升压变压器市场的强劲增长势头,也预示着未来几年内市场将保持持续扩张的态势。在中国市场,随着电力行业的快速发展和电网建设的不断推进,升压变压器的需求量也在稳步增长。 技术创新与趋势: 技术创新是推动升压变压器市场发展的重要力量。随着新材料、新工艺的不断涌现,升压变压器的性能得到了显著提升,能效和可靠性不断提高。同时,智能化、数字化
电机与拖动技术三级项目直流电机串电阻启动项目ppt
MATLAB再生制动模型 制动能量回收模型 电动车电液复合制动模型 刹车回能模型 电机再生制动模型 目标车型:电动汽车 模型包括:轮毂电机充电模型 电池发电模型 控制策略模型 前后制动力分配模型 电液制动力分配模型 输入模型(注:控制策略模型,因此整车参数以及仿真工况等均通过AVL_Cruise中进行导入) 控制策略:最优制动能量回收策略 控制算法:逻辑门限值控制算法 通过逻辑门限值控制算法,依次分配: 前轮制动力 后轮制动力 电机制动力 液压制动力 通过控制策略与传统控制策略对比可知,最优制动能量回收策略具有一定的优越性。 单模型:可运行出仿真图,业内人士首选。 color="#ffffff ">712093537107< font> <img class="alignnone size-large" src="http: img.alicdn.com bao uploaded i3 O1CN01FvosPg1S4ROwl9tSZ_!!53-fleamarket.heic" width="1080" height="1440" > <img class="alignnone s
Matlab领域上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作