AXISJ 소개서

Opensource Javascript UI Library - https://github.com/axisj/axisj

AXModal

AXModal은 웹 애플리케이션에서 한개의 화면 안에 새로운 창을 열어야 하는 경우에 쓰입니다. AXModal은 현재 페이지와 관계없는 새로운 페이지를 iframe으로 불러오는 방식과 현재 페이지 안에 선언된 div를 모달컨텐츠로 사용하는 방식이 이 있습니다.

AXModal.iframe

<div class="tag-result">
	<button class="AXButton" id="ui-modal-iframe-open">모달창 열기</button>
</div>
<script>
(function(){
	var myModal = new AXModal();
	myModal.setConfig({
		windowID:"myModalCT", width:740,
		mediaQuery: { // 모달창 반응형 조건 - 필수 조건 아님
			mx:{min:0, max:767}, dx:{min:767}
		},
		displayLoading: true, // 로딩중 표시 여부
		scrollLock: true, // 모달창이 열렸을 때 페이지 스크롤 금지 옵션
		onclose: function(){
			toast.push("모달 close");
		}
	});
	$("#ui-modal-iframe-open").click(function(){
		myModal.open({
			method:"GET",
			url:"data/modal-iframe.html",
			pars:"",
			closeByEscKey: true // 모달창이 열렸을 때 ESC키로 모달창 닫기 옵션
		});
	});
})()
</script>

Result

AXModal.div

<div class="tag-result">
	<button class="AXButton" id="ui-modal-div-open">모달창 열기</button>
	<div style="display:none;">
		<!-- AXModal 이 컨텐츠로 사용하게된 레이어 -->
		<div id="ui-modal-div-content" style="padding:20px;">
			<h1>MODAL</h1>
			<br/>
			<br/>
			<input type="text" class="AXInput" id="ui-modal-div-content-input" />
			<br/>
			<br/>
			<input type="button" value="창닫기" class="AXButton" onclick="div_modal_target.close('my-modal-div');" />
		</div>
	</div>
</div>
<script>
	(function(){
		var myModal = window.div_modal_target = new AXModal();
		myModal.setConfig({
			windowID:"myModalCT",
			width:740,
			onclose: function(){
				toast.push("모달 close");
			}
		});
		$("#ui-modal-div-open").click(function(){
			myModal.openDiv({
				modalID: "my-modal-div",
				targetID: "ui-modal-div-content",
				width: 300,
				closeByEscKey:true
			});
			$("#ui-modal-div-content-input").bindNumber();
			// 모달창이 열리기 전에 bind하면 안됩니다.
		});
	})()
</script>

Result

MODAL





openDiv를 이용한 모달창 오픈을 하게되면 최초 1회에 한하여 targetID에 레이어 컨텐츠를 모달창으로 옮겨주고 모달창을 오픈하게 됩니다. 한번 옮겨진 컨텐츠는 모달을 닫은 후에 다시 오픈할 때 다시 옮기지 않습니다.

openDiv를 이용하면서 AXInput, AXSelect를 바인딩 하려고 하면 반드시 myModal.openDiv후에 바인딩 해야 합니다. 바인드 코드를 display:none인 컨텐츠에 시도하면 제대로 작동하지 않습니다.

AXGrid

AXGrid는 Array형 데이터를 자바스크립트로 출력할 수 있는 UI 컴포넌트 입니다. 대용량의 JSON데이터를(크롬 60만건 이상, 구형 IE의 경우는 6만건 정도) 그리드에 출력합니다. 인라인 편집, 에디터 편집을 지원하고, 정렬, 셀머지, 소계, 합계, 멀티헤드, 반응형 등의 기능을 지원합니다.

AXGrid는 액시스제이의 다른 UI 콤포넌트들에 비해 가장 역사가 깊습니다. 2008년부터 제작을 시작하여 지속적인 개선과 기능개발이 이루어지고 있습니다.

<div id="ui-grid-target" style="height:120px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-target",
			colGroup: [
				{key:"no", label:"번호", width:50},
				{key:"title", label:"제목", width:300}
			]
		});
		myGrid.setList([
			{no:1, title:"제목입니다. 일번"},
			{no:2, title:"제목입니다. 이번"}
		]);
	})();
</script>

Result

예제에서 AXGrid를 최소한의 코드로 구현했습니다. 여기에 다양한 옵션과 설정을 정의하여 다양한 그리드를 구현할 수 있습니다. targetID, colGroup만 기억하시면 되겠습니다.

AXGrid.configs

그리드의 많은 설정요소중에 단일 값으로 설정되는 요소에 대해 설명드리겠습니다. 틀고정, 정렬, 셀 머지, 높이, 표현등의 요소를 컨트롤 할 수 있습니다.

