Archive for the ‘programming’ Category

Internship, Day 20 (17 May 2012)

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

null
(Photo: Getting from second floor to first, duh. I don’t know the subject.)

เหนื่อยๆๆ อะไรก็ไม่รู้แต่เช้า รู้แต่ว่าต้องรีบปั่นงานต่อเพราะตอนนี้มีสองงาน พอทำไปทำมามาติดบั๊กตรงคำสั่ง JavaScript จึงทำให้ได้บทเรียนที่สำคัญว่า

อย่าลืมว่าการใส่ $.each ให้ ajax (หรือ get หรือ getJSON หรือ post) ไม่ใช่การทำ ajax ทีละอัน แต่เป็นการสร้าง ajax หลายๆ อันทำขนานกัน

อย่า “โยง” ajax เข้าด้วยกันถ้าไม่รู้ว่ากำลังทำอะไรอยู่

เพราะ…

“a” ใน “a”-jax ย่อมาจาก “asynchronous”

วันนี้ผมเขียนระบบเล่นไฟล์สองรูปแบบ (double-format) โดยจะเป็น MP4 (ด้วย <video> tag) กับ YouTube (ด้วย YouTube API) ก็เล่นได้ เพื่อบรรเทาปัญหาที่ว่า Aruba บล็อกการส่งคำขอไปยังเครืองอื่นที่ไม่ใช่ตัวมันเอง แต่ข้อเสียที่สะท้อนกลับมาคือมันใช้พื้นที่มหาศาล และบริหารจัดการได้ยากมาก โดยเฉพาะเวลาสภาพความสอดคล้อง (consistency) เสียไปเนื่องจากเพิ่มวิดีโอใหม่เข้าไปใน playlist ที่เป็นแบบ MP4 แล้ว (อย่าลืมว่า ระบบไฟล์ใหม่ของผมจะกำหนด format ในระดับ playlist ไม่ใช่ระดับไฟล์) จึงใช้วิธีแก้ง่ายๆ ที่อาจฟังดูโหด คือ หากมีการเซฟ playlist ไม่ว่าจะไปแก้ไขมันหรือไม่ ผมจะตีความว่าเป็นการ downgrade playlist จากแบบ MP4 กลับไปเป็น YouTube อัตโนมัติ แต่สามารถ upgrade กลับมาเป็น MP4 ได้ทุกเมื่อเช่นกัน

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

และแน่นอน ปัญหา Aruba จะไม่จบ ถ้าไม่สามารถอัพโหลดงานของผมขึ้นไปไว้ในที่ๆ มัน whitelist ได้

Tiring morning. I had to do everything quickly because I have two jobs to do now. While working on a JavaScript bug I realized that …

$.each over ajax calls don’t do each one after another, but AT THE SAME TIME

Don’t chain ajax calls if you don’t know what you’re doing

because …

The first “a” in “a”-jax means “asynchronous”

Today I finish building the double-format (MP4 using <video> tag & YouTube using YouTube API) player in order to mitigate the Aruba problem, which prevented requests to other servers (i.e. my own media server) from working. The downside of this approach is the immense disk space requirement, and difficult management especially when the playlist is not consistent with the files after new files are added to the playlist. A bit harsh, but I fixed by forcing a “downgrade” (from MP4 to YouTube) upon saving for every playlist, however an “upgrade” is sill one click away so that’s not much of a problem.

Tomorrow, I will rebuild the file cleanup system to reduce space waste. Another thing I will do is to make an easy-to-read manual because my program uses lots of coloring (you only need to watch out for red or orange however, for they represent “error occurred”) and the final one is to test installation on a new machine. Then I can read vCloud. In. Peace.

Certainly, the Aruba problem will not end if I cannot get my work into its “whitelisted zone”. I don’t know how to do that or any kind of help is possible.

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.

[jQuery] … for MySQL Data Manipulation in PHP

Posted on May 16th, 2012 in computer, dedicated entry, in Thai, PHP, programming | No Comments »

<< อ่านบทที่แล้ว (jQuery for Beginners)

ก็กลับมาอีกครั้งกับหัวข้อ jQuery นะครับ วันนี้ผมจะมาเสนอเรื่องการใช้ jQuery ติดต่อกับฐานข้อมูลผ่าน PHP แบบง่ายๆ (ง่ายมากๆ) กัน

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

การอ่านค่าจากฟอร์ม

การอ่านค่าจาก form field ต่างๆ สามารถทำได้โดยใช้ .val() ยกตัวอย่างเช่น จากไฟล์ HTML ต่อไปนี้

 <form>
  <input type="text" id="name" name="name">
  <input type="button" id="btname" name="btname">
</form> 

