블로그 이미지

카테고리

데꾸벅 (194)
Publisher (39)
Scripter (97)
Programmer (1)
Designer (30)
Integrator (18)
Pattern Searcher (4)
News (2)
강좌 및 번역 (3)

최근에 달린 댓글

간단한 CSS Reset

Publisher/CSS / 2010. 5. 24. 11:49


모든 브라우저마다 CSS가 동일하게 적용되는것은 아니다.
CSS Reset 기능은 이러한 각 브라우저마다 동일한 효과를 주기위해 가장 기본이 되는 CSS를 말한다.
보통 구축하는 웹페이지마다 최초 base.css 나  reset.css 를 두어 전체 웹페이지에 적용되는 CSS를 두기 마련인데 이러한 것이 CSS Reset이라고 보면 된다. 특히 웹퍼블리셔들이 여러 프로젝트를 뛰면서 축적된 경험을 바탕으로 항상 가지고 다니는 CSS들이 대부분 이러한 CSS Reset파일들이나 각 요소들, 예를 들어, 테이블, 탭, 버튼 등 프로젝트 특성을 타지 않는 CSS파일들은 어느 프로젝트나 적용시킬수 있다.
일례로 데꾸벅의 경우는 CSS Reset 파일이 항상 base.css로 만들어 놓고 @import 구문을 이용해서 사용한다. 

참고적으로 많이들 사용하는 CSS Mini Reset 파일들을 공개한다.





이외에 CSS를 인터프리터언어와 같이 프로그래밍언어처럼 사용하는 여러 CSS프레임웍들이 존재하나 아직은 많이 사용되고 있지는 않다.


html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, font, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
/* remember to define focus styles! */
:focus {
outline: 0;
}
body {
line-height: 1;
color: black;
background: white;
}
ol, ul {
list-style: none;
}
/* tables still need 'cellspacing="0"' in the markup */
table {
border-collapse: separate;
border-spacing: 0;
}
caption, th, td {
text-align: left;
font-weight: normal;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: "";
}
blockquote, q {
quotes: "" "";
}




body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { margin:0; padding:0; } table { border-collapse:collapse; border-spacing:0; } fieldset,img { border:0; } address,caption,cite,code,dfn,em,strong,th,var { font-style:normal; font-weight:normal; } ol,ul { list-style:none; } caption,th { text-align:left; } h1,h2,h3,h4,h5,h6 { font-size:100%; font-weight:normal; } q:before,q:after { content:''; } abbr,acronym { border:0; }




/*
    Tripoli is a generic CSS standard for HTML rendering. 
    Copyright (C) 2007  David Hellsing

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

* {
text-decoration: none;
font-size: 1em;
outline: none;
padding: 0;
margin: 0;
}
code, kbd, samp, pre, tt, var, textarea, 
input, select, isindex, listing, xmp, plaintext {
white-space: normal;
font-size: 1em;
font: inherit;
}
dfn, i, cite, var, address, em { 
font-style: normal; 
}
th, b, strong, h1, h2, h3, h4, h5, h6 { 
font-weight: normal; 
}
a, img, a img, iframe, form, fieldset, 
abbr, acronym, object, applet, table {
border: none; 
}
table {
border-collapse: collapse;
border-spacing: 0;
}
caption, th, td, center { 
vertical-align: top;
text-align: left;
}
body { 
background: white; 
line-height: 1; 
color: black; 
}
q { 
quotes: "" ""; 
}
ul, ol, dir, menu { 
list-style: none; 
}
sub, sup { 
vertical-align: baseline; 
}
a { 
color: inherit; 
}
hr { 
display: none; 
}
font { 
color: inherit !important; 
font: inherit !important; 
color: inherit !important; /* editor's note: necessary? */ 
}
marquee {
overflow: inherit !important;
-moz-binding: none;
}
blink { 
text-decoration: none; 
}
nobr { 
white-space: normal; 
}



html, body, ul, ol, li, form, fieldset, legend
{
margin: 0;
padding: 0;
}

h1, h2, h3, h4, h5, h6, p { margin-top: 0; }

fieldset,img { border: 0; }

