How to find application scripts in node inspector faster? - node.js

While watching node-inspector screencasts I noticed app scripts on top of scripts list and they contains full path.
But when I using it - all scripts are shuffled with system scipts and it very hard to find ones that relates only to my app.
What I do wrong?

You don't do anything wrong, the code has just evolved between the screencasts and now...
To re-enable the full path files visible you could apply the following :
At the line 192 in the file node-inspector/lib/session.js you will find this function call :
scripts.forEach(function(s) {
var hidden = config.hidden &&
config.hidden.some(function(r) { return r.test(s.url); }),
item = { hidden: hidden, path: s.url };
if (s.path.length > 1) s.url = shorten(s.path);
item.url = s.url;
sourceIDs[s.sourceID] = item;
delete s.path;
if (!hidden) {
sendEvent('parsedScriptSource', s);
}
});
To have the full path of the file in the debugger just remove the line where the url is shortened like this :
//if (s.path.length > 1) s.url = shorten(s.path);
This will do the job even if not an optimal solution.
PS : you will find the source of this file here : https://github.com/dannycoates/node-inspector/blob/master/lib/session.js

Related

Loop trough nested folder structure and change a line in all files with node.js

I want to write a script that loops through a nested folder structure and changes for instance console.log('hello world') in each javascript file. I simplified the task and basically can't use the in-built VS search and replace tool. Folder structure looks like this:
My try:
function changeLine(folderPaths) {
folderPaths.forEach(folderPath=> {
const results = fs.readdirSync(folderPath)
const folders = results.filter(res=> fs.lstatSync(path.resolve(folderPath, res)).isDirectory())
const innerFolderPaths = folders.map(folder => path.resolve(folderPath, folder));
if(innerFolderPaths.length ===0) {
return
}
innerFolderPaths.forEach(
inner=>{
if(fs.lstatSync(inner).isDirectory()) {
//go deeper and change individual file
let individualFile = fs.readFileSync(<go to individual file>).toString()
individualFile = fileString.replace(/console.log('hello world')/, 'line changed');
}}
)
})
}
changeLine([path.resolve(__dirname, 'src')] )
I don't have much experience with node.js and that's what I came up with so far. The if condition inside the forEach Loop is not correct, hope someone can make sense of it. Thanks for reading!

Orchard CMS Contrib.Review module

