Internship, Days 22-23 (21-22 May 2012)

Posted on May 23rd, 2012 in cloud, computer, CPE, in English, in Thai, JavaScript, personal, programming | No Comments »

No photo today. Sorry. Read on.

เนื่องจากมีการแก้บั๊กขนานใหญ่เกิดขึ้นซึ่งใช้เวลาสองวัน ผมก็ขออัพรวมไปเลยนะครับ ส่วนที่เป็นสีแดงคือส่วนที่มีการแก้ไขในวันที่สองนะครับ จะได้เห็นว่ามีอะไรเปลี่ยนไปยังไงบ้าง

งานที่ผมทำช่วงสองวันนี้มีสองส่วน ส่วนแรกคือเตรียมเอกสารนำเสนอเรื่อง vCloud Director (vCD) แต่ปัญหาคือผมยังไม่ค่อยเข้าใจสถาปัตยกรรมโดยรวมของ VMware เท่าไหร่ เลยต้องไปอ่านใหม่หมดตั้งแต่ VMware Workstation, VMware ESXi, ฯลฯ จนกระทั่งอ่านไปถึงหัวเรื่องของ vCloud Director เท่านั้น เท่าที่สรุปได้คือ (ไม่ได้บอกว่ารู้แค่นี้นะครับ)

  • ESXi เป็น Hypervisor ที่ติดตั้งลงบนฮาร์ดแวร์โดยตรง ไม่ขึ้นกับ OS ใดๆ
  • vCenter เป็นระบบควบคุมเครื่องที่ทำ virtualization อีกที
  • vSphere Client เป็นตัวที่ต่อไปยัง vCenter หรือโฮสแต่ละเครื่อง
  • vCloud Director เป็นตัวที่มา abstract หรือมาครอบ vCenter ตัวหนึ่งหรือหลายตัวอีกที
  • vMotion คือระบบและกระบวนการย้าย VM จากเครื่องหนึ่งไปอีกเครื่องหนึ่งโดยไม่มี downtime

จากนั้นพี่ก็มาสับงานผมอีกรอบ โดยต้องแก้ไขตัวเล่นวิดีโออีกหลายอย่าง

  • วิดีโอไม่เล่นอัตโนมัติบน iPad สาเหตุเป็นเพราะผมเอาโค้ดที่เคยใช้งานได้ออก แล้วไม่ได้ใส่กลับเข้าไปใหม่ แก้ไขโดยการสั่ง videotag.load(); videotag.get(0).play(); ตามอ้างอิง [1] , [2]   ทั้งนี้ iOS เวอร์ชันใหม่ๆ มีการป้องกัน autoplay ที่แข็งแกร่งขึ้นเรื่อยๆ จนวิธีนี้ใช้ไม่ได้ผล
  • ผลการค้นหาวิดีโอแสดงแค่คอลัมน์เดียว ไม่สะดวกและไม่สวยด้วย แก้โดยการลดขนาดใน CSS (สิ)
  • ลากวัตถุ (object) ไม่สะดวกเมื่อต้องเลื่อนจอไปมา คิดว่าต้องหาพวก autoscroll มาใส่ แต่บั๊กมันเยอะ ต้องค่อยๆ ดูไป ตอนนี้ทำได้แล้ว แต่ถึกมาก ใช้ global เก็บสถานะ แล้วใช้ event ในการ set สถานะของตัวแปรใน global
  • การเปิดปิดเสียง พี่ต้องการให้ no mute ตั้งแต่แรก ในขณะที่ผมไปทำ default mute ไว้เพราะรำคาญเสียงในคลิป (นิดเดียวแต่ก็ยังไม่ได้ทำ) (ตอนนี้ทำแล้ว)
  • พฤติกรรมของกล่อง drop-down ที่มันจะคอยเลือก default playlist ขึ้นมาตลอด ซึ่งแม้ว่าผมจะเซฟไฟล์ชื่ออื่นไปมันก็ยังเด้งกลับมาเป็น default playlist ทุกครั้ง อันนี้แก้ที่ฟังก์ชันสำหรับ rebuild drop-down list ไปเลย โดยถ้าเป็นการเซฟให้ set ชื่อใน drop-down list กลับมาเป็นชื่อที่เพิ่งเซฟไป ทำเสร็จแล้ว ไม่ค่อยยากเท่าไหร่
  • โปรแกรมขาดคำอธิบาย เช่น สัญลักษณ์ที่ใช้บอกว่าวิดีโอ (ทั้งข้อมูลและไฟล์) มาจากฐานข้อมูลหรือจาก YouTube ก็เลยใส่สัญลักษณ์ลงไป
  • ให้คลิกบนวิดีโอ MP4 แล้ว play/pause ได้เหมือนกับบน YouTube (ทำแล้ว)

