How to access callback on grunt task set up in initConfig - javascript

I've got an issue that I can't seem to resolve. I have tried a couple different ways, but nothing is working yet.
I am using grunt-messageformat to create my i18n localized copy. I have 2 folders with languages in them and I'd like to have grunt automatically generate the correct output for each folder (language).
The task that got me closest is this:
grunt.registerTask("ReadFolders", "Read the language folders in app/data/i18n/", function () {
// Returns an array of the paths to the language folders.
// ['app/data/i18n/en', 'app/data/i18n/key', ...]
var languageFolders = grunt.file.expand("app/data/i18n/*");
var path;
var languageName;
var i;
for (i = 0; i < languageFolders.length; i++) {
path = languageFolders[i];
languageName = path.substring(path.lastIndexOf("/") + 1, path.length);
grunt.config.set("mFormat.locale", languageName);
grunt.config.set("mFormat.inputdir", "app/data/i18n/" + languageName);
grunt.config.set("mFormat.output", "app-dist/test/js/locales/" + languageName + "/i18n.js");
grunt.task.run("messageformat:all");
}
});
This also uses the following code for my messageformat task, which is set up in initConfig:
messageformat: {
all: {
locale: "<%= mFormat.locale %>",
inputdir: "<%= mFormat.inputdir%>",
output: "<%= mFormat.output%>"
}
}
The problem is that my loop in 'readFolders' runs through twice before the messageFormat task runs, which means the task runs twice, but both times it uses the last values for the mFormat variables.
I don't see any examples of how to access a callback of a task that is set up using initConfig.
Any thoughts? Or other ideas?
Thanks

Well I didn't find a way to do what I had originally asked... But I found a good workaround that fulfills my needs. Instead of running the task for each folder, I instead rewrite the messageformat config dynamically for each language.
grunt.registerTask("ReadFolders", "Read the language folders in app/data/i18n/", function () {
// Returns an array of the paths to the language folders.
// ['app/data/i18n/en', 'app/data/i18n/key', ...]
var languageFolders = grunt.file.expand("app/data/i18n/*");
var path;
var languageName;
var locale;
var messageFormat = {};
var i = 0;
for (i = 0; i < languageFolders.length; i++) {
path = languageFolders[i];
languageName = path.substring(path.lastIndexOf("/") + 1, path.length);
locale = languageName;
if (languageName === "key") {locale = "en"; }
messageFormat[languageName] = {
locale: locale,
inputdir: "app/data/i18n/" + languageName,
output: "app-dist/test/js/locales/" + languageName + "/i18n.js"
};
}
grunt.config.set("messageformat", messageFormat);
grunt.task.run("messageformat");
});
After quite an exhaustive search, I think this is the only possible (and quite frankly, in my case, the better) solution.
Still happy to hear about any other ideas if anyone's got any.

Related

javascript functions wait for data availability or variable not capable of handling huge data

forgive the trivial question but I am more used to C++ and Python code than javascript.
I have the following code from the THREE JS PLY loader:
var geometry;
var scope = this;
if (data instanceof ArrayBuffer) {
geometry = isASCII(data) ? parseASCII(bin2str(data)) : parseBinary(data);
} else {
geometry = parseASCII(data);
}
parse: function (data) {
function isASCII(data) {
var header = parseHeader(bin2str(data));
return header.format === 'ascii';
}
function bin2str(buf) {
var array_buffer = new Uint8Array(buf);
var str = '';
for (var i = 0; i < buf.byteLength; i++) {
str += String.fromCharCode(array_buffer[i]); // implicitly assumes little-endian
}
return str;
}
It works fine if I load a small ply file but browser crashes on very large one. I believe there are two "possible" issues:
1) on a large file the string str returned by the function bin2str(buf) might not be able to handle the parsing process
2) in the function isASCII(data) the line
parseHeader(bin2str(data));
crashes the browser as the bin2str(data) cannot return a proper value in time as the process is very memory consuming
I am using the conditional as i am not totally sure of what the problem is. Any suggestion and/or possible solution?
Thank you,
Dino
In the end the solution I have adopted was to decimate my file using the free software MeshLab.
Hope this helps.
Dino

Nodeschool's Stream-Adventure #12 Duplexer redux

