Friday, August 27, 2010

Easy way lazyload image on UITableViewCell

This is sample article lazyload image on UITableViewCell. The libary for use this article
http://allseeing-i.com/ASIHTTPRequest/ and the sample code from Apple
ThumbImageView.h

#import "ASIHTTPRequest.h"

@protocol ThumbImageViewDelegate;




@interface ThumbImageView : UIImageView {
id delegate;
NSString *imageName;
CGSize imageSize;
CGRect home;
BOOL dragging;
CGPoint touchLocation; // Location of touch in own coordinates (stays constant during dragging).
}

@property (nonatomic, assign) id delegate;
@property (nonatomic, retain) NSString *imageName;
@property (nonatomic, assign) CGSize imageSize;
@property (nonatomic, assign) CGRect home;
@property (nonatomic, assign) CGPoint touchLocation;

- (void)goHome;
- (void)moveByOffset:(CGPoint)offset;
- (id)initWithImageAtUrl:(NSURL*)theUrl;

@end



@protocol ThumbImageViewDelegate

@optional
- (void)thumbImageViewWasTapped:(ThumbImageView *)tiv;
- (void)thumbImageViewStartedTracking:(ThumbImageView *)tiv;
- (void)thumbImageViewMoved:(ThumbImageView *)tiv;
- (void)thumbImageViewStoppedTracking:(ThumbImageView *)tiv;

@end


ThumbImageView.m
#import "ThumbImageView.h"
#import "MoMagIO.h"

#define DRAG_THRESHOLD 10
#define ACTIVITYVIEW_TAG 123

float distanceBetweenPoints(CGPoint a, CGPoint b);

@interface ThumbImageView(PrivateMethods)

-(void)addLoadingCircle;
-(void)removeLoadingCircle;
-(void)downloadImageWithURL:(NSURL*)theUrl;

@end


@implementation ThumbImageView


@synthesize delegate;
@synthesize imageName;
@synthesize imageSize;
@synthesize home;
@synthesize touchLocation;

- (id)initWithImageAtUrl:(NSURL*)theUrl{

self = [super init];
if (self) {
[self setUserInteractionEnabled:YES];
[self setExclusiveTouch:YES];
self.image = nil;
// Add loading circle
[self addLoadingCircle];
// Asyncronous download image
[self downloadImageWithURL:theUrl];
}
return self;
}

-(void)addLoadingCircle{

UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray;
indicatorView.center = CGPointMake((152/2),(195/2));
indicatorView.tag = ACTIVITYVIEW_TAG;
[self addSubview:[indicatorView autorelease]];
[indicatorView startAnimating];
}

-(void)removeLoadingCircle{

UIActivityIndicatorView *indicatorView = (UIActivityIndicatorView*)[self viewWithTag:ACTIVITYVIEW_TAG];
[indicatorView stopAnimating];
[indicatorView removeFromSuperview];
}
-(void)downloadImageWithURL:(NSURL*)theUrl{
NSLog(@"Url for download %@",theUrl);
NSString *pathToSave = [[MoMagIO getCacheDirPath] stringByAppendingPathComponent:[[theUrl path] lastPathComponent]];
//
if(imageName != pathToSave){
[imageName release];
imageName = [pathToSave retain];
}
NSFileManager *fm = [NSFileManager defaultManager];
if([fm fileExistsAtPath:self.imageName]){
UIImage *img = [[UIImage alloc] initWithContentsOfFile:imageName];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];
[self removeLoadingCircle];
}else {

ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:theUrl];
[request setDelegate:self];
request.didFailSelector = @selector(downloadDidFailed:);
request.didFinishSelector = @selector(downloadDidCompleted:);
request.downloadDestinationPath = imageName;
[request startAsynchronous];
}
}
-(void)downloadDidFailed:(ASIHTTPRequest *)request{
#ifdef DEBUG
NSLog(@"ThumbImageView:-(void)downloadDidFailed:(ASIHTTPRequest *)request %@",[request error]);
#endif
NSBundle *bundle = [NSBundle mainBundle];
NSString *root = [[bundle resourcePath] stringByAppendingPathComponent:@"cover_preload.jpg"];
UIImage *img = [[UIImage alloc] initWithContentsOfFile:root];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];
[self removeLoadingCircle];
}
-(void)downloadDidCompleted:(ASIHTTPRequest *)request{
UIImage *img = [[UIImage alloc] initWithContentsOfFile:imageName];
if(img){
self.image = img;
[self setNeedsDisplay];
}
[img release];

[self removeLoadingCircle];
}