Since there’s a big chunk of bug hunt which spanned two days, I decided to group them into one entry. The red bits indicate changes made during the second day.

I’ve done parts of two jobs during the two days. The first one is vCloud Director (vCD) presentation preparation. Since I did not really understand much about the entire VMware architecture, I had to read everything from start: Workstation, ESXi, etc., until the introduction to vCloud Director (where I left off) and here’s the summary (not “what I know” though)

  • ESXi is a Hypervisor installed on top of hardware (bare-metal), which is not OS-dependent
  • vCenter controls the virtualization host machines
  • vSphere Client connects to vCenter or individual hosts
  • vCloud Director abstracts one or more vCenters
  • vMotion is the thing that lets you move VM from one host to another without downtime
Then the supervisor came and asked me to change and fix my video player.
  • Video does not auto-play on iPad. This is because I forgot to add the force-autoplay code back into the main piece. Just a simple videotag.load(); videotag.get(0).play(); as described in  [1] [2] . However, newer iOS versions block autoplay more aggressively, and this method also fails.
  • Only one column of search result is displayed on mobile devices, so I reduced each search result’s size in CSS.
  • Object cannot be dragged from one part of document to another far side without auto-scroll. I managed to do so, but it’s a lot of kludge like global variables and get-set style of events, very old-fashioned.
  • Supervisor wants default playlist to no-mute, so I changed player behavior as required .
  • Drop-down list (of playlists) has a quirky behavior because I set it to “snap” to default playlist whenever the drop-down list is regenerated. Even if we save another playlist for example, the drop-down list still snaps to default playlist. I changed it so that when you save, it snaps to the name you just saved. Simple if-then, not really hard.
  • Application lacks explanation, such as video legend (video color codes, for example), so I added them in a bit.
  • Play/Pause when user clicks on MP4, just like that of YouTube.

Click-to-dismiss (requires jQuery)

Purpose: Ideal for simple message boxes, alert messages, etc.

Syntax: click_to_dismiss(what_to_dismiss [, where_to_click] );
(where_to_click defaults to “document”, which means “anywhere”)

 function click_to_dismiss(what_to_dismiss, where_to_click){
  if(where_to_click == undefined){
    where_to_click = document;
  }
  $(document).bind('click', function(){
    $(what_to_dismiss).hide();
    $(what_to_dismiss).unbind();
  });
} 

Limitation: This function also unbinds everything attached to what_to_dismiss, which is usually not a problem for me because my message boxes don’t have any other bindings attached. Please respond if you manage to make it work better (while readable by beginner because that’s what I am!)
Recommendation for Improvement: Overcome the limitation

Autoscroll page when dragging some element (requires jQuery. VERY BAD CASE OF KLUDGE!)

Purpose: Allows page to scroll up or down when you drag an element near the top or bottom edge of the browser.

