블로그 이미지

카테고리

데꾸벅 (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 최적화 기법  (7) 2010.03.08
지금 바로 쓸수 있는 CSS3  (0) 2010.03.07
Firefox에서 링크 점선 없애기  (2) 2010.03.06
Post by 넥스트리소프트 데꾸벅(techbug)
, |

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)
, |


기본적으로 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 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)
, |

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)
, |