(JS) Custom, inheritable, namespace to call controllers in MVC - javascript

I am currently trying to wrap my head around creating a JavaScript namespace for organizing our JS files, that can be used to access specific methods that allow calling methods from MVC controllers. My confusion revolves around namespacing and inheriting the or applying the namespace when it is called in a different source.
Namespace TEST.js
var TEST = TEST || {}; // Needed?
(function() {
if (typeof String.prototype.trimLeft !== "function") {
String.prototype.trimLeft = function () {
return this.replace(/^\s+/, "");
};
}
if (typeof String.prototype.trimRight !== "function") {
String.prototype.trimRight = function () {
return this.replace(/\s+$/, "");
};
}
if (typeof Array.prototype.map !== "function") {
Array.prototype.map = function (callback, thisArg) {
for (var i = 0, n = this.length, a = []; i < n; i++) {
if (i in this) a[i] = callback.call(thisArg, this[i]);
}
return a;
};
}
this.Settings = {
Timer: 300
};
this.Service = (name, isApi) => {
let location = isApi === true ? "~/Controller/api/" + name : "~/Controller/" + name;
this.Call = (data, method, type, callback) => {
let method = location + "/" + method + ".cs";
let data = typeof data === "object" ? data : {};
let type = type || "GET";
callback = fetch(method, {
method: type,
headers: {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json"
},
body: JSON.stringify(data)
})
.then((res) => res.json())
.then((data) => console.log(data));
return callback;
};
};
this.Functions = {
PageWidth: function () {
// return parseInt main container css width
},
setCookie: function (name, value) {
var val = value + ";domain=" + window.location.host + ";path=/;";
document.cookie = name + "=" + val;
},
deleteCookie: (name) => { document.cookie = name + "=null;domain=" + window.location.host + ";path=/;expires=Thu, 01 Jan 1900 00:00:00 GMT;"; },
getCookie: (name) => { getCookies()[name]; },
getCookies: () => {
var c = document.cookie, v = 0, cookies = {};
if (document.cookie.match(/^\s*\$Version=(?:"1"|1);\s*(.*)/)) {
c = RegExp.$1;
v = 1;
}
if (v === 0) {
c.split(/[,;]/).map(function (cookie) {
var parts = cookie.split(/=/, 2),
name = decodeURIComponent(parts[0].trimLeft()),
value = parts.length > 1 ? decodeURIComponent(parts[1].trimRight()) : null;
cookies[name] = value;
});
} else {
c.match(/(?:^|\s+)([!#$%&'*+\-.0-9A-Z^`a-z|~]+)=([!#$%&'*+\-.0-9A-Z^`a-z|~]*|"(?:[\x20-\x7E\x80\xFF]|\\[\x00-\x7F])*")(?=\s*[,;]|$)/g).map(function ($0, $1) {
var name = $0,
value = $1.charAt(0) === '"'
? $1.substr(1, -1).replace(/\\(.)/g, "$1")
: $1;
cookies[name] = value;
});
}
return cookies;
},
getQSParams: (query) => {
query
? (/^[?#]/.test(query) ? query.slice(1) : query)
.split('&')
.reduce((params, param) => {
let [key, value] = param.split('=');
params[key] = value ? decodeURIComponent(value.replace(/\+/g, ' ')) : '';
return params;
}, {}
)
: {}
}
}
this.ClientState = {};
this.getWidth = function () {
return Math.max(
document.body.scrollWidth,
document.documentElement.scrollWidth,
document.body.offsetWidth,
document.documentelement.offsetWidth,
document.documentElement.clientWidth
);
}
this.getHeight = function () {
return Math.max(
document.body.scrollHeight,
document.documentElement.scrollHeight,
document.body.offsetHeight,
document.documentElement.offsetHeight,
document.documentElement.clientHeight
);
}
}).apply(ELITE); // Var up top go here instead?
And my testing code to see if this works:
<script type="text/javascript" src='<%=ResolveUrl("~/Content/Scripts/TEST.js") %>'></script>
<script type="text/javascript">
$(function () {
var test = new TEST.Service("TestController", true);
var data = {};
test.Call(data, "TestMethod", "GET", function (resp) {
console.log(resp);
});
}(TEST));
</script>
I am sure it is something simple or a mix-up of things.
Question: Correctly namespacing a JS file to be inherited by other JS files or JS script calls for calling MVC controller methods?
Bonus: Would this be better executed as a class instead? I do have access to using ES5/ES6 and of course jQuery will be minified in with this TEST.js file!

Related

Problems with ReactJS and ExtJS3

I have page with ExtJS3 and ReactJS.
In order for the React to work in IE11 i use #babel/polifyll
In turn, Babel uses core-js which has this method:
"use strict";
var LIBRARY = __webpack_require__(/*! ./_library */ "./node_modules/core-js/library/modules/_library.js");
var $export = __webpack_require__(/*! ./_export */ "./node_modules/core-js/library/modules/_export.js");
var redefine = __webpack_require__(/*! ./_redefine */ "./node_modules/core-js/library/modules/_redefine.js");
var hide = __webpack_require__(/*! ./_hide */ "./node_modules/core-js/library/modules/_hide.js");
var Iterators = __webpack_require__(/*! ./_iterators */ "./node_modules/core-js/library/modules/_iterators.js");
var $iterCreate = __webpack_require__(/*! ./_iter-create */ "./node_modules/core-js/library/modules/_iter-create.js");
var setToStringTag = __webpack_require__(/*! ./_set-to-string-tag */ "./node_modules/core-js/library/modules/_set-to-string-tag.js");
var getPrototypeOf = __webpack_require__(/*! ./_object-gpo */ "./node_modules/core-js/library/modules/_object-gpo.js");
var ITERATOR = __webpack_require__(/*! ./_wks */ "./node_modules/core-js/library/modules/_wks.js")('iterator');
var BUGGY = !([].keys && 'next' in [].keys()); // Safari has buggy iterators w/o `next`
var FF_ITERATOR = '##iterator';
var KEYS = 'keys';
var VALUES = 'values';
module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
$iterCreate(Constructor, NAME, next);
var getMethod = function (kind) {
if (!BUGGY && kind in proto) return proto[kind];
switch (kind) {
case KEYS: return function keys() { return new Constructor(this, kind); };
case VALUES: return function values() { return new Constructor(this, kind); }; //AT THIS POINT
} return function entries() { return new Constructor(this, kind); };
}
//SOME PARTS OF THIS METHOD
};
in case VALUES: return function values() { return new Constructor(this, kind); }; i have something which make something and this part of code broke ExtJS3 methods like this:
Ext.XTemplate = function(){
Ext.XTemplate.superclass.constructor.apply(this, arguments);
var me = this,
s = me.html,
re = /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
nameRe = /^<tpl\b[^>]*?for="(.*?)"/,
ifRe = /^<tpl\b[^>]*?if="(.*?)"/,
execRe = /^<tpl\b[^>]*?exec="(.*?)"/,
m,
id = 0,
tpls = [],
VALUES = 'values',
PARENT = 'parent',
XINDEX = 'xindex',
XCOUNT = 'xcount',
RETURN = 'return ',
WITHVALUES = 'with(values){ ';
s = ['<tpl>', s, '</tpl>'].join('');
while((m = s.match(re))){
var m2 = m[0].match(nameRe),
m3 = m[0].match(ifRe),
m4 = m[0].match(execRe),
exp = null,
fn = null,
exec = null,
name = m2 && m2[1] ? m2[1] : '';
if (m3) {
exp = m3 && m3[1] ? m3[1] : null;
if(exp){
fn = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + RETURN +(Ext.util.Format.htmlDecode(exp))+'; }');
}
}
if (m4) {
exp = m4 && m4[1] ? m4[1] : null;
if(exp){
exec = new Function(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES +(Ext.util.Format.htmlDecode(exp))+'; }');
}
}
if(name){
switch(name){
case '.': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + VALUES + '; }'); break;
case '..': name = new Function(VALUES, PARENT, WITHVALUES + RETURN + PARENT + '; }'); break;
default: name = new Function(VALUES, PARENT, WITHVALUES + RETURN + name + '; }');
}
}
tpls.push({
id: id,
target: name,
exec: exec,
test: fn,
body: m[1]||''
});
s = s.replace(m[0], '{xtpl'+ id + '}');
++id;
}
Ext.each(tpls, function(t) {
me.compileTpl(t);
});
me.master = tpls[tpls.length-1];
me.tpls = tpls;
};
Ext.extend(Ext.XTemplate, Ext.Template, {
// private
re : /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\\]\s?[\d\.\+\-\*\\\(\)]+)?\}/g,
// private
codeRe : /\{\[((?:\\\]|.|\n)*?)\]\}/g,
// private
applySubTemplate : function(id, values, parent, xindex, xcount){
var me = this,
len,
t = me.tpls[id],
vs,
buf = [];
if ((t.test && !t.test.call(me, values, parent, xindex, xcount)) ||
(t.exec && t.exec.call(me, values, parent, xindex, xcount))) {
return '';
}
vs = t.target ? t.target.call(me, values, parent) : values;
len = vs.length;
parent = t.target ? values : parent;
if(t.target && Ext.isArray(vs)){
Ext.each(vs, function(v, i) {
buf[buf.length] = t.compiled.call(me, v, parent, i+1, len);
});
return buf.join('');
}
return t.compiled.call(me, vs, parent, xindex, xcount);
},
// private
compileTpl : function(tpl){
var fm = Ext.util.Format,
useF = this.disableFormats !== true,
sep = Ext.isGecko ? "+" : ",",
body;
function fn(m, name, format, args, math){
if(name.substr(0, 4) == 'xtpl'){
return "'"+ sep +'this.applySubTemplate('+name.substr(4)+', values, parent, xindex, xcount)'+sep+"'";
}
var v;
if(name === '.'){
v = 'values';
}else if(name === '#'){
v = 'xindex';
}else if(name.indexOf('.') != -1){
v = name;
}else{
v = "values['" + name + "']";
}
if(math){
v = '(' + v + math + ')';
}
if (format && useF) {
args = args ? ',' + args : "";
if(format.substr(0, 5) != "this."){
format = "fm." + format + '(';
}else{
format = 'this.call("'+ format.substr(5) + '", ';
args = ", values";
}
} else {
args= ''; format = "("+v+" === undefined ? '' : ";
}
return "'"+ sep + format + v + args + ")"+sep+"'";
}
function codeFn(m, code){
return "'"+ sep +'('+code+')'+sep+"'";
}
// branched to use + in gecko and [].join() in others
if(Ext.isGecko){
body = "tpl.compiled = function(values, parent, xindex, xcount){ return '" +
tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn) +
"';};";
}else{
body = ["tpl.compiled = function(values, parent, xindex, xcount){ return ['"];
body.push(tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn).replace(this.codeRe, codeFn));
body.push("'].join('');};");
body = body.join('');
}
eval(body);
return this;
},
applyTemplate : function(values){
return this.master.compiled.call(this, values, {}, 1, 1);
},
compile : function(){return this;}
});
Ext.XTemplate.prototype.apply = Ext.XTemplate.prototype.applyTemplate;
Ext.XTemplate.from = function(el){
el = Ext.getDom(el);
return new Ext.XTemplate(el.value || el.innerHTML);
};/*!
On line 92 in vs variable i have this method function values() { return new Constructor(this, kind); }; from core-js.
I don't know what i need to do, because we need a several months (maybe year) to stay with ExtJS3 but many things in ExtJS3 not work.
EDIT
Also no one have access to ExtJS3 for make software crutch
Hard fix:
just create fix.sh file, put it in a root of project along with webpack config and put this source to fix.sh:
sed -i 's/getMethod/_getMethod/g' target/application/static/js/*.js && sed -i 's/KEYS/_KEYS/g' target/application/static/js/*.js &&
sed -i 's/VALUES/_VALUES/g' target/application/static/js/*.js &&
sed -i 's/keys/_keys/g' target/application/static/js/*.js &&
sed -i 's/values/_values/g' target/application/static/js/*.js
also replace target/application/static/js path to yours.
Add WebpackShellPlugin and in webpack add this:
plugins: [
new WebpackShellPlugin({
onBuildEnd: ['bash ./fix.sh']
})
]

Intercepting function calls in javascript

I appreciate if anyone can tell me how to intercept a function call in javascript.
I know it is possible with making use of proxies.
for example I tried the code below to intercept it but now I want to intercept toDataURL(). in order to call toDataURL you need to create a canvas element first.So, now I want to know how is this possible to define a proxy to intercept toDataURL().
Example code to intercept it :
window.x = 0;
let calls = (function(){
let canvas = document.createElement('canvas');
let fun = canvas.toDataURL;
canvas.toDataURL = function(){
window.x++;
return fun.apply(document, arguments);
}
return ()=>calls;
})();
Though one always should have a good reason for modifying standard methods of standard types, the base approach of method modification in JS is wrapping. One might even think about standardizing Function.prototype[before|after|around|afterThrowing|afterFinally]. Then modifying any given method or function will be as easy as with the next provided example that also might be the answer the OP is looking for ...
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
};
Function.prototype.before = function (handler, target) { // before
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var args = arguments;
handler.call((target || this), args);
return proceed.apply((target || this), args);
}) || proceed;
};
Function.prototype.after = function (handler, target) { // afterReturning
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var ret, args = arguments;
ret = proceed.apply((target || this), args);
handler.call((target || this), ret, args);
return ret;
}) || proceed;
};
Function.prototype.around = function (handler, target) { // around
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
return handler.call((target || this), proceed, handler, arguments);
}) || proceed;
};
}(Function));
function modifyCanvasToDataUrlAfter(returnValue, thisArgs) {
console.log('modifyCanvasToDataUrlAfter :: thisArgs : ', thisArgs);
console.log('modifyCanvasToDataUrlAfter :: returnValue : ', returnValue);
}
HTMLCanvasElement.prototype.toDataURL = HTMLCanvasElement.prototype.toDataURL.after(modifyCanvasToDataUrlAfter);
var elmToJpgLow = document.getElementById('canvasToLowResolutionJpg');
var elmToJpgMedium = document.getElementById('canvasToMediumResolutionJpg');
console.log("elmToJpgLow.toDataURL('image/jpeg', 0.1) : ", elmToJpgLow.toDataURL('image/jpeg', 0.1));
console.log('elmToJpgLow.toDataURL : ', elmToJpgLow.toDataURL);
console.log("elmToJpgMedium.toDataURL('image/jpeg', 0.1) : ", elmToJpgMedium.toDataURL('image/jpeg', 0.5));
console.log('elmToJpgMedium.toDataURL : ', elmToJpgMedium.toDataURL);
.as-console-wrapper { max-height: 100%!important; top: 0; }
<canvas id="canvasToLowResolutionJpg" width="5" height="5"></canvas>
<canvas id="canvasToMediumResolutionJpg" width="5" height="5"></canvas>
Edit
A Proxy based approach might look like the following provided example ...
const canvasToDataUrlModifier = {
apply: function(target, thisArg, argumentsList) {
let returnValue = target.apply(thisArg, argumentsList);
console.log('toDataUrlAfterModifier :: argumentsList : ', argumentsList);
console.log('toDataUrlAfterModifier :: returnValue : ', returnValue);
return returnValue;
}
};
var elmToJpgLow = document.getElementById('canvasToLowResolutionJpg');
var elmToJpgMedium = document.getElementById('canvasToMediumResolutionJpg');
var proxyToJpgLow = new Proxy(elmToJpgLow.toDataURL, canvasToDataUrlModifier);
var proxyToJpgMedium = new Proxy(elmToJpgMedium.toDataURL, canvasToDataUrlModifier);
console.log("proxyToJpgLow.call(elmToJpgLow, 'image/jpeg', 0.1) : ", proxyToJpgLow.call(elmToJpgLow, 'image/jpeg', 0.1));
console.log("proxyToJpgMedium.call(elmToJpgMedium, 'image/jpeg', 0.5) : ", proxyToJpgMedium.call(elmToJpgMedium, 'image/jpeg', 0.5));
.as-console-wrapper { max-height: 100%!important; top: 0; }
<canvas id="canvasToLowResolutionJpg" width="5" height="5"></canvas>
<canvas id="canvasToMediumResolutionJpg" width="5" height="5"></canvas>

List all possible paths using lodash

I would like to list all paths of object that lead to leafs
Example:
var obj = {
a:"1",
b:{
foo:"2",
bar:3
},
c:[0,1]
}
Result:
"a","b.foo","b.bar", "c[0]","c[1]"
I would like to find simple and readable solution, best using lodash.
Here is a solution that uses lodash in as many ways as I can think of:
function paths(obj, parentKey) {
var result;
if (_.isArray(obj)) {
var idx = 0;
result = _.flatMap(obj, function (obj) {
return paths(obj, (parentKey || '') + '[' + idx++ + ']');
});
}
else if (_.isPlainObject(obj)) {
result = _.flatMap(_.keys(obj), function (key) {
return _.map(paths(obj[key], key), function (subkey) {
return (parentKey ? parentKey + '.' : '') + subkey;
});
});
}
else {
result = [];
}
return _.concat(result, parentKey || []);
}
Edit: If you truly want just the leaves, just return result in the last line.
Doesn't use lodash, but here it is with recursion:
var getLeaves = function(tree) {
var leaves = [];
var walk = function(obj,path){
path = path || "";
for(var n in obj){
if (obj.hasOwnProperty(n)) {
if(typeof obj[n] === "object" || obj[n] instanceof Array) {
walk(obj[n],path + "." + n);
} else {
leaves.push(path + "." + n);
}
}
}
}
walk(tree,"tree");
return leaves;
}
Based on Nick answer, here is a TS / ES6 imports version of the same code
import {isArray,flatMap,map,keys,isPlainObject,concat} from "lodash";
// See https://stackoverflow.com/a/36490174/82609
export function paths(obj: any, parentKey?: string): string[] {
var result: string[];
if (isArray(obj)) {
var idx = 0;
result = flatMap(obj, function(obj: any) {
return paths(obj, (parentKey || '') + '[' + idx++ + ']');
});
} else if (isPlainObject(obj)) {
result = flatMap(keys(obj), function(key) {
return map(paths(obj[key], key), function(subkey) {
return (parentKey ? parentKey + '.' : '') + subkey;
});
});
} else {
result = [];
}
return concat(result, parentKey || []);
}
Feeding that object through this function should do it I think.
recursePaths: function(obj){
var result = [];
//get keys for both arrays and objects
var keys = _.map(obj, function(value, index, collection){
return index;
});
//Iterate over keys
for (var key in keys) {
//Get paths for sub objects
if (typeof obj[key] === 'object'){
var paths = allPaths(obj[key]);
for (var path in paths){
result.push(key + "." + path);
}
} else {
result.push(key);
}
}
return result;
}
Here is my function. It generates all possible paths with dot notation, assuming there are no property names containing spaces
function getAllPathes(dataObj) {
const reducer = (aggregator, val, key) => {
let paths = [key];
if(_.isObject(val)) {
paths = _.reduce(val, reducer, []);
paths = _.map(paths, path => key + '.' + path);
}
aggregator.push(...paths);
return aggregator;
};
const arrayIndexRegEx = /\.(\d+)/gi;
let paths = _.reduce(dataObj, reducer, []);
paths = _.map(paths, path => path.replace(arrayIndexRegEx, '[$1]'));
return paths;
}
Here's my solution. I only did it because I felt the other solutions used too much logic. Mine does not use lodash since I don't think it would add any value. It also doesn't make array keys look like [0].
const getAllPaths = (() => {
function iterate(path,current,[key,value]){
const currentPath = [...path,key];
if(typeof value === 'object' && value != null){
return [
...current,
...iterateObject(value,currentPath)
];
}
else {
return [
...current,
currentPath.join('.')
];
}
}
function iterateObject(obj,path = []){
return Object.entries(obj).reduce(
iterate.bind(null,path),
[]
);
}
return iterateObject;
})();
If you need one where the keys are indexed using [] then use this:
const getAllPaths = (() => {
function iterate(path,isArray,current,[key,value]){
const currentPath = [...path];
if(isArray){
currentPath.push(`${currentPath.pop()}[${key}]`);
}
else {
currentPath.push(key);
}
if(typeof value === 'object' && value != null){
return [
...current,
...iterateObject(value,currentPath)
];
}
else {
return [
...current,
currentPath.join('.')
];
}
}
function iterateObject(obj,path = []){
return Object.entries(obj).reduce(
iterate.bind(null,path,Array.isArray(obj)),
[]
);
}
return iterateObject;
})();
const allEntries = (o, prefix = '', out = []) => {
if (_.isObject(o) || _.isArray(o)) Object.entries(o).forEach(([k, v]) => allEntries(v, prefix === '' ? k : `${prefix}.${k}`, out));
else out.push([prefix, o]);
return out;
};
Array are returned as .0 or .1 that are compatible with _.get of lodash
const getAllPaths = (obj: object) => {
function rKeys(o: object, path?: string) {
if (typeof o !== "object") return path;
return Object.keys(o).map((key) =>
rKeys(o[key], path ? [path, key].join(".") : key)
);
}
return rKeys(obj).toString().split(",").filter(Boolean) as string[];
};
const getAllPaths = (obj) => {
function rKeys(o, path) {
if (typeof o !== "object") return path;
return Object.keys(o).map((key) =>
rKeys(o[key], path ? [path, key].join(".") : key)
);
}
return rKeys(obj).toString().split(",").filter(Boolean);
};
const test = {
a: {
b: {
c: 1
},
d: 2
},
e: 1
}
console.log(getAllPaths(test))

Angular filter with typescript is not working after minification

I wrote an angular filter with typescript which works fine until I minify the source code.
Here is the filter:
module App.Test {
export interface IGroupingFilter extends ng.IFilterService {
(name:"grouping-filter"): (collection:any[]) => collection:any[];
}
class GroupingFilter {
static $inject:string[] = ["underscore"];
static ConvertDateTime(item:any):number {
var time = "" + item.time;
var newTime = (time.length == 3) ? "0" + time : time;
return +(item.pickupDate.replace(/\-/g, '') + newTime);
}
public static Factory(underscore:UnderscoreStatic) {
return underscore.memoize((collection:any[]) => {
var groupKey = "id";
var group:any = underscore.groupBy(collection, (item:any) => {
return item[groupKey];
});
var grpArray = [];
angular.forEach(group, (item) => {
grpArray.push({
"groupKey": item[0][groupKey],
"items": item
});
});
var grpArraySorted = underscore.sortBy(grpArray, (grpObj:any) => {
var min:any = underscore.min(grpObj.items, (item:any) => {
return GroupingFilter.ConvertDateTime(item);
});
return GroupingFilter.ConvertDateTime(min);
});
return grpArraySorted;
});
}
}
angular.module("app").filter("groupingFilter", GroupingFilter.Factory);
}
Here is the minified version:
var App;
!function (t) {
var e;
!function (t) {
var e = function () {
function t() {
}
return t.ConvertDateTime = function (t) {
var e = "" + t.time, r = 3 == e.length ? "0" + e : e;
return +(t.pickupDate.replace(/\-/g, "") + r)
}, t.Factory = function (e) {
return e.memoize(function (r) {
var n = "id", i = e.groupBy(r, function (t) {
return t[n]
}), o = [];
angular.forEach(i, function (t) {
o.push({groupKey: t[0][n], items: t})
});
var a = e.sortBy(o, function (r) {
var n = e.min(r.items, function (e) {
return t.ConvertDateTime(e)
});
return t.ConvertDateTime(n)
});
return a
})
}, t.$inject = ["underscore"], t
}();
angular.module("app").filter("groupingFilter", e.Factory)
}(e = t.Test || (t.Test = {}))
}(App || (App = {}));
Here is the angular error message
Error: [$injector:unpr] Unknown provider: eProvider <- e <-
groupingFilterFilter
Many thanks
The reason it does not work when minified is that you inject "underscore" into the FooFilter class not the actual filter, which is the result of FooFilter.Factory. To create such a simple filter you don't really need a class, just pass a simple function.
angular.module('app').filter('fooFilter', fooFilter);
fooFilter.$inject = ['underscore'];
function fooFilter(underscore) {
return underscore.memoize((collection:any[]) => {
return underscore.shuffle(collection);
});
}
If you really want to write the filter factory function as a static class method, you could use the array syntax like this:
angular.module("app")
.filter("groupingFilter", ['underscore', GroupingFilter.Factory]);
Remove the $inject array from your class in this case.

How do I do JavaScript Prototype Inheritance (chain of prototypes)

This is a question for the guru of JavaScript. I'm trying to do work with JavaScript prototype model more elegant. Here is my utility code (it provides real chain of prototypes and correct work with instanceof operator):
function Class(conf) {
var init = conf.init || function () {};
delete conf.init;
var parent = conf.parent || function () {};
delete conf.parent;
var F = function () {};
F.prototype = parent.prototype;
var f = new F();
for (var fn in conf) f[fn] = conf[fn];
init.prototype = f;
return init;
};
It allows me to do such thigns:
var Class_1 = new Class({
init: function (msg) { // constructor
this.msg = msg;
},
method_1: function () {
alert(this.msg + ' in Class_1::method_1');
},
method_2: function () {
alert(this.msg + ' in Class_1::method_2');
}
});
var Class_2 = new Class({
parent: Class_1,
init: function (msg) { // constructor
this.msg = msg;
},
// method_1 will be taken from Class_1
method_2: function () { // this method will overwrite the original one
alert(this.msg + ' in Class_2::method_2');
},
method_3: function () { // just new method
alert(this.msg + ' in Class_2::method_3');
}
});
var c1 = new Class_1('msg');
c1.method_1(); // msg in Class_1::method_1
c1.method_2(); // msg in Class_1::method_2
var c2 = new Class_2('msg');
c2.method_1(); // msg in Class_1::method_1
c2.method_2(); // msg in Class_2::method_2
c2.method_3(); // msg in Class_2::method_3
alert('c1 < Class_1 - ' + (c1 instanceof Class_1 ? 'true' : 'false')); // true
alert('c1 < Class_2 - ' + (c1 instanceof Class_2 ? 'true' : 'false')); // false
alert('c2 < Class_1 - ' + (c2 instanceof Class_1 ? 'true' : 'false')); // true
alert('c2 < Class_2 - ' + (c2 instanceof Class_2 ? 'true' : 'false')); // true
My question is: Is there more simple way to do this?
Yes, there is a better way to do this.
var call = Function.prototype.call;
var classes = createStorage(),
namespaces = createStorage(),
instances = createStorage(createStorage);
function createStorage(creator){
var storage = new WeakMap;
creator = typeof creator === 'function' ? creator : Object.create.bind(null, null, {});
return function store(o, v){
if (v) {
storage.set(o, v);
} else {
v = storage.get(o);
if (!v) {
storage.set(o, v = creator(o));
}
}
return v;
};
}
function Type(){
var self = function(){}
self.__proto__ = Type.prototype;
return self;
}
Type.prototype = Object.create(Function, {
constructor: { value: Type,
writable: true,
configurable: true },
subclass: { value: function subclass(scope){ return new Class(this, scope) },
configurable: true,
writable: true }
});
function Class(Super, scope){
if (!scope) {
scope = Super;
Super = new Type;
}
if (typeof Super !== 'function') {
throw new TypeError('Superconstructor must be a function');
} else if (typeof scope !== 'function') {
throw new TypeError('A scope function was not provided');
}
this.super = Super;
this.scope = scope;
return this.instantiate();
}
Class.unwrap = function unwrap(Ctor){
return classes(Ctor);
};
Class.prototype.instantiate = function instantiate(){
function super_(){
var name = super_.caller === Ctor ? 'constructor' : super_.caller.name;
var method = Super.prototype[name];
if (typeof method !== 'function') {
throw new Error('Attempted to call non-existent supermethod');
}
return call.apply(method, arguments);
}
var Super = this.super,
namespace = namespaces(Super),
private = instances(namespace)
var Ctor = this.scope.call(namespace, private, super_);
Ctor.__proto__ = Super;
Ctor.prototype.__proto__ = Super.prototype;
namespaces(Ctor, namespace);
classes(Ctor, this);
return Ctor;
}
example usage:
var Primary = new Class(function(_, super_){
var namespace = this;
namespace.instances = 0;
function Primary(name, secret){
this.name = name;
_(this).secret = secret;
namespace.instances++;
}
Primary.prototype.logSecret = function logSecret(label){
label = label || 'secret';
console.log(label + ': ' + _(this).secret);
}
return Primary;
});
var Derived = Primary.subclass(function(_, super_){
function Derived(name, secret, size){
super_(this, name, secret);
this.size = size;
}
Derived.prototype.logSecret = function logSecret(){
super_(this, 'derived secret');
}
Derived.prototype.exposeSecret = function exposeSecret(){
return _(this).secret;
}
return Derived;
});
var Bob = new Derived('Bob', 'is dumb', 20);
Bob.logSecret();
console.log(Bob);
console.log(Bob.exposeSecret());
After some research I've concluded there is no more simple way to do this.

Categories

Resources