Firefox 3.5 [Officeial] & 10 new Features

หลังจากที่ออกรุ่น RC มาถึง 3 รุ่นแล้ว(คาดว่าหลายคนคงจะโหลดมาใช้กันแล้ว) ทาง Mozilla ก็ปล่อย Firefox 3.5 ตัวเต็มออกมาเสียที...

ทีนี้ เรามาดูกันดีกว่าว่า Firefox 3.5 นี้ มีอะไรที่เปลี่ยนไปบ้าง..

  1. Undo closed window


    หลายคนคงจะติดใจกัน Undo Closed Tab กันมาแล้ว(ผมก็คนนึงหละ.. 555) ทีนี้ ถ้าเผลอปิดทั้ง Windows หละ... Firefox แก้ให้ครับ ตอนนี้สามารถ restore เจ้า tab ที่ถูกปิดไปได้แล้วนะครับ
  2. Forget this site


     ก็คือ สามารถลบข้อมูลการเข้าของเว็บที่ต้องการได้ทั้งหมด ทั้ง History, Cookie หรือ อื่นๆ ที่ทำให้คนอื่นรู้ได้ว่า เราเคยเข้าเว็บนี้ อันนี้ หลายคนคงจะชอบ (555 รู้นะคิดอะไรอยู่) แต่ข้อเสียนิดหน่อย คือ มันยังไม่ฉลาดพอที่จะลบ Sub Domain ดังนั้นก็ระวังกันด้วยนะ (อิอิ)
  3. Tab Tearing
    หลายคนที่ใช้ Google Chrome ก็คงจะคุ้นเคยกับเจ้า Feature ตัวนี้นะครับ ก็คือ สามารถดึง Tab ออกมาเป็น Window ใหม่อีกตัวเลยนะครับ สะดวกไปอีกแบบ :3
  4. Keyword smart filters


    ผมว่าระบบเดิมมันก็ทำงานได้ดี ตอนนี้ระบบ Fillter คำใน URL จะฉลาดขึ้นครับ โดยจะดึงข้อมูลจาก History, Bookmark, Tags และ URL รวมทั้งยังตัด ข้อมุลที่ไม่ได้ถูกใช้ ออกไปอีกด้วย นอกจากนั้น ยังมีลูกเล่นคือ.. สมมุติ ผมใส่ "Hara *"ลงไปใน URL ระบบจะค้นหาจาก Bookmark หรือ "Theblogfor +" จะหาจาก Tag ครับ

  5. Smarter session restore


    เคยเจอไหม ถ้าคุณกำลังพิพม์ข้อมูลก่อนทำการส่งไปให้ server แล้ว Firefox เกิด Crash ก็ต้องกลับมานั่งพิพม์ใหม่ ทางทีมพัฒนารู้ดีครับ จริงทำ Feature นี้ออกมา เพราะนอกจากเราจะ Restore Page หน้านั้นได้แล้ว เรายัง restore session กลับมาได้อีกด้วย (ชอบจริงๆ :3)
  6. private browsing mode


    พูดง่ายก็คือ "โหมดไร้ร่องรอย" คือ ถ้าหากเราไปยืมเครื่องคนอื่น เช็คเมลล์ หรือ ทำธุระ ทางการเงิน หรือสิ่งที่เป็น เรื่องส่วนตัว, สำคัญ เราก็สามารถใช้ Mode นี้ได้นะครับ เพราะน้อง Cookies ก็จะไม่มาให้กวนใจเลย ^^
  7. Color profiles that pop


    รุ่นนี้ ได้ปรับ Profiles ของการเข้ารหัสสีใหม่นะครับ เรียกง่ายๆ ก็คือ เราจะได้เห็นสีที่เป็นจริงมากขึ้นครับ และสีจะสดกว่ารุ่นก่อน (ส่วนตัว ผมก็แยกไม่ค่อยออกนะครับว่าต่างกันอย่างไร? ถ้าไม่ดูเปรียบเทียบ)
  8. TraceMonkey JavaScript engine



    หลังจากที่รุ่นก่อน (Firefox 3.0) ได้ใช้ Engine: SpiderMonkey ในการเรียนใช้ JavaScript (แต่ผลที่ได้คือ ช้า อืด แฮ้งค์) ทาง Developer ก็เลยพัฒนาตัวใหม่ในการเรียกใช้ JavaScript ใหม่ชื่อ TraceMonkey ซึ่งเค้าว่ากันว่า เร็วกว่า 20 ถึง 30 เท่าเลยทีเดียว
  9. Geo-location

    โหมดนี้เป็นประโยชน์ให้คนที่อยู่ใน USA แต่ผมก็ไม่มั่นใจว่า ประเทศไทยจะได้ใช้ไหม? ก็คือ มันจะตรวจสอบ สถานที่ที่เราอยู่โดย IP address สมมุติ ผม Search "ธนาคาร" มันจะทำงานคู่กับ Search engine ว่าธนาคารไหนที่อยู่ใกล้เราบ้าง
  10. Video supperpowers with HTML5

    นี่เป็น Feature ที่ผมชอบอีกFeature หนึ่งครับ คือ เราสามารถ ย่อ หด ขยาย ขนาดวีดีโอเอาได้ หรือไม่ก็ สามารถซูมเวลาเรียกวีดีโอเราจากหน้าเว้บได้ โดยไม่ต้องพึ่ง Add-on หรือ ตัวช่วยอื่นใด

 