I am beginner in Orchard CMS and i need add voting functionality to content. I have installed Contib.Vote and Contrib.Review modules. After that i have added Review part to page content type. Also, i have executed recipe. At the first look everything is fine, but link for review refer to the same page with # symbol and nothing is happenning by clicking on it. It seems like module does not work or work incorrectly. Please help with my problem.
UPD.
Hi devqon and thanx for your help. Your answer was really useful for me. According to your advice i was looking around javascript inside Review Part view file (Parts_Reviews.cshtml). Just for a test i changed its source code a little bit.
#using (Script.Foot())
{
<script type="text/javascript">
//<![CDATA[
(function () {
var numberOfReviewsToShowByDefault = 5;
var $showAllReviewsLink = $('#showAllReviewsLink');
var $deleteReviewConfirmationDialogDiv = $('#deleteReviewConfirmationDialogDiv');
$deleteReviewConfirmationDialogDiv.dialog({ autoOpen: false, modal: true, resizable: false });
$('#deleteReviewLink').click(function () {
$('#reviewId').val($(this).attr("data-review-id"));
ShowDeleteReviewDialog();
return false;
});
$('#showReviewFormLink').click(function () {
$('#createReviewLinkDiv').slideToggle('fast', function () { $('#reviewFormDiv').slideToggle('fast'); });
return false;
});
$('#cancelCreateReviewLink').click(function () {
$('#reviewFormDiv').slideToggle('fast', function() { $('#createReviewLinkDiv').slideToggle('fast'); });
return false;
});
$('#deleteReviewForm').submit(function () {
$('input[type=submit]', this).attr('disabled', 'disabled');
});
$('#cancelDeleteReviewButton').click(function () {
CloseConfirmationDialogDiv();
return false;
});
var rowCount = $('#reviewsList li').length;
if (rowCount > numberOfReviewsToShowByDefault) {
SetupToggle();
}
if (document.location.hash === '#Reviews') {
var topPx = $('#reviews-heading').position().top;
$('body,html').animate({ scrollTop: topPx }, 'slow');
}
if ($("#comment").length) {
var characterCountUpdater = new CharacterCountUpdater($("#comment"), $("#commentCharactersLeft"));
setInterval(function() { characterCountUpdater.UpdateCharacterCount(); }, 100);
$("#comment").keypress(function() { characterCountUpdater.UpdateCharacterCount(); });
if ($("#comment").val().length) {
$("#showReviewFormLink").trigger("click");
}
}
function CharacterCountUpdater(commentBox, charactersLeftBox)
{
this.commentBox = commentBox;
this.charactersLeftBox = charactersLeftBox;
this.maxLength = commentBox.attr("maxlength");
commentBox.removeAttr("maxlength");
return this;
}
Now form for review is displayed. The form looks good, submit button works, character counter works too. But i still can't apply my rating. Stars not react on clicking. That is why submit operation ends with error 'In order to submit a review, you must also submit a rating.'. Look like something inside Parts.Stars.NoAverage.cshtml does not work. Please, help me.
According to the project's site it is a known issue: broken from version 1.7.2.
When looking at the code of the Parts_Reviews.cshtml it says the following on lines 20-24:
string showReviewUri = "#";
if (!Request.IsAuthenticated)
{
showReviewUri = Url.Action("LogOn", "Account", new { area = "Orchard.Users", ReturnUrl = Context.Request.RawUrl });
}
and on line 29:
<div id="createReviewLinkDiv"><span id="createReviewLinkSpan">#noReviewsYetText<a id="showReviewFormLink" href="#showReviewUri">#reviewLinkText</a></span></div>
Therefore, it was intended to let the anchor be # when the request is authenticated (you are logged on). This means it probably will be handled in JavaScript, which can be seen on lines 105-112:
$('#showReviewFormLink').click(function () {
$('#createReviewLinkDiv').slideToggle('fast', function () { $('#reviewFormDiv').slideToggle('fast'); });
return false;
});
$('#cancelCreateReviewLink').click(function () {
$('#reviewFormDiv').slideToggle('fast', function() { $('#createReviewLinkDiv').slideToggle('fast'); });
return false;
});
This piece of code should let you see the form to write a review, so something is going wrong there presumably. When there's something wrong in this jQuery code it probably gives an error in the console, so check out the browser's console when you click the 'Be the first to write a review' link.
This should get you further, if you don't know what to do please provide the error and I will try to dig more. I haven't downloaded the module so I don't have live feed.
Console of Firefox tells: $(...).live is not a function. It refers to Contrib.Stars.js source code file. This function is not supported in jquery now and i replaced it by .on() function in all places api.jquery.com/on. Now module works fine.
Check out my comment at the site below to see how I was was able to get it working again on Orchard 1.8.1:
Orchard Reviews Project Site
You basically just need to change 3 different lines in the Contrib.Stars.js file but I would recommend copying the .js file along with the Review module's different views to a custom theme directory, in order to override everything and force the Reviews module to use your edited .js file:
On line 12 & 13:
Change this:
$(".stars-clear").live(
"click",
To this:
$("body").on(
"click", ".stars-clear",
On line 44 & 45:
Change this:
.live(
"mouseenter",
To this:
.mouseenter(
On line 48 & 49:
Change this:
.live(
"mouseleave",
To this:
.mouseleave(

How to scan an entire directory tree with node.js?

Often I would want to scan an entire directory tree (a directory, and everything inside it, including files, subdirs, and those subdir contents too, and their subdir contents too, etc etc).
How would one accomplish this with node? Requirements, is that it should be asynchronous to take advantage of super fast non-blocking IO - and not crash when processing too many files at once.
-- I've updated this answer in 2017 for the progress since 2012 --
Ended up creating these to accomplish it:
https://github.com/bevry/safefs - which now uses https://npmjs.org/package/graceful-fs (which didn't exist before)
https://github.com/bevry/scandirectory - there is also now a vast array of like projects like this
I also created this which is lightweight and super fast:
https://github.com/bevry/readdir-cluster
You can use the module npm dree if you want to achive that. It returns a json that describes the directory tree and it allows you to specify also a fileCallback and a dirCallback, so you can do this:
Here is the code:
const dree = require('dree');
const fileCb = function(file) {
// do what you want
}
const dirCb = function(directory) {
// do what you want
}
dree.scan('path-to-directory', { extensions: [ 'html', 'js' ] }, fileCb, dirCb);
If you want to stick with the 'fs' module, you can do some recursive functions to get them.
Heres a function I made recently to get the tree of a directory.
const fs = require("fs");
// dir is file, depth is how far into a directory it will read.
function treeFiles(dir, depth = 1000) {
if (depth < 1) return;
var sitesList = {};
fs.readdirSync(dir).forEach((file) => {
let base = dir + '/' + file;
// Add file to siteslist object.
sitesList[file] = {"stats": fs.statSync(base), "dir": false};
// Recursive to get directory and tree of files
if (fs.statSync(base).isDirectory()) {
sitesList[file]["dir"] = true;
sitesList[file]["ls"] = treeFiles(base, depth - 1);
}
});
return sitesList;
}
So if I have a file structure which looks like
nodejs_app >
- app.js
- config.js
- images >
- - logo.png
Then the final output of my function reading the nodejs_app directory will look like
{
"app.js": {"stats": {}, "dir": false},
"config.js": {"stats": {}, "dir": false},
"images": {"stats": {}, "dir": true, "ls": {
"logo.png": {"stats": {}, "dir": false}
}
}
Then just call the function with directory and depth into the directory if you want.
let dir = require("path").join(__dirname, "nodejs_app");
let tree = treeFiles(dir);
console.log(tree);
Of course change paths and names to fit your code. I included the depth as to reduce time it takes for it to finish reading a directory.

When I close a window and then open a different one, the selected tab is recreated by Chrome

I am writing a Chrome extension that saves/restores your browsers window state - So, I save the state of a given window:
var properties = [ "top",
"left",
"width",
"height",
"incognito",
"focused",
"type"
];
var json = {};
var cache = chrome_window_object;
// copy only the keys we care about:
_.each(properties,function(key,value) {
json[key] = cache[key];
});
// then copy the URLs of the tabs, if they exist:
if(cache.tabs) {
json.url = [];
_.each(cache.tabs,function(tab) {
json.url.push(tab.url);
});
}
return json;
At some point in the future, I remove all windows:
closeAllWindows: function(done_callback) {
function got_all(windows) {
var index = 0;
// use a closure to only close one window at a time:
function close_next() {
if(windows.length <= index) return;
var window = windows[index++];
chrome.windows.remove(window,close_next);
}
// start closing windows:
close_next();
}
chrome.windows.getAll(got_all);
}
and then I restore the window using:
chrome.windows.create(json_from_before);
The window that is created has an extra tab in it, whatever was in the window that I just closed... I am completely floored, and I assume the problem is something that I am doing in the code that I haven't posted (it's a big extension). I've spent a few hours checking code line by line and making sure I'm not explicitly asking for this tab to be created. So - has anybody seen anything like this before?

Chrome Bookmarks API -

I'm attempting to create a simple example that would just alert the first 5 bookmark titles.
I took Google's example code and stripped out the search query to see if I could create a basic way to cycle through all Nodes. The following test code fails my alert test and I do not know why.
function dumpBookmarks() {
var bookmarkTreeNodes = chrome.bookmarks.getTree(
function(bookmarkTreeNodes) {
(dumpTreeNodes(bookmarkTreeNodes));
});
}
function dumpTreeNodes(bookmarkNodes) {
var i;
for (i = 0; i < 5; i++) {
(dumpNode(bookmarkNodes[i]));
}
}
function dumpNode(bookmarkNode) {
alert(bookmarkNode.title);
};
Just dump your bookmarkTreeNodes into the console and you will see right away what is the problem:
var bookmarkTreeNodes = chrome.bookmarks.getTree(
function(bookmarkTreeNodes) {
console.log(bookmarkTreeNodes);
});
}
(to access the console go to chrome://extensions/ and click on background.html link)
As you would see a returned tree contains one root element with empty title. You would need to traverse its children to get to the actual bookmarks.
Simple bookmark traversal (just goes through all nodes):
function traverseBookmarks(bookmarkTreeNodes) {
for(var i=0;i<bookmarkTreeNodes.length;i++) {
console.log(bookmarkTreeNodes[i].title, bookmarkTreeNodes[i].url ? bookmarkTreeNodes[i].url : "[Folder]");
if(bookmarkTreeNodes[i].children) {
traverseBookmarks(bookmarkTreeNodes[i].children);
}
}
}

Resources