It's been days since I'm trying several ways to solve this exercice. I give up. What am I doing wrong here ? Why am I getting "write after end" error if the event I'm using is the "end" event and I don't write anything to the pipe ? I'm just changing an object after it's use. Or at least I think so.
var duplexer2 = require("duplexer2");
var through = require('through2');
module.exports = function (counter) {
var countries = {};
var duplex = duplexer2(through.obj(function (obj, encoding, done) {
if (obj.country in countries)
countries[obj.country]++;
else
countries[obj.country] = 1;
done();
}), counter);
duplex.on("finish", function() {
counter.setCounts(countries);
});
counter.pipe(duplex);
return duplex;
};
If I substitute the line counter.setCounts(countries); for console.log(countries) I see that it's populated correctly.
Problem text: http://pastebin.com/vAM4vKZg
I have read this exercice test file and counldn't get any clue from it as it only compares the objects to see if they're correct.
Your solution is almost correct. Just remove the counter.pipe(duplex); line and it works. You do not need to pipe anything to the duplex stream you created, the stream adventure is going to do that to check if it works :).

Dynamically adjust object names based on parameter

I'm running a script on an apache webserver on a linux box. Based on the parameter I want to change the name of variable(or set it)
The idea is that humDev(lines 11 and 14) is named humDev21 for example. Where devId is the number 21 in this example.
My script looks like this:
function getHumDev(devId){
$.ajax({
async: false,
url: "/url" + devId,
success: function(result) {
var array = result["Device_Num_" + devId].states;
function objectFindByKey(array, key, value) {
for (var i = 0; i < array.length; i++) {
if (array[i][key] === value) {
humDev = array[i].value;
}
}
return humDev;
};
objectFindByKey(array, 'service', 'some');
}
});
};
If Im looking in the wrong direction, please do let me know. Maybe its bad practice what Im trying. The reason I want to have the object a unique name is because this function is called several times by another function, based on the content of an array. But when I have the humDev object named without the number suffix to make it unique, the content of the object is getting mixed up between the different calls.
I may be off base but I am making some assumptions based on what I understand of what you are trying to do.
First, you need to understand how to do file I/O in node.js. So lets start there:
var pathToFile, //set with file path string
fs = require('fs'), //require the file i/o module API
bunchOfHumDevs = {},
fileContents; //we'll cache those here for repeated use
fs.readFile(pathToFile, function(err, result) {
if (err) {
throw new Error(); //or however you want to handle errors
} else {
fileContents = JSON.parse(result); //assumes data stored as JSON
}
});
function getHumDev(devId) {
//first make sure we have fileContents, if not try again in 500ms
if (!fileContents) {
setTimeout(function() {
getHumDev(devId);
}, 500);
} else {
var array = fileContents["Device_Num_" + devId].states,
i = array.length,
//if 'service' and 'some' are variable, make them params of
//getHumDev()
while (i--) {
if (array[i]['service'] === 'some') {
//store uniquely named humDev entry
bunchOfHumDevs['humDev' + devId.toString()] = array[i].value;
break; //exit loop once a match is found
}
}
}
return null;
}
getHumDev(21);
assuming a match is found for the devId 21, bunchOfHumdevs will now have a property 'humDev21' that is the object (value?) in question. Also, the fileContents are now cached in the program so you don't have to reopen it every time you call the function.

ExtJS 4 - Cannot read property 'substring' of undefined

I am new to Ext JS 4 and I am currently developing a pretty complex Ext JS MVC application that follows the architecture explained in this (basic) tutorial.
http://docs.sencha.com/extjs/4.0.7/#%21/guide/application_architecture.
Almost all the times I add a new view with the related model, controller and store, as first step I have to fix some mispelled alias or id. It comes to be very tricky since ext does not help me as I would expect, and there is a lot of these ids to look for.
Using Firebug, the error message given to me is:
Uncaught TypeError: Cannot read property 'substring' of undefined localhost:8080/Web/extjs4/ext-debug.js:5246
Is there a way to quickly undestand where the mispelling is?
This is the code portion where the exception is thrown
parseNamespace: function(namespace) {
var cache = this.namespaceParseCache,
parts,
rewrites,
root,
name,
rewrite, from, to, i, ln;
if (this.enableNamespaceParseCache) {
if (cache.hasOwnProperty(namespace)) {
return cache[namespace];
}
}
parts = [];
rewrites = this.namespaceRewrites;
root = global;
name = namespace;
for (i = 0, ln = rewrites.length; i < ln; i++) {
rewrite = rewrites[i];
from = rewrite.from;
to = rewrite.to;
// 5246
if (name === from || name.substring(0, from.length) === from) {
name = name.substring(from.length);
if (typeof to != 'string') {
root = to;
} else {
parts = parts.concat(to.split('.'));
}
break;
}
}
parts.push(root);
parts = parts.concat(name.split('.'));
if (this.enableNamespaceParseCache) {
cache[namespace] = parts;
}
return parts;
},
Thanks in advance.
I sanity check my code with console.log( Ext.getClassName(someObj) ); -- sometimes JSLint can help you find unused variables -- Good Luck!