Syntax: set_item_detect_drag(selector);
Selector is jQuery element like $(‘img’), $(‘.items’) or $(‘#namebox’)

 var autoscroll_mouse_item;
var autoscroll_click_item;
var autoscroll_drag_item;

function set_item_detect_drag(sel){
  sel.mouseenter(function(){
    autoscroll_mouse_item=this;
    set_drag_status();
  });
  sel.mouseleave(function(){
    autoscroll_mouse_item=undefined;
    set_drag_status();
  });
  sel.mousedown(function(){
    autoscroll_click_item=this
    set_drag_status();
  });
  sel.mouseup(function(){
    autoscroll_click_item=undefined
    set_drag_status();
  });
}

// Set detection vars
function set_drag_status(){
  if(autoscroll_mouse_item==autoscroll_click_item&&autoscroll_mouse_item!=undefined){
    autoscroll_drag_item = autoscroll_mouse_item;
  } else {
    autoscroll_drag_item = undefined;
  }
}

$(document).mousemove(function(e){
  //if drag_item is acquired and mouse is near edge, scroll.
  if(autoscroll_drag_item!=undefined){
    //mouse near top
    if(e.pageY - $(window).scrollTop() < 40)
    {
      //scroll a bit up
      $(window).scrollTop($(window).scrollTop()-5);
    }
    else if($(window).scrollTop()+parseInt(window.height)-e.pageY < 40)
    {
      //scroll a bit down
      $(window).scrollTop($(window).scrollTop()+5);
    }
  }
}); 

Limitation: Lots.
Recommendation: Use OO, extending jQuery and make it a full-blown plugin instead of a global-var-ridden kludge. Another: Variable, smooth scrolling speed (slow when not very close to edge, for example)

Internship, Day 21 (18 May 2012)

Posted on May 19th, 2012 in cloud, computer, in English, in Thai, personal, PHP, programming | No Comments »


(Photo: We have SCB. Your argument is invalid. << Wait what?!)

วันนี้ผมเริ่มจากการทำระบบตรวจสอบและปรับไฟล์ก่อนเลย โดยคราวนี้มามาดใหม่ แทนที่จะเอาไฟล์มาไล่ทีละชื่อ (โคตรเชยเลย) ผมใช้คำสั่ง array_diff($a, $b) เพื่อหา A-B (เมื่อ A และ B เป็นเซตที่แทนด้วยอาร์เรย์ $a และ $b ตามลำดับ) แล้วลบหรือโหลดไฟล์ทีเดียวหมดเลย ง่ายดี ทำไมตอนนั้นคิดไม่ได้แบบนี้ก็ไม่รู้ จากนั้นผมก็เขียนคู่มือการใช้งานต่อจนจบ โดยเปลี่ยนจาก text เป็น HTML จะได้อ่านง่ายๆ หน่อย แล้วก็ใส่ spinner (ไอ้ตัวหมุนๆ เวลารอ ajax ทำงาน) ขณะมีการดาวน์โหลดไฟล์ที่ใช้เวลาค่อนข้างนานโดยใช้ spin.js ซึ่งใช้งานได้ง่ายและเป็น MIT License ด้วย จึงนำมาใช้กับชิ้นงานของบริษัทได้ทันที

สุดท้ายผมก็เลยได้ทำงานชิ้นต่อไปคือการศึกษาเกี่ยวกับ vCloud Director อธิบายกันสั้นๆ จากผู้เริ่มต้น vCloud Director เป็นตัวที่มาครอบบน vCenter อีกที ก็หลักๆ ก็รู้แค่นี้แหละครับ (ยอมรับว่ารู้แค่นี้ เพราะตรงนี้เป็นรายงานประจำวัน ไม่ใช่บทความ) สำหรับลิงค์ที่อ่านไปจะไว้ท้ายเอนทรีนะครับ

Today I started from file consistency restorer, which I revised to use array_diff($a, $b) to find missing or extra files and take appropriate actions. Then, I finished the manual, which I converted into HTML format from plain text. Finally, I added spinner (that spinning thing when there are ajax calls) using spin.js , which uses MIT License and thereby is compatible with this work.

At the end of the day I started reading about vCloud Director. From a newbie, it’s something that runs on top of vCenter. That’s all I know. (And I’m going to admit my limits here because this is a daily report not an article).

References

http://www.yellow-bricks.com/2010/08/31/vmware-vcloud-director-vcd/
http://frankdenneman.nl/2010/09/provider-vdc-cluster-or-resource-pool/

Internship, Day 19 (16 May 2012)

Posted on May 17th, 2012 in computer, CPE, in English, in Thai, personal, PHP, programming | No Comments »

วันนี้ผมไปทำงานก็เจอดีแต่เช้าเลย เพราะหัวหน้าฝ่ายเรียกให้ไปคุยงานนิดหน่อย สรุปได้ใจความว่าผมต้องอ่านเรื่อง vCloud Director แล้วทำสไลด์ไปอธิบายให้ฟัง

ต่อมา ผมก็ทำงานต่อ แต่ไม่ทันไรพี่เลี้ยงก็มาคุยเรื่องการอัพโหลดไฟล์ขึ้น Aruba Captive Portal ซึ่งอัพไปแล้วมันใช้งานไม่ได้ด้วยเหตุผลบางประการ คือ พออัพไปแล้ว (หน้า video player ของผมเป็น iframe) มันพยายามที่จะเรียก iframe ขึ้นมาแต่ทำไม่ได้ โดยไม่ว่าจะ request ไปกี่ครั้งก็ได้ HTTP 302 กลับมาตลอด (ควรเป็น 200) และติดลูปอยู่อย่างนั้นจนเบราเซอร์หยุดการทำงานให้เอง อาการนี้ไม่รู้จะแก้ยังไง แถมไฟล์ที่จะเล่นอยู่บน YouTube ยิ่งยากเข้าไปใหญ่ เลยตัดสินใจเอาระบบโหลดไฟล์กลับมาอีกครั้ง แต่มาในร่างใหม่ที่บริหารในระดับ playlist แทน นั่นคือ ทั้ง playlist จะต้องเป็น YouTube หรือเป็น MP4 อย่างใดอย่างหนึ่ง (แต่ต้นกำเนิดมาจาก YouTube เหมือนกัน คือ สร้าง YouTube playlist ก่อน แล้วค่อยโหลดไฟล์มาลงเครื่องอีกทีด้วย youtube-dl)

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

Today I was summoned to the Department and he assigned me to read vCloud Director, then make a presentation to explain to him.

Then I continued my work for a bit before supervisor discussed uploading the file to Aruba Captive Portal, which failed. For some reasons after uploading (the video player which uses an iframe), the iframe (stored on “media server” separate from Aruba) cannot be loaded and the browser always gets HTTP 302, instead of 200, over and over until browser killed the tab. I don’t know how to fix it yet, but the fact that the files are on YouTube will make it all worse so we decided to bring back the file download system, in a new form that it is managed at playlist level instead, downloading entire playlists at a time. All or nothing. First, the user would create a YouTube playlist, then “convert” it to MP4.

I spent the rest of the day implementing all that, but did not progress much due to wrestling with the old code. It can now load files, but cannot play them yet.

Internship, Day 17 (14 May 2012)

Posted on May 15th, 2012 in computer, CPE, in English, in Thai, programming | No Comments »


(Photo: Can I leave work on 17? DAT ANNOYING ALARM!)
(Sorry for late upload)

วันนี้เช้าผมเข้าไปทำงาน กำลังทดสอบงานเตรียมส่ง ปรากฏว่าพี่เอางานมาเพิ่ม โดยให้

  • เลือก default playlist จากเมนูได้เลย
  • ปรับ interface ให้ใช้ง่ายขึ้น
  • ทำให้ embed ได้ง่ายๆ
  • ทำให้เรียกไฟล์จากที่อื่นได้

ถึงกับอึ้งรับประทานไปเลยทีเดียว แถมทำแทบตายกว่าจะได้ เพราะต้องเพิ่มฟังก์ชันให้เก็บ default playlist ได้ ต้องทำ iframe interface มาครอบ ไม่งั้นก็ embed ยาก (การทำ iframe ครอบจะทำให้ออกมาคล้ายๆ YouTube iframe API อีกที) สรุปว่าวันนี้ทำงานแบบรีบๆ มึนๆ ก็เลยจบแบบงงๆ ว่าทำอะไรลงไปบ้าง กลับมาก็น็อกอีก เลยเขียนได้แค่นี้ครับ :(

I was testing my work when the senior got more tasks for the job.

  • “Select Default Playlist” menu which affects all player instances without further configuration
  • Easier-to-use UI, and optimize for mobile use
  • Easier embedding
  • Call the player from foreign domain

Yeah, I got stunned, and it was a hell a lot of work in one day just to store default playlist. There’s also iframe interface (not unlike YouTube iframe API) so all in all it was pretty confusing and ended up very confusing. I got sick after work so this is all I remembered.

NOTE: There will NOT be an Internship Day 18. It’s skipped.

Internship, Day 16 (11 May 2012)

Posted on May 12th, 2012 in computer, CPE, in English, in Thai, personal, programming | No Comments »


(Photo: This is Madness! Madness? THIS. IS. ALAINAAAAAA!!!!)

ผมติดบั๊กค้างมาแต่เมื่อวาน ปรากฏว่าเป็นปัญหาการเปิดวิดีโออะไรบางอย่างของ Chrome 18 (ตั้งแต่เมื่อไหร่เนี่ย!) เอง ไม่เกี่ยวกับสคริปต์แต่อย่างใด จึงได้แต่ภาวนาขอให้ Google แก้ไวๆ (แต่เล่นบน IE และ Firefox ได้ตามปกติ)

อีกอย่างที่ทำในวันนี้คือลอง optimize ในรูปแบบต่างๆ แต่เนื่องจาก JavaScript มันเป็นภาษาระดับสูงที่ใช้คำสั่งจำนวนน้อยๆ เลยไม่รู้จะไปลดตรงไหน ก็เลยได้แค่เปลี่ยนกระบวนการเปลี่ยนวิดีโอ จากการแก้ tag โดยตรงเปลี่ยนมาใช้ API เปลี่ยนไฟล์แทน (จริงๆ API สามารถโหลด playlist เป็นสตริง เช่น “vid1,vid2,vid3″ มาเลยก็ได้ แต่มันมึนๆ เลยใช้เปลี่ยนไฟล์เองดีกว่า) คิดว่าน่าจะเสถียรมากขึ้น ไม่รู้เหมือนกัน

ต่อจากนี้ก็ไม่มีอะไรแล้วครับ เหลือแต่เก็บรายละเอียดเล็กๆ น้อยๆ เวลาที่เหลือก็หยิบความรู้ CSS มาปัดฝุ่นบ้าง นั่งทบทวนนิดๆ หน่อยๆ

The bug that persisted from yesterday turned out to be some kind of video problem in Chrome 18 (since when?!) and not the script error. The only thing I can do right now is to pray that Google fixes it. (No problem in IE and Firefox)

Another thing I did was optimizing the code, but there wasn’t much to do because JavaScript is already high-level and there’s nothing to optimize “code-wise” so I changed the video change method from tag editing to using API. (Actually, the API can load comma-separated strings like “vid1,vid2,vid3″ as playlist but it seemed problematic so I ditched that idea) It might be more stable now, I don’t know.

There’s not much other than fine details. I spent some time revising my CSS knowledge and techniques.

Internship, Day 15 (10 May 2012)

Posted on May 11th, 2012 in computer, CPE, in English, in Thai, personal, programming | No Comments »


(Photo: From skywalk in front of Cyber World Tower, looking at Robinson Dept. Store)

วันนี้ไม่ค่อยมีงานแล้ว เนื่องจากทุกอย่างเกี่ยวกับโปรแกรมวิดีโอใกล้เสร็จ จึงใช้เวลาส่วนใหญ่เขียนรายงานมากกว่า แต่เมื่อตอนบ่ายมาเจอปัญหาว่า เมื่อกำลังจะเล่นวิดีโอบางตัว ระบบจะไม่สามารถโหลดไฟล์ได้ โดยตัดเป็นจอดำๆ ที่ไม่สามารถทำอะไรได้อีกเลย อาการนี้เป็นเฉพาะใน Chrome เท่านั้น (ใน IE และ Firefox ปกติดี) จึงไม่แน่ใจว่าเป็นที่ Chrome หรือไม่ เพราะไม่ได้แก้ไขโค้ดใดๆ จากเมื่อวาน

I had almost no work today because the video player is almost done, so I spent more time writing reports. In the afternoon however I found out that some videos cannot be played and causes the YouTube screen to black out. This happens only in Chrome (and not in IE or Firefox) so I’m not sure if it’s the browser’s fault, because the code wasn’t changed.

Follow-up: It’s problem with only one instance of Chrome, too. I’m trying to isolate that to extensions.

Internship, Day 14 (9 May 2012)

Posted on May 10th, 2012 in computer, CPE, in English, in Thai, personal, programming | No Comments »


(Photo: That awkward moment when it took one photo and five minutes to realize there’s a … YAKINIKU!)

วันนี้งานเริ่มหมด หนักไปทางเก็บรายละเอียดและทำ installer ให้เสร็จ จะได้ปิดงานได้ซักที งานที่ทำจึงไม่ค่อยมีอะไรโดดเด่นเป็นสาระเท่าไหร่เช่นกัน โดยเริ่มจากการล็อกปุ่ม Load ตอนที่เพิ่งกดไปใหม่ๆ เพื่อไม่ให้เกิดภาระงานมากจนเกินไป ทำ embed code ให้ update ทุกอักขระที่พิมพ์ (โดยไม่มีการ ช้าไปหนึ่งจังหวะ ) รวมไปถึงการปรับโค้ดของการโหลดวิดีโอจากฐานข้อมูลเพื่อให้ระบบตอบสนองได้ไวขึ้น

ที่เหลือก็ไม่ค่อยมีอะไรมากแล้ว อาจมีการปรับ CSS บ้างอะไรบ้างไปตามเรื่อง รวมไปถึงการอธิบายโค้ดให้เรียบร้อย (กว่าเดิมนิดนึง) เพื่อให้กลับมาพัฒนาต่อในภายหลังได้ง่ายขึ้น

There’s not many things to do left. I spent most time creating installer and polishing old code, such as locking the Load button while loading data from database, as well as updating embed code more rapidly (without ” falling one character behind “), and making the database loading process more responsive.

Then I adjusted some of the CSS, and documented the entire job for easier development in the future.

Internship, Day 13 (8 May 2012)

Posted on May 9th, 2012 in computer, CPE, in English, in Thai, personal, PHP, programming | No Comments »


(Photo: A report to be submitted to the company)

วันนี้ผมลืมบัตรพนักงานไว้ที่บ้าน ซึ่งแน่นอนว่าต้องกลับไปเอา ไม่เช่นนั้นจะเกิดความลำบากหลายอย่างมากตลอดทั้งวัน แต่กว่าจะกลับไปเอาบัตรแล้วกลับมาทำงานได้ก็เกือบสายเช่นกัน (ก็ยังดีที่ไม่สาย แต่ท่อนบนเปียกเหงื่อเต็มๆ ฮ่าๆ)

เข้าเรื่องกันดีกว่า ผมต้องการให้ระบบจัด playlist ของผมเรียงลำดับได้ด้วย (เช่น อยากสลับให้ไฟล์ 2 เล่นก่อนไฟล์ 1) แต่ไม่รู้ว่าจะสลับข้อมูลในฐานข้อมูลยังไงให้เหมาะสม ผมเลยใช้วิธีลบทั้งหมดแล้วสร้างใหม่เอาดื้อๆ เลย โดยใช้ความรู้เกี่ยวกับ transaction ในการรักษาสภาพฐานข้อมูล เพราะการลบสร้างใหม่จะมีหลายขั้นตอนมาก และหากมีปัญหาจะทำให้ข้อมูลที่เก็บไว้เสียหายได้ สำหรับการใช้ transaction ใน mysqli นั้นไม่ยาก แต่ขอเก็บไว้ทีหลังเหมือนเดิมครับ นอกจากนี้ เพื่อให้ได้ความเร็วในการทำงานมากขึ้น ผมจึงทดลองนำ prepared statements ออกมาใช้ด้วย

ต่อมา ผมก็ทำระบบดึง playlist กลับออกมา อันนี้ไม่ค่อยยากแล้ว แค่ใช้ SELECT ด้วย SQL จากนั้นจึง print ผ่าน json_encode เพื่อให้เรียกผ่าน jQuery ได้ง่ายๆ

พี่มาบอกว่า iPad ใช้งานตัวนี้ไม่ได้ ผมก็ไม่ค่อยแน่ใจว่าเกิดอะไรขึ้น (ยกเว้นว่าผมจะมี iPad ใช้ซักตัว 555+) แต่ก็ลง jQuery UI Touch Punch ไปแล้ว น่าจะใช้ได้ดีขึ้นเพราะผมทดลองใช้งานดูก็ไม่มีปัญหาแล้ว แต่ถ้าจะทำใช้บนมือถือคงต้องลดขนาดภาพลงอีก (ลองดูแล้วเต็มจอมากๆ)

จากนั้น ผมไม่อยากให้ต้องมากดดูรายชื่อ playlist ผมก็เลยลง AutoComplete เพิ่มอีกตัว ตรงนี้ยากเล็กน้อย แต่ผมจะพยายามอธิบายให้ง่ายตอนท้ายเช่นกัน สุดท้ายผมก็ไม่ต้องแสดงรายชื่อ playlist ทั้งหมด แค่พิมพ์ลงไปก็ได้ ซึ่งตรงนี้ผมเขียน PHP ดักไว้แล้วว่าถ้าเป็น playlist ที่มีอยู่แล้วก็ทำงานได้เลย แต่ถ้ายังไม่มีก็ต้องสร้างใหม่ก่อน เป็นต้น

I forgot the staff ID at home, so I had to go back and get it to avert further complications. As a result, I was almost late for work, sweating all over.

On point. I wanted the playlist manager to support “sorting” playing order, but I don’t know the optimal method so I just wiped the playlist and create it anew, using what I learned about transactions. I used transactions because it needed many steps to complete and I can’t risk any problem. Using transactions in mysqli is not very hard, so is “prepared statements” feature.

Then, I created the playlist loader that pulls data back from the database. I already got the hang of it, and a simple SELECT + json_encode did it all very well.

Senior staff came and told me it’s not working on iPad. I’m not sure how it looked like (unless I had, of course, an iPad!) but I installed jQuery UI Touch Punch and it partially works now. (Partial because there’s no screen real estate on my phone!!)

Finally, I don’t want to list every single playlist when user wants to find one so I used AutoComplete. It’s a bit tricky, but I’ll try to keep it easy. The end product is a text field with, of course, AutoComplete. If user enters something not already in the list, it will be added after the playlist is saved.

mysqli transactions with prepared statements

(I’m using procedural style here, and I assume that you’ve already created a connection.)

 // Disable autocommit (we're doing it manually here)
mysqli_autocommit($db, false);

// Your query here
// Replace potential variables with question marks
$q = "INSERT INTO files (fileName, fileAuthor) VALUES (?, ?)";

$stmt = mysqli_prepare($db, $q) or die('Prepare Failed');

// If we have an array, we can foreach over it
foreach ($newData as $row){
  $bind = mysqli_stmt_bind_param($stmt,'ss',$row ['Name'] ,$row ['Author'] );
  if (!$bind){
    mysqli_rollback($db);
    die('Bind Failed');
  }

  $result = mysqli_stmt_execute($stmt);
  if (!$result) {
    mysqli_rollback($db);
    die('Insert Failed');
  }
}

// All done, we can now commit and re-enable autocommit
mysqli_commit($db);
print('OK! All done!');

mysqli_autocommit($db, true); 

jQuery UI AutoComplete

HTML Part: Interface

 <div id="menu-container" style="position:absolute; width: 20px;"></div>
<input type="text" name="searchq" id="searchq"> 

JS Part: Just one function

 $(function(){
  $("#searchq").autocomplete({
    source:'get_data.php',
    minLength: 1,
    delay: 100,
    appendTo: '#menu-container'
  });
}); 

PHP Part is the trickiest. You will need to accept a GET variable, $_GET ['term'] , which are supplied as the user types into the text box. Yes, you will need to perform filtering here. The following is the easiest method, displaying every candidate alphabetically without limit.

 function filter_result($term){
  $r = mysqli_query("SELECT fileName FROM files WHERE fileName LIKE '%$term%'");
  $result = Array();
  while($row = mysqli_fetch_assoc($r)){
    $result []  = $row ['fileName'] ;
  }
  return $result;
}
print json_encode(playlist_list($_GET ['term'] )); 

Reference: [StackOverflow]

Internship, Day 12 (4 May 2012)

Posted on May 5th, 2012 in computer, CPE, in English, in Thai, personal, PHP, programming | No Comments »


(Photo: Food center, fl. B1)

วันนี้ผมทำกราฟให้กับงานนับอีเมล์ โดยเมื่อวานใช้ Google Chart API แต่ก็ไม่เวิร์ก เพราะพี่บอกว่าอยากให้มีตัวเลขเหนือแท่งกราฟของแต่ละวันด้วย ก็เลยต้องเปลี่ยนไปใช้ jqplot แทน สิ่งที่แตกต่างอย่างเห็นได้ชัดคือ jqplot อ่อนกว่าเรื่อง documentation มาก แต่ก็ยังอยู่ในเกณฑ์ที่ใช้งานได้ง่ายเช่นกัน นอกจากนี้ plugin เยอะและกระจัดกระจายมาก (มี .js ประมาณยี่สิบกว่าไฟล์) ผมเลยแก้ปัญหาง่ายๆ (โค้ดอยู่ตอนท้าย ให้ทายก่อนว่าผมทำอะไรลงไป)

จากนั้นผมจึงส่งงาน (โดยการบอกพี่ว่าเสร็จแล้ว เพราะงานอยู่บนเซิร์ฟเวอร์) แล้วกลับมาทำงานวิดีโอต่อ โดยพี่ทดสอบให้ดูว่า jQuery UI ใช้กับ iPad และอุปกรณ์สัมผัสไม่ได้ สาเหตุก็คือ jQuery UI ใช้ mouse event ในขณะที่การสัมผัสมันไปสร้าง touch event ซึ่งพอไม่เหมือนกัน jQuery ก็ไม่จับ event ให้ ทำให้ไม่สามารถทำงานได้เหมือนปกติ ทางแก้หนึ่งคือการหา plugin ต่างๆ มาใส่ เช่น Touch Punch หรือ jQuery for iPad and iPhone เป็นต้น ซึ่งผมก็ยังไม่ได้ทำ

แต่ส่วนที่ทำแล้วคือ sidebar และเปลี่ยนกล่อง unordered list (UL) ให้แสดงผลเป็นตารางแบบ grid แทนที่จะเป็น list ไล่ลงมาแถวเดียว ซึ่งตรงนี้ไม่ยาก แต่ขอเก็บไว้ตอนท้ายเช่นกัน

Today I fixed the stat graphing for email checker. Yesterday I used Google Chart API but it didn’t go very well because the senior wanted it to display data labels on each bar, which Google Chart API did not support. I switched to jqplot , which was not as well-documented but still very useful. Its another downside is the scattered plugin files (20+ .js files) so I had to kludge it somehow. (Code is at the end)

After finishing the job I told the senior it’s done and got back to work on the video player. The senior tested jQuery UI on iPad which failed because jQuery UI uses mouse events while touchscreens generate touch events, which are not captured by jQuery UI. One way to fix is to install plugins like Touch Punch or jQuery for iPad and iPhone , but I haven’t tried any yet.

There’s something I got done though, and it’s the sidebar and grid-style list.

Kludging scattered files

 cat *jqplot*min*js > jqplot.all.js  

Sidebar CSS

Add a new div over your sidebar, then add these CSS lines to it

 .sidebar{
  position: absolute;
  top: 0;
  right: 0;
  z-index: 199;
} 

Absolute means the item is pinned to a particular spot on the page (while “fixed” pins the element to the window ). Top and Right properties specify how far from each edge this thing needs to be. In this case, it should be on the top-right. Z-index can be anything high enough that it’s in front of everything.

If you want it to be “integrated” into UI, not extending beyond the confines of your window, and also make it scrollable, just add these two more lines to the sidebar CSS

 .sidebar{
  height: 100%;
  overflow-y: scroll;
} 

Internship, Day 11 (3 May 2012)

Posted on May 4th, 2012 in computer, CPE, in English, in Thai, personal, PHP, programming | No Comments »


(Photo: My two friends. This is the only shot of the day, so I couldn’t be picky about quality.)

ตอนเช้าทำ YouTube Player ต่อนิดหน่อย พี่ก็เอางานใหม่มาให้ทำก่อน งานใหม่ที่ว่าคือ เซิร์ฟเวอร์มีระบบดูดเมล์จาก mailbox เข้าฐานข้อมูลอยู่แล้ว แต่ต้องการให้มีการนับจำนวนด้วย และแสดงผลออกมาว่ามีเมล์เข้ามาเท่าไหร่ในแต่ละวัน และแต่ละเดือน ซึ่งระบบดังกล่าวมี filter ด้วย ซึ่งจะแยกเมล์ออกเป็นชนิดต่างๆ ซึ่งผมไม่สามารถบอกได้ว่าแต่ละชนิดคืออะไร (ทั้งในเชิงเทคนิคและนโยบาย) รู้แต่ว่า เมล์แต่ละชนิดจะมีรหัสเป็นของตัวเองอยู่

แต่พอผมเข้าไปดูฐานข้อมูล พบว่าไม่มี primary key เลย แสดงว่าฐานข้อมูลนี้จริงๆ แล้วไม่ได้มีเจตนาให้ใช้งานเหมือนฐานข้อมูลทั่วไป แต่เป็นการเก็บเมล์จำนวนมากๆ มารวมๆ กันเท่านั้น นอกจากนี้ ระบบยังเก็บเวลาของเมล์เป็นข้อความด้วย ไม่ใช่ข้อมูลชนิดเวลาตามหลักฐานข้อมูล ดังนั้น ผมจึงสร้างตารางใหม่ขึ้นมา ตารางนี้จะดูดเอาเมล์ต่างๆ มา แล้วคัดไว้แต่รหัสกับเวลา (ซึ่งผมแปลงให้เป็น DATETIME เป็นที่เรียบร้อย) เอาที่เหลือทิ้งไปทั้งหมด จากนั้นผมก็ใช้คำสั่งต่างๆ ในการนับว่าแต่ละวันมีเมล์เข้ามาเท่าไหร่

พฤติกรรมการเขียนโค้ดของผมจะแปลกๆ อยู่อย่างนึง คือผมจะยอมใช้ SQL ที่ยากและซับซ้อน แต่จะพยายามทำให้ PHP ทำงานได้ง่ายที่สุด ตรงนี้อาจสะท้อนอะไรบางอย่างก็เป็นได้ ดังนั้น ในตัวอย่างที่จะให้ตอนท้ายจะเป็นอะไรที่แบบ … (นะ)

ในที่สุด ข้อมูลที่ดึงออกมาจากฐานข้อมูลแล้วจะถูกดึงออกมาจนถึงระดับ jQuery ซึ่งจะโยนให้ Google Chart API ต่อไป ได้ภาพออกมา เป็นอันเสร็จพิธี

I continued the YouTube Player for a bit before senior gave me a new job. I was tasked to add counting tool for an existing email checker solution, which opens mailbox (via POP3) and retrieves them into database. This solution also has filters, which divides emails into different types. I cannot tell what types exist in this solution, for technical and policy reasons. All I can tell is each email type has its unique “filter ID.”

When I inspected the database however it had no primary key. This means it’s really intended just to collect data and nothing else. Additionally, this database solution stores timestamps as text, not the appropriate date-time type. Therefore, I created a new table which collects every email entry, strip everything except filter ID and timestamp (which I changed to appropriate type now) then used various commands to count daily mail arrivals.

My coding style is a bit strange however, as I tend to use more complex SQL commands but always keep PHP as simple as possible. It might reflect something very strange in me. I don’t know.

Finally, this data, now in PHP form, is passed to jQuery layer, then to Google Chart API. We get a nice chart. End of story.

Code after the break.

Read the rest of this entry »