Showing posts with label Javascript. Show all posts
Showing posts with label Javascript. Show all posts

10/03/2022

Disable css-modules in Next.js v12.3.1 (Sept, 2022)

In the next.js document, component-level CSS is only supported by CSS Modules. There is no configuration to disable CSS Modules. The following article will show you how to use non-css-module styling in next.js.

Verified in next.js version: v12.3.1 (Sept, 2022)

In the next.config.js, add the following config:


/** @type {import('next').NextConfig} */

const path = require('path');

const nextConfig = {

  reactStrictMode: true,

  swcMinify: true,

  // Disable css--modules component styling

  // Source: https://cwtuan.blogspot.com/2022/10/disable-css-module-in-nextjs-v1231-sept.html

  webpack(config) {

    config.module.rules.forEach((rule) => {

      const { oneOf } = rule;

      if (oneOf) {

        oneOf.forEach((one) => {

          if (!`${one.issuer?.and}`.includes('_app')) return;

          one.issuer.and = [path.resolve(__dirname)];

        });

      }

    })

    return config;

  },

}

module.exports = nextConfig



7/02/2016

[React] Don't Use Loop Index as Component Key

var ResultList = React.createClass({
  getInitialState: function() {
    return {results:[{id:1,text:'hello'}]};
  }, 
  onclick: function() {
    this.setState( {results:[{id:1},{id:2}]} );
  }, 
  render: function() {
    return (
      <div> 
   <button onClick={this.onclick} >click me!</button>
      <ul>
        {this.state.results.map(function(result, i) {
           return <ResultItem result={result}/>;
        })}
      </ul>
      </div>
    );
  }
});

var ResultItem = React.createClass({
  getInitialState: function() {
    return {clicked:false};
  },
  onclick: function() {
    this.setState( {clicked: !this.state.clicked } );
  }, 
  render: function() {
    return (
      <li onClick={this.onclick}>{' [clicked state] =  ' + this.state.clicked}</li>
    );
  }
});

ReactDOM.render(<ResultList />, mountNode);
If you render a list of components in a loop, don't forget to add key attribute to each of the component or React will give you a warning message like: "Each child in an array should have a unique "key" prop. Check the render method of undefined. See http://fb.me/react-warning-keys for more information".
To solve this problem, many people may just make a loop index as component key as below. Well, this solution does make the warning message disappear. However, it's an anti-pattern and will make your stateful components have incorrect state.
{this.state.results.map(function(result, i) {
  return <ResultItem key={i} result={result}/>;
})}
React's diff algorithm will try to find the min steps to add, remove, and update component's state in O(n) time. When it detects the component's class name (i.e., ResultItem) is the same and have the same key, it assume the component instance is the same one. Therefore, React will not update this component's state. So when the button is clicked in ResultList, you may think the ResultItem's result props is changed, then ResultItem will be re-inializated with the initial state {clicked: false}. It's not true. Since React think the ResultItem with id = 1 is the old instance, the state still remains the old state.
The correct to add a key to component is just use the unique id in the database like:
{this.state.results.map(function(result, i) {
   return <ResultItem key={result.id} result={result}/>;
})}
It's noted that the key should be added to a component's props instead of added to the children's HTML. Otherwise, React's diff algorithm will not know the children component's id.
// WRONG!
var ResultItem = React.createClass({
  render: function() {
    return (
      <li key={this.props.result.id}></li>
    );
  }
});
Ref: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children

[React] Don't Use Loop Index as Component Key

var ResultList = React.createClass({
  getInitialState: function() {
    return {results:[{id:1,text:'hello'}]};
  }, 
  onclick: function() {
    this.setState( {results:[{id:1},{id:2}]} );
  }, 
  render: function() {
    return (
      <div> 
   <button onClick={this.onclick} >click me!</button>
      <ul>
        {this.state.results.map(function(result, i) {
           return <ResultItem result={result}/>;
        })}
      </ul>
      </div>
    );
  }
});

var ResultItem = React.createClass({
  getInitialState: function() {
    return {clicked:false};
  },
  onclick: function() {
    this.setState( {clicked: !this.state.clicked } );
  }, 
  render: function() {
    return (
      <li onClick={this.onclick}>{' [clicked state] =  ' + this.state.clicked}</li>
    );
  }
});

