<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jquery show hide column</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
$(function(){
var tb = $('#column_hidable');
var cbp = $('#checkbox_panel');
tb.find('tr:first > td').each(function(){
var cb = $('<input type="checkbox" checked="checked" />').click(function(){
var cbidx = cbp.find(':checkbox').index($(this));
tb.find('tr').each(function(){
$(this).find('td').eq(cbidx).toggle();
});
});
cb.appendTo(cbp).after($(this).text()+'<br'+'/>');
});
});
</script>
</head>
<body>
<?php
$cols = array("Field 1","Field 2","Field 3","Field 4","Field 5");
?>
<div id="checkbox_panel"></div>
<table border="1" cellspacing="0" cellpadding="5" id="column_hidable">
<tr bgcolor="#CC99FF">
<?php foreach($cols as $col_name):?>
<td><?php echo $col_name;?></td>
<?php endforeach;?>
</tr>
<?php $i=0; while($i++<5):?>
<tr>
<?php foreach($cols as $col_name):?>
<td><?php echo $col_name;?></td>
<?php endforeach;?>
</tr>
<?php endwhile;?>
</table>
</body>
</html>
วันจันทร์ที่ 29 พฤศจิกายน พ.ศ. 2553
jquery ซ่อนแสดง show/hide column โดยใช้ checkbox
วันอาทิตย์ที่ 28 พฤศจิกายน พ.ศ. 2553
google order check tool
เวลาค้นหาว่าเว็บอยู่อันดับไหนใน google ถ้าไม่ได้อยู่หน้าบนๆ นับลำดับกันลำบากทีเดียวครับ
ผมเลยทดลองเขียนโปรแกรมสำหรับช่วยหาอันดับเว็บไซท์โดยใช้ jquery โหลดข้อมูลมาทาง ajax ว่าจะโหลดมาได้หรือเปล่า
(ตอนแรกไม่ค่อยแน่ใจ เพราะไม่รู้ google จะกันไม่ให้โหลดหน้าเว็บไซท์มาได้หรือเปล่า)
เมื่อเขียนออกมาเวอร์ชั่นแรกใช้กับ firefox และ opera ได้ดีทีเดียว แต่เอามาใช้กับ ie ได้ไม่ดีเลยใช้แล้วโปรแกรมค้างเลยครับ
ผมเข้าใจว่าเป็นเพราะ ie ไม่สามารถโหลดข้อมูล html โดยใช้ ajax ได้เยอะๆ0
เวอร์ชั่นนี้เป็นเวอร์ชั่นใหม่แก้ใหม่สามารถใช้ได้ด้ทั้ง ie และ firefox ครับ
สำหรับท่านที่เคยโหลดเวอร์ชั่นแรกไปแนะนำให้เปลี่ยนมาใช้เวอร์ชั่นนี้จะเร็วขึ้นกว่าเดิมหลายเท่าครับ
เพราะเวอร์ชั่นแรกผมปล่อยให้ server ส่ง html มาตรงๆ เลย 100K คราวนี้ใช้ function ตัด string มาเฉพาะที่ใช้เหลือแค่ 4-5K เท่านั้นครับ :D
เวอร์ชั่น 2 ทำให้เร็วขึ้น แต่ทำการค้นหาเพียงหน้าเดียว (หน้าละ 5, 10, 20, 50, 100 รายการ)
เวอร์ชั่น 3 สามารถค้นหาหน้าละ 10 รายการ หลายๆ หน้า ทำให้ได้ผลลัพธ์เหมือนการค้นหาแบบปกติ
มีคนเคยแจ้งมาว่าโค้ดใช้การไม่ได้ผมตรวจดูแล้ว
เกิดจากเว็บโฮสนั้นไม่อนุญาติให้ใช้ allow url fopen (เปิดอ่าน url)
ลองตรวจสอบจุดนี้ก่อนครับ หลังจากนั้นถ้ายังไม่ได้แจ้งให้ผมตรวจสอบแก้ไขได้ครับ
ผมเลยทดลองเขียนโปรแกรมสำหรับช่วยหาอันดับเว็บไซท์โดยใช้ jquery โหลดข้อมูลมาทาง ajax ว่าจะโหลดมาได้หรือเปล่า
(ตอนแรกไม่ค่อยแน่ใจ เพราะไม่รู้ google จะกันไม่ให้โหลดหน้าเว็บไซท์มาได้หรือเปล่า)
เมื่อเขียนออกมาเวอร์ชั่นแรกใช้กับ firefox และ opera ได้ดีทีเดียว แต่เอามาใช้กับ ie ได้ไม่ดีเลยใช้แล้วโปรแกรมค้างเลยครับ
ผมเข้าใจว่าเป็นเพราะ ie ไม่สามารถโหลดข้อมูล html โดยใช้ ajax ได้เยอะๆ0
เวอร์ชั่นนี้เป็นเวอร์ชั่นใหม่แก้ใหม่สามารถใช้ได้ด้ทั้ง ie และ firefox ครับ
สำหรับท่านที่เคยโหลดเวอร์ชั่นแรกไปแนะนำให้เปลี่ยนมาใช้เวอร์ชั่นนี้จะเร็วขึ้นกว่าเดิมหลายเท่าครับ
เพราะเวอร์ชั่นแรกผมปล่อยให้ server ส่ง html มาตรงๆ เลย 100K คราวนี้ใช้ function ตัด string มาเฉพาะที่ใช้เหลือแค่ 4-5K เท่านั้นครับ :D
เวอร์ชั่น 2 ทำให้เร็วขึ้น แต่ทำการค้นหาเพียงหน้าเดียว (หน้าละ 5, 10, 20, 50, 100 รายการ)
เวอร์ชั่น 3 สามารถค้นหาหน้าละ 10 รายการ หลายๆ หน้า ทำให้ได้ผลลัพธ์เหมือนการค้นหาแบบปกติ
<?php
if (isset($_GET['search'])){
set_time_limit (60);
unset($_GET['search']);
//set total num (total result)
$total_num = ($_GET['total_num']>100) ?100:intval($_GET['total_num']);
unset($_GET['total_num']);
//set num (num per page)
$num = ($_GET['num']<5) ?5:intval($_GET['num']);
if ($num==10){
unset($_GET['num']);
}
//set default query
$q = '';
foreach($_GET as $k=>$v){
$q.='&'.urlencode($k).'='.urlencode($v);
}
//request all result from google
$s = '';
$start_num = 0;
while ($start_num < $total_num) {
$start = '&start='.$start_num;
$buffer = file_get_contents('http://www.google.co.th/search?'.$q.$start);
if (empty($buffer)){
$s .= '<cite>ERROR</cite>';
break;
}else{
$buffer = strstr($buffer,'<ol>');
$s .= substr($buffer,0,strpos($buffer,'</ol>')+5);
}
$start_num += $num;
}
//create xml response
header('Content-type:text/html;charset=tis-620');
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("cache-Control: no-store, no-cache, must-revalidate");
header("cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$matches = array();
preg_match_all('/<cite>(.+?)<\/cite>/',$s,$matches,PREG_SET_ORDER);
unset($s);
$cites = '';
foreach($matches as $m){
list($c) = explode(' - ',strip_tags($m[1]));
$c = preg_replace('/\s+/','',$c);
$cites .= "<c>{$c}</c>";
}
echo "<google>{$cites}</google>";
exit();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="th" xml:lang="th">
<head>
<title>google order check tool</title>
<meta http-equiv="Content-Type" content="text/html; charset=tis-620" />
<script src="http://code.jquery.com/jquery-latest.js" type="text/javascript"></script>
<script type="text/javascript">
/*<![CDATA[*/
var gTimer;
var gProgress;
function progress(){
if (gProgress){
gProgress.val(gProgress.val()*1+1);
}
gTimer = setTimeout('progress()',1000);
}
function clearProgress(){
gProgress.val(0);
if (gTimer) clearTimeout(gTimer);
}
$(document).ready(function(){
var website = $('#website');
var num = $('#num');
var total_num = $('#total_num');
var keyword = $('#keyword');
var order = $('#order');
var result = $('#result');
gProgress = $('#progress');
$('#searchForm').submit(function(e){
var meta = $('input[name=meta]:checked');
var data;
if (meta.val()=='')
data = {
q: keyword.val(),
num: num.val(),
total_num: total_num.val(),
oe: 'ISO-8859-11',
sa: 'N'
};
else
data = {
hl: 'th',
q: keyword.val(),
as_qdr: 'all',
num: num.val(),
total_num: total_num.val(),
meta: meta.val(),
oe: 'ISO-8859-11',
sa: 'N'
};
$.ajax({
dataType: 'html',
type: "GET",
url: "?search",
data: data,
beforeSend: function() {
clearProgress();
progress();
order.html('');
result.html('');
},
success: function(google) {
var strOrder='';
var strResult='';
var websiteTrim=website.val().replace(/^\s+|\s+$/g,'');
$('c',google).each(function(n){
var site = $(this).text();
n++;
if (websiteTrim=='' || site.indexOf(websiteTrim) == -1) {
strResult += n+': '+site+'<br'+' />';
} else {
strOrder += websiteTrim+' ติดอันดับที่ '+n+
' ของ keyword \''+keyword.val()+'\'<br'+' />';
strResult += n+': <span >'+site+'</span>'+'<br'+' />';
}
});
clearProgress();
result.hide();
if (strOrder=='') {
order.html('ยังไม่ติดอันดับ '+total_num.val()+' อันดับแรก');
}else{
order.html(strOrder);
}
if (strResult=='') {
result.html('ไม่พบผลลัพธ์จาก keyword นี้').show('normal');
}else{
result.html(strResult).show('normal');
}
},
error: function(a,b,c){
alert(b);
}
});
return false;
});
});
/*]]>*/
</script>
</head>
<body>
<b>ค้นหา ว่า website 'website' ติด 100 อันดับแรกของ keyword 'keyword' หรือยัง</b>
<br />
<div><form action="?" id="searchForm">
website: <input type="text" id="website" /><br />
keyword: <input type="text" id="keyword" /><br />
แสดงหน้าละ: <select id="num">
<option value="5">5</option>
<option value="10" selected="selected">10</option>
<option value="20">20</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<br />
result: <select id="total_num">
<option value="5">5</option>
<option value="10">10</option>
<option value="20" selected="selected">20</option>
<option value="30">30</option>
<option value="40">40</option>
<option value="50">50</option>
<option value="60">60</option>
<option value="70">70</option>
<option value="80">80</option>
<option value="90">90</option>
<option value="100">100</option>
</select>
<br />
ค้นหา :
<input type="radio" name="meta" value="" checked="checked" />เว็บ
<input type="radio" name="meta" value="lr=lang_th" />หน้าที่เป็นภาษาไทย
<input type="radio" name="meta" value="cr=countryTH" />เว็บจากประเทศไทย
<br />
progress: <input type="text" id="progress" /><br />
<input type="submit" id="request" value="search" />
</form></div>
<div style="background-color:yellow">
อันดับ : <br /><span id="order"></span>
</div>
<div style="background-">
ผลลัพธ์ : <span id="result"></span>
</div>
</body>
</html>
มีคนเคยแจ้งมาว่าโค้ดใช้การไม่ได้ผมตรวจดูแล้ว
เกิดจากเว็บโฮสนั้นไม่อนุญาติให้ใช้ allow url fopen (เปิดอ่าน url)
ลองตรวจสอบจุดนี้ก่อนครับ หลังจากนั้นถ้ายังไม่ได้แจ้งให้ผมตรวจสอบแก้ไขได้ครับ
วันศุกร์ที่ 26 พฤศจิกายน พ.ศ. 2553
service user pattern
ในการเขียน function เราก็สามารถจัดระเบียบให้เป็น oop pattern รูปแบบหนึ่งได้เช่นกันครับ
( เป็น oop โดยการจัดรูปแบบ )
เช่น
/services/global-service.php
/services/project1-service.php
/services/project2-service.php
/services/project3-service.php
กับ
/project1/home.php
/project1/contactus.php
ซึ่งเราจะแบ่งส่วนให้มีส่วนประกาศ function เฉพาะใน mylibs เท่านั้น
และส่วนเรียกใช้งาน function ต่างๆจะมีอยู่ใน user เท่านั้น
ซึ่งเราอาจจะเรียกว่า oop แบบนี้ว่าเป็น service - user pattern ครับ
โดยมีไฟล์กลุ่มหนึ่งทำหน้าที่เป็น service ไฟล์อีกกลุ่มหนึ่งทำหน้าที่เรียกใช้ service object เรียกว่า user object
โดย service จะไม่เข้าไปปะปนกับ user ,แบ่งหน้าที่โดย service เป็นผู้ให้บริการส่วน user เป็นผู้เรียกและขอรับบริการจาก service เท่านั้น
global-service.php
<?php
function f1(){...}
?>
project1-service.php
<?php
function f2(){...}
?>
เราอาจจะนับได้ว่า project1-service.php ได้รับการสืบทอบมาจาก global-service.php
ซึ่งในการเรียก service มาใช้งานเพื่อความสะดวกเราจะสร้างไฟล์สำหรับ initial ค่าต่างๆ สำหรับ project
ซึ่่งไฟล์ดังกล่าวจะเป็น user ที่ทำการติดต่อกับ service ก่อน user อื่นๆ ทุกครั้งขึ้นมาโดยให้ชื่อว่า coordinator.php (แปลว่าผู้ติดต่อประสานงาน)
coordinator.php
<?php
require '/services/global-service.php';
require '/services/project1-service.php';
//connect db
//initial project1 global value
?>
home.php
<?php
require 'coordinator.php';
f1();
f2();
?>
เรียกได้ว่า home.php สืบทอดคุณสมบัติจาก coordinator.php เพื่อทำการติดต่อกับ service ต่างๆ
แต่การเขียนแบบนี้ส่วนใหญ่เรามักจะไม่ระมัดระวังโดยมักจะแทรก function ในไฟล์ user
และแอบแทรกคำสั่งทำงานทันทีในส่วน service
ซึ่งทำให้หาส่วนประกาศ function ยาก และหาลำดับขั้นตอนการทำงานตั้งแต่เริ่มต้นยากครับ
( เป็น oop โดยการจัดรูปแบบ )
เช่น
/services/global-service.php
/services/project1-service.php
/services/project2-service.php
/services/project3-service.php
กับ
/project1/home.php
/project1/contactus.php
ซึ่งเราจะแบ่งส่วนให้มีส่วนประกาศ function เฉพาะใน mylibs เท่านั้น
และส่วนเรียกใช้งาน function ต่างๆจะมีอยู่ใน user เท่านั้น
ซึ่งเราอาจจะเรียกว่า oop แบบนี้ว่าเป็น service - user pattern ครับ
โดยมีไฟล์กลุ่มหนึ่งทำหน้าที่เป็น service ไฟล์อีกกลุ่มหนึ่งทำหน้าที่เรียกใช้ service object เรียกว่า user object
โดย service จะไม่เข้าไปปะปนกับ user ,แบ่งหน้าที่โดย service เป็นผู้ให้บริการส่วน user เป็นผู้เรียกและขอรับบริการจาก service เท่านั้น
global-service.php
<?php
function f1(){...}
?>
project1-service.php
<?php
function f2(){...}
?>
เราอาจจะนับได้ว่า project1-service.php ได้รับการสืบทอบมาจาก global-service.php
ซึ่งในการเรียก service มาใช้งานเพื่อความสะดวกเราจะสร้างไฟล์สำหรับ initial ค่าต่างๆ สำหรับ project
ซึ่่งไฟล์ดังกล่าวจะเป็น user ที่ทำการติดต่อกับ service ก่อน user อื่นๆ ทุกครั้งขึ้นมาโดยให้ชื่อว่า coordinator.php (แปลว่าผู้ติดต่อประสานงาน)
coordinator.php
<?php
require '/services/global-service.php';
require '/services/project1-service.php';
//connect db
//initial project1 global value
?>
home.php
<?php
require 'coordinator.php';
f1();
f2();
?>
เรียกได้ว่า home.php สืบทอดคุณสมบัติจาก coordinator.php เพื่อทำการติดต่อกับ service ต่างๆ
แต่การเขียนแบบนี้ส่วนใหญ่เรามักจะไม่ระมัดระวังโดยมักจะแทรก function ในไฟล์ user
และแอบแทรกคำสั่งทำงานทันทีในส่วน service
ซึ่งทำให้หาส่วนประกาศ function ยาก และหาลำดับขั้นตอนการทำงานตั้งแต่เริ่มต้นยากครับ
วันพฤหัสบดีที่ 25 พฤศจิกายน พ.ศ. 2553
singleton pattern
<?php
//singleton โครงสร้างเพื่อป้องกันไม่ให้มีการสร้าง instance ขึ้นหลายครั้ง
//อย่างเช่น database class connection ที่ควรจะมีแค่ครั้งเดียว
class Example
{
private static $obj;
private function __construct() {}
public static function singleton() // singleton method
{
if (!isset(self::$obj)) {
$c = __CLASS__;
self::$obj = new $c;
}
return self::$obj;
}
public function __clone(){ // Prevent users to clone the instance
trigger_error('Clone is not allowed.', E_USER_ERROR);
}
}
$obj = Example::singleton();
//$obj = new Example();// error (private constructor)
//$obj2 = clone $obj;// error
?>
template method
<?php
//template method คือ
//method ที่เตรียมไว้เป็นโครงสร้างแต่คำสั่งที่จะปรับปรุงเงื่อนไขต่างๆ ที่ซับซ้อน
//จะมอบให้เป็นหน้าที่ของ function ที่มันเรียกอีกทีหนึ่ง
abstract class Shape
{
public abstract function height();
public abstract function width();
public function area(){ //template method
return $this->height()*$this->width();
}
}
class Rectangle extends Shape
{
function height(){ return 10;}
function width(){ return 20;}
}
class Square extends Shape
{
function height(){ return 10;}
function width(){ return 10;}
}
$r = new Rectangle(); echo $r->area();
echo '<br','>';
$s = new Square(); echo $s->area();
?>
javascript only number ควบคุมให้ป้อนข้อมูลได้เฉพาะตัวเลขเท่านั้น
นำเสนอสองวิธีการในการควบคุมครับ วิธีแรก replaceDigit เป็นการแทนค่า string ที่ผู้ใช้ป้อนเข้าไปครับ
วิธีที่สองเป็น appeptOnlyDigit จะยอมรับคำสั่งที่ป้อนมาทาง keyboard เฉพาะตัวเลขและรหัสควบคุมบางตัวเท่านั้นครับ
ทั้งสองวิธียังไม่ได้กันการ copy และ paste นะครับในส่วนนี้ต้องหาทางแก้ไขเพิ่มเติมครับ
วิธีที่สองเป็น appeptOnlyDigit จะยอมรับคำสั่งที่ป้อนมาทาง keyboard เฉพาะตัวเลขและรหัสควบคุมบางตัวเท่านั้นครับ
ทั้งสองวิธียังไม่ได้กันการ copy และ paste นะครับในส่วนนี้ต้องหาทางแก้ไขเพิ่มเติมครับ
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="th" xml:lang="th">
<head>
<meta http-equiv="content-type" content="text/html; charset=tis-620" />
<title>javascript only digit textbox</title>
<script type="text/javascript">
//<![CDATA[
function replaceDigit(el){
el.value=el.value.replace(/\D/,'');
}
function acceptOnlyDigit(event,el){
var e=window.event?window.event:event;
var keyCode=e.keyCode?e.keyCode:e.which?e.which:e.charCode;
//0-9 (numpad,keyboard)
if ((keyCode>=96 && keyCode<=105)||(keyCode>=48 && keyCode<=57)){
return true;
}
//backspace,delete,left,right,home,end
if (',8,46,37,39,36,35,'.indexOf(','+keyCode+',')!=-1){
return true;
}
return false;
}
//]]>
</script>
</head>
<body>
<form method="post" action="?" id="box">
<br/>replace digit: <input type="text" name="onlydigit" value="" onkeyup="replaceDigit(this)" />
<br/>accept only digit: <input type="text" name="onlydigit2" value="" onkeydown="return acceptOnlyDigit(event,this)" />
</form>
</body>
</html>
สมัครสมาชิก:
บทความ (Atom)