<div id="ui-grid-configs" style="height:150px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-configs",
			theme: "AXGrid", // 그리드 theme CSS 클래스 명
			fixedColSeq : 1,
			// {Number} -- 컬럼고정 기능을 사용합니다. 고정할 마지막 컬럼의 인덱스 값입니다.
			fitToWidth  : false,
			// {Boolean} [false] -- 컬럼 가로 길이를 그리드의 가로 길이에 맞춥니다.
			colHeadAlign: "center",
			// {String} 헤드의 기본 정렬. "left"|"center"|"right" 값을 사용할 수 있습니다. colHeadAlign 을 지정하면
			// colGroup 에서 정의한 정렬이 무시되고 colHeadAlign : false 이거나 없으면 colGroup 에서 정의한 속성이 적용됩니다.
			mergeCells  : [1,2],
			// {Boolean|Array} -- 전체셀병합,병합안함,지정된 인덱스열만 병합
			height      : 150,
			// {Number|String} -- 그리드의 높이를 지정합니다.
			// 숫자를 사용하면 픽셀 단위로, "auto" 값을 사용하면 그리드의 높이가 내용에 맞춰서 늘어납니다.
			sort        : true,
			// {Boolean} -- true: 그리드의 헤더를 클릭해서 정렬 할 수 있습니다. false: 정렬 기능을 비활성화 합니다.
			// 이 설정은 colGroup의 sort 보다 우선적으로 적용됩니다.
			remoteSort  : true,
			// {Boolean} [false] -- 서버에서 정렬을 처리(서버에서 별도 처리 필요)합니다.
			// 헤더 클릭시 'sortBy=cost desc' 형식의 정렬 정보가 ajax 요청에 포함됩니다.
			colHeadTool : true,
			// {Boolean} -- 컬럼 툴 display 여부를 설정 합니다.
			// 이 설정은 colGroup의 colHeadTool 보다 우선적으로 적용됩니다.
			viewMode    : "grid",
			// {String} -- 그리드가 보여지는 형태("grid"|"icon"|"mobile")를 지정합니다.
			// viewMode는 mediaQuery에 의해서 자동으로 결정되기도 합니다.
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"200"},
				{key:"writer", label:"작성자", width:"80", align:"center"},
				{key:"regDate", label:"작성일", width:"100", align:"center"},
				{key:"desc", label:"비고", width:"200"}
			]
		});
		myGrid.setList([
			{no:1, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:2, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:3, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:4, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:5, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:6, title:"AXGrid 두번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"}
		]);
	})();
</script>

Result

AXGrid.multiHead

그리드 컬럼 헤드가 단일 row값으로만 구성되어지지 않고 colspan, rowspan값을 가지는 경우에 HTML table 에서 td에 colspan, rowspan속성을 사용하는 룰과 같은 방법으로 colHead에 rows를 추가하게 됩니다. table태그와 마찬가지로 colspan과 rowspan값을 잘못 입력하면 테이블이 깨져 보일 수 있습니다.

<div id="ui-grid-multihead" style="height:200px;"></div>
<script>
(function(){
	var myGrid = new AXGrid();
	myGrid.setConfig({
		targetID: "ui-grid-multihead",
		colHeadAlign:"center",
		colGroup: [
			{key:"no", label:"번호", width:"50", align:"right"},
			{key:"title", label:"제목", width:"*"}, // *는 테이블의 남은 너비를 모두 차지합니다.
			{key:"writer", label:"작성자", width:"100", align:"center"},
			{key:"regDate", label:"작성일", width:"100", align:"center"},
			{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
			{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
			{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
				return (this.item.price.number() * this.item.amount.number()).money();
			}},
			{key:"desc", label:"비고", width:"*"}
		],
		colHead: {
			rows: [
				[
					{key:"no", rowspan:2},
					{colspan:3, label:"표현식", align:"center"}, // colspan을 사용할 땐 key를 정의하면 안됩니다.
					{key:"price", rowspan:2},
					{key:"amount", rowspan:2},
					{key:"cost", rowspan:2},
					{key:"desc", rowspan:2}
				],
				[
					{key:"title"},
					{key:"writer"},
					{key:"regDate"}
				]
			]
		}
	});
	myGrid.setList([
		{no:1, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
			desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법", price:123000, amount:0}, // item
		{no:2, title:"AXGrid 두번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
			desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법", price:12300, amount:7}
	]);
})();
</script>

Result

AXGrid.multiBody

colHead에 정의한 rows를 body엔에 추가합니다.

<div id="ui-grid-multibody" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-multibody",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"*"},
				{key:"writer", label:"작성자", width:"100", align:"center"},
				{key:"regDate", label:"작성일", width:"100", align:"center"},
				{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
				{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
				{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
					return (this.item.price.number() * this.item.amount.number()).money();
				}},
				{key:"desc", label:"비고", width:"*"}
			],
			body: {
				rows: [
					[
						{key:"no", rowspan:2},
						{colspan:3, label:"표현식", formatter: function(){
							return "표현식";
						}}, // colspan을 사용할 땐 key를 정의하면 안됩니다.
						{key:"price", rowspan:2},
						{key:"amount", rowspan:2},
						{key:"cost", rowspan:2},
						{key:"desc", rowspan:2}
					],
					[
						{key:"title"},
						{key:"writer"},
						{key:"regDate"}
					]
				]
			}
		});
		myGrid.setList([
			{no:1, title:"AXGrid 첫번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법", price:123000, amount:0}, // item
			{no:2, title:"AXGrid 두번째 줄 입니다.", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법", price:12300, amount:7}
		]);
	})();