ReactDOM.render(<ResultList />, mountNode);
If you render a list of components in a loop, don't forget to add key attribute to each of the component or React will give you a warning message like: "Each child in an array should have a unique "key" prop. Check the render method of undefined. See http://fb.me/react-warning-keys for more information".
To solve this problem, many people may just make a loop index as component key as below. Well, this solution does make the warning message disappear. However, it's an anti-pattern and will make your stateful components have incorrect state.
{this.state.results.map(function(result, i) {
  return <ResultItem key={i} result={result}/>;
})}
React's diff algorithm will try to find the min steps to add, remove, and update component's state in O(n) time. When it detects the component's class name (i.e., ResultItem) is the same and have the same key, it assumes the component instance is the same one. Therefore, React will not update this component's state.
So when the button is clicked in ResultList, you may think the ResultItem's result props is changed, then ResultItem will be re-inializated with the initial state {clicked: false}. It's not true. Since React think the ResultItem with id = 1 is the old instance, the state still remains the old one.
The correct to add a key to component is just use the unique id in the database like:
{this.state.results.map(function(result, i) {
   return <ResultItem key={result.id} result={result}/>;
})}
It's noted that the key should be added to a component's props instead of added to the children's HTML. Otherwise, React's diff algorithm will not know the children component's id.
// WRONG!
var ResultItem = React.createClass({
  render: function() {
    return (
      <li key={this.props.result.id}></li>
    );
  }
});

Ref: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children

10/19/2014

[JavaScript] function scope and block scope

In many languages such as C, C++, and Java, the scope is defined by a block. In the following Java example, the variable x in the inner scope is not accessible by outer scope.
for(int i=0;i<10;++i) {
    int x = 1;
}
System.out.println(x); // error
However, in Javascript, scope is defined by a function.
In the following sample, variable x is defined in the loop block which doesn't create a new scope while variable y is defined in a function which create a new scope. So, The foo function is in inner scope and global window is in outer scope.
Since variable x is in the outer scope, the function foo is able to access it. And variable y is in the inner scope, we can't access it in outer scope (window).
var i;
for(i = 0; i < 10; ++i) {
  var x = 1;
}

// function will create a new scope   
function foo() {
  var y = 1;
  x++;
}

console.log('x', x); // 1
foo();
console.log('x', x); // 2
console.log('y', y); // Uncaught ReferenceError: y is not defined

10/16/2014

[ExtJS 5] Migrate from ComponentColumn to WidgetColumn

In Ext 4, we use componentcolumn to render Ext component in a grid cell.
{
  dataIndex: 'age',
  xtype: 'componentcolumn',
  renderer: function(value, m, record) {
    if (value < 30) {
      return {
        xtype: 'myWidget1';
      };
    } else {
      return {
        xtype: 'myWidget2';
      };
    }
  }
}
In Ext 5, the built-in widgetcolumn have the same ability to do so. But the widgetcolumn have better rendering performance.
{
  xtype: 'widgetcolumn',
  widget: {
    xtype: 'container',
  },
  onWidgetAttach: function(widget, record) {
    var items = [];
    if (record.get('age') < 30) {
      items.push({
        xtype: 'myWidget1'
      })
    } else {
      items.push({
        xtype: 'myWidget2'
      })
    }  
    widget.removeAll();
    widget.add(items);
  }
}
Note that onWidgetAttach() is a public but not documented method.

10/10/2014

[Javascript] Event Bubbling and Capturing Propagating Order

Problem

We have three elements in the DOM shown below. When users click on the element3, all of elements' click handler will be executed. But what's the order of executing handler?
<div class="element1">element1
    <div class="element2">element2
        <div class="element3">element3</div>
    </div>     
</div>

The W3C Event Bubbling and Capturing Propagating Order

According to W3C standard, there are two major phases for propagating event object.
Capturing phase:
Firstly, The event object will propagate through the target's ancestors from the Window to the target's parent (Note that target in this case is element3.)
Bubbling phase:
Then event object propagates through the target's ancestors in reverse order, starting with the target's parent and ending with the Window.
Event Bubbling and Capturing Propagating Order
Event Bubbling and Capturing Propagating Order
So let's add some event listeners to print out the propagating order of event object. Before that, let's see the arguements of addEventListener.
/**
  * @param {String} type The event type
  * @param {Function} listener The event handler
  * @param {Boolean} useCapture If True, use capturing. Otherwise, use bubbling.
  */
  element.addEventListener(type, listener[, useCapture]);
The following code make all elements register a click event for both of bubbling and capturing. Note that registering an event for the same listener doesn't affect the order of event object propagating.
var element1 = document.getElementsByClassName('element1')[0],
    element2 = document.getElementsByClassName('element2')[0],
    element3 = document.getElementsByClassName('element3')[0],
    foo = function(e) { console.log(this.className); };