how to reload javascript file

I have a question about reloading JavaScript files. I develop web pages front-ends and do a lot of coding in JS. Every time when I want to check an application's flow is correct (or do some debugging) I have to hit F5 key to reload whole page and it's scripts, and I have to wait. Waiting time depends on page's weight and sometimes I get impatient. Therefore I wonder if there is any way to reload only changed script file *.js? or maybe there is some plugin for Chrome to reload chosen script? It could be a very handy way to ease development. Thank you for replies.
this one uses jQuery, it is here for example:
var scs=$('script[type*=javascript]');
var scsl = scs.length;
var scsi = 0;
var o = [];
var oi = 0;
var ol = 0;
var s = '';
var fws = 0;
var sws = 0;
var v = {};
function i1(){
fws = window.setInterval(function(){
        v = $(scs[scsi]);
        
        s = v.attr('src');
        if(typeof s!='undefined' && s.indexOf('http')==-1 && s.indexOf('index')==-1){
                console.log([scsl,scsi,s]);
                o.push({src:s});
                v.remove();
        }
        if(scsi==scsl){
                console.log(o);
                window.clearInterval(fws);
                ol = o.length;
i2();
        }
        else{
                scsi++;
        }
},800);
}
function i2(){
                sws=window.setInterval(function(){
                        v = o[oi];
                        sc = $('<script>').attr({type:'text/javascript',src:v.src+'?t='+(new Date().getTime())});
                        console.log([ol,oi,v.src]);
                        $('head').append(sc);
                        if(oi==ol-1){
                                window.clearInterval(sws);
                        }
                        else{
                                oi++;
                        }
                },800);
}
i1();
As far as I know, there is no way to to do that. The problem is, you just cannot unload a script from a page, once it was evaluated.
Even if you remove the <script> node, it will not change the behavior. It might be possible with some third-party plugin for instance, but I'm almost sure its not possible with any vanilla js implementation.
Of course you could just load the same script file from your server and execute (eval) it, but again, you still didn't unload the previous code which could lead to very unexpectable behavior.
So, you have to keep your F5 key on its toes.
You might try the new Scratchpad feature in Firefox (I think it's been in releases since 7.0).
When I'm revving hard on a new piece of javascript I do it in the scratchpad and then copy out to my editor when I like it. Basically, I do all my work in functions and objects that can be redefined on the fly (doesn't everyone?). This way I can just re-run the function definition or reassign an objects method/data and it's a lot faster than waiting for refresh cycles.
In Dojo or CommonJS based frameworks its not a problem at all. Javascript code is usually hold in a module.
In our web-based IDE we reload scripts all the time like this (#reloadCustomMobileStack) :
define([
'dojo/_base/declare',
'require'
], function(declare,require)
{
return dojo.declare("xappstudio.manager.DynamicScriptMixin", null,
{
_reloadModule:function(module,reload)
{
require.undef(module);
var scripts = document.getElementsByTagName('script');
for (var i = scripts.length - 1; i >= 0; i--)
{
var script = scripts[i];
if (script.getAttribute('src') && script.getAttribute('src').length > 0 && script.getAttribute('src').indexOf(module)!=-1)
{
script.parentNode.removeChild(script);
break;
}
}
if(reload)
{
require([module], function(_moduleIn)
{
console.error('got module' + _moduleIn);
});
}
},
reloadCustomMobileStack:function()
{
var modulesToReload = [
'cxapp/delegates/BootDelegate',
'cxapp/delegates/FormDelegate',
'cxapp/delegates/HeaderToolbarDelegate',
'cxapp/delegates/ImageResizeDelegate',
'cxapp/delegates/ServiceDelegate',
'cxapp/delegates/UrlDelegate',
'cxapp/manager/Context',
'cxapp/manager/CustomApplication',
'cxapp/manager/DataManager',
'cxapp/types/Types',
'cxapp/utils/RPCProxyPOSTEnvelope'
];
for(var i = 0 ; i < modulesToReload.length ; i++)
{
this._reloadModule(modulesToReload[i],true);
}
}
});
});
In order to use require.undef(module), you need to add this here to your Dojo config: has:{'dojo-undef-api': true}
Of course that won't work with any Javascript since Dojo/Common-JS Javascript is different but enables you also a kind of dependency injection or resolving.

Categories