- (id)initWithImage:(UIImage *)image {
self = [super initWithImage:image];
if (self) {
[self setUserInteractionEnabled:YES];
[self setExclusiveTouch:YES];
}
return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// store the location of the starting touch so we can decide when we've moved far enough to drag
touchLocation = [[touches anyObject] locationInView:self];
if ([delegate respondsToSelector:@selector(thumbImageViewStartedTracking:)])
[delegate thumbImageViewStartedTracking:self];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
// we want to establish a minimum distance that the touch has to move before it counts as dragging,
// so that the slight movement involved in a tap doesn't cause the frame to move.
/**CGPoint newTouchLocation = [[touches anyObject] locationInView:self];
if (dragging) {
float deltaX = newTouchLocation.x - touchLocation.x;
float deltaY = newTouchLocation.y - touchLocation.y;
[self moveByOffset:CGPointMake(deltaX, deltaY)];
}
else if (distanceBetweenPoints(touchLocation, newTouchLocation) > DRAG_THRESHOLD) {
touchLocation = newTouchLocation;
dragging = YES;
}**/
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (dragging) {
[self goHome];
dragging = NO;
} else if ([[touches anyObject] tapCount] == 1) {
if ([delegate respondsToSelector:@selector(thumbImageViewWasTapped:)])
[delegate thumbImageViewWasTapped:self];
}
if ([delegate respondsToSelector:@selector(thumbImageViewStoppedTracking:)])
[delegate thumbImageViewStoppedTracking:self];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self goHome];
dragging = NO;
if ([delegate respondsToSelector:@selector(thumbImageViewStoppedTracking:)])
[delegate thumbImageViewStoppedTracking:self];
}

- (void)goHome {
float distanceFromHome = distanceBetweenPoints([self frame].origin, [self home].origin); // distance is in pixels
float animationDuration = 0.1 + distanceFromHome * 0.001;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
[self setFrame:[self home]];
[UIView commitAnimations];
}
- (void)moveByOffset:(CGPoint)offset {
CGRect frame = [self frame];
frame.origin.x += offset.x;
frame.origin.y += offset.y;
[self setFrame:frame];
if ([delegate respondsToSelector:@selector(thumbImageViewMoved:)])
[delegate thumbImageViewMoved:self];
}

@end

float distanceBetweenPoints(CGPoint a, CGPoint b) {
float deltaX = a.x - b.x;
float deltaY = a.y - b.y;
return sqrtf( (deltaX * deltaX) + (deltaY * deltaY) );
}

Then use it
// Left photo
ThumbImageView *thumbViewLeft = [[[ThumbImageView alloc] initWithImageAtUrl:url] autorelease];
thumbViewLeft.userInteractionEnabled = YES;
thumbViewLeft.exclusiveTouch = NO;
thumbViewLeft.layer.borderWidth = 1.0f;
thumbViewLeft.layer.borderColor = [[UIColor lightGrayColor] CGColor];
[thumbViewLeft setDelegate:self];
CGRect frame = [thumbViewLeft frame];
frame.origin.y = IMAGE_PADDING;
frame.origin.x = xPosition;
frame.size = CGSizeMake(imageWidth,IMAGE_HEIGHT);
[thumbViewLeft setFrame:frame];
[thumbViewLeft setHome:frame];
thumbViewLeft.tag = LEFT_IMAGE;
//image =[[UIImage alloc] initWithContentsOfFile:[root stringByAppendingPathComponent:@"cover_preload.jpg"]];
//[thumbViewLeft setImage:[ImagePopulate image:image fitInSize:thumbViewLeft.frame.size]];
//[image release];
[cell.contentView addSubview:thumbViewLeft];
xPosition += (frame.size.width + IMAGE_PADDING);


Happy with programming

Wednesday, August 18, 2010

การ embed youtube ใน UIWebView

โดยปรกติแล้วการเล่นวีดีโอผ่าน youtube ส่วนมากจะเป็น 3rd party ที่เวลาเล่นแล้ว
จำเป็นจะต้องดีดออกจาก app แต่ถ้าอยากให้เล่นใน app ก็สามารถทำได้ครับ


- (void)embedYouTube:(NSString *)urlString frame:(CGRect)frame {

NSString *embedHTML = @"starthtml starthead\ \ endhead startbody style=\"margin:0\">\
\
endbody endhtml";
NSString *html = [NSString stringWithFormat:embedHTML, urlString,
frame.size.width, frame.size.height];

if (!webView) {
webView = [[UIWebView alloc] initWithFrame:frame];
[self.view addSubview:webView];
}

[webView loadHTMLString:html baseURL:nil];

}


หลังจากนั้นแค่เรียก


[self embedYouTube:self.url frame:CGRectMake(20, 20, 280, 300)];


more information
http://apiblog.youtube.com/2009/02/youtube-apis-iphone-cool-mobile-apps.html
http://iphoneincubator.com/blog/audio-video/how-to-play-youtube-videos-within-an-application

Wednesday, August 11, 2010

UIScrollView zooming centered UIImageView

การซูมใน UIScrollView ถ้าซูมรูปเดียวคงไม่มีปัญหาอะไร เพราะมี method ให้เลือกใช้งานดังนี้