สุดท้าย ขอขอบคุณภาพ และเนื้อหาจาก lifehacker  และ Blognone

พร้อมแล้วเราก็โหลดกันเลย Firefox Thai   Firefox ENG

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (9) | RSS


Scripty2 !!!

A new javascript API has lauched a while ago named "Scripty2". Note that it's now an alpha version .Scripty2 is based on Scriptaculous (a refinement of the visual effects framework of script.aculo.us 1.X.) and Prototype frameworks. The site does not provides much information about their products. So ,if you are now a big fan of Scriptaculous ,you must be fun with the demo that's built from this API. 

Here for the link : http://scripty2.com/demos/cards/ and http://scripty2.com/demos/puzzle/

This API is well-developed with CSS ,for example ,CSS morphing engine,CSS parsing,color normalization and tweening.

  • scripty2 core - Core contains various JavaScript and DOM extensions used by scripty2 fx and scripty2 ui, plus developer utility classes.
  • scripty2 fx - The scripty2 effects framework provides for time-based transformations of DOM elements and arbitrary JavaScript objects. This is at the core of scripty2 and presents a refinement of the visual effects framework of script.aculo.us 1.X.
  • scripty2 ui - s2.css: functions for CSS parsing, color normalization and CSS value interpolation.

For a full documentation : http://scripty2.com/doc/

I haven't play with this yet. If you try something on it ,you can share your thinking here..

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (3) | RSS


Find Direction From Your home to AnyWhere? Put in action

Now we've learned how to put google map into your website. Next big step is how to use Google API efficiently. In this example, i'm going to show you guys how to find direction, show it on map and literary detail about how to get to that position.

Our scenario is : I want to find the way from my home(fake location of cos lol) to Salaya, Central Pinkrao And Siam Centre.

1. From last example see it here or you can find example code and view it source.

2. Let's edit it a little bit. Put new Table. Then put 3 button, new div Tag called "detail".

<table style="width:100%;"> 
<tr>
<td width="800"> 
<input type="button" value="Salaya, Mahidol" /> : <input type="button" value="Central Pinkrao" /> : <input type="button" value="Siam Center" />
</td>
<td>&nbsp;</td> 
<tr> 
<td width="800"> 
<div id="mapCanvas" style="width: 800; height: 600"></div> 
</td> 
<td> 
<div id="detail"></div></td> 
</tr></tr> 
</table> 

I'll give action of these three buttons later.

3. Edit javascript as the example. Put map and direction as global variable. Then add new object called direction = new GDirections(map, detail); To set map path to div called "map", and Detail in div Called "detail".

