Confirmed: Google is able to execute and index JavaScript

Quote

1. Ran a series of tests that verified Google is able to execute and index JavaScript with a multitude of implementations. Confirmed Google is able to render the entire page and read the DOM, thereby indexing dynamically generated content.

2. SEO signals in the DOM (page titles, meta descriptions, canonical tags, meta robots tags, etc.) are respected. Content dynamically inserted in the DOM is also crawlable and indexable. Furthermore, in certain cases, the DOM signals may even take precedence over contradictory statements in HTML source code. This will need more work, but was the case for several of our tests.

 

Read more here: http://searchengineland.com/tested-googlebot-crawls-javascript-heres-learned-220157

How to close duplicated tabs in your Chrome browser

Open a New Tab
Press F12 to open Web Developer Tool
Open Console tab
Paste these code, and press ENTER to run:

chrome.tabs.query({}, function(tabs) {
    var firstSee = [];
    for (var i = 0; i < tabs.length; i++) {
        var url = tabs[i].url;
        var id = tabs[i].id;
        if (firstSee.indexOf(url) >= 0){
            chrome.tabs.remove(id);
        } else{
            firstSee.push(url);
        }
    }
})

Bonus: you can create a Bookmarklet to do it:

javascript:chrome.tabs.query({}, function(tabs) {var firstSee = [];for (var i = 0; i < tabs.length; i++) {var url = tabs[i].url;var id = tabs[i].id;if (firstSee.indexOf(url) >= 0){chrome.tabs.remove(id);} else{firstSee.push(url);}}})

Then open a New Tab, click that Bookmarklet. Done!

FASTFOOD: Use relative font-sizing for responsive web design

When developing with Responsive web design (RWD), you should use these CSS3 feature

  • reset padding, margin of body and container element. Set max-width to have no horizontal scrollbar.
  • set font-size for your body
  • use relative font-sizing unit
    • VERY IMPORTANT: use rem (relative to root element). Note: em is relative to parent element, so it is difficult to debug sizes on complex pages. With rem, we are always have font-size-relate-to root (e.g.: your body)
    • use vh, vw, vmin for sizing your box
    • 1vw is 1% of the viewport width, 100vw = 100% viewport width
    • 1vh is 1% of the viewport height, 100vh = 100% viewport height
    • 1vmin is the smallest of 1vw and 1vh

See more here

FASTFOOD: 2013 sẽ là năm cất cánh cho web

Vì sao?

Một số công nghệ web đã trưởng thành và sẽ được triển khai trên nhiều trang web, mang lại nhiều ấn tượng cho user, giảm công sức cho lập trình viên khi phát triển và phân phối ứng dụng

CSS filters, mang sức mạnh đồ hoạ 3D

Cho phép thực hiện nhiều hiệu ứng đồ hoạ phức tạp (làm mờ, đổ bóng, bóp mép, đổi hình dạng của đối tượng, thay đổi mật độ màu, …) bằng các khai báo đơn giản.

Cho phép thực hiện các thao tác đồ hoạ phức tạp như đổ bóng vertex (như dùng GLSL, được ứng dụng phổ biến nhiều năm nay trong các xử lý đồ hoạ 3D)

Xem ví dụ tại CSS Filter

Lợi ích lớn cho các game nền web, các ứng dụng cần những hiệu ứng gây shock về đồ hoạ, xử lý ảnh

 

Google Chrome Apps

Google ko đối đầu trực tiếp với Windows, Mac, Linux, mà họ tạo ra Chrome,  cố gắng làm cho Chrome có mặt tại nhiều nơi, nhiều thiết bị như TV, laptop, điện thoại