element1.addEventListener('click', foo); // bubbling
element1.addEventListener('click', foo, true); // capturing
element2.addEventListener('click', foo);
element2.addEventListener('click', foo, true);
element3.addEventListener('click', foo);
element3.addEventListener('click', foo, true);
When you click element3, it will show
element1
element2
element3
element3
element2
element1 
As we expected, the event object will first propagate in capturing phase (top-down) and  then bubbling phase (bottom-up).
By the way, you can stop the propagation by calling e.stopPropagation().
var stop = function(e) { 
    console.log('stop', this.className); 
    e.stopPropagation();
};

element1.addEventListener('click', foo);
element1.addEventListener('click', foo, true); 
element2.addEventListener('click', stop); // Change handler to "stop"
element2.addEventListener('click', foo, true);
element3.addEventListener('click', foo);
element3.addEventListener('click', foo, true);
The output
element1
element2
element3 
element3
stop element2 
The Playground in JS fiddle.

10/09/2014

[ExtJS] Add Custom CSS Class to Grid Cell

You can make Ext JS 5 gird cell more pretty by applying twitter bootstrap.css to grid cell. It look like:

All you have to do is override the renderer function which returns a span element with bootstrap's label css class.
{
  header: 'Status',
  dataIndex: 'status',
  width: 100,
  renderer: function(value, meta, record) {
    var cls;
    if (value === 'Success') {
      cls = 'label label-success';
    } else if (value === 'Failure') {
      cls = 'label label-important';
    } else if (value === 'Processing') {
      cls = 'label label-warning';
    }
    return Ext.String.format('<span class="{0}">{1}</span>', cls, value);
  }
}
The code above is tested with Ext JS 5.0.1.

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;
}

3/28/2014

[ExtJS] Cancel Duplicate Store Loading Request Automatically

In the previous article, we mentioned how to abort a store request manually. It's used when programmer want to cancel a store loading request manually.


"Refresh" button in grid

Image there's a "Refresh" button in your grid, the user may press the button quickly multiple times. This behavior make store send multiple requests at a short period of time. So it's better to abort the previous requests for performance and data correctness issue.


Cancel Duplicate Store Loading Request Automatically

The following code overrides ExtJS store behavior, making all of stores in web application abort duplicated store loading request automatically. Just put it to somewhere your application initialized.

Ext JS 4.1.1a:

Ext.define('Tonytuan.data.Store', {
  override: 'Ext.data.Store',
  abort: function () {
    var me = this;
    if (me.loading && me.lastOperation) {
      var requests = Ext.Ajax.requests;
      for (id in requests) {
        if (requests.hasOwnProperty(id) && requests[id].options == me.lastOperation.request) {
          Ext.Ajax.abort(requests[id]);
          delete requests[id];
          break;
        }
      }
    }
  },
  constructor: function (config) {
    var me = this;
    me.callParent([config]);
    me.on({
      'beforeload': function (store, operation) {
        // Abort previous request if it has not been completed.
        if (me.loading) {
          me.abort();
        }
        store.lastOperation = operation;
      }
    });
  }
});

Ext JS 5.0.1:

Ext.define('Ext.enhance.data.Store', {
  override: 'Ext.data.Store',
  abort: function() {
    var me = this;
    if (me.isLoading() && me.lastOperation) {
      var requests = Ext.Ajax.requests;
      for (id in requests) {
        if (requests.hasOwnProperty(id) && requests[id].options.url == me.lastOperation.request._url) {
          Ext.Ajax.abort(requests[id]);
          delete requests[id];
          break;
        }
      }
    }
  },
  constructor: function(config) {
    var me = this;
    me.callParent([config]);
    me.on({
      'beforeload': function(store, operation) {
        // abort previous request
        if (me.isLoading()) {
          me.abort();        }
        store.lastOperation = operation;
      }
    });
  }
});

3/05/2014

[ExtJS] RowEditing: Save Data to Server Immediately When Clicking Update Button.

The RowEditiing in ExtJS doesn’t send a request after a user click Update button. The records in grid will become dirty state after user click. But it doesn’t not mean that records in remote DB are changed. Even you call grid.store.commitChanges(), this would not send a request to server as well. The method commitChanges() only clear dirty state in store.

