I'm using this online tool to uglify my code although i'm using grunt-uglify to do the same but same error with this also, It works fine to minify the code but when i evaluate this code it returns an error of expected :. since it's not working for nested if-else case.
Sample code.
$._ext_ILST = {
changeColorLabel: function() {
spots = app.documents[0].spots;
var colorLabelArray = new Array();
for (var i = 0; i < spots.length; i++) {
try {
if (spots[i].toString() !== "[Spot]") {
if (spots[i].name.indexOf('$') == 0) {
colorLabelArray.push(spots[i].name.substring(1, spots[i].name.length));
}
}
} catch (e) {}
}
var colorInfo = getColorInfromation();
var obj = {}
if (colorInfo.length > 0)
colorLabelArray = [];
for (var i = 0; i < colorInfo.length; i++) {
colorLabelArray.push(colorInfo[i].colorName);
if ((colorInfo[i].hasOwnProperty('colorType') && colorInfo[i].colorType != "teamColorVariable")) {
if (colorInfo[i].isGarmentColor) {
obj[colorInfo[i].colorName] = "G"
} else {
obj[colorInfo[i].colorName] = "D"
}
} else if (!colorInfo[i].hasOwnProperty('colorType')) {
if (colorInfo[i].isGarmentColor) {
obj[colorInfo[i].colorName] = "G"
} else {
obj[colorInfo[i].colorName] = "D"
}
}
}
var mainColorObj = {
colorLabelArray: colorLabelArray,
colorMapArray: obj
}
return JSON.stringify(mainColorObj);
}
}
Minified ouput -
$._ext_ILST = {
changeColorLabel: function() {
spots = app.documents[0].spots;
for (var a = new Array, b = 0; b < spots.length; b++) try {
"[Spot]" !== spots[b].toString() && 0 == spots[b].name.indexOf("$") && a.push(spots[b].name.substring(1, spots[b].name.length))
} catch (c) {}
var d = getColorInfromation(),
e = {};
d.length > 0 && (a = []);
for (var b = 0; b < d.length; b++) a.push(d[b].colorName), d[b].hasOwnProperty("colorType") && "teamColorVariable" != d[b].colorType ? d[b].isGarmentColor ? e[d[b].colorName] = "G" : e[d[b].colorName] = "D" : d[b].hasOwnProperty("colorType") || (d[b].isGarmentColor ? e[d[b].colorName] = "G" : e[d[b].colorName] = "D");
var f = {
colorLabelArray: a,
colorMapArray: e
};
return JSON.stringify(f)
}
};
Any help will be appreciated.
Thanks,
Upendra sengar
You should lint your JS first.
Here’s a post-lint (and slightly modified) version of your code:
/* globals app, $, getColorInfromation */
(function(app, $, JSON, undefined) {
$._ext_ILST = {
changeColorLabel: function() {
var spots = app.documents[0].spots;
var colorLabelArray = [];
var i;
for (i = 0; i < spots.length; i++) {
try {
if (spots[i].toString() !== "[Spot]") {
if (spots[i].name.indexOf('$') === 0) {
colorLabelArray.push(spots[i].name.substring(1, spots[i].name.length));
}
}
} catch (e) {}
}
var colorInfo = getColorInfromation();
var obj = {};
if (colorInfo.length > 0)
colorLabelArray = [];
for (i = 0; i < colorInfo.length; i++) {
colorLabelArray.push(colorInfo[i].colorName);
if ((colorInfo[i].hasOwnProperty('colorType') && colorInfo[i].colorType != "teamColorVariable")) {
if (colorInfo[i].isGarmentColor) {
obj[colorInfo[i].colorName] = "G";
} else {
obj[colorInfo[i].colorName] = "D";
}
} else if (!colorInfo[i].hasOwnProperty('colorType')) {
if (colorInfo[i].isGarmentColor) {
obj[colorInfo[i].colorName] = "G";
} else {
obj[colorInfo[i].colorName] = "D";
}
}
}
var mainColorObj = {
colorLabelArray: colorLabelArray,
colorMapArray: obj
};
return JSON.stringify(mainColorObj);
}
};
}(app, $, JSON));
Note that I wrapped your code in an IIFE to give you better uglification results. Also notice that I only did a topical sweeping of your code … there’s more that I think you could do to make it better (e.g., brackets around if statements, I personally like to explicitly hoist all my vars, etc.).
Next, I quickly googled for an online minification/uglification tool and copy/pasted the linted version of your code; here’s the result:
!function(o,r,e,a){r._ext_ILST={changeColorLabel:function(){var r,a=o.documents[0].spots,n=[];for(r=0;r<a.length;r++)try{"[Spot]"!==a[r].toString()&&0===a[r].name.indexOf("$")&&n.push(a[r].name.substring(1,a[r].name.length))}catch(t){}var l=getColorInfromation(),c={};for(l.length>0&&(n=[]),r=0;r<l.length;r++)n.push(l[r].colorName),l[r].hasOwnProperty("colorType")&&"teamColorVariable"!=l[r].colorType?l[r].isGarmentColor?c[l[r].colorName]="G":c[l[r].colorName]="D":l[r].hasOwnProperty("colorType")||(l[r].isGarmentColor?c[l[r].colorName]="G":c[l[r].colorName]="D");var m={colorLabelArray:n,colorMapArray:c};return e.stringify(m)}}}(app,$,JSON);
Not sure if that’s what you’re looking for, and/or if the code still functions, but hopefully that puts you in the right direction?
Related
I'd like to extend javascript to add custom type checking.
e.g.
function test(welcome:string, num:integer:non-zero) {
console.log(welcome + num)
}
which would compile into:
function test(welcome, num) {
if(Object.prototype.toString.call(welcome) !== "[object String]") {
throw new Error('welcome must be a string')
}
if (!Number.isInteger(num)) {
throw new Error('num must be an integer')
}
console.log(welcome + num)
}
What's the most straightforward way of doing this?
So far i've looked at:
sweet.js (online documentation looks out of date as I think it's going through some sort of internal rewrite)
esprima and escodegen (not sure where to start)
manually parsing using regular expressons
After evaluating all the various options, using sweet.js appears to be the best solution. It's still fairly difficult to get working (and I am probably doing stuff the wrong way) but just in case someone want's to do something similar this here was my solution.
'use strict'
syntax function = function(ctx) {
let funcName = ctx.next().value;
let funcParams = ctx.next().value;
let funcBody = ctx.next().value;
//produce the normal params array
var normalParams = produceNormalParams(funcParams)
//produce the checks
var paramChecks = produceParamChecks(funcParams)
//produce the original funcBody code
//put them together as the final result
var params = ctx.contextify(funcParams)
var paramsArray = []
for (let stx of params) {
paramsArray.push(stx)
}
var inner = #``
var innerStuff = ctx.contextify(funcBody)
for (let item of innerStuff) {
inner = inner.concat(#`${item}`)
}
var result = #`function ${funcName} ${normalParams} {
${paramChecks}
${inner}
}`
return result
function extractParamsAndParamChecks(paramsToken) {
var paramsContext = ctx.contextify(paramsToken)
//extracts the actual parameters
var paramsArray = []
var i = 0;
var firstItembyComma = true
for (let paramItem of paramsContext) {
if (firstItembyComma) {
paramsArray.push({
param: paramItem,
checks: []
})
firstItembyComma = false
}
if (paramItem.value.token.value === ',') {
firstItembyComma = true
i++
} else {
paramsArray[i].checks.push(paramItem.value.token.value)
}
}
for (var i = 0; i < paramsArray.length; i++) {
var checks = paramsArray[i].checks.join('').split(':')
checks.splice(0, 1)
paramsArray[i].checks = checks
}
return paramsArray
}
function produceNormalParams(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
//Produces the final params #string
var inner = #``
var first = true
for (let item of paramsArray) {
if (first === true) {
inner = inner.concat(#`${item.param}`)
} else {
inner = inner.concat(#`,${item.param}`)
}
}
return #`(${inner})`
}
function produceParamChecks(paramsToken) {
var paramsArray = extractParamsAndParamChecks(paramsToken)
var result = #``
for (let paramObject of paramsArray) {
var tests = produceChecks(paramObject)
result = result.concat(#`${tests}`)
}
return result
}
function produceChecks(paramObject) {
var paramToken = paramObject.param
var itemType = paramObject.checks[0]
var checks = paramObject.checks
if (itemType === undefined) return #``
if (itemType === 'array') {
return #`if (Object.prototype.toString.call(${paramToken}) !== "[object Array]") throw new Error('Must be array:' + ${paramToken})`
else {
throw new Error('item type not recognised: ' + itemType)
}
}
}
I am trying to figure out a javascript function that will help resolve this test. I need to be able to determine if the string of words (var matches) that is given is an anagram of the word that I am running through (var subject). In this case there would not be a match. Any and all help will be greatly appreciated. Thank you in advance!
var anagram = require('./anagram');
describe('Anagram', function() {
it("no matches",function() {
var subject = anagram("diaper");
var matches = subject.matches([ "hello", "world", "zombies", "pants"]);
expect(matches).toEqual([]);
});
});
This is what I have so far:
for (var i = 0; i < matches.length; i++) {
if (subject.length != matches[i].length) {
return false
} else if (subject.length == matches[i].length){
var anagram = function(subject, matches) {
return subject.split("").sort("").join("") === matches[i].split("").sort("").join("");
};
}
Here is the fiddle:
http://jsfiddle.net/hn8r4v3u/2/
I alphabetized the letters within the word, as you were doing, in a function.
function getAlphaSortedWord(word) {
var baseWordCharArray = word.split("");
baseWordCharArray.sort();
return baseWordCharArray.join("");
}
The code has a set up:
var baseWord = getAlphaSortedWord("bob");
var thingsToCheck = ["obb", "2", "bob", "", "bo", "ob"];
And then solves it two ways, once with filter and once without it.
var matches = _.filter(thingsToCheck, function (str) {
return (baseWord === getAlphaSortedWord(str));
});
var matches2 = [];
for (index = 0; index < thingsToCheck.length; index++) {
if (baseWord === getAlphaSortedWord(thingsToCheck[index])) {
matches2.push(thingsToCheck[index]);
}
}
You should be able to use these to tie in with your real data for the test to pass.
NOTE, I would add some sanity for "is string" to my function if this is going to be production code.
Found here and it works: https://gist.github.com/AlbertoElias/10005056
function areAnagrams(a, b) {
var c = false;
if (a.length !== b.length) {
return c;
}
var hashMap = {};
var char;
var i;
for (i=0;i<a.length;i++) {
char = a[i];
hashMap[char] = hashMap[char] !== undefined ? hashMap[char]+1 : 1;
}
for (i=0;i<b.length;i++) {
char = b[i];
if (hashMap[char] !== undefined) {
if (hashMap[char] > 1) {
hashMap[char]--;
} else {
delete hashMap[char];
}
} else {
return c;
}
}
if (Object.keys(hashMap).length === 0) c = true;
return c;
}
Given the following obj:
var inputMapping = {
nonNestedItem: "someItem here",
sections: {
general: "Some general section information"
}
};
I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.
Here is what I have so far and it works okay. But improve!
function getNode(name) {
var n = name.split(".");
if (n.length === 1) {
n = name[0];
} else {
var isValid = true,
evalStr = 'inputMapping';
for (var i=0;i<n.length;i++) {
evalStr += '["'+ n[i] +'"]';
if (eval(evalStr) === undefined) {
isValid = false;
break;
}
}
if (isValid) {
// Do something like return the value
}
}
}
Linky to Jsbin
You can use Array.prototype.reduce function like this
var accessString = "sections.general";
console.log(accessString.split(".").reduce(function(previous, current) {
return previous[current];
}, inputMapping));
Output
Some general section information
If your environment doesn't support reduce, you can use this recursive version
function getNestedItem(currentObject, listOfKeys) {
if (listOfKeys.length === 0 || !currentObject) {
return currentObject;
}
return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.
function getNode(mapping, name) {
var n = name.split(".");
if (n.length === 1) {
return mapping[name];
} else {
var tmp = mapping;
for (var i = 0; i < n.length; i++) {
tmp = tmp[n[i]];
}
return tmp;
}
}
i have this xml file:
<dist>
<key>keynumber1</key>
<string>value1</string>
<key>keynumber2</key>
<string>value2</string>
<key>keynumber3</key>
<string>value3</string>
<key>keynumber4</key>
<integer>value4</integer>
</dist>
how can i parse this with jquery like:
{ "dist": {"keynumber1":"value1", "keynumber2":"value2"}}
Thanks a lot for help
First step is parsing xml with jQuery using $.parseXML(str);
Then I used this pretty function, created by David Welsh
function xmlToJson(xml) {
// Create the return object
var obj = {};
if (xml.nodeType == 1) { // element
// do attributes
if (xml.attributes.length > 0) {
obj["#attributes"] = {};
for (var j = 0; j < xml.attributes.length; j++) {
var attribute = xml.attributes.item(j);
obj["#attributes"][attribute.nodeName] = attribute.nodeValue;
}
}
} else if (xml.nodeType == 3) { // text
obj = xml.nodeValue;
}
// do children
if (xml.hasChildNodes()) {
for(var i = 0; i < xml.childNodes.length; i++) {
var item = xml.childNodes.item(i);
var nodeName = item.nodeName;
if (typeof(obj[nodeName]) == "undefined") {
obj[nodeName] = xmlToJson(item);
} else {
if (typeof(obj[nodeName].length) == "undefined") {
var old = obj[nodeName];
obj[nodeName] = [];
obj[nodeName].push(old);
}
obj[nodeName].push(xmlToJson(item));
}
}
}
return obj;
};
DOM4 compareDocumentPosition
I want to implement compareDocumentPosition. Resig has made a great start at doing just this. I've taken his code and neatened it up
function compareDocumentPosition(other) {
var ret = 0;
if (this.contains) {
if (this !== other && this.contains(other)) {
ret += 16;
}
if (this !== other && other.contains(this)) {
ret += 8;
}
if (this.sourceIndex >= 0 && other.sourceIndex >= 0) {
if (this.sourceIndex < other.sourceIndex) {
ret += 4;
}
if (this.sourceIndex > other.sourceIndex) {
ret += 2;
}
} else {
ret += 1;
}
}
return ret;
}
This works for Element but does not for Text or DocumentFragment. This is because IE8 does not give .sourceIndex on those nodes. (It doesn't give .contains either but I've fixed that problem already)
How do I efficiently write the +=4 and +=2 bit which correspond to DOCUMENT_POSITION_FOLLOWING and DOCUMENT_POSITION_PRECEDING.
For extra reference those two are defined by tree-order which DOM4 defines as
An object A is preceding an object B if A and B are in the same tree and A comes before B in tree order.
An object A is following an object B if A and B are in the same tree and A comes after B in tree order.
The tree order is preorder, depth-first traversal.
Most modern browsers implement this (including IE9). So you only need something that works in IE8 (I don't care about IE6/7, but if it works awesome!)
function recursivelyWalk(nodes, cb) {
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i];
var ret = cb(node);
if (ret) {
return ret;
}
if (node.childNodes && node.childNodes.length) {
var ret = recursivelyWalk(node.childNodes, cb);
if (ret) {
return ret;
}
}
}
}
function testNodeForComparePosition(node, other) {
if (node === other) {
return true;
}
}
function compareDocumentPosition(other) {
function identifyWhichIsFirst(node) {
if (node === other) {
return "other";
} else if (node === reference) {
return "reference";
}
}
var reference = this,
referenceTop = this,
otherTop = other;
if (this === other) {
return 0;
}
while (referenceTop.parentNode) {
referenceTop = referenceTop.parentNode;
}
while (otherTop.parentNode) {
otherTop = otherTop.parentNode;
}
if (referenceTop !== otherTop) {
return Node.DOCUMENT_POSITION_DISCONNECTED;
}
var children = reference.childNodes;
var ret = recursivelyWalk(
children,
testNodeForComparePosition.bind(null, other)
);
if (ret) {
return Node.DOCUMENT_POSITION_CONTAINED_BY +
Node.DOCUMENT_POSITION_FOLLOWING;
}
var children = other.childNodes;
var ret = recursivelyWalk(
children,
testNodeForComparePosition.bind(null, reference)
);
if (ret) {
return Node.DOCUMENT_POSITION_CONTAINS +
Node.DOCUMENT_POSITION_PRECEDING;
}
var ret = recursivelyWalk(
[referenceTop],
identifyWhichIsFirst
);
if (ret === "other") {
return Node.DOCUMENT_POSITION_PRECEDING;
} else {
return Node.DOCUMENT_POSITION_FOLLOWING;
}
}
I wrote it myself. I thought this implementation was bugged but it was a bug in some other code of mine. Seems pretty solid.
The answer from Raynos is a top start, but is not runnable out of the box. Node.* cannot be found and .bind is not available in IE8.
Here is the code ready for use in Internet Explorer 8:
function recursivelyWalk(nodes, cb) {
for (var i = 0, len = nodes.length; i < len; i++) {
var node = nodes[i];
var ret = cb(node);
if (ret) {
return ret;
}
if (node.childNodes && node.childNodes.length) {
var ret = recursivelyWalk(node.childNodes, cb);
if (ret) {
return ret;
}
}
}
}
function testNodeForComparePosition(node, other) {
if (node === other) {
return true;
}
}
var DOCUMENT_POSITION_DISCONNECTED = 1;
var DOCUMENT_POSITION_PRECEDING = 2;
var DOCUMENT_POSITION_FOLLOWING = 4;
var DOCUMENT_POSITION_CONTAINS = 8;
var DOCUMENT_POSITION_CONTAINED_BY = 16;
function compareDocumentPosition(thisNode, other) {
function identifyWhichIsFirst(node) {
if (node === other) {
return "other";
} else if (node === reference) {
return "reference";
}
}
var reference = thisNode,
referenceTop = thisNode,
otherTop = other;
if (this === other) {
return 0;
}
while (referenceTop.parentNode) {
referenceTop = referenceTop.parentNode;
}
while (otherTop.parentNode) {
otherTop = otherTop.parentNode;
}
if (referenceTop !== otherTop) {
return DOCUMENT_POSITION_DISCONNECTED;
}
var children = reference.childNodes;
var ret = recursivelyWalk(
children,
function(p) {
(function() {
var localOther = other;
return testNodeForComparePosition(localOther, p);
})();
}
);
if (ret) {
return DOCUMENT_POSITION_CONTAINED_BY +
DOCUMENT_POSITION_FOLLOWING;
}
var children = other.childNodes;
var ret = recursivelyWalk(
children,
function(p) {
(function() {
var localOther = reference;
return testNodeForComparePosition(localOther, p);
})();
}
);
if (ret) {
return DOCUMENT_POSITION_CONTAINS +
DOCUMENT_POSITION_PRECEDING;
}
var ret = recursivelyWalk(
[referenceTop],
identifyWhichIsFirst
);
if (ret === "other") {
return DOCUMENT_POSITION_PRECEDING;
} else {
return DOCUMENT_POSITION_FOLLOWING;
}
}
You call it like this:
compareDocumentPosition(sourceElement, elementToTest)
(It's like calling sourceElement.compareDocumentPosition(elementToTest))