/** Suggest from web **/

วันพฤหัสบดีที่ 11 กุมภาพันธ์ พ.ศ. 2553

02 Ext JS Viewport

Viewport เขาบอกว่า เป็น component ชนิดพิเศษ ที่ใช้บรรจุ layout ทั้งหมดทุกอัน แล้ว viewport นี่ก็คือหน้าต่างเต็มๆของ Web Browser อะคับ


Viewport ประกอบด้วย 5 regions แบบเดียวกับเข็มทิศ ที่มี ทิศเหนือ ทิศใต้ ทิศตะวันออก ทิศตะวันตก อ้าว.. ได้แค่ 4 ทิศเอง Viewport เขาเพิ่ม ทิศกลางให้อีกอันคับ สรุป North  South  East  West และ Center ไม่ได้เพิ่มให้เฉยๆนะคับ แต่ยังให้ความสำคัญเป็นอันดับ 1 คือ Viewport อาจประกอบด้วย 1 region ก็ได้ แต่ 1 region นั้น จะต้องเป็น Center ไม่มี Center เป็นได้เห็นดีกันแน่


ลองดูรูปร่างหน้าตากันครับ




ในบทนี้ เราจะมาลองสร้าง Viewport ให้ได้ตามรูปข้างบนกันครับ เริ่มจาก html ชื่อ 02-create-viewport.html ที่จะเรียกใช้ javascript ชื่อ create-viewport.js ต่อตามนี้


File: 02-create-viewport.html


<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>02-create-viewport</title>
<link rel="stylesheet" type="text/css" href="/ext/resources/css/ext-all.css" />
<script type="text/javascript" src="/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="/ext/ext-all-debug.js"></script>
<script type="text/javascript" src="create-viewport.js"></script>
</head>
<body></body>
</html>



File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,xtype: "panel"
      ,html: "North"
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 100
      ,html: "West"
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    },{
      region: "east"
      ,xtype: "panel"
      ,width: 100
      ,html: "East"
    },{
      region: "south"
      ,xtype: "panel"
      ,html: "South"
    }]
  });
});


ลองกดปุ่ม Ctrl+O เพื่อเปิดแบบฝึกหัดที่ 2 กันดูคับ




พอจะเห็นได้แล้วว่า viewport คืออะไร จริงๆแล้ว ก็คือ webpage เต็มจอ browser นั่นเอง ส่วน region ก็มีการวางตัวคล้ายๆกับ เข็มทิศจริงๆ มี N E W S แถม region พิเศษและสำคัญมากอีก 1 อัน คือ center นั่นเอง


จากข้อแนะนำทั่วๆไป North เอาไว้ใส่ Logo ส่วน West เอาไว้ใส่เมนู Center เป็นพื้นที่แสดงผลลัพท์ East ปกติอาจไม่ต้องใช้ หรือเอาไว้ใส่ content เพิ่มเติมได้ และ South เอาไว้แสดงพวก status message ต่อไปเราจะเริ่มต้นกับแค่ 3 regions พอคับ เอาแค่ North West และ Center


ก่อนจะไปต่อ มาทำความเข้าใจกับรายละเอียดปลีกย่อยที่ปรากฎให้เห็น แต่ยังไม่มีการอธิบายกันก่อนนะคับ


Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";


เป็น statement ของ javascript ที่จะบอก Ext ให้ทราบว่า blank image หรือ spacer.gif หรือ s.gif อยู่ตรงไหน


s.gif space.gif หรือ blank image คือ gif image ที่มีขนาด 1 x 1 pixel ที่มีคุณสมบัติพิเศษคือ transparent ตำราเขาพยายามชี้ว่า เนื่องจาก browser ค่ายต่างๆกันมักมีข้อแตกต่างกันไปบ้างเรื่องมาตรฐานจอง css (Cascade Style Sheet) แต่ที่มักจะยึดมาตรฐานตรงกันคือ image และ Ext JS ก้อมีการเขียน widget ต่างๆมากมาย และต้องทำให้ compatible กันใน browser ของค่ายต่างๆ Ext JS เลยขอใช้ s.gif เพื่อทำให้ใช้งานดังกล่าวได้ ก็แค่เล่าให้ฟังเฉยๆคับ