</script>

Result

AXGrid.foot

setList데이터와는 별개로 setDataSet에서 합계 데이터를 전달하게 됩니다. setDataSet에 전달된 데이터는 그리드안에 myGrid.dataSet에 저장되어 foot처리시에 value로 활용됩니다. 그와는 별개로 foot.rows[0].formatter 에서는 this로 list, item를 사용할 수 있습니다.

<div id="ui-grid-foot" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-foot",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"*"},
				{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
				{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
				{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
					return (this.item.price.number() * this.item.amount.number()).money();
				}}
			],
			foot : {
				rows: [
					[
						{ colspan: 2, formatter: function () { return "계"; }, align: "center" },
						{ key:"price",
							formatter: function(){
								var sum = 0;
								for(var i=0, l=this.list.length;i<l;i++){
									sum += this.list[i].price;
								}
								return sum.money();
							}
						},
						{ key:"amount" },
						{ key:"sum_cost", align:"right", formatter:"money" }
					]
				]
			}
		});
		myGrid.setList([
			{no:1, title:"AXGrid 첫번째 줄 입니다.", price:123000, amount:2}, // item
			{no:2, title:"AXGrid 두번째 줄 입니다.", price:12300, amount:7},
			{no:3, title:"AXGrid 두번째 줄 입니다.", price:12300, amount:7}
		]);
		myGrid.setDataSet({
			price: 100,
			amount: 100,
			sum_cost: 10000
		});
	})();
</script>

Result

AXGrid.marker

body.marker.display에서 마커 출력여부를 판단하기도 하지만 아이템마다 display를 거치게 되므로 이를 이용해 소계를 구하는 함수를 직접 구현할 수 있다. 예제에서는 marker.display를 통해 마커를 통해 출력여부가 검증되면 marker.rows를 출력하는 샘플입니다.

<div id="ui-grid-marker" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		var grid_ext_data = {};
		var gridSubToalClear = true;
		var gridSubToalLabel = "";

		myGrid.setConfig({
			targetID: "ui-grid-marker",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"*"},
				{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
				{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
				{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
					return (this.item.price.number() * this.item.amount.number()).money();
				}}
			],
			body:{
				marker: {
					display: function(){ // 아이템 한개가 출력될 때 마다 출력여부를 검사합니다.
						var pitem = this.item.title;
						var nitem = null;
						var _this = this;
						if(this.list.length-1 > this.index){
							nitem = this.list[this.index.number()+1].title;
						}
						if(gridSubToalClear){
							grid_ext_data["price"] = 0;
							grid_ext_data["amount"] = 0;
							gridSubToalClear = false;
						}
						if(pitem != nitem){
							grid_ext_data["price"] += this.item.price;
							grid_ext_data["amount"] += this.item.amount;

							gridSubToalLabel = "<b>" + pitem + "</b> 소계";
							gridSubToalClear = true;
							return true;
						}else{
							grid_ext_data["price"] += this.item.price;
							grid_ext_data["amount"] += this.item.amount;
						}
					},
					rows:[
						[
							{ colspan: 2, formatter: function () { return gridSubToalLabel; }, align: "center" },
							{ key:"price", formatter: function () { return grid_ext_data["price"].money(); }},
							{ key:"amount", formatter: function () { return grid_ext_data["amount"] } },
							{ key:"sum_cost", formatter: function () {
								return (grid_ext_data["price"] * grid_ext_data["amount"]).money()
							} , align:"right" }
						]
					]
				}
			}
		});
		myGrid.setList([
			{no:1, title:"AXGrid 첫번째 줄 입니다.", price:123000, amount:2}, // item
			{no:2, title:"AXGrid 두번째 줄 입니다.", price:12300, amount:7},
			{no:3, title:"AXGrid 두번째 줄 입니다.", price:12300, amount:7}
		]);
	})();
</script>

Result

AXGrid.ajax

AJAX 통신관련 설정을 setList메소드안에 정의하면 AXGrid안에서 AJAX통신을 하게 됩니다. setList의 첫번째 아규먼트가 Array이면 데이터로 인식하고 Object이면 AJAX통신을 하게됩니다.