How to send a request whenever the grid is edited?
Let’s explain by giving an simple user management example. Here is User model with fake data. The model is binding with a REST proxy which is used for building request to server.
Ext.define('TonyTuan.User', {
    extend : 'Ext.data.Store',
    fields : [ 'id', 'name', 'role' ],
    data : [ {
        id : '1',
        name : 'Tony',
        role : 'Programmer'
    }, {
        id : '2',
        name : 'Steve',
        role : 'Programmer'
    }, {
        id : '3',
        name : 'Alice',
        role : 'Manager'
    } ],
    proxy : {
        type : 'rest',
        url : 'rest/users',
        reader : {
            type : 'json'
        }
    }
});
The Role store for combobox.
Ext.define('TonyTuan.Role', {
    extend : 'Ext.data.Store',
    fields : [ 'display', 'value' ],
    // fake data
    data : [ {
        display : 'Programmer',
        value : 'Programmer'
    }, {
        display : 'Designer',
        value : 'Designer'
    }, {
        display : 'Project Manager',
        value : 'Manager'
    } ]
});
The user grid with a rowEditing plugin listens on an edit event which is fired whenever records in grid are changed. Therefore, we can send a http PUT request by calling record.save() in the edit event handler.
Ext.define('TonyTuan.UserGrid', {
    extend : 'Ext.grid.Panel',
    width : 300,
    store : Ext.create('TonyTuan.User'),
    selType : 'rowmodel',
    plugins : [ {
        ptype : 'rowediting' // enable row editing
    } ],
    initComponent : function() {
        var me = this;

        me.columns = [ {
            header : 'id',
            dataIndex : 'id'
       
        }, {
            header : 'name',
            dataIndex : 'name'
        }, {
            header : 'Role',
            dataIndex : 'role',       
            editor : { 
                // for editable field, set a proper field xtype for it
                xtype : 'combobox',
                store : Ext.create('TonyTuan.Role'),
                queryMode : 'local',
                editable : false,
                displayField : 'display',
                valueField : 'value',
                allowBlank : false
            }
        } ];

        // Listen on the edit event to send a request to server
        me.on('edit', function(editor, e) {
            e.record.save({
                success : function(record, operation) {
                    // (show successful message here)
                    me.store.load();
                },
                failure : function(record, operation) {
                    // (show error message here)

                    // clear the dirty state and rollback the records
                    me.store.rejectChanges(); 
                }
            });
        });
        me.callParent(arguments);
    }
});
Ext.create('TonyTuan.UserGrid', {
    renderTo : Ext.getBody()
}); 
Online Demo on Sehcna Fiddle

[ExtJS] Remote Validator for Form Field (Server Side Validator)

ExtJS usually validates form field locally. For example, In register form, you may like to check if the password has more than 8 characters. This could be done easily.

{
 fieldLabel : 'Password',
 name : 'password',
 allowBlank : false,
 validFlag : true,
 validator : function(value) {
    if (value != '' && value.length < 8) {
      return 'Password should has more than 8 characters';
    }
    return true; 
 }
}

However, in some situation, you have to validate the input values in server side. For instance, the username in a website should be unique. Thus, you can let the field validator return true by default, but whenever the inputs has be changed, make the listener trigger an AJAX request to check if the value is valid and validate the field explicitly in the callback function.

{
 fieldLabel : 'Username',
 name : 'username',
 allowBlank : false,
 validFlag : true,
 validator : function() {
  return this.validFlag;
 },
 listeners : {
  'change' : function(textfield, newValue, oldValue) {
   var me = this;
   Ext.Ajax.request({
    url : 'rest/users?action=validate&username=' + newValue,
    success : function(response) {
     // Ausuming responseText is {"valid" : true}
     me.validFlag = Ext.decode(response.responseText).valid ? true : 'The username is duplicated!';
     me.validate();
    }
   });
  }
 }
}

[ExtJS] Get Server Response in Model.save() or Model.destroy() Failure Callback Function

Many people have the same question: How to get server response in model's failure function? It's easy to get response from server when operation success. But it's a little bit tricky to get response when operation fails. I saw a solution which add a listener to store's proxy to listen on exception event. But I found a easier way below.

model.save({
    success: function (record, operation) {
        // json response from server         
        console.log(operation.response);                  
    },
    failure: function (record, operation) {
        // undefined
        console.log(operation.response); 
        // json response from server
        console.log(operation.request.scope.reader.jsonData);
    }
});

[ExtJS] Abort Store Request / Connection / Loading

It's kind of intuitive to abort a Ext.Ajax.request.

var req = Ext.Ajax.request({
    url: 'page.aspx'
});
Ext.Ajax.abort(req);

However, aborting store's request isn't easy since store doesn't return request object when loading. Thus, we need to keep request object on beforeload event. Then cancel the store's request later on.

