9/28/2014

[gulp] Minify Javascript Files and Add License Notice at Head

Suppose we have source file named "myApp.js" like
var myApp = (function(){
   var x = 1;
})();
We'd like to add license notice and build time at the head of minified file (i.e., "myApp-1.0.min.js") like
/**
 * License Notice
 * Version: 1.0
 * Build: Sun, 28 Sep 2014 02:41:31 GMT
 */
 var myApp=(function(){var x=1;})();
In this situation, we can use gulp to automate the process of minifying Javascript files.
1) Create 'LICENSE' file in project. Note that version and build time are variables which will be replaced when we run gulp task.
/**
 * License Notice
 * Version: <%= version %> 
 * Build: <%= build %>
 */
2) Create 'VERSION' file in the project like
1.0
3) Create gulpfile.js in the project.
var gulp = require('gulp'),
    uglify = require("gulp-uglify"),
    rename = require("gulp-rename"),
    fs = require('fs'),
    header = require("gulp-header");

var getLicense = function() {
    return '' + fs.readFileSync('LICENSE');
};
var getVersion = function() {
    return fs.readFileSync('VERSION');
};

gulp.task('minify-js', function() {
    var version = getVersion(),
        proudctionName = 'myApp-' + version + '.min.js',
        dest = './dist',
        src = './myApp.js';

    gulp.src(src)
        .pipe(rename(proudctionName))
        .pipe(uglify())
        .pipe(header(getLicense(), {
            version: version,
            build: (new Date()).toUTCString()
        }))
        .pipe(gulp.dest(dest));
});

4) After running the gulp task, the minified file will be at ./dist/myApp-1.0.min.js
gulp minify-js
In case you haven't installed gulp, here is quick tips to setup.
1) Install nodeJS
2) Install gulp, the streaming build system.
$ npm install -g gulp
$ npm install —-save-dev gulp
3) Install gulp-uglify, gulp-rename, and gulp-header
$ npm install --save-dev gulp-uglify
$ npm install --save-dev gulp-rename
$ npm install --save-dev gulp-header
This tutorial is based on this github project https://github.com/cwtuan/Locale.js. You can fork it to test if your setup work.

6/06/2014

“javascript:void(0)” Fires window.onbeforeunload in IE

When Building a single page web application, we frequently provide a link as a trigger to run JavaScript.
 <a href = "javascript: void(0);" onclick = "alert('hello');" >Link</a>
When user clicks on the link, IE will  fires window.onbeforeunload event, although the link doesn't attempt to redirect to other page. This may make user annoyed. There are two solutions for this issue.
The first one is:
 <a href = "#" onclick = "alert('hello');" >Link</a>
The other one is :
 <a href = "javascript:;" onclick = "alert('hello'); return false;" >Link</a>

The  second one is preferred, since it will not append an anchor in URL.

6/05/2014

[JS] Get Parameters in a JavaScript Script Tag

In google-code-prettify, you can specify the code language and skin just in one line. No extra configuration is necessary since the parameters is already appended to the URL.
<script src="svn/loader/run_prettify.js?lang=css&skin=sunburst"></script>
So how does the JS file know the parameters appended to its URL? You can just call the function getScriptParams(..) to get the parameters in JS object format.
This will get JS object:
console.log(getScriptParams('run_prettify.js')); 
Here is implementation of getScriptParams(..).
function getScriptParams(scriptFileName) {
   // Get all script tag
  var scripts = document.getElementsByTagName('script');
  var result = {};
  for(var i = 0; i < scripts.length; ++i) {
     // Check if the file name is the same as scriptFileName
    if(scripts[i].src.indexOf(scriptFileName) !== -1) {    
      // Get the parameters string     
      var urls = scripts[i].src.split('?');
      if(urls.length == 2) {
        var parameters = urls[1].split('&');        
        for(var j=0; j< parameters.length; ++j) {
          var pair = parameters[j].split('=');
          result[pair[0]] = pair[1];
        }
      }
      break;
    }
  }
  return result;
}

5/28/2014

[Sublime] Code Formatter (Reindent) Shortcut in Sublime

Preference -> Key Bindings-User:
[
  { "keys": ["ctrl+shift+r"], "command": "reindent", "args": { "single_line": false } }
]
This will reindent entire file in Sublime.

5/25/2014

[ExtJS] Close Window if Click Anywhere Other Than The Window Itself

Some web application shows a window for presenting more detail information. It allows user to close the window not only via clicking the close button but also via clicking anywhere other than the window itself.


Click to Close Ext JS Window on Focus Out
If you'd like to have this behavior for a window in ExtJS, you can add the following code to your application.
Ext.define('TonyTuan.window.Window', {
    override: 'Ext.window.Window',
    closeOnFocusOut: false,
    initComponent: function() {
        var me = this;
        if (me.closeOnFocusOut === true) {
            me.mon(Ext.getBody(), 'click', function(el, e) {
                me.close(me.closeAction);
            }, me, {
                delegate: '.x-mask'
            });
        }
        me.callParent(arguments);
    }
});
And set closeOnFocusOut:true for the window you want.
Ext.widget('window', {
    closeOnFocusOut: true,
    title: 'Hello',
    height: 200,
    width: 400,
    layout: 'fit',
    items: {       
        html: 'hello world'
    }
}).show();

Please note that this kind of behavior is not suitable for a window with a input form, since user may click somewhere other than the window incautiously, leading to the loss of input data.

5/23/2014

[ExtJS] RowExpander doesn't show a whole long word

I have a RowExpander grid with a summary field which may contains a very long word. If there's no space between this word, RowExpander cannot show full word. For example, the summery field is '11111 222222 33333344444444444....555555555555'. But the number "5555.." doesn't present.

If a word is too long, I'd like to let the row expander break it a new line instead of hiding it.


Live Example
: RowExpander doesn't show a whole long word

To solve this issue, we can just add a attribute word-wrap:break-word; to x-grid-rowbody class like:

.x-grid-rowbody p {
 word-wrap: break-word;
}
Result:

Force a Long Line of Word (without spaces) to Line Break in ExtJS RowExpander

The solution is verified in ExtJS 4.1.1, 4.2, and 5.0.

5/21/2014

[CSS] Force a Long Line of Word (without spaces) to Line Break

Suppose you have a very long word in DIV as below, the word will not break by default.
<div id="veryLongWord">VeryLongWordVeryLongWordVeryLongWord</div>
<style>    
  #veryLongWord{
    border-style:double;
    width: 250px;
  }    
</style>
Result:
VeryLongWordVeryLongWordVeryLongWord

If you'd like to make a long word have Line Breaks, just add word-wrap:break-word; to your css like:

<div id="breakWord">VeryLongWordVeryLongWordVeryLongWord</div>
<style>    
  #breakWord{
    border-style:double;
    width: 250px;
    word-wrap:break-word;
  }    
</style>
Result:
VeryLongWordVeryLongWordVeryLongWord