<div id="ui-grid-ajax" style="height:300px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-ajax",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"*"},
				{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
				{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
				{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
					return (this.item.price.number() * this.item.amount.number()).money();
				}}
			],
			body:{
				onclick: function(){
					toast.push( Object.toJSON(this.item) );
				}
			},
			page:{
				paging:true
			}
		});
		myGrid.setList({
			method:"GET",
			ajaxUrl:"data/loadGrid.txt", ajaxPars:"", onLoad:function(){
				// AJAX 통신완료
			}
		});
	})();
</script>

Result

AXGrid.setData

AXGrid.ajax에서 AJAX통신으로 그리드의 데이터를 구성하는 예제를 구현하였는데요. 경우에 따라서는 그리드의 리스트데이터와 페이징 정보를 직접 전달해야 하는 경우도 있습니다. 그런 경우를 대비해 setData를 사용합니다.

<div id="ui-grid-setdata" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-setdata",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"*"},
				{key:"price", label:"가격", width:"100", align:"right", formatter:"money"},
				{key:"amount", label:"수량", width:"80", align:"right", formatter:"money"},
				{key:"cost", label:"금액", width:"100", align:"right", formatter:function(){
					return (this.item.price.number() * this.item.amount.number()).money();
				}}
			],
			body:{
				onclick: function(){
					toast.push( Object.toJSON(this.item) );
				}
			},
			page:{
				paging:true
			}
		});

		new AXReq("data/loadGrid.txt", {
			method: "GET", pars: "",
			onsucc:function(res){
				var data = {
					list: res.list,
					page:{
						pageNo: res.page.pageNo, // 현재페이지
						pageCount: res.page.pageCount, // 전체 페이지수
						listCount: res.page.listCount // 우측하단 카운트 표시 갯수
					}
				};
				myGrid.setData(data);
			}
		});
	})();
</script>

Result

AXGrid.inlineEdit

colGroup 아이템에 editor를 정의하고 그리드의 한줄을 두번 클릭하면 editor.type에 따라 인라인에디트가 활성화 됩니다. 이렇게 활성화 된 에디트모드에서 변경된 데이터가 그리드에 반영되면 그리드 리스트 아이템에 _CUD속성이 추가됩니다.

<div id="ui-grid-inline-edit" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-inline-edit",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"200", editor:{
					type:"text"
				}},
				{key:"writer", label:"작성자", width:"80", align:"center", editor:{
					type:"text"
				}},
				{key:"regDate", label:"작성일", width:"100", align:"center", editor:{
					type:"calendar"
				}},
				{key:"desc", label:"비고", width:"200", editor:{
					type:"text"
				}}
			],
			body:{
				onclick: function(){

				}
			}
		});
		myGrid.setList([
			{no:1, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:2, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:3, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:4, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:5, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:6, title:"여기를 더블클릭하세요", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"}
		]);
	})();
</script>

Result

AXGrid.context

AXContextMenu UI를 그리드안에 추가할 수 있습니다. 구현은 AXContextMenu 설정과 거의 동일합니다. 그리드 setConfig구문안에 contextMenu 값을 추가하면 그리드위에서 마우스 오른쪽 버튼 클릭시 정해진 컨텍스트 메뉴가 열립니다.

