OS : Ubuntu 12.0.4

jVectorMap을 개발자 버전으로 다운로드 하게 되면 convert.py 파일이 존재한다.

이 파일을 이용해서 shp 파일을 jVectorMap에서 사용가능하게끔 변환이 가능한데 이를 해야만 했었다......

우선 Ubuntu에 Python2.7.5를 설치해야 하는데 아래 의존성 관계를 먼저 해결해 주었어야 했다.
sudo apt-get install build-essential
sudo apt-get install libreadline-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev 
이후 home 디렉토리에 Python 2.7.5 를 wget으로 다운로드 받고 
wget http://python.org/ftp/python/2.7.5/Python-2.7.5.tgz
압축 풀고 인스톨
tar -xvf Python-2.7.5.tgz 
cd Python-2.7.5/
./configure
make
sudo make altinstall  

jVectorMap에서 사용하는 converter.py는 아래 두 개의 패키지가 추가로 필요하다.

삽질 시작.. 

 Shapely의 간편 설치를 위해 pip를 설치한다.

sudo apt-get install python-pip

pip install Shapely  

GDAL은 easy_install 을 사용한다.
sudo easy_install GDAL 
에러난다.. 아...
GDAL이 easy_install로 설치가 안된다. easy_install은 wget으로 파일을 받아와서 작업을 하는 방식이기에 wget으로도 안된다.
 
결국 아래 방법으로.. 진행

sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable sudo apt-get update sudo apt-get install gdal


안된다..... 레파지토리가 깨진듯하다..  방법이 없는건 아닌듯하다..

svn checkout https://svn.osgeo.org/gdal/trunk/gdal gdal ./configure sudo make install 

설치가 된다.. 근데 엄청 오래 걸린다........ 백그라운드로 실행 안한걸 후회할 정도로... 30분정도..

이렇게 설치하면 계정 Path에 설정해 주어야 하는데..

echo " " >> $HOME/.bashrc echo "# GDAL environment variables" >> $HOME/.bashrc echo "export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH" >> $HOME/.bashrc source $HOME/.bashrc

gdal 설치하다가 시간 다 보낸듯..
맵 파일 넣고 convert를 해보니..

Traceback (most recent call last): File "converter.py", line 10, in <module> from osgeo import ogr ImportError: No module named osgeo

이런 에러 나온다...
찾아보니..
http://gis.stackexchange.com/questions/64398/importing-osgeo-module-in-ubuntu-10-04
다시 gdal... configure 부터...

./configure --with-python sudo make install 



이상 여기까지 삽질.... 2시간..

sudo apt-get install python-gdal sudo apt-get install python-shapely 


위 두개면 설치 된다.... 아..
설치 다 했으니 아래 처럼 실행을 하면...

python ../converter.py \ --width 1000 \ --country_name_index 7 \ --country_code_index 8 \ --where "ISO = 'KOR'" \ --input_file_encoding 'UTF-8' \ --name datag_korea \ --language en \ KOR_adm2.shp \ jquery-jvectormap-data-korea-aea-en.js


이런 에러가 나는데..

ERROR 6: Unable to load PROJ.4 library (libproj.so), creation of OGRCoordinateTransformation failed.


아래 처럼 설치해주고..

sudo apt-get install python-pyproj


확인도 해주어야 하고..

/sbin/ldconfig -p | grep proj libproj.so.0 (libc6,x86-64) => /usr/lib/libproj.so.0 

 심링크도 잡아 주어야 한다....

sudo ln -s /usr/lib/libproj.so.0 /usr/lib/libproj.so


확실하게 이것도 설치하자..

sudo apt-get install python-anyjson

 다시.. 실행하자....  

python ../converter.py \ --width 1000 \ --country_name_index 7 \ --country_code_index 8 \ --where "ISO = 'KOR'" \ --input_file_encoding 'UTF-8' \ --name datag_korea \ --language en \ KOR_adm2.shp \ jquery-jvectormap-data-korea-aea-en.js

  아래는 결과..

vi로 열어보면...

올ㅋ


근데 안된다.....
jVectorMap에서 권장하는 Natural Earth 이곳의 데이터를 기준으로 작업할 경우 지도가 올바른 형태로 나오는데
국가별로 지도를 뽑으려고 해보니 뭔가가 안맞다...
같은 shp 파일이라도 뭔가가 다르다..? 열어봐야 아는건데.. 
급한대로.. 다른 개발자가 작업한 곳을 찾아서 사용은 한다만...



안되는 이유는.. 작업이 죽는다..;;

행정동 레벨 2기준으로 작업을 할 경우 약 200여개의 행정동(시/군/구)가 나오는데 가상서버가 힘들어하더니 작업을 멈추네..

WIndow에서 아래처럼 지도는 나옴. 

 

Sample Data

data.js



 

Result