renderTo: Ext.getBody()


เป็น configuration อันหนึ่งของ viewport เพื่อระบุให้ทราบว่า viewport อันนี้ จะ render (แสดง) to (ที่) ระหว่างนี้อะคับ


xtype: "panel"


http://www.extjs.com/learn/Tutorial:Xtype_defined


Definition


xtype is a symbolic name given to a class. Nothing less, nothing more.


Ext.reg('mygrid', Ext.ux.MyGrid);


จากตัวอย่าง เป็นการสร้าง symbol mygrid ที่จะทำให้ application รับรู้ว่า คืออันเดียวกับ class Ext.ux.MyGrid การใช้งาน xtype เรียกว่า Lazy Instantiation (สร้างแบบเกียจคร้าน) แต่ประหยัดพลังงานมังคับ อันนี้เดาเอา


Remember: Instantiated only if needed. น่าจะหมายความว่า application จะทำการสร้าง object ของ class นี้ เมื่อต้องการเท่านั้น ถ้าไม่ต้องการใช้ ก็จะไม่สร้าง งงไหมคับ ไม่ต้องตกใจคับ ผู้เขียนเอง ตอนนี้ก็ยังงงเหมือนกัน อิอิ


ขั้นต่อไป เราลองมาตั้งโจทย์กันดีกว่า ว่าอยากได้ viewport ที่มี แค่ North West Center แล้วขอขยาย region West ให้เป็น 200 pixel โดยใช้หลักการ C&D


เราก็แค่เอา create-viewport.js มาปรุงแต่งแต่เพียงเล็กน้อยคับ


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,xtype: "panel"
      ,html: "North"
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,html: "West"
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    },{
      region: "east"
      ,xtype: "panel"
      ,width: 100
      ,html: "East"
    },{
      region: "south"
      ,xtype: "panel"
      ,html: "South"
    }]
  });
});



ได้เป็น code ใหม่เอี่ยมตามนี้คับ


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,xtype: "panel"
      ,html: "North"
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,html: "West"
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    }]
  });
});





คราวนี้ viewport เราลดรูปเหลือเท่าที่เราต้องการได้แล้วนะคับ ต่อไปแต่งหน้าแต่งตาให้มันดูดีขึ้นหน่อย เอาเป็นว่า ลองหา banner สวยๆจาก internet มาใส่ใน North กันดีกว่า เริ่มค้นหา banner ที่ถูกใจจาก google กันได้ตามอัธยาศัยคับ


ได้มาแล้วคับ เข้ากับเทศกาลเดือนกุมภาพันธ์พอดีเหมาะเจาะ ตามนี้คับ ตั้งชื่อว่า  banner.png เราควรจะสร้าง folder เฉพาะเอาไว้เก็บ images กันนะคับ เช่น C:\extjs-test\images แล้วเก็บ banner ของเราไว้ตรงนี้




ตอนนี้หาทางเอา banner นี้มาใส่ใน North region ของเรากันดีกว่า ...


ตอนเริ่มหัดใช้แรกๆหาทางอยู่เป็นนาน กว่าจะพอรู้วิธีว่า จะเอา banner มาใส่ไว้ใน North ได้อย่างไร อาจจะมีวิธีอื่นนะคับ แต่หมดแรงหาต่อแระ ใช้วิธีนี้ได้ผลอย่างที่เราต้องการ ผมก็พอใจ เอาเวลาไปทำอย่างอื่นต่อดีกว่า


เขาบอกว่า ... ให้ใช้ BoxComponent อะคับ เอารูปที่เราหามาได้ เช่น banner.png เอามาใส่เป็น background-image ของ BoxComponent อันนี้ วิธีสร้างก็ตามนี้เลยคับ


  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241; '
  })