เราสามารถเอาค่าออกมาจาก field “name” ได้โดยใช้คำสั่ง jQuery (บรรทัดบน) หรือ JS ธรรมดา (บรรทัดล่าง) ได้ดังนี้

 $("#name").val()
document.getElementById("name").value 

โจทย์: จาก starter code ที่ให้ไป ให้เปิดไฟล์ user.html ขึ้นมา ลองพิมพ์อะไรก็ได้ลงไปในช่องทั้งสอง ยังไม่ต้องทำอะไร จากนั้นให้ใช้คำสั่ง val ในการดึงค่าออกมา

การเรียกหน้า PHP จาก jQuery

เรามีไฟล์สองไฟล์ คือ signup.php กับ login.php ซึ่งเป็นไฟล์ที่สร้างผู้ใช้ใหม่กับทำการ login (แบบปลอมๆ) โดยไฟล์ทั้งสองนี้เป็นตัวแทนการ insert และการ select ตามลำดับ ให้ศึกษาไฟล์ให้เข้าใจก่อนที่จะอ่านต่อ …………………… หากอ่านจนพอเข้าใจ จะเห็นว่า ไฟล์ทั้งสองรับตัวแปรชื่อ user กับ pass แล้วเอาไปทำอะไรบางอย่างกับฐานข้อมูล จากนั้นมันจะ print ค่าออกมาหนึ่งในสองค่าคือ “OK” หรือ “FAILED” ขึ้นกับผลการทำงานที่ได้

เมื่อคราวที่แล้วผมสอนให้ผู้อ่านใช้คำสั่ง $.get ไป คราวนี้จะเปลี่ยนมาใช้คำสั่ง $.post บ้าง สำหรับ $.post ไม่ต่างอะไรจาก $.get เลยในแง่ของการใช้งาน ต่างกันแค่ความหมายนิดหน่อยเท่านั้น (สั้นๆ: GET ใช้ในการดึงข้อมูลออกมา โดยใส่ตัวแปรต่อจาก URL ในขณะที่ POST ใช้ในการส่งข้อมูลขึ้นระบบ โดยส่งตัวแปรด้วย HTTP Protocol ในส่วนที่ไม่ใช่ URL)

เช่น หากผมต้องการให้ส่งตัวแปร ‘ticket’ มีค่าเท่ากับ 814418 ไปยังหน้า ‘lottery.php’ โดยเมื่อ PHP ตอบกลับมาแล้วให้แสดงว่าได้รางวัลอะไร ก็จะมีโค้ดสองส่วน คือส่วนของ PHP ก่อน

 //LOTTERY PRIZE LOOKUP
function prize($ticket){
  if($ticket==814418){
    return "First Prize!!"
  } else if (in_array($ticket%1000,Array(504,309,902,101)){
    return "..."
  } // ... (whatever)
}

print prize($_POST ['ticket'] ); 

สังเกตว่าเมื่อเราเรียกไฟล์จริงๆ ไฟล์ lottery จะ print ไม่ใช่ return ซึ่งถูกต้องแล้ว เพราะการเรียก jQuery หรือ ajax มันจะไม่รู้ว่า return อะไรออกมา มันจะเอาแต่สิ่งที่ print ออกมาเท่านั้น

จากนั้นเราไปดู jQuery กันต่อ

 //LOTTERY CHECKER
function checkPrize(ticket){
  $.post(
         'lottery.php',
         {'ticket': ticket},
         function(output){alert(output);}
        );
}

checkPrize(814418); 

อธิบาย: โค้ดนี้จะเรียก lottery.php โดยใช้วิธี POST ส่งตัวแปร ticket ไปหนึ่งตัวมีค่า 814418 ส่วนฟังก์ชันที่รับ output เราเรียกว่า “ฟังก์ชันนิรนาม” (anonymous function) ซึ่งถูกกำหนดขึ้นมาเฉพาะกิจ ใช้งานแค่ใน scope เท่านั้น เช่น ในกรณีนี้ ฟังก์ชันจะเอา output แสดงออกมาผ่าน alert เป็นต้น หากอธิบายคร่าวๆ (มากๆ) ก็จะได้อะไรที่คล้ายๆ กับรูปข้างล่าง

เอาเป็นว่าเราเอาไว้เท่านี้ก่อน สำหรับโจทย์ในวันนี้คือ “พยายาม hack ตัว login ของผมด้วย SQL Injection ให้ได้” สำหรับคราวหน้าหากผมมีแรงเหลือจะมาอธิบายว่าทำไม SQL Injection จะใช้ได้หรือไม่ได้กับชุดคำสั่ง JQ2 ของผมนะครับ :)

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 »