Source

	function numberFormatComma(n) {
		var reg = /(^[+-]?\d+)(\d{3})/;   // 정규식
		n += '';                          // 숫자를 문자열로 변환
		while (reg.test(n)){
			n = n.replace(reg, '$1' + ',' + '$2');
		}
		return n;
	}
	
	var countryData = []; 
	//for each country, set the code and value
	$.each(data.countries, function() {
	    countryData[this.code] = this.pGdp;
	});
	
	var markers = [ 
		{
			latLng : [ 41.90, 12.45 ],
			name : 'Vatican City',
			type : 'eu',
			style: {r: 15},
			population : 800,
			url : 'http://www.vatican.va/phome_en.htm'
		}, {
			latLng : [ 48.856614, 2.352222 ],
			name : 'Paris',
			type : 'eu',
			population : 2229385,
			url : 'http://www.paris.fr/english'
		}, {
			latLng : [ 37.60, 127.00 ],
			name : 'Seoul',
			type : 'asia',
			population : 10442426,
			url : 'http://www.seoul.go.kr'
		} 
	];
	
	var colors = [];
	for (var i = 0; i < markers.length; i++) {
	    if (markers[i].type == 'eu') {
	        colors[i] = 0;
	    }
	    else {
	        colors[i] = 1;
	    };
	};
	
	$(document).ready(function(){
		// map
		$('#jvm_worldMap').vectorMap({
			map : 'world_mill_en',
			series : {
				regions : [ {
					values : countryData,
					scale : [ '#C8EEFF', '#0071A4' ],	// two colors: for minimum and maximum values 
					normalizeFunction : 'polynomial'
				} ]
				,
				markers: [{
		            attribute: 'fill',
		            scale: ['#1B77E0', '#E01B1B'],
		            values: colors,
		            min: 0,
		            max: 1
		        }]
			},
			//-----------------------------------------------
			// changed to onRegionLabelShow from onLabelShow
			//-----------------------------------------------
	        	onRegionLabelShow: function(e, el, code) {
		            //search through data to find the selected country by it's code
		            var country = $.grep(data.countries, function(obj, index) {
		                return obj.code == code;
		            })[0]; //snag the first one
		            //only if selected country was found in dataC
		            if (country != undefined) { 
				el.html(el.html() + 
	                        "
Code: " +country.code + "
Name: " + country.name + "
GDP/Person: $ " + numberFormatComma(country.pGdp)+ "
Population: "+ numberFormatComma(Math.round(Number(country.pop)/10000))+" 만명"); } } ,markerStyle : { initial : { fill : '#F8E23B', stroke : '#383f47' } }, markers : markers, onMarkerClick: function(events, index) { if(confirm('확인을 누르시면 홈페이지로 이동 합니다.')){ window.open(markers[index].url, markers[index].name); } }, onMarkerLabelShow: function(e, el, code) { var msg = ""+el.html()+""; var source = markers[code]; msg += "
population : "+numberFormatComma(source.population)+" 명"; el.html(msg); } }); });


HTML



var obj = {
    foo:    'bar',
    base:   'ball'
};

for(var key in obj) {
    alert('key: ' + key + '\n' + 'value: ' + obj[key]);
}


$.each(obj, function(key, value) {
    alert('key: ' + key + '\n' + 'value: ' + value);
});




d

$('#id').val('').trigger('liszt:updated');

$('#id').find('option:first-child').prop('selected', true).end().trigger('liszt:updated');




한참 헤맸네...

Array.prototype.remove = function(idx) {
    return (idx<0 || idx>this.length) ? this : this.slice(0, idx).concat(this.slice(idx+1, this.length));
};


http://maven.apache.org/ant-tasks/download.html
 에서 최신 버전을 다운로드 받자.

해당 jar 파일은 ant에서 maven 의존성 관리를 위해 필요하다. 

만약 build.xml의 위치가 아래와 같다면 



다운 받은 jar 파일의 위치는 build.xml에서 바라보는 경로를 명시해 주어야 한다. 


	

위 classpath 처럼 build.xml위 위치에서 jar파일 위치를 적어주면 ant에서 maven 사용이 가능하다.


	
	

${main.project.root}는 build.properties에 정의한 것인데 그냥 프로젝트 절대 경로이다. 
예로 윈도우일 경우 D:\project 일 수도 있고 Linux 일 경우 /home/project/ 일 수도 있다.

pom.xml을 pom이란 id로 정의를 했고, 정의한 ID pom을 이용하여 의존성을 관리하겠다고 선언하였다.


	
	
		
		    	
	    		
	  	
	

위 task는 maven을 이용하여 라이브러리를 실제 프로젝스 서비스 경로의 WEB-INF/lib에 복사하는 task이다.
( ${deploy.home}은 쉽게 말해.. 내가 서비스 하고 있는 Tomcat의 프로젝트 경로 )
 

이 작업까지 끝난 후에 컴파일을 하여야 한다.

	



java 파일이 위치한 경로를 src에 넣어주고, 컴파일한 class 파일이 위치하여야 할 Tomcat의 프로젝트 경로를 적어준다.


Maven이 편하다지만 나는 Ant가 제일 편하네..

Local 
 - Windows 7 

Server
 - Ubuntu 12.0


Local에선 크로스 브라우징 코드가 먹힌다.
이걸 확인한 후 서버로 올리니 서버는 익스플로러에서는 IE9만 결과가 나온다.

지금까지 조치...

1. Apache2 cache 해제
   js/html/css 등 Apache가 기본적으로 캐시하는것들을 해제하여 페이지 로드시 읽어들이게 변경.
   -> 해결 안됨.


  FileETag None
  
     Header unset ETag
     Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
     Header set Pragma "no-cache"
     Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
  



2. 코드상의 문제일까 싶어 해당 부분 처음부터 코딩해보았으나 전혀 효과 없음.
   서버의 소스를 삭제하고, 다시 빌드하여도 효과 없음.

3. 환장하는 건 단일 예제로 만든 페이지는 원하는 결과가 나옴.


모르겠다................. 




2013. 06 18

include 된 script를 하나씩 지워보았다 -> 해결 안됨

 include 된 CSS를 하나씩 지워보았다 -> 해결 됨


각기 다른 플러그인의 CSS 충돌로 인해 안나왔던 것.



 

String.prototype.trim = function(){
	return this.replace(/(^\s*)|(\s*$)/gi, "");
};
String.prototype.ltrim = function(){
	return this.replace(/(^\s+)/, "");
};
String.prototype.rtrim = function(){
	return this.replace(/(\s+$)/, "");
};

사용법은..
var str = 'ABC   ' ;
str.trim();


 

그리드 사용중 헤더 통합, 하단에 합계를 노출해야할 업무가 있다.

features에 ftype을 summary로 해서 통계 기능을 이용하면 된다.

기본적으로 sum, max, min, average, count를 제공한다.


//commify는 0,000 포맷으로 변환해주는 펑션
function summaryRenderer(value, summaryData, dataIndex) {
	if(Number(value) > 0) value = commify(Number(value));
	return value+ ' 명';
}

grid = Ext.create('Ext.grid.Panel', {
	store : store,
	stateful : false,
	collapsible : false,
	multiSelect : false,
	stateId : 'stateGrid',
	disableSelection : true,
	loadMask : true,
	features: [{
		ftype: 'summary'
	}],
	columns : Ext.create('Ext.grid.header.Container', {
		items : [
			{ 
				text : '단위지역',	width : 140,	align :  'center',	sortable : false,	dataIndex : 'UNIT_AREA',
				summaryType: 'sum',
				summaryRenderer: function(value, summaryData, dataIndex) {
					return '합계';
				}
			},
			{ 
				text : '인구수',		width : 130,	align : 'center',	sortable : false,	dataIndex : 'TPPCN',
				// 컬럼 값
					renderer: function(value, metaData, record, rowIdx, colIdx, store, view){
					return value;
					},
					xtype: 'numbercolumn', format:'0,000',
					summaryType: 'sum',
					summaryRenderer: summaryRenderer
				},
				{ text : '성별',
					columns: [
							{ 
								text     : '남성',	width    : 90, 	align : 'center',	sortable : false, 	dataIndex: 'MPPCN',
								xtype: 'numbercolumn', format:'0,000',
								summaryType: 'sum',
								summaryRenderer: summaryRenderer
							}, 
							{ 
								text     : '여성', 	width    : 90, 	align : 'center',	sortable : false, 	dataIndex: 'FPPCN',
								xtype: 'numbercolumn', format:'0,000',
								summaryType: 'sum',
								summaryRenderer: summaryRenderer
							}, 
						]
					}
				], 
		sortable : false
	}),
	listeners: {
		itemdblclick: {
			fn: function(grid, selRow, selHtml){
				// your codes...
			}
		}
	}
	autoHeight: true,
	width : 1025,
	renderTo : 'grid',
	viewConfig : {
		stripeRows : true,
		enableTextSelection : false
	}
});







extjs grid에서 dataStore를 모두 불러왔을때 이벤트 처리를 해야할 경우가 생겼다.

이전의 삽질을 바탕으로 listener를 먼저 생각했고, 이벤트는 onLoad, afterLoad 등 하다가 단순하게 load를 하니 작동한다.


		// create the Data Store
		    store = Ext.create('Ext.data.Store', {
		        pageSize: 20,
		        model: 'QnA',
		        //remoteSort: true,
		        proxy: new Ext.data.HttpProxy({ 
		            extraParams : jQuery('form[name="searchForm"]').formParams(),
		            url: REMOTE_URL, 
		            reader: new Ext.data.JsonReader(
				{ root: 'datas', totalProperty: 'totalCount'}
			)}
		        ),
		        listeners: {
		            load: function(dataStore, rows, bool) {
 		                console.log(dataStore);
 		                console.log(rows);
 		                console.log(bool);
		            },
		            scope: this
		        }
		    });






+ Recent posts