Với Chrome, Google mang lại cho các lập trình viên khả năng viết chương trình bằng JS HTML CSS (là đơn giản hơn nhiều so với việc viết bằng C# Java PHP), chạy chương trình trong Chrome.

  • Phát triển nhanh chóng, thuận tiện
  • Rất dễ phân phối (vì có WebStore)
  • Có nhiều khả năng tương tác phần cứng (cổng serial, usb, bluetooth, webcam, mic, loa, âm thanh, …)
  • Vẽ thêm “cánh” (tương tác, tính năng) cho  ”hổ” (các trang web sẵn có)

Hiện tại, viết extension/app cho Chrome là dễ nhất, nhanh nhất và thuận tiện nhất (so với việc viết cho Firefox, IE, Opera)


ECMAScript 6, cải tiến Javascript

ECMAScript 6 (ES6), là cải tiến của JavaScript, sửa các vấn đề “chíu khọ” trong ngôn ngữ JavaScript, cung cấp tính năng mới thuận tiện hơn, dễ bảo trì mã nguồn hơn.

  • thêm class, kế thừa, mixins (lai ghép, tương tự như đa kế thừa trong C++)
  • Hệ thống tải/nạp module (giúp tổ chức mã nguồn gọn gàng, nhanh, dễ quản lý hơn)
  • proxies
  • cải tiến việc gọi hàm bất đồng bộ (asynchronous), vứt bỏ sự rối rắm của các hàm callback

Web Components

Web Components cho ta khả năng thêm tag mới cho trình duyệt, tương tự như những tag gốc sẵn có. VD:

  • Tạo ra thẻ mới (VD mydiv)
  • Tạo style và tính năng cho thẻ đó
  • người dùng khác chỉ cần khai báo thẻ, tương tự như thẻ gốc (div)

Web Components sẽ thay đổi cách viết, sử dụng và phân phối các thư viện JavaScript hiện có theo hướng dễ dàng hơn nhiều.

Tương lai

Các tính năng mới, API mới sẽ được (tự động) đưa vào trình duyệt mới ngày càng nhanh hơn

  • Vì phần lớn các trình duyệt sẽ tự động cập nhật phiên bản mới
  • Với Chrome, cứ 4 tháng là sẽ có một bản mới sẽ được đưa tới 350 triệu người dùng
  • Thị phần của các trình duyệt Webkit đủ lớn, để các trình duyệt khác (như IE, Opera, Firefox) phải chạy theo và đưa tính năng tương đương vào.

Run Dropbox as Service on Windows 2008 Win 7

– Remote desktop to your server (e.g.: with username = YourUserLockeVN)

– On server, download dropbox.exe to C:\
– Start command prompt (with “YourUserLockeVN” please, the idea is dropbox will be installed under this account credential and its role/right)
– Install dropbox by command prompt:

"C:\dropbox.exe" /D=C:\Program Files\Dropbox

– Run through DropBox setup, login to dropbox, use advanced install, determine local folder for sync, …
– (very important) Start Dropbox, Preferences -> uncheck “Show desktop notifications” and “Start Dropbox on system startup
– Exit dropbox (right click tray icon, Exit)
– Check StartMenu/Startup folder, remove the Dropbox shortcut (if any)
– Download Windows Server 2003 Resource Kit Files (Win2003, 2008 can use)
– Install it into your server (don’t worry about conflict, they are all M$ stuff, and they just extracts to folder)
– on command prompt, create Service by:

"C:\Program Files (x86)\Windows Resource Kits\Tools\instsrv" DropBoxService "C:\Program Files (x86)\Windows Resource Kits\Tools\srvany.exe"

– Start/Run, “Regedit”, go to

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\DropBoxService

– Create KEY Parameters
– Create String value name “Application“, value C:\Program Files\Dropbox\Dropbox.exe /home
– Create String value name “AppDirectory“, value C:\Program Files\Dropbox


– Go to Administration Tools / Services -> DropBoxService -> Properties -> Log on -> Use “YourUserLockeVN
– Change the service startup type to “Automatic
– Start service

That’s fine. Now you can logoff, disconnect from the server and Dropbox still up and running, sync your file.

Javascript sleep(), will block browser, block setTimeout either

I found this Javascript sleep function here and it works in FF9, Chrome 14 (tested).

function sleep(ms) {
 ms += new Date().getTime();
 while (new Date() < ms){}
}

This function will block browser from doing anything, even setTimeout()
E.g.:

/*BEGIN*/
setTimeout(alert('stupid'), 1000); 
sleep(2000); 
// after sleep completed, setTimeout has its turn to run. 
// The alert() will be shown after 3 seconds from /*BEGIN*/

This might be a stupid thing but sometimes you have to do stupid work and it’s required.

NodeJS quick sum up July 2011

This is my sum up about NodeJS on July 2011, base on some slides (of geeks in my list from BarCamp Saigon 2011). Just a fastfood of what NodeJS is, why is get buzz at the moment.

 

specs

  • JS and C++ code
    + and commonJS module mechanism 
    ——–> on NodeJS binding (http socket IO …)
    ——–>——–> on JS engine V8 + ThreadPool-libIO + EventLoop-libEV + …
  • programming style: evented with callback function, no thread
  • non blocking IO
  • DB support: mongodb couchdb mysql redis
  • package (module of NodeJS) is NPM (not available on Windows?)
  • IDE support: bad, no great debugger, can use cloud9 online IDE
  • hosting: joyent heroku cloudfoundry dotcloud

 

when to use it?

  • chat/messaging
  • real-time applications
  • intelligent proxies
  • high concurrency applications
  • communication hubs
  • coordinators

 

something bad

  • so young, immature
  • lots of stuffs to look at, must lookup API from internet, and remember yourself (function name, parameter, …)
  • retro compatibility, API is (frequently) subject to change
  • hard to find organized (and centralized) and authoritative information

Adding Client-Side Script Blocks with RegisterStartupScript() and RegisterClientScriptBlock()

The System.Web.UI.Page class contains two methods for emitting client-side script code into the HTML rendered by the ASP.NET Web page:

  • RegisterStartupScript(key, script)
  • RegisterClientScriptBlock(key, script)

Both of these methods take two strings as input. The second parameter, script, is the client-side script—including the opening and closing <script> tags—to insert into the page. The first parameter, key, serves as a unique identifier for the inserted client-side script.

The only difference between these two methods is where each one emits the script block. RegisterClientScriptBlock() emits the script block at the beginning of the Web Form (right after the <form runat="server"> tag), while RegisterStartupScript() emits the script block at the end of the Web Form (right before the </form> tag).

From http://msdn.microsoft.com/en-us/library/aa478975.aspx

jQuery animation queue, create DOM element and its properties, ajaxStart and ajaxStop events

animation queue

By default, animations are queued, but you can disable this by setting the queue property to false. Unqueued animations start immediately and subsequent queued animations are not deferred for unqueued animations.

$("img").fadeIn(500)
        .animate({"width":"+=100"},
                 {queue:false, duration:1000})
        .fadeOut(500);
  • The fadeIn() and fadeOut() effects are queued, but the call to animate() (which animates the width property for 1000ms) is not queued.
  • The width animation begins at the same time the fadeIn() effect begins. The fadeOut() effect begins as soon as the fadeIn() effect ends—it does not wait for the width animation to complete.

 

ajaxStart and ajaxStop events

  • When jQuery is not performing any Ajax requests and a new request is initiated, it fires an “ajaxStart” event.
  • If other requests begin before this first one ends, those new requests do not cause a new “ajaxStart” event.
  • The “ajaxStop” event is triggered when the last pending Ajax request is completed and jQuery is no longer performing any network activity.
  • These “ajaxStart” and “ajaxStop” event handlers can be bound to any document element: jQuery triggers them globally rather than on any one particular element.

 

DOM Element creating

You probably already know that you can pass a tagname to $() to create an element of that type, and that you can pass (as a second argument) an object of attributes to be set on the newly created element.

  • This second argument can be any object that you would pass to the attr() method,
  • but in addition, if any of the properties have the same name as the event registration methods, the property value is taken as a handler function and is registered as a handler for the named event type.
  • Similarly, if any of the properties has the name “css”, “val”, “html”, “text”, “data”, “width”, “height”, or “offset”, then the value of that property is passed to the method with the same name as the property.
var image = $("<img>", {
                  src: image_url,
                  alt: image_description,
                  className: "translucent_image",
                  click: function() {$(this).css("opacity", "50%");},
                  css: { border: "dotted red 3px" }
               });
 

Sum up from: http://answers.oreilly.com/topic/2353-5-things-you-might-not-know-about-jquery/

Take care of accessibility for web

This article is in my FASTFOOD series:

You Are Not The Default

Millions of people around the world have disabilities that hinges them from information.

If you care about a web truly accessible to people w/disabilities, follow @googleaccess team, on the forefront of alt access modes. They are active!

 

Use this site/tool to check your website

 

Read articles

http://www.1stwebdesigner.com/design/web-accessibility-guide-beginners/

http://www.google.com/accessibility/

 

CSS: inline-block for IE7

I was developing a DemoSite and have problem with IE7 (actually we’re only target IE8, but one of our module must run in IE8 emulate IE7 mode so a meta tag <meta http-equiv=”X-UA-Compatible” content=”IE=EmulateIE7″ /> is put in the header). While Firefox is my primary browser and it’s OK with display: inline-block CSS style, BUT IE7 (and IE8EmulateIE7) does not render it.

So this is the hack for IE7 (from http://grasshopperpebbles.com/css/css-inline-block-ie7-hack/):

HTML

<div class="predefinedList">
<div class="predefinedListItem">Cross country skiing</div>
<div class="predefinedListItem">Fine cuisine</div>
<div class="predefinedListItem">Spa</div>
</div>

Put your style settings to the top,
put display: inline-block;zoom:1;*display:inline; to the bottom.

CSS

.predefinedList .predefinedListItem {    padding:0;    /* other the styles should be here */
    display:inline-block;   /* for firefox */
    zoom: 1;    /* for IE7 hack */
    *display:inline;   /* for IE7 hack */
}

Configure XDebug with WAMP and NetBeans IDE 6.8 on Windows 7

This is step – by – step procedure (with sample):

  1. Install WAMP, default location is at c:\wamp
  2. Download latest release of xdebug for PHP version you are using.
    1. I use WampServer 2.0i [07/11/09] and it includes :
      – Apache 2.2.11
      – MySQL 5.1.36
      – PHP 5.3.0 ———> 5.3 is what we need
    2. write a phpinfo() to know what PHP compiled, Find “PHP Extension Build”  ———–>   API20090626,TS, VC6 is what we need
    3. I use Windows 7 64bit, there is nothing 64bit at XDebug (at the moment Apr 2010)  —–> so this is not important
    4. After all, this is what we should download from Xdebug: 5.3 VC6 (32 bit)   ———-> we have php_xdebug-2.0.5-5.3-vc6.dll
  3. Copy php_xdebug-2.0.5-5.3-vc6.dll file into php’s extension directory, it is c:\wamp\php\ext
  4. Now open php.ini (click WAMP tray icon, PHP/php.ini), we need to configure xdebug so that it get recognized by PHP
  5. Add following at the end of your php.ini
  6. [xdebug]
    zend_extension_ts="c:/wamp/php/ext/
    php_xdebug-2.0.5-5.3-vc6.dll"
    xdebug.profiler_output_dir = "c:/wamp/tmp/xdebug"
    xdebug.profiler_output_name = "cachegrind.out.%p"
    xdebug.profiler_enable = 0
    xdebug.profiler_append=0
    xdebug.extended_info=1
    xdebug.remote_enable=1
    xdebug.remote_handler=dbgp
    xdebug.remote_mode=req
    xdebug.remote_host=127.0.0.1
    xdebug.remote_port=9000
    xdebug.idekey=xdebug
    xdebug.remote_log="c:/wamp/tmp/xdebug/xdebug_remot.log"
    xdebug.show_exception_trace=0
    xdebug.show_local_vars=9
    xdebug.show_mem_delta=0
    xdebug.trace_format=0

  7. Just create   c:\wamp\tmp\xdebug folder.
  8. Finally restart Apache service .
  9. Now you can write PHP code and debug with NetBeans

Why Google Buzz will Succeed – Vì sao Google Buzz sẽ được dùng nhiều

Buzz is more “seem-to-be-right” than Wave.

MOST important: Use Buzz in Gmail, an everyday-should-open-address.

Buzz and Wave are different services, carry different objectives of Google, Twitter copycat vs. real-time collaborations. Big problem of Wave is that it wasn’t integrated into Gmail, so I have to open new tab in browser, type new strange address and hit enter, what I don’t like.

Every Google’s user has Gmail along with its address book, and Gmail is a place for people to COMPOSE something (write mail, chat, …), others are READ-oriented services. Whenever I want to share or talk or collaborate (using Google service), I type “gmail”, [enter]

And the other things that I think Buzz will be OK are:

  1. Buzz uses Gmail address book, no need to invite or do some strange tasks and wait like Wave
  2. Buzz is so simple, everyone can click “Allow” to Google pop-out message, and then buzz. It’s also simple enough to integrated to mobile software immediately
  3. Fill the gap between Twitter and Facebook, has comment –> conversation thread, and lack of spam Friend4Sale, Farm, Genie …
  4. A lot of content when user start to use. Buzz united Google Services’ activities of user. Upload a photo, read an article, … friends will know and converse. After import tweets, Buzz account virtually has a lot of status, so people has story to comment

Get siteId of EPiServer site in code

From EPiServer 7.1 and below, read at


EPiServer.Framework.Initialization.SiteMappingConfiguration.Instance.SiteId
(this is a string)

reference your project to EPiServer.Framework.dll

From EPiServer 7.5, you should use

EPiServer.Web.SiteDefinition.CurrentOrDefault.Id (Guid type)

reference your project to EPiServer.dll

EPiServer tuyển người – Hà Nội

EPiServer is the world’s fastest growing provider of Web Content Management (WCM) and online social community platforms. Over 3000 customers worldwide use EPiServer CMS to create collaborative, engaging and attractive websites. The platform EPiServer CMS is the foundation of more than 9000 websites and is used on a daily basis by over 130,000 web editors. It enables true web engagement which allows customers to turn passive web visits into dynamic, personalized web experiences that drive new revenues. EPiServer delivers its WCM platform through a network of more than 340 competent partner companies in 25 countries.

Founded in 1994, the company has offices in the USA, Sweden Denmark, Norway, Finland, the Netherlands, Australia, South Africa and the UK.

http://www.episerver.com

Attached to this mail you will find five different profiles,

  • Profile Software Test Automation Engineer
  • Profile Software Tester
  • Profile Web Designer, User Interaction Designer
  • Profile Web User Interface Developer
  • Profile Product Support Developer

As the Development Manager coming to Hanoi on the January the 22 it is important for candidates to apply ASAP.

Send your CV to pelle[dot]niklasson[at]episerver.com

Quick sample: EPiServer Change access level of Page

Introduction

Bitwise operators give you the ability to store multiple settings in a single primitive data type (e.g. an integer). This is useful when a single item has potentially more than one setting of the same type.

EPiServer AccessLevel is enum, and if you want to set or remove a AccessLevel, we need to use bitwise operators:

Defining the Flags

To start of with, declare an enum to list all the possible flags. Two things are important when declaring the enum. The first thing you will probably notice is the [Flags] attribute. This is necessary in order to indicate that the enumeration should be treated as a set of flags. The second important thing is assigning a value to each of the items in the enum. The first value should be 1, then just double the value for each consecutive item. The integer type in .NET can store up to 32 flags.

EPiServer.Security
{
 // Summary:
 //     The access levels (bitmapped) that are used to control the various actions
 //     that a user is allowed to perform.
 //
 // Remarks:
 //     Primarily used to control access to page manipulation functions in EPiServer,
 //     but can be used for general-purpose access restriction functions.
 [Serializable]
 [Flags]
 public enum AccessLevel

Setting flags ON:

To set multiple flags, concatenate the desired flags using the bitwise OR symbol “|”:

pageACL.Access |= AccessLevel.Delete;

Setting flags OFF:

pageACL.Access &= ~AccessLevel.Delete;

Testing to see if a certain flag is set:

if ((pageACL.Access&AccessLevel.Delete)==AccessLevel.Delete)


Some sample code

  • Get a PageData by PageLink
  • get ACL list
  • Loop though ACL
  • Remove Delete access right, so no one can delete this page
PageData data = DataFactory.Instance.GetPage(e.PageLink);

 // this page also cannot delete, ignore processing
 if (data.QueryDistinctAccess(AccessLevel.Delete) == false)
 {
     return;
 }

 // modify this page accessright, do not allow to delete
 AccessControlList list = data.ACL.CreateWritableClone();
 foreach (KeyValuePair<string, AccessControlEntry> pair in data.ACL)
 {
 if ((pair.Value.Access & AccessLevel.FullAccess) == AccessLevel.FullAccess)
 {
 list.Remove(pair.Key);
 list.Add(new AccessControlEntry(pair.Value.Name, pair.Value.Access & ~AccessLevel.FullAccess, pair.Value.EntityType));
 }

 if ((pair.Value.Access & AccessLevel.Delete) == AccessLevel.Delete)
 {
 list.Remove(pair.Key);
 list.Add(new AccessControlEntry(pair.Value.Name, pair.Value.Access & ~AccessLevel.Delete, pair.Value.EntityType));
 }
 }
 list.Save(SecuritySaveType.Modify);

dùng Cache trong ASP.NET

Bài này đề cập tới DataCaching của ASP.NET. Các vấn đề outputCaching (cache cả trang aspx) và fragmentCaching (cache một ascx, một phần của trang Aspx) là khá dễ, chỉ cần setup vài thẻ trong mã aspx là xong nên không được đề cập trong bài.

Xem thêm tại http://aspnet.4guysfromrolla.com/articles/022802-1.aspx

Cache về bản chất giống như một HashTable, lưu key là một String, value là đối tượng .NET. Tuy nhiên Cache thì có tính năng đặc biệt là tự động gỡ bỏ các entry theo thời gian hoặc khi hết bộ nhớ để lưu.

Truy xuất Cache:

dùng đối tượng tĩnh HttpContext.Current.Cache
nếu trong Page aspx, dùng Server.Cache
nếu trong ashx, dùng context.Cache

tất cả đều truy xuất đến cùng một chỗ lưu cache của ASP.NET.

Có hai kiểu chính sách hết hiệu lực bạn có thể sử dụng khi lưu giữ dữ liệu trong cache.

  • Absolute expiration: hết hiệu lực vào một THỜI ĐIỂM xác định trong tương lai (VD: 10 phút nữa là huỷ đổi tượng).

Cache.Insert("cacheKey", ObjectToCache, null, DateTime.Now.AddMinutes(10), TimeSpan.Zero);

  • Sliding expiration: gỡ bỏ các đối tượng sau một khoảng thời gian không dùng đến. Mỗi khi đối tượng được truy xuất, thời gian sống của nó sẽ được reset. (VD: loại bỏ các đối tượng mà đã lâu (10 phút) không dùng tới)

Cache.Insert("cacheKey", ObjectToCache, null,DateTime.MaxValue, TimeSpan.FromMinutes(10));

Mẫu code chung để sử dụng Cache là:

T GetValue(){
string CACHE_KEY = "cacheKey";
object oValue = cache[CACHE_KEY];
if (oValue == null) {
oValue = GetValueFromSomeWhere();
// Lưu giữ đối tượng theo kiểu nào tuỳ bạn chọn
cache.Insert(CACHE_KEY, oValue, null, DateTime.MaxValue, TimeSpan.FromSeconds(60));
}
return oValue as T;
}

Hàm GetValueFromSomeWhere() là chỗ bạn lấy dữ liệu thực ở đâu đó (VD lấy từ Database, đọc từ file …)

.

Một  số bonus:
Hàm Cache.Insert() có đối số cuối cùng là CallBack. Tính năng này khá tiện, cho phép developer kiểm soát xem nên làm gì mỗi khi Cache entry bị gỡ bỏ (có thể kiểm tra, tạo lại mới luôn, hoặc thực hiện một số tác vụ …) .  Tips: Dùng cái này có thể tránh được việc pooling để kiểm tra xem Cache entry hết hạn chưa.

Callback này không được khởi chạy nếu cache entry bị gỡ bỏ có chủ ý (bằng cách gọi Remove(), hay gọi Insert() mới đè lên)

Hàm Cache.Insert() nếu cung cấp key trùng với key đã có rồi sẽ gỡ bỏ entry cũ, ấn entry mới vào với key tương ứng ấy