float newScale = [imageScrollView zoomScale] * maxZoomLevel;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:tapPoint];
[imageScrollView zoomToRect:zoomRect animated:YES];


แต่เปิด View ขึ้นมาแล้วให้รูปซูมขึ้นมาเลย แล้วก็ให้อยู่ center ด้วยนั้นสามารถทำได้ดังนี้ครับ

CGFloat tempx = view.center.x-160;
CGFloat tempy = view.center.y-160;
myScrollViewOffset = CGPointMake(tempx,tempy);


เเหล่งข้อมูล
http://stackoverflow.com/questions/638299/uiscrollview-with-centered-uiimageview-like-photos-app
http://stackoverflow.com/questions/1316451/center-content-of-uiscrollview-when-smaller
http://discussions.apple.com/thread.jspa?messageID=8322675

Monday, August 9, 2010

iPhone storekit - Handler cancel event by user

เมื่อเราพัฒนาเเอพพลิเคชั่นที่จำเป็นต้องใ่ช้ In-App purchase จำเป็นทำการ implement SKPaymentTransactionObserver
สำหรับการทำ Transaction ในการ purchase item ต่างๆ และเมื่อ storekit ขึ้นหน้าจอให้ confirm การ purchase จะมีสอง
ปุ่มให้เลือกคือ Cancel และ Buy จำการ cancel Transactionstate ที่ได้จะเป็น SKPaymentTransactionStateFailed ซึ่งเรา
สามารถที่จะทำการตรวจสอบว่า transaction state นั้นการจากการ fail หรือ cancel โดย user โดยเช็คได้ดังนี้

transaction.error.code != SKErrorPaymentCancelled


โ่ค้ดเเบบสมบูรณ์


- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
for (SKPaymentTransaction *transaction in transactions)
{
switch (transaction.transactionState)
{
case SKPaymentTransactionStatePurchased:

[self completeTransaction:transaction];

break;

case SKPaymentTransactionStateFailed:

[self failedTransaction:transaction];

break;

case SKPaymentTransactionStateRestored:

[self restoreTransaction:transaction];

default:

break;
}
}
}

- (void) failedTransaction: (SKPaymentTransaction *)transaction
{
if (transaction.error.code != SKErrorPaymentCancelled)
{
// Optionally, display an error here.
if([self.delegate respondsToSelector:@selector(failedTransaction:)])
[self.delegate failedTransaction:transaction];
}else {
if([self.delegate respondsToSelector:@selector(canceledTransaction:)])
[self.delegate canceledTransaction:transaction];

}

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

- (void) completeTransaction: (SKPaymentTransaction *)transaction
{
if([self.delegate respondsToSelector:@selector(completeTransaction:)])
[self.delegate completeTransaction:transaction];

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

- (void) restoreTransaction: (SKPaymentTransaction *)transaction
{
if([self.delegate respondsToSelector:@selector(restoreTransaction:)])
[self.delegate restoreTransaction:transaction];

[[SKPaymentQueue defaultQueue] finishTransaction: transaction];
}

Thursday, July 29, 2010

การ encrypt/decrypt รูป

การ encrypt/decrypt ก็คงเป็นการเข้ารหัสข้อมูลที่สำคัญ ที่ไม่ต้องการจะเปิดเผยให้ใครรู้
ซึ่งในระหว่างการส่งข้อมูลในแต่ละ tier นั้นอาจจะใช้โปรเเกรมพวก sniffer ดักเอาก็ได้ เพื่อ
ความปลอดภัย เราโปรเเกรมเมอร์จึงต้องเข้ารหัสข้อมูลแล้วก็ใส่รหัสผ่านของเราไว้สำหรับถอดรหัสด้วย

ที่นี้การเ้ข้ารหัสนั้นไม่ว่าภาษาใหนก็ทำได้และมีอัลกอลิทึมให้ใช้กันอย่างหลากหลาย ซึ่งการเข้ารหัส
และถอดรหัสด้วยภาษาเดียวกันอาจจะทำได้ง่ายกว่า การเข้ารหัสด้วยภาษาหนึ่งแล้วไปถอดรหัสอีกภาษาหนึ่ง
ซึ่งในกรณีซึ่งเป็นระบบเเบ็คเอ็นต้องเข้ารหัสรูปบน asp.net(c#) แล้วไปถอดบน iphone ใ่ช้เวลา
ลองผิดลองถูกเกือบสองวันในที่สุดก็ทำได้ครับ

ส่วนสำคัญอยู่ตรงนี้ครับ

byte[] images = File.ReadAllBytes(@"C:\Wallpaper\encrypt.jpg");

string x = Convert.ToBase64String(images);
string result = DecryptString(x, "digix");
byte[] data = Convert.FromBase64String(result);
FileStream fsout = new FileStream(@"C:\Wallpaper\decrypt.jpg", FileMode.CreateNew);
fsout.Write(data, 0, data.Length);
fsout.Flush();
fsout.Close();


เเหล่งข้อมูลที่ใช้ในการศึกษา
http://stackoverflow.com/questions/1373032/c-howto-convert-image-to-binary
http://stackoverflow.com/questions/885237/writing-an-image-to-a-text-file-as-binary-data-c
โค้ดการเข้ารหัส string จาก http://dotmac.rationalmind.net/2009/02/aes-interoperability-between-net-and-iphone/

///
/// Encrpyts the sourceString, returns this result as an Aes encrpyted, BASE64 encoded string
///

/// a plain, Framework string (ASCII, null terminated)
/// The pass phrase.
///
/// returns an Aes encrypted, BASE64 encoded string
///

public static string EncryptString(string plainSourceStringToEncrypt, string passPhrase)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passPhrase)))
{
byte[] sourceBytes = Encoding.ASCII.GetBytes(plainSourceStringToEncrypt);
ICryptoTransform ictE = acsp.CreateEncryptor();

//Set up stream to contain the encryption
MemoryStream msS = new MemoryStream();

//Perform the encrpytion, storing output into the stream
CryptoStream csS = new CryptoStream(msS, ictE, CryptoStreamMode.Write);
csS.Write(sourceBytes, 0, sourceBytes.Length);
csS.FlushFinalBlock();

//sourceBytes are now encrypted as an array of secure bytes
byte[] encryptedBytes = msS.ToArray(); //.ToArray() is important, don't mess with the buffer

//return the encrypted bytes as a BASE64 encoded string
return Convert.ToBase64String(encryptedBytes);
}
}