สังเกต path ที่เรียกใช้งานกันหน่อยนะคับ file banner.png ที่เก็บไว้ใน C:\extjs-test\images จะถูก reference ใน url แค่ images/banner.png เท่านั้น จากนั้นก็เอาไปสวมใน javascript code ของเราอีกที create-viewport.js


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241;'
  })
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,html: "West"
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    }]
  });
});




Code เดิมก่อนใส่ banner


    ,items: [{
      region: "north"
      ,xtype: "panel"
      ,html: "North"
    },{



แต่เนื่องจากเราใช้ class ใหม่ BoxComponent ดังนั้น xtype (ที่เคยเล่าให้ฟังว่า มันเป็นแค่สัญญลักษณ์ของ class xtype is a symbolic name given to a class. Nothing less, nothing more.) เราจึงต้องเอา xtype: "panel" ออกไป เพราะมันไม่ใช่ panel อีกต่อไป จากนั้น ก็ทำการบรรจุ component banner ที่เราได้สร้างขึ้นมาใหม่นี้ไว้ใน region north โดยผ่าน configuration ชื่อ items: ทำนองเดียวกันกับ region north ก็เป็น items: ของ viewport อีกทอดหนึ่ง สิ่งที่ต้องระบุเพิ่มเติมให้กับ banner ก็คือ height: เอาตัวเลขมาจาก height ของ banner.png ถ้าไม่ระบุ เราก็จะมองไม่เห็น banner (height = 0)


,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{



หลังจากมี banner ใน north แล้ว เราลองหา widget ง่ายๆมาใส่ใน west กัน เช่น ปุ่ม หรือ button โดยใช้หลักการเดิมคือ สร้าง component button ขึ้นมาใหม่ แล้วค่อยเอาไปบรรจุใน region west


var button = new Ext.Buttons({
  text:  "Google"
  ,width: '50%'
  ,handler: function() {
    Ext.Msg.alert("URL", "www.google.com");
  }
});



เป็นแค่ปุ่มที่มี label ว่า Google ระบุ Action เมื่อ click (handler) จะเกิด popup message ว่า www.google.com ลองเพิ่มไปใน code create-viewport.js ได้เป็น code เต็มๆตามนี้ .....


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241;'
  });
  var button = new Ext.Button({
    text:  "Google"
    ,width: '50%'
    ,handler: function() {
      Ext.Msg.alert("URL", "www.google.com");
    }
  });
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,items: [ button ]
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    }]
  });
});



ลอง refresh Chrome ดูคับ จะเห็นปุ่ม Google เพิ่มขึนมา ให้ลอง click ดูจะได้ผลเหมือนกันไหม






ตกแต่งกันต่ออีกนิด เพื่อให้ดูสวยงาม เพราะปุ่ม Google ดันอยู่ชิดขอบบนซ้าย ดูไม่สวยงาม น่าจะให้อยู่กลาง และมี space พองามห่างจาก banner ของเรา สัก 20 pixels ใหญ่ขึ้นอีกนิดเป็นสัก 75%


สำหรับ padding 20 px น่าจะเป็น config ของ button แต่เรื่องให้อยู่ตรงกลางเนี่ย น่าจะเป็น config ของ container ที่บรรจุ button อยู่ ในที่นี้คือ region west


หลังจากทำการบ้านจึงพบคำตอบของทั้ง 2 ความต้องการคือ
button ใช้ config ชื่อ style
west region ใช้ config ชื่อ bodyCfg


รายละเอียดวิธีการใช้งานตามนี้


  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.Msg.alert("URL", "www.google.com");
    }
  });
  region: "west"
    ,xtype: "panel"
    ,width: 200
    ,bodyCfg: {tag: 'center'}
    ,items: [ button ]



ดูเนื้อไฟล์เต็มๆกันคับ


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241;'
  });
  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.Msg.alert("URL", "www.google.com");
    }
  });
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,bodyCfg: {tag: 'center'}
      ,items: [ button ]
    },{
      region: "center"
      ,xtype: "panel"
      ,html: "Center"
    }]
  });
});




