Saturday, April 28, 2012
Meteor Web Framework - Why I can't use it yet
1. Spent about 10 hours playing with Meteor http://www.meteor.com/
2. Web-app goal: Searching http://500px.com and http://instagr.am for interesting photos
3. 1st iteration: Using node.js + express + connect-auth to search
4. 2nd iteration: Trying to use Meteor to implement #3 above. Bump into a few obstacles and realised that Meteor use case is different.
-- Meteor is designed from the ground up to have a very tight integration between client/server stack (which is very good in some cases).
-- hence no REST end points implementation (is it coming? not sure... can't see it on Github issue tracker), refer how-should-i-run-a-rest-api-with-meteor
---- Meteor.call() defines an entry point on the server which the client can call, however this is not REST-based.
-- This means my native iPhone / Android app will have issues calling the server side end points
5. For now I'll go back to the Express land and implement my REST end points there, waiting for meteor to have REST end point,
and wondering when Node.js can hot-push code into the browser (save me from refreshing the browser manually)
Tuesday, April 17, 2012
OpenLayers Zoom Fade + Resize Transition Effect
Taking the inspiration from Leaffet which uses modern browsers' css3 transition effect to add a fade effect to map zoom/pan, I quickly customised OpenLayers to do similar thing.
The fade effect is supported well in modern version of Firefox and Chrome, as well as in IE10+.
For IE 6, 7 and 8, I use the javascript timer to transition the opacity of a tile.
Get the code from
https://github.com/lydonchandra/openlayers/blob/release-2.11/lib/OpenLayers/Tile/Image.js
or
OpenLayers-distro/OpenLayers-2.11/lib/OpenLayers/Tile/Image.js
show: function(isResize, ratio) {
if( OpenLayers.Util.getBrowserName() === 'msie' ) {
if( isResize &&
this.frame.style.display === 'none' &&
ratio !== undefined && ratio > 1 ) {
//console.log( 'resizing, ratio==' + ratio + ' display==' + this.frame.style.display );
this.frame.style.display = '';
// style.opacity is only supported by IE9+
this.frame.style.opacity = 0;
// have to use filter for IE7 and IE8
this.frame.style.filter = 'alpha(opacity=' + 0 + ')';
var theFrame0 = this.frame;
window.setTimeout(
function() {
theFrame0.style.opacity = 0.5;
theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.4;
// theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.6;
// theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.8;
// theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';
//
window.setTimeout( function(){
theFrame0.style.opacity = 1;
theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';
}, 100);
// }, 100
//
// );
//
// }, 100
//
// );
//
// }, 100
// );
}, 100 );
} else if( !isResize && ratio === 1 && this.frame.style.display === 'none'){
// console.log('resizing, ratio==' + ratio);
this.frame.style.opacity = 1;
this.frame.style.display = '';
this.frame.style.filter = 'alpha(opacity=' + 100 + ')';
} else {
// console.log('else --- ratio==' + ratio + ' display==' + this.frame.style.display + ' isResize==' + isResize );
// this.frame.style.opacity = 1;
// this.frame.style.display = '';
// this.frame.style.filter = 'alpha(opacity=' + 100 + ')';
if( this.frame.style.display === 'none' ) {
this.frame.style.display = '';
// style.opacity is only supported by IE9+
this.frame.style.opacity = 0;
// have to use filter for IE7 and IE8
this.frame.style.filter = 'alpha(opacity=' + 0 + ')';
var theFrame0 = this.frame;
window.setTimeout(
function() {
theFrame0.style.opacity = 0.5;
theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.4;
// theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.6;
// theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.8;
// theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';
window.setTimeout( function(){
theFrame0.style.opacity = 1;
theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';
}, 200);
// }, 100
// );
// }, 100
// );
//
// }, 100
// );
}, 200 );
}
}
}
else {
if( !isResize &&
this.frame.style.display === 'none' ) {
this.frame.style.opacity = 0;
this.frame.style.display = '';
this.frame.style.transition = 'opacity 0.5s ease-in';
this.frame.style.WebkitTransition = 'opacity 0.5s ease-in';
this.frame.style.MozTransition = 'opacity 0.5s ease-in';
var theFrame = this.frame;
setTimeout( function() {
// have to give it some time and then set the opacity
// otherwise the transition effect won't kick in
theFrame.style.opacity = 1;
}, 50 );
} else {
this.frame.style.opacity = 1;
// remove transition effect so it doesn't get applied everytime,
// we control when it gets applied (only when showing the tile as above)
this.frame.style.transition = '';
this.frame.style.WebkitTransition = '';
this.frame.style.MozTransition = '';
this.frame.style.display = '';
}
}
// Force a reflow on gecko based browsers to actually show the element
// before continuing execution.
if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,
this.layer.transitionEffect) != -1) {
if (OpenLayers.IS_GECKO === true) {
// this.frame.scrollLeft = this.frame.scrollLeft;
}
}
}
The fade effect is supported well in modern version of Firefox and Chrome, as well as in IE10+.
For IE 6, 7 and 8, I use the javascript timer to transition the opacity of a tile.
Get the code from
https://github.com/lydonchandra/openlayers/blob/release-2.11/lib/OpenLayers/Tile/Image.js
or
OpenLayers-distro/OpenLayers-2.11/lib/OpenLayers/Tile/Image.js
show: function(isResize, ratio) {
if( OpenLayers.Util.getBrowserName() === 'msie' ) {
if( isResize &&
this.frame.style.display === 'none' &&
ratio !== undefined && ratio > 1 ) {
//console.log( 'resizing, ratio==' + ratio + ' display==' + this.frame.style.display );
this.frame.style.display = '';
// style.opacity is only supported by IE9+
this.frame.style.opacity = 0;
// have to use filter for IE7 and IE8
this.frame.style.filter = 'alpha(opacity=' + 0 + ')';
var theFrame0 = this.frame;
window.setTimeout(
function() {
theFrame0.style.opacity = 0.5;
theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.4;
// theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.6;
// theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.8;
// theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';
//
window.setTimeout( function(){
theFrame0.style.opacity = 1;
theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';
}, 100);
// }, 100
//
// );
//
// }, 100
//
// );
//
// }, 100
// );
}, 100 );
} else if( !isResize && ratio === 1 && this.frame.style.display === 'none'){
// console.log('resizing, ratio==' + ratio);
this.frame.style.opacity = 1;
this.frame.style.display = '';
this.frame.style.filter = 'alpha(opacity=' + 100 + ')';
} else {
// console.log('else --- ratio==' + ratio + ' display==' + this.frame.style.display + ' isResize==' + isResize );
// this.frame.style.opacity = 1;
// this.frame.style.display = '';
// this.frame.style.filter = 'alpha(opacity=' + 100 + ')';
if( this.frame.style.display === 'none' ) {
this.frame.style.display = '';
// style.opacity is only supported by IE9+
this.frame.style.opacity = 0;
// have to use filter for IE7 and IE8
this.frame.style.filter = 'alpha(opacity=' + 0 + ')';
var theFrame0 = this.frame;
window.setTimeout(
function() {
theFrame0.style.opacity = 0.5;
theFrame0.style.filter = 'alpha(opacity=' + 50 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.4;
// theFrame0.style.filter = 'alpha(opacity=' + 40 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.6;
// theFrame0.style.filter = 'alpha(opacity=' + 60 + ')';
// window.setTimeout(
// function() {
// theFrame0.style.opacity = 0.8;
// theFrame0.style.filter = 'alpha(opacity=' + 80 + ')';
window.setTimeout( function(){
theFrame0.style.opacity = 1;
theFrame0.style.filter = 'alpha(opacity=' + 100 + ')';
}, 200);
// }, 100
// );
// }, 100
// );
//
// }, 100
// );
}, 200 );
}
}
}
else {
if( !isResize &&
this.frame.style.display === 'none' ) {
this.frame.style.opacity = 0;
this.frame.style.display = '';
this.frame.style.transition = 'opacity 0.5s ease-in';
this.frame.style.WebkitTransition = 'opacity 0.5s ease-in';
this.frame.style.MozTransition = 'opacity 0.5s ease-in';
var theFrame = this.frame;
setTimeout( function() {
// have to give it some time and then set the opacity
// otherwise the transition effect won't kick in
theFrame.style.opacity = 1;
}, 50 );
} else {
this.frame.style.opacity = 1;
// remove transition effect so it doesn't get applied everytime,
// we control when it gets applied (only when showing the tile as above)
this.frame.style.transition = '';
this.frame.style.WebkitTransition = '';
this.frame.style.MozTransition = '';
this.frame.style.display = '';
}
}
// Force a reflow on gecko based browsers to actually show the element
// before continuing execution.
if (OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,
this.layer.transitionEffect) != -1) {
if (OpenLayers.IS_GECKO === true) {
// this.frame.scrollLeft = this.frame.scrollLeft;
}
}
}
Monday, March 5, 2012
OpenLayers + PhoneGap + JQuery
As published in http://lydon.ch/content/openlayers-phonegap-jquery
http://ozmin.es is written using OpenLayers, JQuery, and JQueryUI.
It was easy to have http://ozmin.es as iPad or iPhone app using PhoneGap,
where the difficult thing is to setup PhoneGap to know where iOS SDK is!
The next step is to investigate JQuery Mobile on iPad and iPhone and also Android and maybe Windows 7 Phone
http://ozmin.es is written using OpenLayers, JQuery, and JQueryUI.
It was easy to have http://ozmin.es as iPad or iPhone app using PhoneGap,
where the difficult thing is to setup PhoneGap to know where iOS SDK is!
The next step is to investigate JQuery Mobile on iPad and iPhone and also Android and maybe Windows 7 Phone
Wednesday, February 8, 2012
How do I organize my GIS projects?
from http://gis.stackexchange.com/questions/18199/how-do-i-organize-my-gis-projects
Base Files/DBS
- These are files that are "raw" in nature and constitute the base of all my analysis
- These files, databases, and data are hosted outside of my
projects
folder, and are hosted on my internet server, local computer, and dropbox. I always have access to them, and they are very organized, dis and aggregated. You'll spend a lot of time organizing these. - I put them all in databases whether in Arc or PostGIS.
- To each table, I add 3 fields in the table itself or the meta data: DATE_OBTAINED, DATA_DATE, SOURCE_NOTES
- Also Base files could be queries of multiple other tables. For example, a table could aggregate all the traffic count I obtain into one large query/table.
- I also put here all other data that I find scouring the internet.
- I NEVER DO ANY DIRECT ANALYSIS ON ANY OF THE FILES IN THE BASE FILES
Project Files
- All my project files go in a
my_projects
folder. It contains everything related to that project as in, if I copy and paste that folder somewhere else, it will contain everything. - Usually I have the following structure:
- my_project/
- admin/
- communication/
- raw_data/
- analyzed_data/
- output_data/
- from_client/
- FINAL/
- code/
- some_document_date_time.doc
- README
- my_project/
- Slowly I've been moving to a local GIT. (you can even host it locally or on your own server). The reason I do not put it on GitHub is that github has a 1.2gb limit which is useless for GIS analysis
- For my projects, I usually replicate all the GIS tables that I need for my analysis into a new db: project_whatever.
- 9 times out of 10, I work only in shp files and I save all my GIS (images, excel, coordinates, etc) to my
projects/my_project/raw_data
,projects/my_projects/analyzed_data
, andprojects/my_projects/output_data
. - When a project is complete, I put the final submitted copy in
my_projects/FINAL/date_submitted
- For my MXD, I usually save to a new MXD every 2 or 3 hours
my_proj_dec_22_11__13_20.mxd
for example - For Ms Word documents, illustrations, and mostly editing documents, they go in my_projects folder such as
RFP_TENDER_Dec_22_11__11_15.doc
anddraft_ver5_Dec_31_11__12_30.doc
. Again all my final deliverables go in in the FINAL folder - For R, Python code and some C#, it gets a bit tricky, as I host it outside of the project but with a working copy to
my_projects/code
folder. I do this as most of the python code is reusable. If you put all your python code besides the projects, you'll forget about them. Also, all my python code goes on github. - To me project files include any file types including time tracking, communications (I save all my emails as .msg files), I log all our verbal communications in a word file, and I put all those files my_project/communication
- With ArcGIS use Models, LYR, and "save selection as a new shp layer". These tools will make it easy to store files in smaller formats, reuse files, and with models, be able to use something in another place.
Final Output
- Each project when finalized gets zipped and put on my external harddrive.
- All final products are converted to files from Tables, and to PDF from all other formats.
- Every Project I do, gets printed for a hard copy backup
The Bottom Line
- Each person uses multiple and different software and tools. A lot of people I know get organized using basecamp, Harvest, or any other multitude of tools. Also people have different working habits and OCD tendencies. I'm fairly obsessed with getting stuff organized maybe a bit more than others. So develop the system that causes you the least stress while guaranteeing you'll be consistent in applying and updating it
- Backup and replicate everything
- Don't work directly on your raw / base data
- For your projects always use a replica file, as data changes over time, and you don't want to be scrambling to find the
base_layer_2006.shp
. - each my_projects folder must have a README text file that you edit it while you're doing the projects to give some basic information that you know you'll forget later when you visit the project 2 years down the road
Tuesday, January 17, 2012
Orbeon XForms and ANZLIC Metadata Editor
http://orbeon.com/ has a very good platform to build XForms based web-application.
This is very suitable for an ANLIC Metadata Editor which should have the same or more functionality than
xMET (eXtensible Metadata Editing Tool)
http://www.mymaps.gov.au/xmet/1.0t/xmet-setup.exe
Other XForms implementation:
1. FormFaces, a javascript implementation of XForms Engine
2. AJAXForms, XSLTForms, betterFORM, Chiba and Orbeon Forms
This is very suitable for an ANLIC Metadata Editor which should have the same or more functionality than
xMET (eXtensible Metadata Editing Tool)
http://www.mymaps.gov.au/xmet/1.0t/xmet-setup.exe
Other XForms implementation:
1. FormFaces, a javascript implementation of XForms Engine
2. AJAXForms, XSLTForms, betterFORM, Chiba and Orbeon Forms
Wednesday, January 4, 2012
Broadleafdemo-1.5 & IBM Websphere v8.5
Once you got broadleafdemo running in JBoss 7 as per http://lydonchandra.blogspot.com/2011/12/running-broadleaf-ecommerce-150-demo-in.html , then it should be trivial to deploy it onto IBM Websphere v8.5.
1. Go to Websphere admin console http://host:9043/ibm/console
2. Applications > New Application > New Enterprise Application
3. Choose "Local file system" and select a compressed broadleafdemo.war (not exploded).
4. Choose "Details" settings, and make sure you map broadleafdemo.war onto /broadleafdemo context (and not onto the root context / )
5. Save and start broadleafdemo.
1. Go to Websphere admin console http://host:9043/ibm/console
2. Applications > New Application > New Enterprise Application
3. Choose "Local file system" and select a compressed broadleafdemo.war (not exploded).
4. Choose "Details" settings, and make sure you map broadleafdemo.war onto /broadleafdemo context (and not onto the root context / )
5. Save and start broadleafdemo.
Subscribe to:
Posts (Atom)