<div id="ui-grid-context" style="height:200px;"></div>
<script>
	(function(){
		var myGrid = new AXGrid();
		myGrid.setConfig({
			targetID: "ui-grid-context",
			colGroup: [
				{key:"no", label:"번호", width:"50", align:"right"},
				{key:"title", label:"제목", width:"200"},
				{key:"writer", label:"작성자", width:"80", align:"center"},
				{key:"regDate", label:"작성일", width:"100", align:"center"},
				{key:"desc", label:"비고", width:"200"}
			],
			body:{
				onclick: function(){

				}
			},
			contextMenu: {
				theme: "AXContextMenu", // 선택항목
				width: "150", // 선택항목
				menu:[
					{userType:1, label:"추가하기", className:"plus", onclick:function(){}},
					{userType:1, label:"삭제하기", className:"minus", onclick:function(){}},
					{userType:1, label:"수정하기", className:"edit", onclick:function(){}}
				],
				filter:function(id){
					return true;
				}
			}
		});
		myGrid.setList([
			{no:1, title:"마우스 오른쪽 버튼 클릭", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"},
			{no:2, title:"마우스 오른쪽 버튼 클릭", writer:"장기영", regDate:"2013-01-18",
				desc:"myGrid.setList 의 첫번째 사용법 list json 직접 지정 법"}
		]);
	})();
</script>

Result

http://dev.axisj.com/samples/AXGrid/index.html에 가시면 보다 다양하고 빠른 정보를 얻을 수 있습니다.

AXTree

AXTree는 Tree형데이터 또는 부모자식 관계가 있는 Array형데이터를 Tree구조로 표현해주는 UI 컴포넌트 입니다. expand, collapse처리와 노드이동, 추가, 삭제 등의 기능을 수행할 수 있습니다.

<div id="ui-tree-target" style="height:200px;"></div>
<script>
(function(){
	var myTree = new AXTree();
	myTree.setConfig({
		targetID : "ui-tree-target",
		theme: "AXTree_none",
		indentRatio: 0.7,
		reserveKeys:{
			parentHashKey: "pHash", // 부모 트리 포지션
			hashKey: "hash", // 트리 포지션
			openKey: "open", // 확장여부
			subTree: "subTree", // 자식리스트 키
			displayKey: "display" // 표시여부
		},
		colGroup: [
			{
				key:"nodeName",
				label:"제목",
				width:"100%", align:"left",
				indent:true, // indent 속성값이 있는 컬럼만 인덴트 처리 합니다.
				getIconClass: function(){
					//folder, AXfolder, movie, img, zip, file, fileTxt, fileTag
					return "file";
				},
				formatter:function(){
					return this.item.activity;
				}
			}
		]
	});

	var tree = [
		{no:"1", activity:"WBS 이름", open:true, subTree:[
			{no:"1.1", activity:"기획 및 설계", open:true, subTree:[
				{no:"1.1.1", activity:"기획단계", open:true, subTree:[
					{no:"1.1.1.1", activity:"요구사항정의"},
					{no:"1.1.1.2", activity:"업무분할"}
				]}
			]}
		]},
		{AXTreeSplit:true},
		{no:"9", activity:"WBS 이름"}
	];
	myTree.setTree(tree);

})();
</script>

Result

AXTree.configs

트리의 많은 설정요소중에 단일 값으로 설정되는 요소에 대해 설명드리겠습니다.

var myTree = new AXTree();
myTree.setConfig({
    targetID : "AXTreeTarget",  //{String} - HTML 엘리먼트 타겟아이디
    theme: "AXTree_none",   //[String] - ("AXTree","AXTree_none") CSS Class 이름

	//부모자식 키 정의
    relation:{
        parentKey:"pno",    //부모아이디 키
        childKey:"no"   //자식아이디 키
    },
    persistExpanded: true, // 쿠키를 이용해서 트리의 확장된 상태를 유지합니다.
    persistSelected: true, // 쿠키를 이용해서 트리의 선택된 상태를 유지합니다.
    colGroup: [ //트리 헤드정의
        {
            key:"nodeName", //{String} - 컬럼에 매치될 item 의 키
            label:"제목", //{String} - 컬럼에 표시할 라벨
            width:"100%",   //[Number["px", "%"] = "auto"] - "100%", "500px", "auto"지정하면 트리의 너비만큼 단일 컬럼의 너비가 자동 맞춤 처리됩니다.
            align:"left",   //[String = "left"[left, center, right]] - 정렬방식 지정
            indent:true,    //[Boolean = true]
            getIconClass: function(){   // [Function] - indent 속성 정의된 대상에 아이콘을 지정할 수 있습니다.
                var iconNames = "folder, AXfolder, movie, img, zip, file, fileTxt, fileTag".split(/, /g);
                var iconName = "";
                if(this.item.type) iconName = iconNames[this.item.type];
                return iconName;
            },
            formatter:function(){   // [Function] - 컬럼값의 표현형식 각각 화폐표현식, urlDecode, input.Checkbox, input.radioBox, 사용자 정의 함수
                return "<b>"+this.item.no.setDigit(2) + "</b> : " + this.item.nodeName + " (" + this.item.writer + ")";
            }
        }
    ],
    body: {
        onclick:function(idx, item){ //[Function] 바디 클릭 이벤트 콜백함수
            toast.push(Object.toJSON(item));
        },
        ondblclick:function(idx, item){ //[Function] 바디 더블클릭 이벤트 콜백함수
            toast.push(Object.toJSON(item));
        },
        oncheck:function(idx, item){ //[Function] 트리 체크박스클릭시 함수연결
            toast.push(Object.toJSON(item));
        },
        onexpand:function(idx, item){ //[Function] 트리 아이템 확장 이벤트 콜백함수
            toast.push(Object.toJSON(item));
        },
        oncontract:function(idx, item){ //[Function] 트리 아이템 축소 이벤트 콜백함수
            toast.push(Object.toJSON(item));
        },
        addClass:function(idx, item){ //[Function] 트리 아이템에 사용자 CSS 클래스를 추가할 수 있는 사용자 함수 추가하려는 클래스명을 return 으로 반환하십시요
            toast.push(Object.toJSON(item));
        }
    }
});

AXTree.setList

트리를 구성하기 위해 Tree형 데이터를 이용하여 setTree할 수 도 있지만 부모자식키를 가진 Array형 데이터를 이용하여 setList할 수도 있습니다. 다음은 setList를 이용하여 트리를 구성하는 예제 입니다. 트리를 리스트로 만들수 있으니 참으로 편리합니다.

<div id="ui-tree-setlist-target" class="axisj-ui" style="height:200px;"></div>
<script>
(function(){
	var myTree = new AXTree();
	myTree.setConfig({
		targetID : "ui-tree-setlist-target",
		theme: "AXTree_none",

		xscroll:false,
		emptyListMSG:"<i class='fa fa-spinner'></i> List of Empty",
		iconWidth: 22,
		indentRatio: 1,

		relation:{
			parentKey: "pno",
			childKey: "no",
			parentName: "parentnm",
			childName: "nodenm",
			openKey: "open"
		},

		colGroup: [
			{
				key:"nodeName",
				label: "제목",
				width: "800",
				align:"left",
				indent:true,
				getIconClass: function(){
					return {
						addClass:"userHtml",
						html: ((this.item.__subTreeLength > 0) ? '<i class="axi axi-folder-open2"></i>' : '<i class="axi axi-file"></i>')
					};
				},
				formatter:function(){
					return "<b>"+this.item.no.setDigit(2) + "</b> : " + this.item.nodeName + " (" + this.item.writer + ")";
				}
			}
		],

		body: {
			onclick:function(idx, item){
				toast.push(Object.toJSON(item));
			}
		}
	});

	var List = [
		{pno:0, no:1, nodeName:"LEVEL 1-1", writer:"tom", type:"0", open:true}, // 최상위 부모
		{pno:0, no:2, nodeName:"LEVEL 2-1", writer:"tom", type:"0", open:true},
		{pno:0, no:3, nodeName:"LEVEL 3-1", writer:"tom", type:"0"},
		{pno:1, no:11, nodeName:"LEVEL 1-1-1", writer:"tom", type:"0"},
		{pno:2, no:21, nodeName:"LEVEL 2-1-1", writer:"tom", type:"0"},
		{pno:2, no:24, nodeName:"LEVEL 2-1-4", writer:"tom", type:"0"},
		{pno:24, no:241, nodeName:"LEVEL 2-1-4-1", writer:"tom", type:"0"},
		{pno:241, no:2411, nodeName:"LEVEL 2-1-4-1-1", writer:"tom", type:"0"},
		{pno:241, no:2412, nodeName:"LEVEL 2-1-4-1-1", writer:"tom", type:"0"},
		{pno:2, no:25, nodeName:"LEVEL 2-1-2", writer:"tom", type:"0"}
	];
	myTree.setList(List);

})();
</script>

Result

getIconClass에서 html을 리턴하면 노드 아이콘을 html로 직접 컨트롤 할 수 있습니다.

AXTree.control

<div id="ui-tree-control-target" class="axisj-ui" style="height:200px;"></div>
<div class="DH10"></div>
<input type="button" value="추가" class="AXButton" />
<input type="button" value="자식추가" class="AXButton" />
<input type="button" value="선택삭제" class="AXButton" />
<input type="button" value="수정" class="AXButton" />
<input type="button" value="위로" class="AXButton" />
<input type="button" value="아래로" class="AXButton" />
<input type="button" value="이동하기" class="AXButton" />
<script>
	(function(){
		var myTree = new AXTree();
		myTree.setConfig({
			targetID : "ui-tree-control-target",
			theme: "AXTree",
			relation:{
				parentKey: "pno",
				childKey: "no",
				openKey: "open"
			},
			colGroup: [
				{key:"no", label:"No.", width:"60", align:"left"},
				{
					key:"nodeName", label: "제목", width: "500", indent:true,
					getIconClass: function(){
						return {
							addClass:"userHtml",
							html: ((this.item.__subTreeLength > 0) ? '<i class="axi axi-folder-open2"></i>' : '<i class="axi axi-file"></i>')
						};
					},
					formatter:function(){
						return "<b>"+this.item.no.setDigit(2) + "</b> : " + this.item.nodeName + " (" + this.item.writer + ")";
					}
				}
			],
			colHead: {
				display:true
			}
		});

		var List = [
			{pno:0, no:1, nodeName:"LEVEL 1-1", writer:"tom", type:"0", open:true}, // 최상위 부모
			{pno:0, no:2, nodeName:"LEVEL 2-1", writer:"tom", type:"0", open:true},
			{pno:0, no:3, nodeName:"LEVEL 3-1", writer:"tom", type:"0"},
			{pno:1, no:11, nodeName:"LEVEL 1-1-1", writer:"tom", type:"0"},
			{pno:2, no:21, nodeName:"LEVEL 2-1-1", writer:"tom", type:"0"},
			{pno:2, no:24, nodeName:"LEVEL 2-1-4", writer:"tom", type:"0"}
		];
		myTree.setList(List);
	})();
</script>

Result

AXSearch

AXSearch UI는 검색바를 효과적으로 표현해주는 UI 컴포넌트입니다. 빈 레이어를 타겟으로 스크립트만으로 검색필드를 구성하는 방법과 HTML태그로 만들어진 검색필드들을 변환해주는 두가지 방법이 있습니다.

<div id="ui-search-target" style="border-top:1px solid #ccc;"></div>
<script>
(function(){
	var mySearch = new AXSearch();
	var get_list = function(idx) {
		var list = [{
			label        : "Selector-" + idx,
			labelWidth   : "",
			width        : "150",
			key          : "inputTextSelector-" + idx,
			addClass     : "",
			valueBoxStyle: "",
			type         : "inputText",
			value        : "123",
			AXBind       : {
				type: "selector", config: {
					method: "GET", ajaxUrl: "data/selectorData.txt", ajaxPars: ""
				}
			}
		}, {
			label        : "Date-" + idx,
			labelWidth   : "",
			width        : "110",
			key          : "inputTextDate-" + idx,
			addClass     : "secondItem",
			valueBoxStyle: "",
			type         : "inputText",
			value        : (new Date).print(),
			AXBind       : {
				type: "date"
			}
		}];
		return list;
	};
	mySearch.setConfig({
		targetID: "ui-search-target",
		theme : "AXSearch",
		rows:[
			{display:true, addClass:"", style:"", list:get_list(0)},
			{display:false, addClass:"gray", style:"", list:get_list(1)}
		]
	});
})();
</script>

Result

AXSearch.tagBind

HTML 태그로만들어진 필드에 AXSearch UI를 바인딩 하는 방식입니다.

<form id="ui-search-tagbind-target" style="border-top:1px solid #ccc;border-bottom:1px solid #ccc;">
	<table>
		<tr>
			<td>
				<select name="field-1" class="AXSelect">
					<option value="A">A</option>
					<option value="B">B</option>
				</select>
			</td>
			<td>
				<input type="text" name="field-2" value="" class="AXInput" />
			</td>
			<td>
				<input type="checkbox" name="field-3" value="C1" />
				<input type="checkbox" name="field-3" value="C2" />
			</td>
			<td>
				<button type="button" class="AXButton" id="ui-search-tagbind-btn">확인</button>
			</td>
		</tr>
	</table>
</form>
<script>
(function(){
	var mySearch = new AXSearch();
	mySearch.setConfig({
		targetID: "ui-search-tagbind-target",
		onsubmit: function(){
			alert("submit");
		}
	});
	$("#ui-search-tagbind-btn").click(function(){
		mySearch.submit();
		toast.push( mySearch.getParam() );
	});
})();
</script>

Result

필드에 값을 입력하거나 선택한 후 "확인"버튼을 클릭하면 submit이벤트와 생성된 파라미터 값이 출력됩니다. mySearch.setConfig에 선언된 onsubmit이벤트는 스크립트로 submit을 호출하거나 form필드에서 submit이벤트가 발생하는 경우에 호출됩니다. (submit 이벤트가 발생하는 상황은 form안에 submit타입 버튼이 있거나[button에 type을 지정안하면 기본 submit타입이 됩니다.] input[type=text]가 한개만 있는 경우에 input안에서 return키가 입력되었을 때 입니다.)

자바스크립트로 필드의 값을 수집할 때엔 checkbox 나 radio의 값을 가져오는 것이 까다로운데 파라미터 확인을 해볼 수 있습니다. 잘 되시나요?

AXSearch.finditem

경우에 따라 AXSearch에 내장된 검색 필드들을 직접 컨트롤 해야 하는 경우가 있습니다. 외부에서 값을 비동기적으로 부여 할 때도 있습니다. 이러한 상황에서 내장된 검색 필드들은 찾는 방법에 대해 알아보겠습니다.

<div id="ui-search-finditem-target" style="border-top:1px solid #ccc;"></div>
<div class="DH10"></div>
<button class="AXButton" id="ui-search-finditem-find-0">필드 아이디 찾기</button>
<button class="AXButton" id="ui-search-finditem-find-1">필드 값 변경</button>
<script>
	(function(){
		var mySearch = new AXSearch();
		var get_list = function(idx) {
			var list = [{
				label        : "Selector-" + idx,
				labelWidth   : "",
				width        : "150",
				key          : "inputTextSelector-" + idx,
				addClass     : "",
				valueBoxStyle: "",
				type         : "inputText",
				value        : "123",
				AXBind       : {
					type: "selector", config: {
						method: "GET", ajaxUrl: "data/selectorData.txt", ajaxPars: ""
					}
				}
			}, {
				label        : "Date-" + idx,
				labelWidth   : "",
				width        : "110",
				key          : "inputTextDate-" + idx,
				addClass     : "secondItem",
				valueBoxStyle: "",
				type         : "inputText",
				value        : (new Date).print(),
				AXBind       : {
					type: "date"
				}
			}];
			return list;
		};
		mySearch.setConfig({
			targetID: "ui-search-finditem-target",
			theme : "AXSearch",
			rows:[
				{display:true, addClass:"", style:"", list:get_list(0)}
			]
		});

		$("#ui-search-finditem-find-0").click(function(){
			alert( mySearch.getItemId("inputTextDate-" + 0) );
		});
		$("#ui-search-finditem-find-1").click(function(){
			mySearch.setItemValue("inputTextDate-" + 0, "2012-01-01");
			// mySearch.setItemValue("inputTextDate-" + 0); 값을 지울땐 이렇게
			// mySearch.setItemValue("checkbox", ["all","open"]); 체크박스
		});

	})();
</script>

Result

"필드 아이디 찾기"를 클릭하면 Date-0의 input필드 아이디가 출력됩니다. 이 아이디 값을 이용해서 필드의 값을 컨트롤 할 수 있습니다. "필드 값 변경"을 클릭하면 Date-0의 값을 "2012-01-01"으로 변경합니다. setItemValue를 이용합니다.

AXUpload5

AXUpload5는 HTML5업로드 모드와 Flash 업로드 모드를 사용자 브라우저에 따라 선택적으로 로드합니다. 그러므로 파일 탐색기에서 파일 다중 선택이 모든 브라우저에서 가능하게 해줍니다. 또한 업로드 진행상황을 큐 박스에 출력시켜주는 기능은 사용자에게 업로드 상황을 답답하지 않게 해줍니다.

본 문서에서는 AXUpload5의 설정문만 설명하고 샘플은 dev.axisj.com에서 보도록 하겠습니다.

var myUpload = new AXUpload5(); // 인스턴스를 만듭니다.
myUpload.setConfig({
	targetID: "AXUpload5",
	targetButtonClass: "Green",
	uploadFileName: "fileData",
	file_types: "image/*",  //audio/*|video/*|image/*|MIME_type (accept)
	dropBoxID: "uploadQueueBox",
	queueBoxID: "uploadQueueBox", // upload queue targetID

	// 파일 큐에 아이템을 삭제 할 수 없는 상태를 원할 때
	//openMode: "view",
	//queueBoxAppendType:"prepend|append",

	// html 5를 지원하지 않는 브라우저를 위한 swf upload 설정 원치 않는 경우엔 선언 하지 않아도 됩니다. ------- s
	flash_url : "lib/swfupload.swf",
	flash9_url : "lib/swfupload_fp9.swf",
    flash_file_types: "*.jpg;*.jpeg;*.gif;*.bmp;*.png",
    flash_file_types_description: "image",

	// 업로드된 목록을 클릭했을 때.
	onClickUploadedItem: function(){
		window.open(this.uploadedPath.dec() + this.saveName.dec(), "_blank", "width=500,height=500");
	},

	// 업로드될 개별 파일 사이즈 (클라이언트에서 제한하는 사이즈 이지 서버에서 설정되는 값이 아닙니다.)
	uploadMaxFileSize: (20*1024*1024),
	// 업로드될 파일갯수 제한 0 은 무제한
	uploadMaxFileCount: 10,

	uploadUrl: "fileUpload.php",
	uploadPars: {p1:"1"},
	deleteUrl: "fileDelete.php",
	deletePars: {p1:"1"},

	buttonTxt:"파일올리기",

	// 서버에서 리턴하는 json key 정의 (id는 예약어 사용할 수 없음)
	// 서버에서 키값을 다르게 설정 할 수 있다는 것을 확인 하기 위해 이름을 다르게 처리한 예제 입니다.
	fileKeys:{
		//id:"id",
		name:"name",
		type:"type",
		saveName:"saveName",
		fileSize:"fileSize",
		uploadedPath:"uploadedPath",
		thumbPath:"thumbUrl"

	},
	onbeforeFileSelect: function(){
		// 파일선택창이 열리기 전 - 여기서 return true하지 않으면 파일 선택창이 열리지 않습니다.
		trace(this);
		return true;
	},
	onUpload: function(){
		//trace(this);
	},
	onComplete: function(){
		trace(this);
	},
	onStart: function(){
		trace(this);
	},
	onDelete: function(){
		trace(this);
	},
	onError: function(errorType, extData){
		if(errorType == "html5Support"){
			//dialog.push('The File APIs are not fully supported in this browser.');
		}else if(errorType == "fileSize"){
			//trace(extData);
			alert("파일사이즈가 초과된 파일을 업로드 할 수 없습니다. 업로드 목록에서 제외 합니다.\n("+extData.name+" : "+extData.size.byte()+")");
		}else if(errorType == "fileCount"){
			alert("업로드 갯수 초과 초과된 아이템은 업로드 되지 않습니다.");
		}
	}
});

실제 파일이 업로드되는 예제는 다음의 페이지에서 확인하세요. http://dev.axisj.com/samples/AXUpload5/index.html

file_types의 값은 mime type값 입니다. (http://www.freeformatter.com/mime-types-list.html) 에서 설명을 자세히 하고 있는데요. HTML5의 fileSelect 스펙이 mime type으로 되어 있기 때문에. flash 모드에서의 확장자 타입으로 처리하지 않고 있습니다.