///
/// Decrypts a BASE64 encoded string of encrypted data, returns a plain string
///

/// an Aes encrypted AND base64 encoded string
/// The passphrase.
/// returns a plain string
public static string DecryptString(string base64StringToDecrypt, string passphrase)
{
//Set up the encryption objects
using (AesCryptoServiceProvider acsp = GetProvider(Encoding.Default.GetBytes(passphrase)))
{
byte[] RawBytes = Convert.FromBase64String(base64StringToDecrypt);
ICryptoTransform ictD = acsp.CreateDecryptor();

//RawBytes now contains original byte array, still in Encrypted state

//Decrypt into stream
MemoryStream msD = new MemoryStream(RawBytes, 0, RawBytes.Length);
CryptoStream csD = new CryptoStream(msD, ictD, CryptoStreamMode.Read);
//csD now contains original byte array, fully decrypted

//return the content of msD as a regular string
return (new StreamReader(csD)).ReadToEnd();
}
}

private static AesCryptoServiceProvider GetProvider(byte[] key)
{
AesCryptoServiceProvider result = new AesCryptoServiceProvider();
result.BlockSize = 128;
result.KeySize = 128;
result.Mode = CipherMode.CBC;
result.Padding = PaddingMode.PKCS7;

result.GenerateIV();
result.IV = new byte[] {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

byte[] RealKey = GetKey(key, result);
result.Key = RealKey;
// result.IV = RealKey;
return result;
}

private static byte[] GetKey(byte[] suggestedKey, SymmetricAlgorithm p)
{
byte[] kRaw = suggestedKey;
List kList = new List();

for (int i = 0; i < p.LegalKeySizes[0].MinSize; i += 8)
{
kList.Add(kRaw[(i / 8) % kRaw.Length]);
}
byte[] k = kList.ToArray();
return k;
}

Thursday, May 27, 2010

Objective-C Part 1

Extension ใน objective-c
.h = header file ที่จัดเก็บ header file,function,type,constant,declaretion
.m = objective-c code และ c
.mm = ที่จัดเก็บ code ที่เป็น c++

การประกาศ class ใน objective-c

@interface Dog{
NSString *name;
NSString *origin;
}

//Region properties
@property (retain) NSString *name;
@property (retain) NSString *origin;
//Region method
-(void)run:(int) speed;
@end

การ Implement class

@Implement Dog
@synthesize name,origin;
-(void)run:(int) speed){
NSLog("Dog run speed %@",speed);
}
@end

ทั้ง interface และ implement class สามารถอยู่ไฟล์เดียวกันและเเยกไฟล์กันก็ได้
ถ้าเเยกไฟล์ interface class จะอยู่ใน .h
@synthesize เพื่อบอกให้ compiler gen setter และ getter method ของ properties

การสร้าง object สามารถทำได้โดย

Dog *dog1 =[[Dog alloc] init];


การเรียกเมธอดหรือส่งเมจเสจ

[dog1 speed:5];