หน้าตาตอนนี้ดูดีขึ้นเยอะแล้วคับ ต่อไปแทนที่จะ click ปุ่ม Google ให้แสดงหน้าต่าง popup ขึ้นมาเฉยๆ เราจะเอา webpage ของ google มาใส่ไว้ใน region center กันเลยดีกว่า อันนี้น่าสนใจ และคงจะเป็นประโยชน์สำหรับการใช้งานข้างหน้า


คำตอบที่มีให้ตอนนี้คือการเลือกใช้ iframe แล้วให้มันมาโผล่ที่ center หลักการง่ายๆมีเท่านี้คับ แต่วิธี การทำ ไม่หมูเท่าไร แต่หลังจากเฉลย ให้ทราบกัน แล้ว  เชื่อว่าท่านจะสามารถ Copy เอาวิธีการนี้ไปใช้ต่อได้คับ มั่นใจเต็มที่ หุหุ


Step ที่ 1 ให้เก็บรักษาคัมภีร์สูตรลับเฉพาะสำหรับการใช้ iframe กันก่อน


Ext.ux.IFrameComponent = Ext.extend(Ext.BoxComponent, {
  onRender : function(ct, position){
    this.el = ct.createChild({tag: 'iframe', id: 'iframe-'+ this.id, frameBorder: 0, src: this.url});
  }
});



อย่าถามโผมเลยนะคับว่ารู้วิธีเขียนสูตรลับ คัมภีร์ข้างบนหรือเปล่า แบ๊ะๆๆๆๆ แต่ขอให้จำไว้อย่างเดียวคับว่า เจ้า id ของ iframe นี้ จะมีค่าเท่ากับ iframe-  ตามด้วย id ของ component ที่เรากะลังจะสร้างใน Step ที่ 2 เท่านั้นพอ


Step ที่ 2 สร้าง component สำหรับบรรจุใน center กัน และใช้กระบวนท่าเอา iframe มาเชื่อมต่อ


var browser = new Ext.Panel({
  id: 'mybrowser'
  ,title: 'Welcome to my browser',
  ,closable: true,
  ,width: '100%',
  ,autoHeight: true,
  ,items: [ new Ext.ux.IFrameComponent({
                  id: 'ifx'
                  ,width: '100%'
                  ,height: '100%'
                  ,url: 'about:blank'
               })
  ]
});



ถึงตอนนี้ create-viewport.js ของเราเริ่มเจริญงอกงามไปเรื่อย หวังว่าเรายังคงติดตาม และเข้าใจวิวัฒนาการของมันอยู่นะคับ สภาพปัจจุบันให้ดูกันอีกที ก่อนจะจบบทที่ 2 ด้วยการสั่งให้เอา Web Google มาแสดงกันจริงๆ


File: create-viewport.js


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  Ext.ux.IFrameComponent = Ext.extend(Ext.BoxComponent, {
    onRender : function(ct, position){
      this.el = ct.createChild({tag: 'iframe', id: 'iframe-'+ this.id, frameBorder: 0, src: this.url});
    }
  });
  var mybrowser = new Ext.Panel({
    id: 'mybrowser'
    ,title: 'Welcome to my browser'
    ,closable: true
    ,width: '100%'
    ,height: '100%'
    ,items: [ new Ext.ux.IFrameComponent({
                  id: 'ifx'
                  ,width: '100%'
                  ,height: '100%'
                  ,url: 'about:blank'
               })
    ]
  });
  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241;'
  });
  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.Msg.alert("URL", "www.google.com");
    }
  });
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,bodyCfg: {tag: 'center'}
      ,items: [ button ]
    },{
      region: "center"
      ,items: [ mybrowser ]
    }]
  });
});




หลังจาก save create-viewport.js version ล่าสุด แล้ว refresh Chrome จะได้ภาพทางด้านซ้าย