Let's just override the store's constructor to make every store keep their request object before sending request and implement a method call abort() in store.

Ext.define('Ext.enhance.data.Store', {
    override: 'Ext.data.Store',
    constructor: function(config) {
        var me = this;
        me.callParent([config]);
        me.on({
            'beforeload': function(store, operation) {
                // keep the operation which has request object
                store.lastOperation = operation;
            }
        });
    },
    abort: function() {
        var me = this;
        if (me.loading && me.lastOperation) {
            var requests = Ext.Ajax.requests;
            for (id in requests) {
                if (requests.hasOwnProperty(id) && requests[id].options == me.lastOperation.request) {
                    Ext.Ajax.abort(requests[id]);
                    delete requests[id];
                    break;
                }
            }
        }
    }

});

Then we are able to abort a store request easily.

grid.store.abort();

Reference: http://stackoverflow.com/questions/13251440/selectively-aborting-an-ajax-request-sent-via-extjs-direct-proxy

8/21/2013

[ExtJS] Remove "No file chosen" Tooltip for File Input Field

When I was implementing file uploading feature in js, I found the file field button always shows "No file chosen" in Chrome when the field is empty. I had tried many solutions described in stackoverflow. Unfortunately, none of them could override or remove the "No file chosen" Tooltip. There’s no chance for javasript developer to remove it directly.
No file chosen
"No file chosen" tooltip
<html>
    <head>
    </head>
    <body>
        <input type="file" multiple/>
    </body>
</html>

But when user upload files in gmail, it can show custom tooltip such as “Attach files”.
Gmail file uploading with custom tooltip.
So I checked the source of gmail in firebug, I found the “Attach files” button is defined as a div tag. However, a div tag is not able to open file picker for security issue. How can google make it? Actually, the div tag is just a wrapper. And the file field is hidden in the body. Whenever div tag is clicked, just click the file field programmably. Then you can listen onchange event for file field to get the file metadata. For ExtJS developer, you can refer to the following code in you project.
Custom Tooltip for File Uploading in ExtJS
Ext.define('TonyTuan.BrowseButton', {
    extend : 'Ext.button.Button',
    icon : 'css/images/arrow_up_16x16.png',
    text : 'Browse...',
    constructor : function(config) {
        var me = this;
        // Show custom tooltip instead of "No file chosen".
        config.tooltip = 'Attach Files';
        me.callParent([ config ]);
    },
    handler : function() {
        // To trigger the file field click event
        document.getElementById('upload-field').click();
    }
});

Ext.define('TonyTuan.FileGrid', {
    extend : 'Ext.grid.Panel',
    alias : 'widget.fileGrid',
    title : 'Files',
    store : 'File',
    initComponent : function() {
        var me = this;
        me.columns = [ {
            dataIndex : 'filename',
            header : 'Filename',
        } ];
        me.tbar = [ Ext.create('TonyTuan.BrowseButton', {
            itemId : 'browseButton'
        }) ];
        me.callParent(arguments);
    }
}); 

Ext.define('TonyTuan.FilePanel', {
    extend : 'Ext.panel.Panel',
    title : 'Files',
    layout : 'border',
    initComponent : function() {
        var me = this;
        me.items = [ {
            region : 'center',
            xtype : 'fileGrid',
            layout : 'fit',
            flex : 3,
            margins : '5 5 0 0'
        }, {
            hidden : true,
            region : 'north',
            xtype : 'component',
            html : '<input type="file" multiple id="upload-field"/>'
        } ];
        me.callParent(arguments);
        me.on({
            afterrender : function() {
                document.getElementById('upload-field').onchange = function() {
                    var files = document.getElementById('upload-field').files;
                    console.log('files', files); 
                    // Add files to your fileGrid store
                };
            }
        });
    }
});

5/14/2013

Fix "Requesting JavaScript AST from selection" When Editing Javascript in Eclipse

Eclipse does not work well with js/css/jsp/jspf. I often encounter error such as “An internal error occurred during: Requesting JavaScript AST from selection. java.lang.OutOfMemoryError: Java heap space” when select/edit/search these types of files. It seems Eclipse has no idea how to validate these files, so I tried to disable all validators. But it does not solve the problem. All CPU resource is still occupied until I found out this way to exclude these files for validation.

1. Right click on your project, and click “Properties”.

2. Click “Include Path” and Press “Source” tab. Then edit the excluded file list.

3. Add the folders and files which you want Eclipse to skip to validate.

4. For example, I excluded all files in web app folder.

Hopefully, Out Of Memory error will not happen again.