I was exploring how to get insight into a piece of JS code running on NodeJS. All the things were there but for some reason the unit tests were not behaving correctly.
To debug this using node-inspector seem to be the logical choice but I could not find an easy way avenue to get things started.
I would normally start my unit test pointing nodeunit to a directory using the windows command that becomes available after installing nodeunit via npm globally:
c:\> nodeunit /test
This would run through all the unit tests in the /test directory. I wanted a similar mechanism when I needed to run debugging. Googling things was not very helpful as all the examples I found were OSX or Linux specific. However, the solution in the end was fairly simple.
Here are the steps from the beginning:
a) install node-inspector globally
c:\> npm install -g node-inspector
b) install nodeunit globally
c:\> npm install -g nodeunit
c) locate the nodeunit command file normally somewhere like C:\Users\[logged in user]\AppData\Roaming\npm\nodeunit.cmd. Or you can use the "where" command like so:
c:\> where nodeunit
d) use a text editor like notepad to open the command file
e) change the nodeunit command file by adding the debug flags (--debug-brk) and save as nodeunit-debug.cmd. Here is the content of the fully changed command file:
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "--debug-brk %~dp0\node_modules\nodeunit\bin\nodeunit" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node --debug-brk "%~dp0\node_modules\nodeunit\bin\nodeunit" %*
)
You are done with your setup config. Thereafter you only need to use the new debug command when you want to debug test cases.
a) run your tests with new nodeunit-debug command you just created. You should, of course, do so in the directory of your application rather than in the root of the drive. Assuming that all your unit tests are under a /test subdirectory you could do it like so:
c:\[app dir]> nodeunit-debug /test
b) in second command window run node inspector instance and inspect code in browser (Chrome)
c:\> node-inspector
c) open chrome to debug your code (http://127.0.0.1:8080/?ws=127.0.0.1:8080&port=5858)
Here is an image of a,b, and c steps in action:
That is it.
Cheers,
B.
Bilal's view on tech and code (Java, C#, vb, cfml, JavaScript, NodeJS, etc, etc.) and some random other musings.
Wednesday, November 11, 2015
Wednesday, July 15, 2015
JQM: A mini MVC Application Structure using jQuery Mobile and RequireJS
The Rational
When it comes to the power jQuery Mobile (jqm) to help us organize our code we could pretty much say it in one hyphened word: "non-existent".How could this pass with such a popular library. Well, the simple answer is that it is by design. This does not mean, however, that you should not organize your jqm code projects. You are free to use any JavaScript organizing principle or helper library, e.g. BackBone or Ember, you like. Jqm's focus is the page paradigm and rendering of touch friendly UI.
This, of course, does mean that you have your work cut out for you to make decisions surrounding your project. Looking at very common pattern of jqm apps, they tend to be an amalgamation of different libraries that have many layers of code and logic that needs to be organized. And, needless to say, there is always seems to be a little bit of overlap in library's coverage, e.g. if you used Backbone for route handling, we will need to turn off the native jqm methodology etc.
In the particular approach I am outlining in this post, the goal was to use minimal amount of libraries while still creating convention based organization of code, ui, and data. We should be able to split our program into distinct parts that the browser can load when needed.
This will help us in following manner:
- decoupling of presentation and logic
- modular JavaScript code
- decoupling of the page paradigm from singular page apps
- organization of code by convention
Overall, the maintenance of our program should be easier, while adding new parts becomes child-play ;o)
After a little experimentation, I decided the only thing needed was a little extra JavaScript and the RequireJS library. Let me explain how.
The Setup
Standard application initialization occurs through the index.html page. However, unlike most JS apps there is only one <script> tag and that tag loads RequireJS. Thereafter the application parts are either loaded by RequireJS or JQM page loader. Thus, the script tag jungle is avoided. Clean abstractions of dependencies and libraries are all captured in the RequireJS config file.Since this is a sample app it makes liberal use of console.log function.
<script data-main="app/config" src="libs/require.js"></script>
Also something that is different here is the externalized page header. I did not add an externalized page footer which can be easily done but was not needed for my example. An externalized header can easily be repeated on each subsequently loaded jqm page and thus we can focus on the page content. We will still change the header display dynamically and add proper navigation as we move between pages.
<!-- external header used on all pages we will hide buttons dynamically --> <header data-theme="b" data-role="header" data-title="Simple App" data-position="fixed"> <a id="btnHome" data-rel="back" data-transition="slide" class="ui-btn ui-shadow ui-corner-all ui-icon-arrow-l ui-btn-icon-notext ui-btn-inline" title="move back">back</a> <h1></h1> <a href="#info" id="btnInfo" class="ui-btn-right ui-btn ui-btn-inline ui-btn-icon-notext ui-mini ui-corner-all ui-icon-info" title="">Info</a> </header>
The Application Structure
The application is structured in such a fashion that a certain convention can be observed.The main directories under /app are
- controllers
- data
- pages
- services
- stores
All code files except the RequireJS config file are in a slightly modified JavaScript AMD Module format.We are also caching jqm views (pages) once they have been loaded using the jqm domCache directive:
$.mobile.page.prototype.options.domCache = true;
controllers
This is where we place all controller logic for our views. I maintained a convention where views do not have any logic or binding and minimal links. Controllers are automatically loaded and initialized based on the view (page) that is being requested. The app will check for a similarly named controller and start the process. Thus, all page behavior, event binding, business logic would be handled here.If the controller exports (or exposes) a function named "init", that function will be called after each page load or display.
The overall convention for the controller loading process and application behavior are coded into start.js module. It acts as the overall controller for the application.
Here is the basic controller construct example.
//controller sample define( function() { console.log("empty controller loaded"); //public (export) return { init: function(){ console.log("init was called") } } });
data
I have placed a file containing a json array of objects into this file. Thus, we can refer to this as our "database". This is not a convention that is enforced on the code layer. I chose to abstract data in this fashion. It could easily be extended to be the connection layer to a database API etc.pages
The pages in our app are the view of the MVC model. I chose to use very simple views. These are snippets of HTML just with the JQM markup needed to render a basic skeleton. Logic that changes the view is either in controller or services layer.Here is an example of a view. It is just the date-role="page" part of the jqm html markup.
<section data-role="page" id="composerDetail" data-title="Composer Detail"> <div role="main" class="ui-content"> <h2 id="composerName">Composer Name</h2> <hr> <!-- composer info --> <div class="ui-grid-a ui-responsive" > <div class="ui-block-a center" style="width:20%;"> <div class=""> <img id="composerImage" src="" alt="composer image" style="vertical-align: middle;"> </div> </div> <div class="ui-block-b" style="width:80%; vertical-align: top;"> <div class="ui-body ui-body-d"><p id="composerDescription">composer information</p></div> </div> </div> <!-- buttons --> <div class="ui-grid-a center" > <div class="ui-block-a" style="width:20%;"> <div class="ui-body ui-body-d"><a data-rel="back" data-transition="slide" class="ui-btn ui-shadow ui-corner-all ui-icon-arrow-l ui-btn-icon-notext ui-btn-inline" title="Back to composer list">back to list of composers</a></div> </div> <div class="ui-block-b" style="width:80%;"> <div class="ui-body ui-body-d"> <button id="btnWiki" class="ui-btn ui-icon-arrow-u-r ui-btn-icon-right ui-corner-all" title="More information on WikiPedia" style="width:80%">WikiPedia</button> </div> </div> </div> </div> </section>
services
This is where I paced example services that can be used in other modules. In my case just a way to abstract jquery ajax calls and handle generic responses. But, this could be easily expanded to anything that is shareable across the modules or detailed implementation that would be make controllers large and unwieldy. This is not a enforced by code but a convention I am suggesting. It helps to separate heavy logic into distinct modules for maintainability.stores
I used the stores to abstract interaction with the data layer. For example my sample ComposersDataStore.js in this project can sort the composers, return a specific one etc. This is also not enforced by code, but rather a convention I am proposing for your app build.The Init Process
After loading of the index.html a list of dominoes begins to fall- Require will load config.js which contains the environment definition and load dependencies.
- config.js will, in turn, load the start.js module which contains our overall application controller
- config.js will also switch to the "main" page (view) which will trigger common actions by the overall application controller as defned in start.js:
- Load the main view (main.htm)
- Load the main_controll.js controller
- Call the init function of main controller
Thereafter it is up to the user and his/her interactions which pages will be loaded and which actions will be triggered.
Unfortunately there seems to be a bug in the jQuery Mobile page loading (page widget) which makes initialization phase inconsistent. The process is not always kicked of correctly so it required for me to do a check in the index.html itself. If we did not find the main controller module loaded after 5 seconds, we would switch to the main view one more time, which triggers the part 3 and seems to fix things. This loaded the app consistently across all devices.
setTimeout(function(){ if (!require.defined("controllers/main_controll")) { console.log("catch all triggered."); $( ":mobile-pagecontainer" ).pagecontainer( "change", "app/pages/main.htm", { showLoadMsg: true } ); } },5000)
The Hook
The element that drives the main convention of this app is implemented in the pagecontainerchange event hook. This event is exposed by jQuery mobile.
$(document ).on( "pagecontainerchange", function() {}
Here we automatically load the appropriate controller based on the id of the view (page) and initialize and call the init() function of the module. In addition, we change display name of the view based on what is in the data-title of the jqm view definition. All this happens in the start.js application controller.
Of course, in a more opinionated implementation, additional conventions could be coded here; for example, automatic loading of data-stores and even binding of the store's fields to form elements. Thus, the concept can be expanded. Experiment and see if you could add to it.
GitHub baby
The complete project can be reviewed or downloaded from GitHub. I have included the libraries and versions of jQuery and RequireJS so things should be able to work out of the box:Expanded Project for Download from GitHub
Enjoy,
B.
Saturday, May 23, 2015
App Idea: CircleDJ
The Idea
So you have music you are listening to, you like a piece of music so much you take out your ear-buds and press them on your friends to listen to the part of the song that you like so much. You guys start chatting about how cool the song is and how some other band is equally cool. You go back and forth pulling things from your individual play lists and having fun chatting about music and friendship.
The way you go about it seems rather old-school in the age of mobile tech, doesn't it? What if you had each an app loaded that could make this sharing easier, better and even more fun? What if you could comment on parts of pieces of the song as it was being played? Even bring in other friends into a "circle" to listen to the same song as it is being played. No more sharing of ear-buds while being able to comment and recommend a dynamic playlist? Everyone in the "circle" could assume DJ duties, putting things on a queue or taking over playback directly?
Initial idea assumes that songs are owned outright by all participants, but alternatives are possible where this is build to work on top of premium subscription services that give people already access to all songs in catalog.
More Features
- Users can invite friends into special purpose circles, e.g. School, Workout etc.
- You can see who is being DJ in which circle
- Listening and comment history is available for circle members
- Circle members can compare their song libaries
- Allow in-app purchases of "missing" songs
- Record snippets with comments to post on twitter or Vine
Techno Mumbo Jumbo
This is the section I am trying to sound edumacated.
- The basic principle is based on synchronized playback (stream or local) of media (audio or video) with shared playback control.
- Dymanic content and control of media, e.g. different users can control speed, and location of playback and this can by dynamically changed either via an election or granting scheme.
Extensions
- Build on a music streaming service, e.g. Pandora or Spotify
- This idea of "social-sharing" and "active" commenting can be extended to field of any stream-able media, e.g.Video. If you are wanting to do similar App on the basis of YouTube or other video streaming services.
- Bots could partake in playback control to make recommendation to groups and playback parts or tracks.
- The potential exists to "redefine" radio as we know it in this format. "Radio" users could take alternate control and "DJ" or curate for specific group or at specific times for other listeners.
- Feedback loop and control look can be build via twitter like services. If enough of a hastag is tweeted alongside another song specific hashtag, a bot can put the most on demand songs into the play-queue.
Social Implications
- Circle songs and comments can be shared on twitter, facebook, etc.
- Big Data: comments can be analyzed for trends (frequency language, power parts in songs etc.)
- Song Ratings for activity types
- Extract snippets to post with comments
Related Competitive Ideas
- It would be expected that streaming services will build something like this into their apps to ensure higher level of stickiness for their premium services. This could be only available for premium subscribers, inviting others to their listening circle would require subscription. Or, in a modified form without the subscription you cannot participate actively (no commenting, no DJing)
Monetization
- The assumption here is that everyone owns a copy of the song, if not friend that wish to listen in will have to purchase the song. An affiliate payment system can be used or direct resale of music.
- Recomendation engines to build suggestion to the circle members for purchase.
- Advertising (I do not like to mention this since this seems to be overused)
- Subscription element to unlock features, e.g. ability to DJ for the circle
- In app purchase of songs
- DJs could be hired to remote play and interact
What are these post about
So, like seemingly, everyone I have been collecting ideas about apps that would be "next big thing" and promptly putting them on a shelf based on time and resource demands. I am fleshing things out in bullet points. Rough bullet points! You are free to do with it whatever tickles your fancy.I have decided to break with the cycle of selfishness and just post the ideas for anyone to use. Though I am not opposed to gazillions and instant nerd-fame, I have come to the conclusion that I rather have the idea be turned into action when I know that I will not be able to.
Also I am sharing in the hopes that, even, if marginally, I am preempting the people that like to patent just about everything including how my shoe laces tie together from stifling innovation. This is prior art people. Booyah!
Do you expect a return?
In one word, yes! I am hoping that I get attribution credit or free coffee for life whenever one of these makes it big. You don't even have to tell me, just send me my platinum Starbucks card!Fool, this already exists!
If such an idea has already been turned into reality, the world is a better place ! Share it in the comment section. I do not do exhaustive research though I try to look through the app stores trying to find apps with these features. If you think my ideas are a bunch of doodoo, no need to comment, just create better ideas and make the world an even better place.Cheers,
B.
Subscribe to:
Posts (Atom)