1 <script language="javascript">
2 var map, direction;
3 function initialize() {
4 map = new GMap2(document.getElementById("mapCanvas"));
5 map.setCenter(new GLatLng(13.734132, 100.411992), 13);
6 map.setUIToDefault(); 7 direction = new GDirections(map, detail);
8 }
9 </script>
4. Now, put new function to control the map. I'll add setLocation() that take an integer as argument, it's used to indicate destination. add following function to your javascript part.
1 function setLocation(x) {
2 direction.clear();
3 var str = "from:13.715539,100.408602 to:";
4 if (x == 1) str += "13.793635,100.326054";
5 else if (x == 2) str += "13.778776,100.47658";
6 else str += "13.747014,100.53443"; 7 direction.load(str);
8 }
notice that i clear the Direction drawed on map first. Then i called method load that take str as argument. str is called query word which must be understood by google API. You can put it in form of "from:" and "to:" follow by other query word such as "New York"(name of places in Thailand usually not working with query, so i put lat and long instead).
5. i modified the buttons to let it pass argument to invoke setLocation(x) as following
<input type="button" onclick="setLocation(1)" value="Salaya, Mahidol" /> : <input type="button" onclick="setLocation(2)" value="Central Pinkrao" /> : <input type="button" onclick="setLocation(3)" value="Siam Center" />

6. Compare your result with this

Wow!!! If you like this one or if you have any question, leave your comment. Thank you! i hope that i'll update this one again soon! haha

Categories:   AJAX Technology | Javascript
Actions:   E-mail | del.icio.us | Permalink | Comments (4) | RSS


มาดูราคา Windows 7 กัน