โปรโตคอลและเดลิเกต
สัญญลักษณ์ ของโปรโตคอล @protocal โปรโตคอล คือ การประกาศเมธอดที่คลาสอื่นสามารถนำไป implement ได้
อาจจะคล้ายๆ กับ abstract ใน java ซึ่งตัวโปรโตคอลนี้ไม่สามารถเป็นคลาสได้ด้วยตัวมันเอง การประกาศโปรโตคอล
จะมีลักษณะคล้าย interface และ object ตัวอื่นสามารถที่จะตอบสนองเมธอดของโปรโตคอลได้ด้วย การ implement
เมื่อคุณ implement method ของ protocal ในคลาสและคลาสคุณจะทำงานร่วมกันได้กับโปรโตคอล
และลักษณะการประกาศโปรโตคอล

@protocal MyProtocal
-(void) myProtocalMethod;
@end


ิติดตาม Part 2 ต่อครับ

Saturday, May 22, 2010

การ Compile Objective-c บน Windows XP

เมื่อ Download GNUstep
เราก็มาเริ่มการเขียน Objectiv-C กันเลยครับ ก็คงหนีไม่พ้น Hello program สุดคลาสสิก


//First program example
#import

int main(int argc,const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello World!");

[pool drain];
return 0;
}


แล้วก็เข้าไปที่ Start->All Programs->GNustep->shell นะครับ
เเล้วพิมพ์คำสั่งในการ compile ซึ่งจะต่างจากภาษา c เล็กน้อย แต่คล้ายๆ
เช็ตคลาสพาธเหมือน java
$gcc -o hello hello.m -I /GNUstep/System/Library/Headers -L /GNUstep/System/Library/Libraries -lobjc -lgnustep-base -fconstant-string-class=NSConstantString

ยาวใหมละครับเหอะๆ ก็เเบบนี้ละครับ เราไม่มีเครื่อง Mac

Objective-C Programming

ทุกวันนี้ผลิตภัณฑ์ของ Apple Inc. เข้ามีบทบาทอย่างมากในวงการไอที
ไม่ว่าจะเป็น iPod,iPhone,iPad ซึ่งทำให้คนในวงการโปรเเกรมเมอร์
เริ่มขยับด้วยเข้าหา และที่ไม่พูดถึงไม่ได้เลยก็คือ Objective-c เป็น
ภาษา c และ smalltalk เเปลงร่างรวมตัวกันเป็น object oriented programming
เพื่อใช้ในการเขียน application บนผลิตภัณฑ์ของ Apple และผมก็เป็น
หนึ่งในนั้นที่ต้องการเขียน objective-c
เราเริ่มตันหาเครื่องมากันดีกว่าครับ
1. ใช้ VMWare แล้วลง Mac OSX image ไฟล์เอา ซึ่งตอนนี้กำลังโหลดอยู่ครับ
เดียวถ้าเสร็จจะมาเล่าให้ฟัง
2. ใช้ GNUstep ครับ
ตัวเอาไว้เรียนรู้การเขียน objective-c อย่างเดียวนะครับ เขียน application บน i ทั้งหหลายไม่ได้
จบแค่นี้ก่อนครับ

Tuesday, May 18, 2010

jQuery sortable with asp.net