legend { color: #000; }

li { list-style: none; }

sup { vertical-align: text-top; }

sub { vertical-align: text-bottom; }

table
{
border-collapse: collapse;
border-spacing: 0;
}

caption, th, td
{
text-align: left;
vertical-align: top;
font-weight: normal;
}

input, textarea, select
{
font-size: 110%;
line-height: 1.1;
}

abbr, acronym
{
border-bottom: .1em dotted;
cursor: help;
}




'Publisher > CSS' 카테고리의 다른 글

보석같은 CSS3 함수 calc()  (3) 2013.03.11
Height 100% 2~3단 컨텐츠 레이아웃잡기  (18) 2010.07.27
간단한 CSS Reset  (4) 2010.05.24
CSS 최적화 기법  (7) 2010.03.08
지금 바로 쓸수 있는 CSS3  (0) 2010.03.07
Firefox에서 링크 점선 없애기  (2) 2010.03.06
Post by 넥스트리소프트 데꾸벅(techbug)

댓글을 달아 주세요

  1. 2010.06.02 10:28  댓글주소  수정/삭제  댓글쓰기

    비밀댓글입니다

  2. 2010.09.20 15:22 ed hardy shirts  댓글주소  수정/삭제  댓글쓰기

    가끔식 썩혀두기 아까운 글들만 미천한 실력으로 번역을..

  3. 2010.11.22 16:20 online degree  댓글주소  수정/삭제  댓글쓰기

    좋은 기사가 읽을 수 있습니다. 아주 흥미 롭군요. 당신이 공유하는 독특한 아이디어로 좋은 저자입니다. 난 당신의 다음 블로그 게시물 기다리고있을 겁니다. 감사합니다!


jQuery로 프로젝트 수행중 extjs의 grid기능을 맘껏 쓸수 없을까 하다가 데꾸벅! jqGrid라는 아주 좋은 녀석을 발견하였다.

여러가지 테마를 사용할수 있지만 구미에 맞도록 CSS를 바꿔 보았다. extjs의 경우 UI자체를 수정하기가 어려운 반면 이녀석은 상당히 수월하게 바꿀수 있었다.

소스다운로드 :





HTML

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>서학리조트 컨텐츠</title>
<link rel="stylesheet" type="text/css" href="style/css/contents.css" media="screen" />
<link rel="stylesheet" type="text/css" href="style/css/grid.css" media="screen" />
<script type="text/javascript" src="style/js/jquery.js" charset="utf-8"></script>
<script type="text/javascript" src="style/js/jquery.jqGrid.js" charset="utf-8"></script>
<script type="text/javascript" src="style/js/contents_04.js"  charset="utf-8"></script>
</head>
<body>
    <table class="tbl_tit02"><tr><td>담보 사항</td></tr></table>
    <div class="gridJ" style="width:780px"><table id="gridList" class="scroll" ></table></div>


    <div id="rsperror" title="서버에러나오는곳"></div>

 


    <input type="button" value="선택된Row 데이터가져오기" id="a1" />
    <input type="button" value="Row삭제" id="a2" />
    <input type="button" value="마지막Row추가" id="a3" />
    <input type="button" value="id가 13인 Row선택하기" id="a4" /><br />
    <input type="button" value="tax컬럼 숨기기" id="a5" />
    <input type="button" value="tax컬럼 나타내기" id="a6" />

    <input type="button" value="id가 13 에디팅하기" id="a7" />
    <input type="button" value="저장" id="a8" />
    <input type="button" value="취소" id="a9" /><br />

    <input type="button" value="header값 스타일변경" id="a10" />
    <input type="button" value="셀값 스타일변경" id="a11" />
    <input type="button" value="데이타초기화" id="a12" />
    <input type="button" value="그리드 width/height조절" id="a13" /><br />
   
    <input type="button" value="HTML 테이블을 그리드화하기" id="a14" />
</body>
</html>




js file

var lastsel3;

$(document).ready(function(){

    $("#gridList").jqGrid({
        url:'server.json',
        mtype: 'GET',
        datatype: "json",
        colNames:['인벤토리','날짜', '고객', '수량','세금','합계','비고'],
        colModel:[
         {name:'id',index:'id', width:100,align:"center",key:true},
         {name:'invdate',index:'invdate', width:120,editable:true,sorttype:"date",formatter:'date', formatoptions:{srcformat:"Y-m-d",newformat:"d-M-Y"}},
         {name:'name',index:'name asc, invdate', width:100,editable:true,editoptions:{size:"20",maxlength:"30"}},
         {name:'amount',index:'amount', width:100, align:"right",editable:true,editable:true,editrules:{number:true,minValue:100,maxValue:350},formatter:'currency',formatoptions:{thousandsSeparator:","}},
         {name:'tax',index:'tax', width:100, align:"right",editable:true,edittype:"select",editoptions:{value:"FE:FedEx;IN:InTime;TN:TNT;AR:ARAMEX"}},
         {name:'total',index:'total', width:100,align:"right",editable:true,edittype:"checkbox",editoptions: {value:"Yes:No"}},
         {name:'note',index:'note', width:150, sortable:false,editable:true,edittype:"textarea", editoptions:{rows:"1",cols:"20"}}
        ],
        rowNum:30,    <-- 가끔씩 이넘이 말썽부릴때가...  -1로 해놓으면 가져온 데이타 모두 뿌려줍니다
        height:278,
        sortname: 'id',
        sortorder: "desc",
        viewrecords: true,
        multiselect: false,//앞에 체크박스처리
        multikey: "",//multikey: "ctrlKey/shiftKey",
        editurl: "server.json",
        /*onSelectRow: function(id){  //row가 선택되었을 경우
      if(id && id!==lastsel3){
       jQuery('#gridList').restoreRow(lastsel3);
       jQuery('#gridList').editRow(id,true,pickdates);
       lastsel3=id;
      }
     },*/
        /*jsonReader: {//스크롤할때마다 가져오기
      repeatitems : true,
      cell:"",
      id: "0"
     },*/
       afterInsertRow: function(rowid, aData){
         switch (aData.name) {
          case 'Client 1':
           jQuery("#gridList").setCell(rowid,'total','',{color:'green'});
          break;
          case 'Client 2':
           jQuery("#gridList").setCell(rowid,'total','',{color:'red'});
          break;
          case 'Client 3':
           jQuery("#gridList").setCell(rowid,'total','',{color:'blue'});
          break;
          
         }
        },
        loadError : function(xhr,st,err) {
         jQuery("#rsperror").html("Type: "+st+"; Response: "+ xhr.status + " "+xhr.statusText);
        },
        imgpath: 'style/grid'
    });

    $("#a1").click( function(){
     var id = jQuery("#gridList").getGridParam('selrow');
     if (id) {
      var ret = jQuery("#gridList").getRowData(id);
      alert("id="+ret.id+" invdate="+ret.invdate+"...");
     } else { alert("Row를 선택해주세요");}
    });
    $("#a2").click( function(){
     var su=jQuery("#gridList").delRowData(12);
     if(su) alert("id가 12인 Row삭제"); else alert("이미 지워졌삼~");
    });
    $("#a3").click( function(){
     var datarow = {id:"99",invdate:"2007-09-01",name:"test3",note:"note3",amount:"400.00",tax:"30.00",total:"430.00"};
     var su=$("#gridList").addRowData(99,datarow);
     if(su) alert("마지막Row추가 성공- 서버쪽 업데이트처리해주세요"); else alert("처리가 되지 않았음.");
    });

    $("#a4").click( function() {
        $("#gridList").resetSelection();
     $("#gridList").setSelection("13");
    });

    $("#a5").click( function() {
     $("#gridList").hideCol("tax");
    });
    $("#a6").click( function() {
     $("#gridList").showCol("tax");
    });

    jQuery("#a7").click( function() {
     jQuery("#gridList").editRow("13");
     this.disabled = 'true';
     jQuery("#a8,#a9").attr("disabled",false);
    });
    jQuery("#a8").click( function() {
     jQuery("#gridList").saveRow("13");
     jQuery("#a8,#a9").attr("disabled",true);
     jQuery("#a7").attr("disabled",false);
    });
    jQuery("#a9").click( function() {
     jQuery("#gridList").restoreRow("13");
     jQuery("#a8,#a9").attr("disabled",true);
     jQuery("#a7").attr("disabled",false);
    });

    jQuery("#a10").click( function() {
     $("#gridList").setLabel("tax","Tax Amt",{'font-weight': 'bold','font-style': 'italic'});
    });
   
    jQuery("#a11").click( function() {
     $("#gridList").setCell("12","tax","",{'font-weight': 'bold',color: 'red','text-align':'center'});
    });
   
    jQuery("#a12").click( function() {
     $("#gridList").clearGridData();
    });

    jQuery("#a13").click( function() {
     $("#gridList").setGridWidth(500);
     $("#gridList").setGridHeight(400);

    });

    jQuery("#a14").click(function (){
     tableToGrid("#htmlGrid");
     $("#htmlGrid").setGridWidth(810);
    });

});

 

function pickdates(id){
 alert(id);
}




server.json

{
    "page": "1",
    "total": 27,
    "records": "13",
    "rows": [
        {
            "id": "5",
            "cell": [
                "5",
                "2007-10-06",
                "Client 3",
                "200.00",
                "0.00",
                "200.00",
                null
            ]
        },
        {
            "id": "4",
            "cell": [
                "4",
                "2007-10-05",
                "Client 2",
                "120.00",
                "12.00",
                "134.00",
                null
            ]
        },
        {
            "id": "3",
            "cell": [
                "3",
                "2007-10-05",
                "Client 1",
                "50.00",
                "10.00",
                "60.00",
                null
            ]
        },
        {
            "id": "2",
            "cell": [
                "2",
                "2007-10-05",
                "Client 3",
                "100.00",
                "0.00",
                "100.00",
                "no tax"
            ]
        },
        {
            "id": "1",
            "cell": [
                "1",
                "2007-10-04",
                "Client 3",
                "150.00",
                "0.00",
                "150.00",
                "no tax"
            ]
        }
    ]
}



 소스사용은 자유이나 태클달지 맙시다 ^^  현재버전의 jqGrid와 틀립니다..

Post by 넥스트리소프트 데꾸벅(techbug)

댓글을 달아 주세요

  1. 2009.04.15 09:17 신고 후루룩짭짭  댓글주소  수정/삭제  댓글쓰기

    오우.

    이전에 작업해놨던곳에 적용해 봐야겠습니다.
    굿굿

  2. 2009.06.17 18:37 신고 JKwang  댓글주소  수정/삭제  댓글쓰기

    질문을하나 드려도 될까요???데꾸벅님께서 올려주신 소스를 실행시켜봤는데요 항목타이틀을 누르면 정렬이 안되네요..그리고
    .navGrid('#pager1',{edit:false,add:false,del:false});
    이 체인을 써도 오류가 나요...
    jqgrid3.5 API에 나와있는 예제를 보면 정렬도 되고 navGrid 체인도 되던데...ㅎ ㅏ;;
    아참.그리고 페이지 구현해서 해봤는데..페이지 이동은되는데 10페이지 20페이지 수량설정해서 보는게또 안되네요;;;
    도와주실수있나요??힝..

  3. 2009.06.19 13:23 신고 JKwang  댓글주소  수정/삭제  댓글쓰기

    음^^네이게이션그리드는 버전이 안맞아서 그랬는지..아님 JQuery UI를 임포트시키지 않아서 그런건지는 모르겠지만 해결은 했구요. 정렬이나 페이지는 실제로 DB에서 조건에 따라서 데이터를 입력받아와야 하더군요...음.그리고 가장큰 문제가..
    searchGrid에서요..sopt 값을 지정하면 검색조건항목 수정이 안됩니다;.크;;
    $("#GridId").searchGrid({
    odata: ['같을때','다를때','보다클때','보다작을때'],
    sopt: ['eq','ne','gt','lt']
    })

  4. 2009.06.19 14:33 신고 JKwang  댓글주소  수정/삭제  댓글쓰기

    jquery.jqgrid.min.js의
    for(i=0;c.sopt.length<0;i++)
    이부분을
    for(i=0;c.sopt.length>i;i++)
    이렇게 수정하니 되는군요;;;어이없어라..

  5. 2009.06.19 19:36 JKwang  댓글주소  수정/삭제  댓글쓰기

    자꾸질문남겨서 죄송한데요..이건 정말 모르겠어서 질문드립니다.;;
    colmodel : [{name:'note',index:'note',width:50,hidden:true, editable:true}]
    옵션을 이렇게 주고서요..
    리스트엔 'note'컬럼이 안나오지만 view상태에서는 'note'컬럼내용을 나오게 하고싶은데..
    API를 봐도 전혀 모르겠어서요;;;이부분 어떻게 하시는지 아시나요??

  6. 2009.09.18 22:52 조조  댓글주소  수정/삭제  댓글쓰기

    grid의 header가 단일행으로만 처리 가능한가요??
    heager를 rowspan, colspan등을 처리해서 구성 할 수 없을까요??

  7. 2010.01.26 16:00 신고 Simulz  댓글주소  수정/삭제  댓글쓰기

    문제제기...
    고유값 컬럼이 없는 테이블 같은 경우(중복 데이터가 많은 로그 기록용)
    (첫번째 컬럼 값은 중복 가능)

    GRID에서 마우스로 행 선택이 안되는데, (멀티 선택에서는 다른 행이 선택됨)
    행 선택이 제대로 되는 방법이 있나요?? 자체 고유 행 번호를 생성한다던지...
    grid는 첫번째 컬럼 값을 기준으로 선택되나 봅니다.


    ps. 도대체 jQGrid는 API문서가 제대로 된게 없네요 wiki도 조잡한거 같고...

  8. 2010.03.12 16:39 Oh  댓글주소  수정/삭제  댓글쓰기

    안녕하세요

    궁금한점이 있어서 글 남깁니다

    이번에 jqGrid를 써볼려고 하는데 css수정이 쉽다고 하셨는데

    저는 도통 모르겠네요..어떤걸 바꾸려면 어디를 만져야 하는건지..감이 안오네요..

    grid 내부에 쓰이는 코드가 어떤건지도 모르니 타이틀이 아이디가 뭘로 잡혀있고 클래스는 뭘로잡혀있고..

    이런것도 모르는데 css를 어떻게 수정할수 있을까요?

    그리고 여러가지 테마를 사용할수 있다고 하셨는데 테마는 어떻게 쓰는지...

    휴..어렵네요 ㅠ

    • 2010.03.15 14:03 신고 데꾸벅  댓글주소  수정/삭제

      웹표준코딩을 해 보셨다면 쉽게 작업하실 수 있을텐데..
      CSS 파일이 별도로 떨어져 있습니다. 포스트속에 첨부된 파일을 다운로드 받으신후 해당 CSS를 하나씩 수정해 보세요...
      그리고 id값이나 grid안의 코드는 파이어버그와 같은 DOM Inspector가 있는 플러그인들로 뜯어보실 수 있습니다.



기본적으로 grid의 View에 editor와 같이 다른 컴포넌트를 붙이기는 기존 소스보다 컴포넌트를 붙이는 소스가 더 많이 들어가는 경우가 있다.
데꾸벅의 경우도 프로젝트중 각각의 그리드 Row마다 progress bar를 붙여야 하는 경우가 생겼었는데..
포럼글을 뒤지다가 다음과 같은 좋은 사용자 플러그인이 있어 분석을 위해 소스를 까 보았다.



위 그림에서 보는바와 같이 그리드위에 버튼을 만들어 올릴때 new Ext.button이 아닌 new Ext.Action을 사용하여 사용자 플러그인을 사용한 소스이다.
소스 API  및 관련 포럼글 

HTML
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <link rel="stylesheet" type="text/css" href="./css/icons.css">
 <link rel="stylesheet" type="text/css" href="./css/Ext.ux.grid.RowActions.css">
    <link rel="stylesheet" type="text/css" href="../../ext/ext-2.2/resources/css/ext-all.css" />
    <script type="text/javascript" src="../../ext/ext-2.2/adapter/ext/ext-base.js"></script>
    <script type="text/javascript" src="../../ext/ext-2.2/ext-all.js"></script>
 <script type="text/javascript" src="./js/Ext.ux.grid.RowActions.js"></script>
 <script type="text/javascript" src="./js/Ext.ux.Toast.js"></script>
 <script type="text/javascript" src="rowactions.js"></script>
</head>
<body></body>
</html>





JS

Ext.BLANK_IMAGE_URL = '';
Ext.ns('Example');
Example.version = '1.0';

Example.Grid = Ext.extend(Ext.grid.GridPanel, {

  initComponent:function() {

   // Create RowActions Plugin
   this.action = new Ext.ux.grid.RowActions({
    header:'Actions'
   ,autoWidth:true
   ,keepSelection:true
   ,actions:[{
     iconIndex:'action1'
    ,qtipIndex:'qtip1'
    ,iconCls:'icon-open'
    ,tooltip:'Open'
   },{
     iconCls:'icon-wrench'
    ,tooltip:'Configure'
    ,qtipIndex:'qtip2'
    ,iconIndex:'action2'
    ,hideIndex:'hide2'
   },{
     iconIndex:'action3'
    ,qtipIndex:'qtip3'
    ,iconCls:'icon-user'
    ,tooltip:'User'
    ,style:'background-color:yellow'
   }]
   ,groupActions:[{
     iconCls:'icon-del-table'
    ,qtip:'Remove Table'
   },{
     iconCls:'icon-add-table'
    ,qtip:'Add Table - with callback'
    ,callback:function(grid, records, action, groupId) {
     Ext.ux.Message.msg('Callback: icon-add-table'
         , 'Group: <b>{0}</b>, action: <b>{1}</b>, records: <b>{2}</b>'
         , groupId
         , action
         , records.length);
    }
   },{
     iconCls:'icon-graph'
    ,qtip:'View Graph'
    ,align:'left'
   }]
   ,callbacks:{
    'icon-plus':function(grid, record, action, row, col) {
     Ext.ux.Message.msg('Callback: icon-plus'
         , 'You have clicked row: <b>{0}</b>, action: <b>{0}</b>'
         , row
         , action);
    }
   }
  });

  this.action.on({
   action:function(grid, record, action, row, col) {
    Ext.ux.Message.msg('Event: action', '클릭한 Row: <b>{0}</b>, 액션: <b>{1}</b>'
        , row
        , action);
   }
   ,beforeaction:function() {
    Ext.ux.Message.msg('Event: beforeaction', '핸들러에서 false반환시 액션취소.');
   }
   ,beforegroupaction:function() {
    Ext.ux.Message.msg('Event: beforegroupaction', '핸들러에서 false반환시 액션취소');
   }
   ,groupaction:function(grid, records, action, groupId) {
    Ext.ux.Message.msg('Event: groupaction', 'Group: <b>{0}</b>, action: <b>{1}</b>, records: <b>{2}</b>', groupId, action, records.length);
   }
  });

  Ext.apply(this, {
    store:new Ext.data.Store({
    reader:new Ext.data.JsonReader({
      id:'company'
     ,totalProperty:'totalCount'
     ,root:'rows'
     ,fields:[
      {name: 'company'}
        ,{name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'}
        ,{name: 'industry'}
        ,{name: 'desc'}
        ,{name: 'action1', type: 'string'}
        ,{name: 'action2', type: 'string'}
        ,{name: 'action3', type: 'string'}
        ,{name: 'qtip1', type: 'string'}
        ,{name: 'qtip2', type: 'string'}
        ,{name: 'qtip3', type: 'string'}
        ,{name: 'hide2', type: 'boolean'}
     ]
    })
    ,proxy:new Ext.data.HttpProxy({url:'jsonData.json'})
    ,sortInfo:{field:'company', direction:'ASC'}
    ,listeners:{
     load:{scope:this, fn:function() {
      this.getSelectionModel().selectFirstRow();
     }}
    }
   })
   ,columns:[
    {id:'company',header: "Company", width: 40, sortable: true, dataIndex: 'company'}
    ,{header: "Industry", width: 20, sortable: true, dataIndex: 'industry'}
    ,{header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
    ,this.action
   ]
   ,plugins:[this.action]
   ,loadMask:true
   ,viewConfig:{forceFit:true}
  });

  this.bbar = new Ext.PagingToolbar({
    store:this.store
   ,displayInfo:true
   ,pageSize:10
  });

  Example.Grid.superclass.initComponent.apply(this, arguments);
 }


 ,onRender:function() {
  Example.Grid.superclass.onRender.apply(this, arguments);
  this.store.load({params:{start:0, limit:10}});
 }
});

//컴포넌트 등록
Ext.reg('techbuggrid', Example.Grid);

Ext.onReady(function() {
    Ext.QuickTips.init();

    var win = new Ext.Window({
         width:600
  ,minWidth:320
        ,id:'agwin'
        ,height:400
        ,layout:'fit'
        ,border:false
  ,plain:true
        ,closable:false
        ,title:"그리드 Row Action 처리하기"
  ,items:{xtype:'techbuggrid',id:'actiongrid'}
    });
    win.show();
});




사용자 플러그인.JS

Ext.ns('Ext.ux.grid');
if('function' !== typeof RegExp.escape) {
 RegExp.escape = function(s) {
  if('string' !== typeof s) {
   return s;
  }
  return s.replace(/([.*+?\^=!:${}()|\[\]\/\\])/g, '\\$1');
 };
}

Ext.ux.grid.RowActions = function(config) {
 Ext.apply(this, config);
 this.addEvents(
   'beforeaction'
  ,'action'
  ,'beforegroupaction'
  ,'groupaction'
 );
 Ext.ux.grid.RowActions.superclass.constructor.call(this);
};

Ext.extend(Ext.ux.grid.RowActions, Ext.util.Observable, {
  actionEvent:'click'
 ,autoWidth:true
 ,dataIndex:''
 ,header:''
 ,keepSelection:false
 ,menuDisabled:true
 ,sortable:false
 ,tplGroup:
   '<tpl for="actions">'
  +'<div class="ux-grow-action-item<tpl if="\'right\'===align"> ux-action-right</tpl> '
  +'{cls}" style="{style}" qtip="{qtip}">{text}</div>'
  +'</tpl>'
 ,tplRow:
   '<div class="ux-row-action">'
  +'<tpl for="actions">'
  +'<div class="ux-row-action-item {cls} <tpl if="text">'
  +'ux-row-action-text</tpl>" style="{hide}{style}" qtip="{qtip}">'
  +'<tpl if="text"><span qtip="{qtip}">{text}</span></tpl></div>'
  +'</tpl>'
  +'</div>'
 ,hideMode:'visiblity'
 ,widthIntercept:4
 ,widthSlope:21
 ,init:function(grid) {
  this.grid = grid;
  if(!this.tpl) {
   this.tpl = this.processActions(this.actions);
  }
  if(this.autoWidth) {
   this.width =  this.widthSlope * this.actions.length + this.widthIntercept;
   this.fixed = true;
  }
  var view = grid.getView();
  var cfg = {scope:this};
  cfg[this.actionEvent] = this.onClick;
  grid.afterRender = grid.afterRender.createSequence(function() {
   view.mainBody.on(cfg);
   grid.on('destroy', this.purgeListeners, this);
  }, this);

  if(!this.renderer) {
   this.renderer = function(value, cell, record, row, col, store) {
    cell.css += (cell.css ? ' ' : '') + 'ux-row-action-cell';
    return this.tpl.apply(this.getData(value, cell, record, row, col, store));
   }.createDelegate(this);
  }

  if(view.groupTextTpl && this.groupActions) {
   view.interceptMouse = view.interceptMouse.createInterceptor(function(e) {
    if(e.getTarget('.ux-grow-action-item')) {
     return false;
    }
   });
   view.groupTextTpl =
     '<div class="ux-grow-action-text">' + view.groupTextTpl +'</div>'
    +this.processActions(this.groupActions, this.tplGroup).apply()
   ;
  }

  if(true === this.keepSelection) {
   grid.processEvent = grid.processEvent.createInterceptor(function(name, e) {
    if('mousedown' === name) {
     return !this.getAction(e);
    }
   }, this);
  }
  
 }
 ,getData:function(value, cell, record, row, col, store) {
  return record.data || {};
 }

 ,processActions:function(actions, template) {
  var acts = [];

  Ext.each(actions, function(a, i) {
   if(a.iconCls && 'function' === typeof (a.callback || a.cb)) {
    this.callbacks = this.callbacks || {};
    this.callbacks[a.iconCls] = a.callback || a.cb;
   }

   var o = {
     cls:a.iconIndex ? '{' + a.iconIndex + '}' : (a.iconCls ? a.iconCls : '')
    ,qtip:a.qtipIndex ? '{' + a.qtipIndex + '}' : (a.tooltip || a.qtip ? a.tooltip || a.qtip : '')
    ,text:a.textIndex ? '{' + a.textIndex + '}' : (a.text ? a.text : '')
    ,hide:a.hideIndex
     ? '<tpl if="' + a.hideIndex + '">'
      + ('display' === this.hideMode ? 'display:none' :'visibility:hidden') + ';</tpl>'
     : (a.hide ? ('display' === this.hideMode ? 'display:none' :'visibility:hidden;') : '')
    ,align:a.align || 'right'
    ,style:a.style ? a.style : ''
   };
   acts.push(o);

  }, this);

  var xt = new Ext.XTemplate(template || this.tplRow);
  return new Ext.XTemplate(xt.apply({actions:acts}));

 }
 ,getAction:function(e) {
  var action = false;
  var t = e.getTarget('.ux-row-action-item');
  if(t) {
   action = t.className.replace(/ux-row-action-item /, '');
   if(action) {
    action = action.replace(/ ux-row-action-text/, '');
    action = action.trim();
   }
  }
  return action;
 }
 ,onClick:function(e, target) {

  var view = this.grid.getView();

  var row = e.getTarget('.x-grid3-row');
  var col = view.findCellIndex(target.parentNode.parentNode);
  var action = this.getAction(e);

  if(false !== row && false !== col && false !== action) {
   var record = this.grid.store.getAt(row.rowIndex);

   if(this.callbacks && 'function' === typeof this.callbacks[action]) {
    this.callbacks[action](this.grid, record, action, row.rowIndex, col);
   }

   if(true !== this.eventsSuspended && false === this.fireEvent('beforeaction', this.grid, record, action, row.rowIndex, col)) {
    return;
   }
   else if(true !== this.eventsSuspended) {
    this.fireEvent('action', this.grid, record, action, row.rowIndex, col);
   }

  }

  t = e.getTarget('.ux-grow-action-item');
  if(t) {
   var group = view.findGroup(target);
   var groupId = group ? group.id.replace(/ext-gen[0-9]+-gp-/, '') : null;

   var records;
   if(groupId) {
    var re = new RegExp(RegExp.escape(groupId));
    records = this.grid.store.queryBy(function(r) {
     return r._groupId.match(re);
    });
    records = records ? records.items : [];
   }
   action = t.className.replace(/ux-grow-action-item (ux-action-right )*/, '');

   if('function' === typeof this.callbacks[action]) {
    this.callbacks[action](this.grid, records, action, groupId);
   }

   if(true !== this.eventsSuspended && false === this.fireEvent('beforegroupaction', this.grid, records, action, groupId)) {
    return false;
   }
   this.fireEvent('groupaction', this.grid, records, action, groupId);
  }
 }

});

Ext.reg('rowactions', Ext.ux.grid.RowActions);




요기 괜찮은 사용자 플러그인도 함 보세요





















'Scripter > EXTJS' 카테고리의 다른 글

Extjs Core 3.0 Beta 릴리즈  (4) 2009.04.07
Examples Of ExtJS in Action  (2) 2009.03.31
extjs RowAction 붙이기  (1) 2009.03.31
extjs 2.2의 IE에서 iframe document load 버그패치  (0) 2009.01.21
Extjs 3.0 Roadmap  (10) 2008.11.12
Ext2.2 Release  (11) 2008.08.07
Post by 넥스트리소프트 데꾸벅(techbug)

댓글을 달아 주세요

  1. 2012.04.25 00:43 Management Thesis  댓글주소  수정/삭제  댓글쓰기

    아주 좋은 블로그와 나는 하드 작업을 정말로 감사합니다 .. 그리고 당신이 매일 블로그를 업데이 트 바란다

Basic Concept

이번 장은 이전에 작성해놓은 기본레이아웃잡기 및 기본그리드기리기를 이용하여 레이아웃의 좌측영역(west region)에 그리드를 붙이는 작업을 진행한다.
이전장을 충분히 숙지하였다는 가정하에 Grid를 붙여보자

기본소스 :


<그리드 해부도>

사용자 삽입 이미지









Step 1.  왼쪽 기본 패널을 Grid패널로 변경

basicLayout_AttachedGrid.html

<html>
<head>
<title>Basic Layout</title>
<link rel="stylesheet" type="text/css" href="http://techbug.tistory.com/resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
<script type="text/javascript" src="basicLayout_AttachedGrid.js"></script>
</head>
<body id="basicLayoutBody"></body>
</html>

 

basicLayout_AttachedGrid.js

// 그리드 패널 클래스 시작
LeftArea = function(viewport){ //왼쪽 패널(LeftArea)을 정의한다.
this.viewport = viewport;

this.store = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({
url: 'basicGrid.json'
}),
sortInfo: {
field: 'price',
direction: "DESC"
},
reader: new Ext.data.JsonReader({
root: 'testData'
}, [{
name: 'company',
type: 'string',
mapping: 'company'
}, {
name: 'price',
type: 'float',
mapping: 'price'
}, {
name: 'change',
type: 'float',
mapping: 'change'
}, {
name: 'pctChange',
type: 'float',
mapping: 'pctChange'
}, {
name: 'lastChange',
type: 'date',
dateFormat: 'n/j h:ia',
mapping: 'lastChange'
}])
});
// 왼쪽 패널의 config옵션을 정의한다.
LeftArea.superclass.constructor.call(this, {
region: 'west', // 굵게 표시된 부분은 기본레이아웃을 잡는 config옵션이다.
title: 'WEST',
collapsible: true,
collapsed: false,
width: 250,
split: true,
layout: 'fit',
margins: '5 0 5 5',
cmargins: '5 5 5 5',
store: this.store,
columns: [{
id: 'company',
header: "Company",
width: 160,
sortable: true,
dataIndex: 'company'
}, {
header: "Price",
width: 75,
sortable: true,
renderer: 'usMoney',
dataIndex: 'price'
}, {
header: "Change",
width: 75,
sortable: true,
dataIndex: 'change'
}, {
header: "% Change",
width: 75,
sortable: true,
dataIndex: 'pctChange'
}, {
header: "Last Updated",
width: 85,
sortable: true,
renderer: Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}],
stripeRows: true,
autoExpandColumn: 'company',
loadMask: {
msg: '데이타 로드중'
},
sm: new Ext.grid.RowSelectionModel({
singleSelect: true
}),
view: new Ext.grid.GridView({
forceFit: true,
enableRowBody: true,
emptyText: 'No Record found'
})
});
};

//기본레이아웃에서는 Ext.Panel을 상속받았지만
//여기서는 그리드패널이므로 Ext.grid.GridPanel을 상속받음.
Ext.extend(LeftArea, Ext.grid.GridPanel, {
});


// 그리드 패널 클래스 끝



// 메인 레이아웃 클래스 시작
BasicLayoutClass = function(){
return {
init: function(){
Ext.QuickTips.init();
this.viewport = new Ext.Viewport({
layout: 'border',
items: [this.WestPanel = new LeftArea(this), this.CenterPanel = new Ext.Panel({
region: 'center',
title: 'CENTER',
layout: 'fit',
margins: '5 5 5 0',
html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
})]
});

this.viewport.doLayout();
this.viewport.syncSize();

// 좌측그리드의 데이타 스토어를 화면을 최초 그릴때 데이타를 로드한다.
this.WestPanel.store.load();
}
}
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);
// 메인 레이아웃 클래스 끝

 기본레이아웃에서 달라진 부분은 왼쪽 패널(LeftArea)이  기본패널(Ext.Panel)에서 그리드패널(Ext.grid.GridPanel)로 바뀌었을 뿐이다. 

위소스중 기본패널의 config옵션( 굵게 표현된 부분)에 Grid 옵션이 더 추가되었을 뿐이다. 대신 왼쪽 그리드패널의 데이타스토어를 메인레이아웃에서 호출(this.WestPanel.store.load();)하였다.
Step2에서는 좌측 그리드패널 클래스를 별도의 파일로 추가하여 정리해보자

 

Step 2. 좌측그리드패널 클래스 별도 파일로 관리하기

basicLayout_AttachedGrid.html

<html>
<head>
<title>Basic Layout</title>
<link rel="stylesheet" type="text/css" href="http://techbug.tistory.com/resources/css/ext-all.css" />
<script type="text/javascript" src="../../adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../../ext-all.js"></script>
//좌측 그리드 패널클래스 별도 파일로 분리, 반드시 main 레이아웃 클래스보다 먼저 호출
<script type="text/javascript" src="basicLayout_LeftGrid.js"></script>
<script type="text/javascript" src="basicLayout_AttachedGrid.js"></script>
</head>
<body id="basicLayoutBody"></body>
</html>

basicLayout_AttachedGrid.js

BasicLayoutClass = function(){
    return {
        init: function(){
            Ext.QuickTips.init();
            this.viewport = new Ext.Viewport({
                layout: 'border',
                items: [this.WestPanel = new LeftArea(this),
                //좌측 그리드 클래스 호출
                this.CenterPanel = new Ext.Panel({
                    region: 'center',
                    title: 'CENTER',
                    layout: 'fit',
                    margins: '5 5 5 0',
                    html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
                })]
            });
            this.viewport.doLayout();
            this.viewport.syncSize();
            //좌측 패널의 public method호출
            this.WestPanel.loadGridDataSet();
        }
    }
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);

basicLayout_LeftGrid.js

LeftArea = function(viewport){

    this.viewport = viewport;

    this.store = new Ext.data.Store({
        proxy: new Ext.data.HttpProxy({
            url: 'basicGrid.json'
        }),
        sortInfo: {
            field: 'price',
            direction: "DESC"
        },
        reader: new Ext.data.JsonReader({
            root: 'testData'
        }, [{
            name: 'company',
            type: 'string',
            mapping: 'company'
        }, {
            name: 'price',
            type: 'float',
            mapping: 'price'
        }, {
            name: 'change',
            type: 'float',
            mapping: 'change'
        }, {
            name: 'pctChange',
            type: 'float',
            mapping: 'pctChange'
        }, {
            name: 'lastChange',
            type: 'date',
            dateFormat: 'n/j h:ia',
            mapping: 'lastChange'
        }])
    });

    LeftArea.superclass.constructor.call(this, {
        region: 'west',
        title: 'WEST',
        collapsible: true,
        collapsed: false,
        width: 250,
        split: true,
        layout: 'fit',
        margins: '5 0 5 5',
        cmargins: '5 5 5 5',
        store: this.store,
        columns: [{
            id: 'company',
            header: "Company",
            width: 160,
            sortable: true,
            dataIndex: 'company'
        }, {
            header: "Price",
            width: 75,
            sortable: true,
            renderer: 'usMoney',
            dataIndex: 'price'
        }, {
            header: "Change",
            width: 75,
            sortable: true,
            dataIndex: 'change'
        }, {
            header: "% Change",
            width: 75,
            sortable: true,
            dataIndex: 'pctChange'
        }, {
            header: "Last Updated",
            width: 85,
            sortable: true,
            renderer: Ext.util.Format.dateRenderer('m/d/Y'),
            dataIndex: 'lastChange'
        }],
        stripeRows: true,
        autoExpandColumn: 'company',
        loadMask: {
            msg: '데이타 로드중'
        },
        sm: new Ext.grid.RowSelectionModel({
            singleSelect: true
        }),
        view: new Ext.grid.GridView({
            forceFit: true,
            enableRowBody: true,
            emptyText: 'No Record found'
        })
    });
};

Ext.extend(LeftArea, Ext.grid.GridPanel, {
    //public Method 정의 부분
    loadGridDataSet: function(){
        this.store.load();
    }


});


위의 Step1과 변경된것이라고는 좌측그리드패널 클래스를 별도 파일로 분리하고 클래스내의 public 메쏘드를 메인레이아웃에서 호출한다는것이다.
그러나 이 러한 구조의 클래스는 항상 메인 레이아웃에서 특정 레이아웃일때만 사용된다 예를 들어  좌측그리드패널클래스(LeftArea)의 config option중에 레이아웃에 해당하는 값들이 이미 들어가 있기 때문에 다른 구조의 레이아웃에서는 이 클래스를 호출하여 사용할수 없다는 단점이 있다.

 

 

 

Step 3. 클래스 리팩토링

basicLayout_LeftGrid.js
LeftArea = function(viewport, config){

    this.viewport = viewport;
    Ext.apply(this, config);

    this.store = new Ext.data.Store({
        proxy: new Ext.data.HttpProxy({
            url: 'basicGrid.json'
        }),
        sortInfo: {
            field: 'price',
            direction: "DESC"
        },
        reader: new Ext.data.JsonReader({
            root: 'testData'
        }, [{
            name: 'company',
            type: 'string',
            mapping: 'company'
        }, {
            name: 'price',
            type: 'float',
            mapping: 'price'
        }, {
            name: 'change',
            type: 'float',
            mapping: 'change'
        }, {
            name: 'pctChange',
            type: 'float',
            mapping: 'pctChange'
        }, {
            name: 'lastChange',
            type: 'date',
            dateFormat: 'n/j h:ia',
            mapping: 'lastChange'
        }])
    });
    // 레이아웃과 관련된 부분을 제외하고 순수 그리드 config option 부분만 사용
    LeftArea.superclass.constructor.call(this, {
        store: this.store,
        columns: [{
            id: 'company',
            header: "Company",
            width: 160,
            sortable: true,
            dataIndex: 'company'
        }, {
            header: "Price",
            width: 75,
            sortable: true,
            renderer: 'usMoney',
            dataIndex: 'price'
        }, {
            header: "Change",
            width: 75,
            sortable: true,
            dataIndex: 'change'
        }, {
            header: "% Change",
            width: 75,
            sortable: true,
            dataIndex: 'pctChange'
        }, {
            header: "Last Updated",
            width: 85,
            sortable: true,
            renderer: Ext.util.Format.dateRenderer('m/d/Y'),
            dataIndex: 'lastChange'
        }],
        stripeRows: true,
        autoExpandColumn: 'company',
        loadMask: {
            msg: '데이타 로드중'
        },
        sm: new Ext.grid.RowSelectionModel({
            singleSelect: true
        }),
        view: new Ext.grid.GridView({
            forceFit: true,
            enableRowBody: true,
            emptyText: 'No Record found'
        })
    });
};

Ext.extend(LeftArea, Ext.grid.GridPanel, {
    loadGridDataSet: function(){
        this.store.load();
    }
});



 

basicLayout_AttachedGrid.js

BasicLayoutClass = function(){
return {
init: function(){
Ext.QuickTips.init();
//레이아웃과 관련된 내용을 메인레이아웃 클래스 밖으로 빼냄
this.WestPanel = new LeftArea(this, {
region: 'west',
title: 'WEST',
collapsible: true,
collapsed: false,
width: 650,
split: true,
layout: 'fit',
margins: '5 0 5 5',
cmargins: '5 5 5 5'
}), this.viewport = new Ext.Viewport({
layout: 'border',
items: [this.WestPanel, this.CenterPanel = new Ext.Panel({
region: 'center',
title: 'CENTER',
layout: 'fit',
margins: '5 5 5 0',
html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
})]
});
this.viewport.doLayout();
this.viewport.syncSize();
this.WestPanel.loadGridDataSet();
}
}
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);

위 와 같이 작성되었을 경우는 별도 파일로 빼낸 BasicLayout_LeftGrid.js 파일은 다른 곳에서도 재사용할수 있다. 그러나 ExtJS Panel특성상 바로 Ext.apply()를 통하여 해당 config option을 LayoutContainer에 적용할수 없다. 위 소스를 실행 시켜 보면  왼쪽 판넬의 collapseMode가  잘못 적용되어 container 속성까지 변경되었다. 이럴 경우에는 NestedLayout Manager를 사용하여 다음과 같이 표현하면 된다.


basicLayout_AttachedGrid.js

BasicLayoutClass = function(){
    return {
        init: function(){
            Ext.QuickTips.init();
            
            this.viewport = new Ext.Viewport({
                layout: 'border',
                items: [{
                    region: 'west', // 일반 Ext.panel로 설정하여 왼쪽
                    title: 'WEST',
                    collapsible: true,
                    collapsed: false,
                    width: 650,
                    split: true,
                    margins: '5 0 5 5',
                    cmargins: '5 5 5 5',
                    layout: 'border',
                    items: [ // 일반 Ext.panel에 Nested된 좌측패널
                        this.WestPanel = new LeftArea(this, {
                        region: 'center',
                        layout: 'fit',
                        border: false
                    })]
                }, this.CenterPanel = new Ext.Panel({
                    region: 'center',
                    title: 'CENTER',
                    layout: 'fit',
                    margins: '5 5 5 0',
                    html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
                })]
            });
            this.viewport.doLayout();
            this.viewport.syncSize();
            this.WestPanel.loadGridDataSet();
        }
    }
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);

 

Step 4. 그리드 판넬에 새로고침 메뉴넣기

basicLayout_AttachedGrid.js

BasicLayoutClass = function(){
return {
init: function(){
Ext.QuickTips.init();

this.viewport = new Ext.Viewport({
layout: 'border',
items: [{
region: 'west',
title: 'WEST',
collapsible: true,
collapsed: false,
width: 650,
split: true,
margins: '5 0 5 5',
cmargins: '5 5 5 5',
layout: 'border',
items: [this.WestPanel = new LeftArea(this, {
region: 'center',
layout: 'fit',
border: false,
tbar: [{
text: '새로고침',
scope: this,
handler: function(){
this.WestPanel.store.reload();
}
}]
})]
}, this.CenterPanel = new Ext.Panel({
region: 'center',
title: 'CENTER',
layout: 'fit',
margins: '5 5 5 0',
html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
})]
});
this.viewport.doLayout();
this.viewport.syncSize();
this.WestPanel.loadGridDataSet();
}
}
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);

 위의 Toolbar 를 basicLayout_LeftGrid.js를 이용하여 붙일수도 있으나 사용하는곳 마다 툴바가 틀릴수 있으므로 되도록이면 좌측 그리드패널 클래스를 호출하는 메인 클래스에 붙이는것이 재사용성에 좋다. 넥스트리소프트의 경우는 모두 좌측그리드패널 클래스 안에 private로 선언되어 있다. 어느것이 좋을지는 사용하는곳마다 틀리므로 해당 상황을 보면서 붙여보도록 한다.

넥스트리의 경우는 모두 클래스안에 private method로 해당 클래스내에서만 사용하는 메쏘드를 두었으며 필요에 따라 외부클래스에서 호출하는 식으로 되어 있다. 취향에 따라 맞춰 하면 될듯... ^^

 

 

 

Step 5. 선택시 우측컨텐츠 판넬(cente region Basic fit layout)의 body 업데이트하기

basicLayout_AttachedGrid.js

BasicLayoutClass = function(){
return {
init: function(){
Ext.QuickTips.init();

this.viewport = new Ext.Viewport({
layout: 'border',
items: [{
region: 'west',
title: 'WEST',
collapsible: true,
collapsed: false,
width: 650,
split: true,
margins: '5 0 5 5',
cmargins: '5 5 5 5',
layout: 'border',
items: [this.WestPanel = new LeftArea(this, {
region: 'center',
layout: 'fit',
border: false,
tbar: [{
text: '새로고침',
scope: this,
handler: function(){
this.WestPanel.store.reload();
}
}]
})]
}, this.CenterPanel = new Ext.Panel({
region: 'center',
title: 'CENTER',
layout: 'fit',
margins: '5 5 5 0',
html: '<div id="_CONTENTS_AREA_">컨텐츠 영역입니다.</div>'
})]
});
this.viewport.doLayout();
this.viewport.syncSize();
this.WestPanel.loadGridDataSet();
//Row선택시 발생하는 이벤트를 this.updateCenter() 메쏘드에서 실행
this.WestPanel.getSelectionModel().on('rowselect', this.updateCenter, this);
},

// 선택된 Row의 데이타를 가져와서 오른쪽 center Region의 Body에 업데이트한다.
updateCenter: function(selectionModel, index, record){
// 선택된 Row의 데이타를 가져온다.
var data_company = record.get('company');
var data_price = record.get('price');
var data_change = record.get('change');
var data_pctChange = record.get('pctChange');
var data_lastChange = record.get('lastChange');
// update할 HTML생성
var updateHTML = "<table cellpadding=2 cellspacing=1 border=1 width='100%'>" +
"<tr><td>Company</td><td>" +
data_company +
"</td></tr>" +
"<tr><td>Price</td><td>" +
data_price +
"</td></tr>" +
"<tr><td>Change</td><td>" +
data_change +
"</td></tr>" +
"<tr><td>Percentage</td><td>" +
data_pctChange +
"</td></tr>" +
"<tr><td>Last</td><td>" +
data_lastChange +
"</td></tr>" +
"</table>";

Ext.get("_CONTENTS_AREA_").update(updateHTML); //update
},



//다른 방법으로 선택된 데이타 모두 가져오기
updateCenter1: function(selectionModel, index, record){
var updateHTML = "<table cellpadding=2 cellspacing=1 border=1 width='100%'>"
// 선택된 데이타의 컬럼을 모두 가져오기
var cmc = this.WestPanel.getColumnModel().getColumnCount();
for (var i = 0; i < cmc; i++) {
//선택된 데이타의 컬럼Head (그리드 헤더 가져오기)
var columnName = this.WestPanel.getColumnModel().getColumnHeader(i);
//그리드 헤더의 데이타 인덱스 코드 가져오기
var columnCode = this.WestPanel.getColumnModel().getDataIndex(i);
var updateHTML = updateHTML + "<tr><td>" + columnName + "</td><td>" + record.get(columnCode);
+"</td></tr>" //데이타 가져와서 업데이트할 HTML 셋팅하기
}
var updateHTML = updateHTML + "</table>";
Ext.get("_CONTENTS_AREA_").update(updateHTML);

}
}
}
();
Ext.EventManager.onDocumentReady(BasicLayoutClass.init, BasicLayoutClass, true);

위 의 소스에서 updateCenter() 메쏘드는 this.WestPanel의 데이타 및 데이타인덱스 코드값을 모두 알고 있을 경우(대부분 소스까보면 다 나옴.. ㅡ.,ㅡ;) 사용하기 편리하고 아래의 updateCenter1() 메쏘드의 경우는 데이타 인덱스값을 모르거나 동적으로 필드값들이 셋팅 되는 경우에 상당히 유용하게 사용할수 있다. 넥스트리에서는 용어사전에 등록된 용어필드들을 자동으로 가져올때 사용되었던 소스이다.

 

 

Post by 넥스트리소프트 데꾸벅(techbug)

댓글을 달아 주세요

Extjs를 사용하다가 각 그리드 row에 각각의 프로세스바를 구현하게 되었다.
각 grid의 node 마다 프로세스 클래스를 재선언하였더니 너무 페이지자체가 무거워져
taskMgr를 이용하여 CSS로 구현하기로 하였다.
아래 소스는 넥스트리 사내프로젝트에서 구현되었던 일부소스이다.


[Extjs 소스중 일부] 기밀이므로 요기 까지만... ^^
// 타스크매니저로 autorefresh한다.
this.showTask = Ext.TaskMgr.start({
    run: this.store.reload,
    scope: this.store,
    interval:1000,
    args:[{params:{'appId':appId, 'deployId':deployId}, add:false}]
});

// 배포상태를 가져오는것을 멈춘다.
 Ext.TaskMgr.stop(this.showTask);



// 데이타가 모두 로드되었을 경우 해당 데이타값을 비교하여 계속
// autoRefresh할것인가를 결정한다.
this.store.on('load',function(store,records,opts){
    this.loadCompleteStatus(store,records,opts);
},this);



/**
 * 데이타가 모두 로드되었을 경우 해당 데이타값을 비교하여 계속 autoRefresh할것인가를 결정한다.
 * this.store.on('load',fn) 에 해당하는 메쏘드 실제 그리드안의
 * record에 해당하는 내용들을 모두 update한다.
 */
loadCompleteStatus : function(store,records,opts){
    var totalSize = store.getCount();
    var totalStop = 0;


    for(var i=0; i < totalSize; i++){
        var record = store.getAt(i);
        var pid = '_PROGRESSING_'+record.data.instsId;
        var lastMessage = (record.data.lastMessage) ? record.data.lastMessage : '';
        var progressRate= (record.data.progressRate)? parseInt(record.data.progressRate) : 0;
        var curStop = (record.data.isStop) ? parseInt(record.data.isStop) : 0 ;
       
        totalStop = totalStop + curStop;
        // 성공+실패 횟수가 전체 갯수와 같을 경우 autorefresh를 멈춘다.
        if(totalStop == totalSize) this.stopDeployStatus();


    }// for end
}

/**
 * 각 인스턴스마다의 정보(인스턴스명, 인스턴스Id, IP,port)를 그리드Row에 모두 표현한다.
 */
rendererDeployStatus : function(value, metadata, record,rowIndex,colIndex,store) {
return String.format(
        '<div class="_DEPLOYSTATUS_ROW_"><b>{0}</b><span class="_INSTANCE_IP_">{1}</span>'
        +'<div class="_PROGRESSBAR_CLASS_">'
        +'<div class="_PROGRESSBAR_" style="background-position-x:{2}%">{2}% : {3}</div>'
        +'<div id="_PROGRESSING_{4}" class="_PROGRESSBAR_COM_" '
        +'style="top:0;width:{2}%">{2}% : {3}</div></div></div>',
        value
        ,'http://'+record.data.ip +':'+record.data.port
        , record.data.progressRate
        , record.data.lastMessage
        , record.data.instanceId
        );
},


스타일시트
/* Progress bar 만들기 시작*/
DIV._DEPLOYSTATUS_ROW_ { padding-left:20px; }
DIV._DEPLOYSTATUS_ROW_ B {
    display:block;
    color:#333;
}
DIV._DEPLOYSTATUS_ROW_ SPAN._INSTANCE_IP_ { color:#333; }
._PROGRESSBAR_CLASS_LEFT_ {text-align:left !important}
DIV._PROGRESSBAR_CLASS_ {
    text-align:left !important;
    vertical-align:middle !important;
    padding:0 !important;
    height:18px !important;
    overflow:hidden !important;
    margin:7px 20px 10px 0 !important;
    background : transparent url(../img/progressbgwhite.png) 0 0 repeat-x !important;
    border:#6593CF solid 1px !important;
    position:relative;
}

DIV._PROGRESSBAR_ {
    text-align:left !important;
    vertical-align:middle !important;
    padding:0 3px 0 10px !important;
    margin:0 !important;
    height:18px !important;
    line-height:18px !important;
    white-space:nowrap !important;
    overflow:hidden !important;
    font-family:'segoe ui',verdana,arial;
    color:#396095;
    background-image : url(../img/progressbgwhite.png) !important;
    background-repeat : no-repeat ;
    background-position-y : 0;
    border:0 !important;
}

DIV._PROGRESSBAR_COM_ {
    text-align:left !important;
    vertical-align:middle !important;
    padding:0 3px 0 10px !important;
    margin:0 !important;
    height:18px !important;
    line-height:18px !important;
    white-space:nowrap !important;
    overflow:hidden !important;
    font-family:'segoe ui',verdana,arial;
    color:white;
    background: url(../img/progressbarbg.png) 0 0 repeat-x !important;
    border:0 !important;
    position:absolute;left:0;
    z-index:10;
}




.failrow DIV._PROGRESSBAR_COM_ {
    background-image: url(../img/progressbarfail.png) !important;
    background-color:#EFF39B !important;
}

/*프로그레스바 만들기 끝 */








Post by 넥스트리소프트 데꾸벅(techbug)

댓글을 달아 주세요

  1. 2008.10.01 12:14 신고 보라엄마  댓글주소  수정/삭제  댓글쓰기

    extjs grid 에서 특정행들에 대해 text color 를 빨강색으로 주고 싶은데 방법이 뭘까요?
    그러니까 예를들어 기본 검정색 텍스트인데, 가져온 데이터중 무언가가 값이 잇는 행들만 빨강색으로 처리하고자 하는데 addclass 나 이런걸 쓰면 될거같은데.
    어떤걸 어느부분에 적용해야 될지 모르겟네요,,

    • 2008.10.01 13:08 신고 데꾸벅  댓글주소  수정/삭제

      컴럼모델에 보시면 해당 컬럼마다 rederer라는 속성을 지원합니다.
      this.columns = [
      {header:'컴럼1',renderer:this.formatRed }
      {header:'컴럼2',renderer:this.formatName }
      ]

      formatRed: function(value, p, record) {
      return String.format('<span stye="color:red">{0}</span>', value)}

      라고 해주심 됩니다.

  2. 2008.11.06 08:27 미친수  댓글주소  수정/삭제  댓글쓰기

    늦었지만..
    {header:'컬럼1', css:'color: red;'} 이런식으로도 가능합니다.^^;