หลังจากหายไปจากบล๊อกนาน(ขอโทษคร้าบบ ไม่ว่างเขียนเลยอะ ><'") งั้นขอเริ่มกันเลยละกัน

หลังจากที่ Microsoft ได้ประกาศวันที่จะเริ่มจำหน่าย Windows 7 (22.10.09)  เมื่อวาน (25.06.09) ทาง Microsoft ได้เปิดเผยว่า จะเริ่มให้ลูกค้าที่สนใจ สั่งจอง Windows 7 ผ่านทางเว็บ โดยผู้ที่จองจะได้รับสิทธิพิเศษคือ จะสามารถซื้อ Windows ได้ในราคาเพียง 50% ของราคาเต็ม(หรือได้ราคาต่ำกว่านี้)

 

 ที่นี้ มาว่าเรื่องราคากันต่อดีกว่า ราคาของ Windows 7 รุ่นต่างๆมีดังนี้

สำหรับท่านที่ต้องการ UPDATE จาก Window รุ่นอื่นเป็น Window 7 [US area]

  • Windows 7 Home Premium (Upgrade): $119.99 หรือประมาณ 4110บาท
  • Windows 7 Professional (Upgrade): $199.99 หรือประมาณ 6799 บาท
  • Windows 7 Ultimate (Upgrade): $219.99 หรือประมาณ 7699 บาท

ทีนี้มาดูราคาสำหรับซื้อปกติครับ 

  • Windows 7 Home Premium (Full): $199.99 หรือประมาณ 6799 บาท
  • Windows 7 Professional (Full): $299.99 หรือประมาณ 10499 บาท
  • Windows 7 Ultimate (Full): $319.99 หรือประมาณ 11199 บาท 
และที่สำคัญ สำหรับผู้ที่ซื้อ PC พร้อม Windows Vista ทุกรุ่น (OEM) ตั้งแต่วันศุกร์นี้เป็นต้นไป จะได้รับสิทธิ์ในการอับเกรดเป็น Window 7 ฟรีครับ
 
ปล. แต่สมาชิก MSP [ มาที่นี่เลย! ]ก็คงไม่ต้อง Worry อะไรมากมาย ซึ่ง ถ้าได้เมื่อไรจะอัปเดทให้ทราบทันทีจ้า
ที่มา: windowsteamblog    arip

 

Categories:   News
Actions:   E-mail | del.icio.us | Permalink | Comments (11) | RSS


Entity Life Cycle and Handling Concurrency in LINQ to SQL

LINQ to SQL is not limited itself only for mapping objects and relational data. It also plays an important roles for managing the entity life cycle ,that is tracking change for each entity by service tracking ,and handle when there are conflicts. Today we gonna learn more in this features LINQ to SQL provides.

When you query some values from the database (with DataContext) ,at that time before giving those values's object to application code to consume ,DataContext will retain a referrence to the object. Therefore ,DataContext can refer back to that object and track it by the identity management service. If two queries want to retrieve the same value from the database ,the second query will get the object that's returned by the first query from the cache rather than remapping with SQL database again this is one crucial task of DataContext. When that object is queried there's no saving the data back to the database until we issue the command "SubmitChanges" to save that data. You must know that there are the data in memory and the data in the database and they're seperated.

If I create two DataContexts(context1,context2) then I submit changes on context1 ,context1 will commit the chages to the database and its service tracking will be flushed and it'll use the newly changed value. But for context2 ,it retains to use its old value from its service tracking because its service tracking's not flushed as same as the context1s'.

TestLINQToSQLDataContext context1 = new TestLINQToSQLDataContext();
            TestLINQToSQLDataContext context2 = new TestLINQToSQLDataContext();

            Console.WriteLine("Before SubmitChanges");
            Console.WriteLine(context1.Teachers.SingleOrDefault().Name);
            Console.WriteLine(context2.Teachers.SingleOrDefault().Name);

            //change the value and submit change via context1
            Teacher teacher = context1.Teachers.SingleOrDefault();
            teacher.Name = "Dr.Ochin";
            context1.SubmitChanges();

            Console.WriteLine("After SubmitChanges");
            Console.WriteLine(context1.Teachers.SingleOrDefault().Name);
            Console.WriteLine(context2.Teachers.SingleOrDefault().Name);

Because DataContext makes use of optimistic concurrency principle(it's not serialize and lock the occupied data) ,so that can bring on some conflicts when the same object identity is modified by more than two people. DataContext must have a way to control the degree of conflict detection by setting the "UpdataCheck" value of each column which has 3 properties : "Always" ,"Never" ,"WhenChanged". "Always" means that LINQ to SQL always checks that column whether or not its actual value's been changed that means the column's name will always appear in WHERE clause of a SQL UPDATE statement generated by LINQ to query the database(to check if that column is changed). For example ,if I set "Always" to "Name" column ,this query will have this "Name" in WHERE clause everytime when submitting changes : UPDATE SET .... FROM ... WHERE ... Name=@p4 ... .If we're sure which columns don't need to participate in WHERE clause ,we can exclude it by setting "UpdateCheck" to "Never". For the "WhenChanged" property ,imagine that two users simultaneously want to update on the same table but on different columns (if using "Always", there'll be a conflict) ,thus your choice'll be "WhenChanged". But again that is not the best choice ,especially when you have a "derived field" (field that its value is calculated from other fields) e.g. Mr.Suppy is trying to update the price field of the product A while Mr.Ochin is changing its quantity field ,the "TotalPrice" field might not be correct.

Ok let's move ahead and see how we can manage if there're concurrency conflicts occurred between 2 users. In that case ,DataContext will raise "ChangeConflictException" if the second user tries to submit changes. In fact ,you can simply just specify "ConflictMode" ,which has two options ConflictMode.ContinueOnConflict and ConflictMode.FailOnFirstConflict(stop evaluating further) ,and "RefreshMode" to handle the problem. I've created simple scenarios for you to understand. Note that sometimes when conflict occurs there're 3 values you must consider : original value(which is cached in its DataContext at the early time) ,changed value(the new value we've changed) ,current database value(actual value stored in database).

TestLINQToSQLDataContext context1 = new TestLINQToSQLDataContext();
            TestLINQToSQLDataContext context2 = new TestLINQToSQLDataContext();

            Console.WriteLine("Before SubmitChanges");
            Teacher t1 = context1.Teachers.SingleOrDefault();
            Console.WriteLine(t1.Name+" || "+t1.School+" || "+t1.Subject);
            Teacher t2 = context2.Teachers.SingleOrDefault();
            Console.WriteLine(t2.Name + " || " + t2.School + " || " + t2.Subject);

            //the current teacher's name in database is "Dr.Database","DatabaseSchool","Database Management" respectively
            t1.Name = "Dr.Context1";
            t1.Subject = "Context1 Subject";
            t2.Name = "Dr.Context2";
            t2.School = "Context2 School";
            //just submit the value to the database for context1 first.
            context1.SubmitChanges();
            //try to submit by context2 with ConflictMode
            try
            {
                context2.SubmitChanges(ConflictMode.ContinueOnConflict);    //conflict occurs!!!
            }
            catch(ChangeConflictException)
            {
                context2.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
                context2.SubmitChanges();
            }

            Console.WriteLine("After SubmitChanges");
            Console.WriteLine(t1.Name + " || " + t1.School + " || " + t1.Subject);
            Console.WriteLine(t2.Name + " || " + t2.School + " || " + t2.Subject);

The first example one is for RefreshMode.KeepChanges : (from MSDN)Forces the Refresh method to keep the current value that has been changed, but updates the other values with the database values.

The output is as we've expected. The others 2 ConflictMode are RefreshMode.KeepCurrentValues : Forces the Refresh method to swap the original value with the values retrieved from the database. No current value is modified.

 

And RefreshMode.OverwriteCurrentValues : Forces the Refresh method to override all the current values with the values from the database.

"ChangeConflictException" isn't only that useful but it can tell you what are the names of table and column that's occurred the conflicts and show the comparison between the original value and the value to be change as the code suggests below.

catch(ChangeConflictException)
            {
                context2.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges);
                GridView1.DataSource = 
                    from conflict in context2.ChangeConflicts
                    from member in conflict.MemberConflicts
                    select new {
                        MemberName = member.Member.Name,
                        ChangedValue = member.CurrentValue.ToString(),
                        OriginalValue = member.OriginalValue.ToString(),
                        DatabaseValue = member.DatabaseValue
                    };
                GridView1.DataBind();
            }

Using the same scenario as above ,we'll get this result and we'll know that which fields and values cause the problem. You can apply this code to match your need.

What if we don't want those three default RefreshModes or we don't want to change anything when conflict occurs ,we want to roll it back! One of the popular solutions is using System.Transactions.TransactionScope that comes with ASP.NET 2.0. The most awesome thing about this transaction scope is it can scope the transaction to match with the object that requires it. If there's multiple connections or DataContext objects ,it'll span its transaction scope. Another thing is you don't need to catch its exception and type "Rollback" manually ,it'll do that for you.

For the transaction scope ,if the Complete() method is called that means it reaches the checkpoint and you cannot roll back anymore but if conflict happens ,the Complete() method'll be bypassed. I'll show how to write the transaction scope below and with this thing ,my database'll be rolled back to its original value.

using (System.Transactions.TransactionScope ts = new System.Transactions.TransactionScope())
            {
                try
                {
                    context1.SubmitChanges();

//conflict'll occur here and it'll roll back as if nothing happened.. context2.SubmitChanges(ConflictMode.ContinueOnConflict); ts.Complete(); } catch (ChangeConflictException) { context2.ChangeConflicts.ResolveAll(RefreshMode.KeepChanges); GridView1.DataSource = from conflict in context2.ChangeConflicts from member in conflict.MemberConflicts select new { MemberName = member.Member.Name, ChangedValue = member.CurrentValue.ToString(), OriginalValue = member.OriginalValue.ToString(), DatabaseValue = member.DatabaseValue }; GridView1.DataBind(); } }

This code provided here is not a good solution because you should avoid using multiple database connections in one transaction scope ,it creates overhead and it's not recommended but just for me to show you that we can do like this and can also roll back them all. If you have the problem that you cannot use multiple connections in transcation scope ,i.e. MSDTC on server 'XXXXXX' is unavailable. You have to start the service called "Distributed Transaction Coordinator" to enable using MSDTC first in Control Panel > Adminitrative Tools > Services. And again it's not recommended when using in a real world application.

Transaction scope can be used with StoreProcedure as well,see more : http://msdn.microsoft.com/en-us/library/bb425822.aspx#linqtosql_topic20

Enough for today!! I'll continue next with one remaining topic : When you work with disconnected data. Thanks for reading...

Categories:   .NET ASP.NET C# | Tip(s)
Actions:   E-mail | del.icio.us | Permalink | Comments (15) | RSS


 

Tag Cloud