การ sorttable จะใช้ jquery ui อยู่ 3 ไฟล์นะครับ คือ jquery.x.x.js ,ui.core.js,ui.sortable.js
ในส่วนของ form
  • ">
  • หน้าที่ #
    " width="120" height="64">
    ส่วนของ javascript
    $(document).ready(function(){
    $("#reorder").sortable({ handle:"span", start:sorting, stop:sortStop, update:updatePageNo });
    });

    function sorting(event,ui){
    $(ui.item).addClass("draging");
    //Set loading image
    $('#loading').html("").text("กรุณารอสักครู่...");
    }
    function sortStop(event,ui){
    $(ui.item).removeClass("draging");
    }
    function updatePageNo(event,ui){
    var idArr = $('#reorder').sortable('toArray');
    var dataTransfer;
    //var issueID = $("#HiddenIssueID").val();
    dataTransfer = "[";
    //Convert to json array
    jQuery.each(idArr,function(index){
    dataTransfer +="{\"ContentID\":"+this+",\"PageNo\":"+(index+1)+"},";
    });
    dataTransfer = dataTransfer.substring(0,dataTransfer.length-1);
    dataTransfer += "]";
    //$.toJSON(idArr);
    //Sys.Serialization.JavaScriptSerializer.serialize(idArr
    $.post(
    'UpdateReorderHandler.ashx?q='+dataTransfer,
    function(data) {
    //Remove loading image
    $('#loading').empty();
    if(data=="success"){
    alert("เเก้ไขข้อมูลการเรียงลำดับเรียบร้อยแล้ว");
    window.location = window.location;
    }else{
    alert("ไม่สามารถเเก้ไขข้อมูลการเรียงลำดับได้");
    $('#reorder').sortable('cancel');
    window.location = window.location;
    }
    }
    );
    }

    และส่วนของ Server
    context.Response.ContentType = "text/plain";
    string q = context.Request.QueryString["q"];
    JsonTextParser parser = new System.Net.Json.JsonTextParser();
    JsonObject obj = parser.Parse(q);
    JsonUtility.GenerateIndentedJsonText = false;
    string name = string.Empty;
    string value = string.Empty;
    JsonArrayCollection arrjSon = (JsonArrayCollection)obj;
    List PageList = new List();
    ContentPage page = null;
    foreach (JsonObject field in arrjSon)
    {
    List jsons = (List)field.GetValue();
    page = new ContentPage();
    foreach (JsonObject o in jsons)
    { //issue = new Issue();
    if (o.Name == "ContentID")
    page.ContentID = Convert.ToInt64(o.GetValue());
    if (o.Name == "PageNo")
    page.PageNo = Convert.ToInt32(o.GetValue());
    //if (o.Name == "IssueID")
    //issue.IssueID = o.GetValue().ToString();
    //page.Issue = issue;
    }
    PageList.Add(page);
    }
    if (_issueService == null)
    _issueService = new IssueService();
    try
    {
    if (_issueService.UpdateSequenceNo(PageList.ToArray()))
    { //Success
    context.Response.Write("success");
    }
    else
    {
    //Fail
    context.Response.Write("fail");
    }
    }
    catch (Exception)
    {
    context.Response.Write("fail");
    }


    Thursday, May 13, 2010

    asp.net(c#) upload file by ajax

    ก่อนอื่นให้ไปโหลดไลบรารีตัวนี้มาก่อนนะครับ valums.com/ajax-upload/
    copy code ส่วนนี้ไปว่างระหว่าง
    //
    $(document).ready(function(){
    var button = $('#upload_button'), interval;
    new AjaxUpload(button, {
    action: 'UploadHandler.ashx',
    name: 'myfile',
    responseType: 'json',
    onSubmit : function(file, ext){
    //if (! (ext && /^(mp3|wma|wmv|mp4|mpeg|dat)$/i.test(ext))){
    // extension is not allowed
    //alert('Error: invalid file extension');
    // cancel upload
    //return false;
    //}
    // change button text, when user selects file
    button.text('Uploading');
    // If you want to allow uploading only 1 file at time,
    // you can disable upload button
    this.disable();
    // Uploding -> Uploading. -> Uploading...
    interval = window.setInterval(function(){
    var text = button.text();
    if (text.length <>
    button.text(text + '.');
    } else {
    button.text('Uploading');
    }
    }, 200);
    },
    onComplete: function(file, response){
    button.text('Upload');
    window.clearInterval(interval);
    // enable upload button
    this.enable();

    // add file to the list
    if(response.Status=='success'){
    $('
  • ').appendTo('#result').html($("Delete"));
    }else{
    $('#result').append('
  • Fail to upload!
  • ');
    }
    }
    });
    });
    //Delete file
    function FileDelete(sender,path){
    var currentDate = new Date();
    var q = "q="+path+"&seek="+currentDate.getMilliseconds();
    var response = confirm("Are you sure?");
    if(response){
    $.ajax({
    dataType : "json",
    url: "FileDeleteHandler.ashx",
    data: q,
    success: function(msg){
    if(msg.status == "success"){
    $(sender).parents('li:eq(0)').hide();
    }else{
    alert('Error can not delete!');
    }
    },
    error : function(msg){
    alert('Error can not delete!');
    }
    });
    }
    return false;
    }
    //]]>

    ส่วนในform
    begin div id="upload_button"
    Upload
    end div
    ul
    id="result" style="list-style-type: none">
    ul

          หลังจากนั้นให้สร้าง GenericHandler ขึ้นมาครับ
          แล้วโค้ดในมธอด ProcessRequest เป็นเเบบนี้ครับ
          public void ProcessRequest(HttpContext context)
          {

          string strFileName = System.IO.Path.GetFileName(context.Request.Files[0].FileName);
          string strSaveLocation = context.Server.MapPath("ContentImage") + "" + strFileName;
          context.Request.Files[0].SaveAs(strSaveLocation);
          }

          Wednesday, May 12, 2010

          C# write binary to file

          FileInfo fileInfo = new FileInfo(filenamePath);
          if (!IsExistsDirectory(fileInfo.DirectoryName))
          {
          CreateDirectory(fileInfo.DirectoryName);
          }
          FileStream fs = new FileStream(filenamePath, FileMode.Create, FileAccess.Write);
          using (BinaryWriter bw = new BinaryWriter(fs))
          {
          bw.Write(buff);
          }

          Friday, April 23, 2010

          try-catch on T-SQl

          try-catch เป็น feature ใหม่ของ sqlserver 2005
          ลักษณะการใช้งานมีดังนี้ครับ
          BEGIN TRY
          --sql statement
          END TRY
          BEGIN CATCH
          SELECT ERROR_NUMBER() ErrorNBR, ERROR_SEVERITY() Severity,ERROR_LINE () ErrorLine, ERROR_MESSAGE() Msg
          ROLLBACK TRANSACTION
          END CATCH

          Saturday, March 27, 2010

          Drupal theme development

          วันนี้ว่าจะเริ่มพัฒนาเว็บของบริษัทโดย Drupal ก็เลยเริ่มหาข้อมูล
          เกี่ยวกับการพัฒนาธีม Drupal ว่าต้องใช้อะไรบ้าง ข้อมูลที่ได้ส่วนมาก
          จะเป็นเครื่องที่โปรเเกรมเมอร์อย่างเราๆ คุ้นเคยกันดีอยู่แล้ว
          1. firebug
          2. Web developer
          3. Devel module
          4. drupal firebug
          5. conditional stylesheet
          ตอนนี้เท่าที่ทราบมีแค่นี้นะครับ มีเครืองมือตัวใหนอีกใหมครับ
          ช่วยๆ กันแนะนำหน่อยครับ

          Monday, March 15, 2010

          Unit test case for JPA

          วันนี้นั้งเขียน ejb3 กับ jpa ซึ่งเป็นที่ระบบเก่า ที่เคยทำไว้เดือนพฤศจิกายนปี 2009
          วันหัวหน้าให้เพิ่มความสามารถบางเข้าไป พอ check out code ลงดูแล้วเกิดอาการงง
          เนื่องจากไม่ได้ัจับ ejb3 และ jpa นาน เพราะไปอยู่กับ struts และ c# ส่วนใหญ่
          แต่ยังก็ยังอยากจะเขียน java เหมือนเดิมนะเพราะชอบ พอเขียนเสร็จดันอยากจะเทส jpa query
          สักหน่อย ก็นั้งหาไปหามาไปเจอตัวนี้ครับ https://jpaquerytool.dev.java.net/ และ
          http://www.antoniogoncalves.org/xwiki/bin/view/Article/TestingJPA ซึ่งก็พอ
          ประทันชีวิตไปได้ ใครมีตัวใหนแนะนำอีกใหมครับ

          Saturday, March 13, 2010

          Begin to my corporate

          บนถนนที่เต็มไปอุปสรรค์และปัญหามากมาย และแล้วก็มาถึงนะจุดจุดหนึ่งที่
          ต้องทำอะไรบ้างอย่าง และสิ่งนั้นก็เป็นหนึ่งในความฝันแล้วถ้ามีโอกาสจะทำไมละ
          ก็คงต้องตอบว่า
          ทำแน่นอน
          แต่คนรอบข้าง
          เรานี่ซิไม่เห็นด้วยกันทั้งนั้น ไม่ว่าจะเป็นพ่อเเม่ เพื่อนก็บอกว่ามันเร็วเกินไปนะ แต่
          ถึง ณ จุดนี้แล้ว อย่างน้อยความฝันอันเเรกก็สำเร็จไปเรียบร้อยคือ Java Programmer
          ตามที่เราฝันไว้
          ความฝันอันที่สองคือ การมีกิจการเป็นของตนเอง แน่นอนว่าการจะทำได้นั้นต้องมีความพร้อม
          พอสมควร ต้องมีความรู้ ประสบการณ์ การเเก้ปัญหา การหาลูกค้า สุดท้ายแล้วก็ได้เจอกับคนๆหนึ่ง
          ก็ได้ความร่วมมือช่วยเหลือจากพี่เค้าอย่างดีเยี่ยมและเราก็จะทำกิจการร่วม แน่น่อนว่าการทำอะไรร่วม
          กันอย่างน้อย เราต้องไว้ใจหุ้นส่วนของเราด้วย เเต่เราเหมือนจะยังมีภาระอยู่มากหลายเรื่อง แน่นอนแล้ว
          ตอนนี้ถอยไม่ได้ ถ้าเริ่มเมื่อไหร่ก็จะเต็มที่กับมัน งดรับงานนอก(แล้วตังจะพอใช้เหรอเนี่ย 555+)
          ฉะนั้นจะทำอะไรควรคิดให้ ปรึกษาพ่อเเม่บ้างนะครับ

          Thursday, February 25, 2010

          C# เเปลงค่าเงินให้เป็นตัวหนังสือ



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

          public static string ConvertMoneyToThaiText(string monery)
          {
          int dotIndex = monery.IndexOf('.');
          string integer = "";
          string point = "";
          if (dotIndex > 0)
          {
          integer = monery.Substring(0, dotIndex);
          point = monery.Substring(dotIndex + 1);
          }
          else
          {
          integer = monery;
          }
          string valDecimal = GetMoneyText(integer);
          valDecimal += "บาท";
          if (string.IsNullOrEmpty(point) == false)
          {
          valDecimal += GetMoneyText(point) + "สตางค์";
          }
          return valDecimal;

          }

          อันนี้ส่วนที่สองครับ

          private static string GetMoneyText(string monery)
          {
          int length = monery.Length;

          string value = "";
          string result = "";
          string numText = "";
          string currPosition = "";
          string valOfPosition = "";

          for (int i = 0; i < length; i++)
          {
          currPosition = monery.Substring(i, 1);
          valOfPosition = monery.Substring(i, monery.Length - i);
          int num = Int32.Parse(currPosition);
          if (num != 0)
          {
          numText = GetNumText(num);
          value = GetValue(valOfPosition.Length);
          if (valOfPosition.Length == 2)
          {
          numText = "ยี่";
          }
          }
          result += numText + value;
          numText = "";
          value = "";
          }
          return result;
          }

          อันนี้ส่วนที่สามครับ

          private static string GetNumText(int num)
          {
          switch (num)
          {
          case 1:
          return "หนึ่ง";
          case 2:
          return "สอง";
          case 3:
          return "สาม";
          case 4:
          return "สี่";
          case 5:
          return "ห้า";
          case 6:
          return "หก";
          case 7:
          return "เจ็ด";
          case 8:
          return "เเปด";
          case 9:
          return "เก้า";
          case 0:
          return "ศูนย์";
          default:
          return "";
          }
          }

          อันนี้ส่วนที่สี่ครับ

          private static string GetValue(int length)
          {
          switch (length)
          {
          case 2:
          return "สิบ";
          case 3:
          return "ร้อย";
          case 4:
          return "พัน";
          case 5:
          return "หมื่น";
          case 6:
          return "แสน";
          case 7:
          return "ล้าน";
          case 8:
          return "สิบล้าน";
          case 9:
          return "ร้อยล้าน";
          case 10:
          returnjavascript:void(0) "พันล้าน";
          case 11:
          return "หมื่นล้าน";
          case 12:
          return "แสนล้าน";
          case 13:
          return "ล้านล้าน";
          default:
          return "";
          }
          }

          เป็นอันเสร็จเรียบร้อยลองรันดูผลที่ได้คือ

          Thursday, February 18, 2010

          การ Seriaize Object ด้วย Java

          ในทางคอมพิวเตอร์นั้นเราสามารถที่เขียน Object ลงไฟล์แล้ว
          อ่านกลับมาเป็น Object ได้ไม่ว่าจะ .Net หรือ Java
          ลองมาดูตัวอย่างภาษาจาวาเเบบง่ายกันครับ

          private void writeCurrentDir(PreviousDirectory prevDir) throws Exception {

          FileOutputStream fos = null;
          ObjectOutputStream out = null;
          try {
          log.debug("Start write object PreviousDirectory to file");
          fos = new FileOutputStream(filename);
          out = new ObjectOutputStream(fos);
          out.writeObject(prevDir);
          out.close();
          log.debug("Write object PreviousDirectory to file success!");
          } catch (IOException ex) {
          log.error(ex);
          throw new Exception(ex);
          }
          }

          สำหรับการอ่าน

          private PreviousDirectory getPreviousDir() {

          FileInputStream fis = null;
          ObjectInputStream in = null;
          PreviousDirectory prevDir = null;
          try {
          log.debug("Start read file to object PreviousDirectory");
          fis = new FileInputStream(filename);
          in = new ObjectInputStream(fis);
          prevDir = (PreviousDirectory) in.readObject();
          in.close();
          log.debug("Read file to object PreviousDirectory success!");
          } catch (IOException ex) {
          //ignore
          return null;
          } catch (ClassNotFoundException ex) {
          //ignore
          return null;
          }
          return prevDir;
          }

          Tuesday, February 16, 2010

          cmdHere


          เราคงเลยจะทำอะไรบ้างอย่างกับ current folder โดยใช้ command line ผ่าน
          MS-Dos แล้วต้องเปิดไล่มาตั้งแต่ home current user กันใช่ใหมครับ แต่ Microsoft
          ได้ทำโปรเเกรมพวก Power Toys for windows คือพวกโปรเเกรมที่เป็น Utility ของ
          Windows ต่างๆ นั้นแหละครับและตัว cmdHere ก็เป็นหนึ่งในนั้นครับ ทำให้การทำงานง่ายยิ่งขึ้น

          ลองโหลดมาเล่นกันดูนะครับ Microsoft PowerTroys

          CruiseControl

          CruiseControl เป็น CI ต้วนึ่งที่นิยมใช้กันอย่างเเพร่หลาย ไม่ว่าจะเป็นโปรเจ็คที่พัฒนาด้วย Java , .Net
          ซึ่ง Cruisecontrol นั้นถูกเขียนขึ้นด้วย Java การ config นั้นก็สามารถทำได้ง่ายและเชื่อมต่อกับเครื่องมือที่นิยม
          ใช้กันในปัจจุบัน ไม่ว่าจะเป็น Maven , Ant , CVS,SubVersion,Git อื่นๆ อีกมากมายและยัง support dashboard
          สำหรับตัวอย่างการ config ดูได้จาก ที่นี้ ครับ