ถ้าลองกดปุ่ม Google ดูก็จะได้หน้าต่าง popup แสดง www.google.com เหมือนเดิม


ขั้นตอนสุดท้ายของบทที่ 2 นี้ มีหลักการแค่ สั่งให้มีการเปลี่ยน config src ของ iframe ที่มี id ย่อยว่า ifx และมี id ใหญ่กว่า คือ iframe- เราต้องใช้กระบวนท่าขั้นสุดยอด หลอมรวม 2 id เข้าไว้ด้วยกันให้ได้ เป็น iframe-ifx จากนั้น จึงจะสามารถใช้ท่าไม้ตาย สั่งให้ URL ทำการเปลี่ยนไปได้ดังใจนึก ท่าไม้ตายที่ว่าคือ


Ext.get เพื่อสั่งให้ iframe เปลี่ยน URL ส่วนคำสั่งนั้น เราจะฝากไว้กับ button ที่เดิมสร้างแต่ popup แต่คำสั่งใหม่ของเรา คือการระบุ src ใหม่ที่เราต้องการกันยังไงคับ


code เดิมในส่วนของ handler 


  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.Msg.alert("URL", "www.google.com");
    }
  });



code ใหม่ที่เราเพิ่งได้ร่ำเรียนกระบวนท่ามาเมื่อครู่


  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.get('iframe-ifx').dom.src = "http://www.google.com";
    }
  });



File: create-viewport.js FINAL


Ext.onReady (function(){
  Ext.BLANK_IMAGE_URL = "/ext/resources/images/default/s.gif";
  Ext.ux.IFrameComponent = Ext.extend(Ext.BoxComponent, {
    onRender : function(ct, position){
      this.el = ct.createChild({tag: 'iframe', id: 'iframe-'+ this.id, frameBorder: 0, src: this.url});
    }
  });
  var mybrowser = new Ext.Panel({
    id: 'mybrowser'
    ,title: 'Welcome to my browser'
    ,closable: true
    ,width: '100%'
    ,height: '100%'
    ,items: [ new Ext.ux.IFrameComponent({
                  id: 'ifx'
                  ,width: '100%'
                  ,height: '100%'
                  ,url: 'about:blank'
               })
    ]
  });
  var banner = new Ext.BoxComponent({
    height:106
    ,style: 'background-image:url(images/banner.png);background-repeat:no-repeat;border:solid 1px #1D6241;'
  });
  var button = new Ext.Button({
    text:  "Google"
    ,width: '75%'
    ,style: 'padding: 20px;'
    ,handler: function() {
      Ext.get('iframe-ifx').dom.src = "http://www.google.com";
    }
  });
  var viewport = new Ext.Viewport({
    layout: "border"
    ,renderTo: Ext.getBody()
    ,items: [{
      region: "north"
      ,height: 106
      ,items: [ banner ]
    },{
      region: "west"
      ,xtype: "panel"
      ,width: 200
      ,bodyCfg: {tag: 'center'}
      ,items: [ button ]
    },{
      region: "center"
      ,items: [ mybrowser ]
    }]
  });
});



สิ่งที่ได้หลังจากกดปุ่ม Google หลังจาก save create-viewport.js ล่าสุด




จบตอนที่ 2 แล้วคร้าบบบบ


ก่อนจาก สำหรับท่านที่ใช้โปรแกรม Firefox บน Windows มีความจำเป็นต้องใส่ Path เต็มๆ ในรูปแบบ  file:///C:/   ใน 02-create-viewport.html เช่น


File: 02-create-viewport.html


<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>02-create-viewport</title>
<link rel="stylesheet" type="text/css" href="file:///C:/ext/resources/css/ext-all.css" />
<script type="text/javascript" src="file:///C:/ext/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="file:///C:/ext/ext-all-debug.js"></script>
<script type="text/javascript" src="create-viewport.js"></script>
</head>
<body>
</body>
</html>

1 ความคิดเห็น: