Showing posts with label Web Development. Show all posts
Showing posts with label Web Development. Show all posts

Google dictionary tooltip – a cool thing

Have you ever seen something on the internet that surprised you a great deal? I saw something cool today that made me realize that there are companies out there like Google© that do clever things in their work even if it is a very small thing. I am talking about Google dictionary extension for chrome which employs some cool techniques to render the tooltip arrow. I have seen a couple of tooltip implementations online like on LinkedIn® and Twitter, but all they do is use an image for the arrow and sometimes complete tooltip balloon as an image. What caught my attention in Google Dictionary balloon was the use of simple plain html divs, and after I dug deeper, I realized there is no magic going on in there. Check this out.

Using chrome on a Wikipedia page for “Programmer”, I look up the meaning of this terminology in Google dictionary.

img-01

 

I do an “Inspect element” to see what styles arrows has.

img-02

 

The div I am interested in is next to the div with class “gd-bubble”, which is just a container for two inner divs which are creating the arrow effect. If you click the second inner div of this container, you can get all the styles. In order to figure out what exactly is happening there, I give some different colors to its borders (left,right and top).

img-04

 

As soon as I give the colors, it (second inner div) will look like this:

img-03

 

Next, in addition to border colors, I now try to change its height and width and see what happens.

img-05

 

It is now time to touch the first inner div as well. We give a green color to its top border (border-top) in order to distinguish it from its sibling (second inner div). The result I get is this:

img-06

 

To my surprise, the tooltip arrow is nothing but just a box with its bottom border (border-bottom) stripped off. Now, In order to give it an arrow shape, what I have to do is reduce its width to zero.

img-07

 

And, changed the height to “auto”.

img-08

Now change the border colors of the second inner div back to “transparent”.

img-09

 

As well as change the border-top color of the first inner div back to “transparent” and there I go. What I get is not a multi-color box, but a nice tooltip arrow pointing downwards.

Untitled-10

 

I know tooltip is not a big thing, but the point is that at times even the smallest thing can make a big difference in the performance of the site. It doesn’t imply at all that using an image will slow down the rendering of the page for the image can be cached, but when I can use native html to accomplish something, then why not.

 

HTH,

Watchout for getElementById bug

Being a web developer targeting IE 7, We should be very careful with the way getElementById method behaves in IE 7. According to getElementById explanation on MSDN:

this method performs a case-insensitive match on both the ID and NAME attributes, which might produce unexpected results

We may NOT see any problem with this method as long as the ID and Name attributes of the controls on the webpage are same (which is the case most of the time). But, when values of these attributes are different e.g. while using a Master Page which mangles ID attributes by appending "_" and Name attribute using "$", getElementById in IE 7.0 might produce unexpected results. Read more about this bug here.

HTH,

ThreadAbortException ― This behavior is by design

If you are coding in .NET and want to transfer a web request from one page to another then you don’t have many options in terms of API to does that for you. You will either use Server.Redirect or Server.Transfer . The former does the client side redirection and later is responsible for server side. The problem with both of them is their dependency on Response.End which in turn calls Thread.Abort that causes ThreadAbortException (Reference: MSDN). To work around this problem Microsoft suggests the followings alternatives:

  1. Using Server.Execute instead of Server.Transfer
  2. Supplying endResponse parameter to Response.Redirect method to suppress the internal call to Resonse.End

In case of not implementing the above will result in showing output of 2 different web pages (caller and callee) in the same web browser window. These alternatives are most likely to work 99% of the time as in general in everyday programming they are not followed by any other statement. And rightly so, why would one write something which is not meant to be executed. This implies that you are completely safe even if:

1. Control comes back from Server.Execute and continues execution on the current page.
2. Response.Redirect transfers control to the other page and due to the presence of endResponse=true parameter, it continues execution on the current page.

just because we don't write any database processing, file processing or any other code logic that follows Server.Execute or Server.Execute. However, in a situation where you must directly use Response.End, you can call HttpContext.Current.ApplicationInstance.CompleteRequest method in lieu of Response.End which bypasses the code execution of Application_EndReqeust event (Reference: MSDN).

If you are thinking as I was thinking that it's a bug in .NET, then you are wrong. MSDN explains that this is not a bug but a behavior by design. However, I would really love to see that real world usage of this behavior in everyday programming that could justify this design decision.

References:

File "Save As" issue while downloading with Content-Disposition: inline

It has been a long a time since I wrote anything on the blog. I was on a long holiday and (honestly speaking) wanted to stay away from the technology. But now, since life is back on rails, let's start with the very first issue I faced after I joined my workplace a couple of days ago. It is about an issue with the file name not being considered when using "inline" as HTTP response Content-Disposition header.

Downloading a file using Content-Disposition: attachment as HTTP response header displays a "File Download" dialog box asking the user whether to "Open", "Save" or "Cancel" the document. In certain scenarios this dialog box can be really painful specially when user has to repeatedly do this exercise for multiple links available on our website. In order to avoid this we use Content-Disposition: inline which opens the document without asking by using appropriate software like MS Word, Adobe Acrobat Reader etc. installed on the user's machine. This document can be saved later on using "Save As" option.

Before I move on, let's have a look on the following statement that shows the way to add Content-Disposition header to Response stream:

context.Response.AddHeader("Content-Disposition", "inline; filename=resume.doc")

The problem with the Content-Disposition: inline is that it doesn't pick the file name from filename attribute we use in AddHeader function rather, it always takes the name of web page from the URL while saving the document. Content-Disposition: attachment seems to be working fine even with the "Save As" command, but this is something I didn't want to use. I spent some time researching on this issue and couldn't found a workable solution. In order to workaround I came up with the below solution that seems to be doing the job.

I actually decided to use a URL for the document link that reflects the name of the document being downloaded. For example for the document "MyResume.doc", the URL I have used looks something like this:

<a href="Default/FileName/882bd3e9-5035-4946-8c2a-98ef0eccc6e0/uploads/MyResume.doc.aspx">Download File</a>

Did you notice ".aspx" at the end of the URL? It is very important to append it in the end in order to send the request back to server whenever user clicks on the link. On the server, I have created an HTTPHandler to catch this sort of request that contains "*.doc.aspx". Without appending ".aspx", browser will server your document directly without changing the URL in the browser. But, we want to change the URL which means request has to go to the server.

The rest of the solution is very easy as I have written below code under the body of ProcessRequest function in my HTTPHanlder which helps dump file contents into response stream. It is also important to note that URL of the document must be relative and not absolute. The reason being, it's a dummy URL which doesn't exist at all. Relative URL guarantees that request will come to the same web site/application where we can catch it before it goes to ASP.NET engine. QueryString data can be made part of the URL as in my case GUID is the piece of information which is part of the URL and I receive it on the server.


Public Sub ProcessRequest(ByVal context As System.Web.HttpContext) Implements System.Web.IHttpHandler.ProcessRequest

'Context.RewritePath("Test-Page.aspx")
context.Response.ContentType = "application/msword"
context.Response.AddHeader("Content-Disposition", "inline; filename=adeel.doc")
context.Response.TransmitFile("C:\inetpub\wwwroot\Uploads\882bd3e9-5035-4946-8c2a-98ef0eccc6e0.doc")
context.Response.Flush()
context.Response.End()

End Sub


The last bit is to add the below statement in web.config to enable HTTPHandler to catch "*.*.aspx" so that it will serve for all kinds of file type extensions.

<add verb="*" path="/uploads/*.*.aspx" type="Test.HttpHandler, Test"/>

Uploading files using HTTPWebRequest

I want to upload a file but can't use html input file control as I don't have any html page in my application. I am into a situation where i want to utilize all the power of HTTP protocols and internet media types like POST and multipart/form-data respectively without using any html control. This situation is not very rare and most likely you will face it while creating an automatic batch file upload utility where this is no chance of manual intervention hence no possibility of using html input file control.

Since I am using .NET, I can use low level HTTPWebRequest to upload files to webserver. This class helps simulate manual upload using ContentType=multipart/form-data. multipart/form-data can be used for forms that are presented using representations other than HTML (spreadsheets, Portable Document Format, etc), and for transport using other means than electronic mail or HTTP.

An important aspect of uploading files is the way web request is structured where every form value has to start with --{boundary} and full web reqeust has to end with --{boundary}--. This can be seen by debugging the request using any web request debugging tools like Fiddler while uploading through html input file control. We will have to immitate the same request format in order for it to be accepted by web server. Let's quickly mention some of the important parts of this request that we need to set in order to successfully upload a file.

  • ContentType: Multipart/form-data
  • Request Method: Post
  • Content-Disposition: form-data
  • Boundary: Guid

The reason to use multipart MIME type is that its is used by file upload which has a more complicated than a simple post. For a detailed explanation you can read the RFC2388 - Returning Values from Forms: multipart/form-data. For boundary we can use Guid as this is value that should not occur in any of the form value.

The funciton UploadFile() mentioned below uploads a file along with 2 other form values using the parameters mentioned above. Apart from them, HTTPWebRequest.Headers can also be used to supply credentials if our server requires authentication.

Request: (UploadFile.aspx)

Private Sub UploadLocalFile()

Dim objWebReq As HttpWebRequest
Dim memStream As MemoryStream = Nothing
Dim writer As StreamWriter = Nothing
Dim newLine As String = vbCrLf
Dim fileContent As Byte() = Nothing
Dim fileText As String = Nothing
Dim rStream As Stream = Nothing
Dim webResponse As HttpWebResponse = Nothing
Dim stReader As StreamReader = Nothing
Dim output As String = Nothing

Try

Dim boundary As String = Guid.NewGuid().ToString().Replace("-", String.Empty)
Dim obj As Object = HttpWebRequest.Create("http://localhost:3860/ReceiveFile.aspx")

objWebReq = CType(obj, HttpWebRequest)

objWebReq.ContentType = "multipart/form-data; boundary=" + boundary
objWebReq.Method = "POST"
objWebReq.Headers.Add("loginName", "{username}")
objWebReq.Headers.Add("loginPassword", "{password}")

memStream = New MemoryStream(100240)
writer = New StreamWriter(memStream)

'Feed ID
writer.Write("--" + boundary + newLine)
writer.Write("Content-Disposition: form-data; name=""{0}""{1}{2}", "FeedID", newLine, newLine)
writer.Write("10250")
writer.Write(newLine)

'Feed Category
writer.Write("--" + boundary + newLine)
writer.Write("Content-Disposition: form-data; name=""{0}""{1}{2}", "FeedCategory", newLine, newLine)
writer.Write("Automotive")
writer.Write(newLine)

'XML File
writer.Write("--" + boundary + newLine)
writer.Write("Content-Disposition: form-data; name=""{0}""; filename=""{1}""{2}", "XMLfile", "C:\Users\Irfan\Desktop\feed-automotive.xml", newLine)
writer.Write("Content-Type: text/xml " + newLine + newLine)
writer.Write(File.ReadAllText("C:\Users\Irfan\Desktop\feed-automotive.xml"))
writer.Write(newLine)

writer.Write("--{0}--{1}", boundary, newLine)

writer.Flush()

objWebReq.ContentLength = memStream.Length
rStream = objWebReq.GetRequestStream()
memStream.WriteTo(rStream)
memStream.Close()

webResponse = objWebReq.GetResponse()
stReader = New StreamReader(webResponse.GetResponseStream())
stReader.ReadToEnd()
output = stReader.ReadToEnd()

Response.Write(output)

Catch ex As Exception

Response.Write(ex.Message)

End Try

End Sub

Response: (ReceiveFile.aspx)

Private Sub ReceiveFile()

Dim reader As System.IO.StreamReader = Nothing

Try

If Not Reqeust.Files.Count > 0 AndAlso Not Request.Files("XMLFile") Is Nothing Then
reader = New System.IO.StreamReader(Request.Files("XMLFile").InputStream)
System.IO.File.WriteAllText("c:\feed.xml", reader.ReadToEnd())
Else
Response.Write("No feed file received in the request.")
End If

Catch ex As Exception
Response.Write(ex.Message)
End Try

End Sub

Checklist for Multilingual website development

I sometimes wish if i could have a checklist or to do list to follow before actually starting developing something new. Checklists are great as they, in certain situations, prove to be more helpful than full length articles due to their short and precise nature. The checklist I am going to propose in this post is solely for those who want to have some idea about multilingual websites and the core steps involved in developing them. By just skimming through the steps below, one can calculate the amount of time required to translate a website into a another language. This checklist is nothing but merely a set of suggestions and recommendations based upon my very recent experience that I had while translating a website from English to Arabic.
  • First and foremost, a seperate style sheet can be created for each language. I have created two in my project en-US-main.css and ar-SA-main.css. Using a separate style sheet while doing the translation guarantees that the existing design and layout will remain intact.

  • We should never embed any content or label text/values directly into html page like this:
    <p>embedded text.</p>
    <input id="lblFirstName" type="label">First Name</input>
    <input id="lblLastName" type="label">Last Name</input>

    By using the above approach, we take away the privilege that we get through resource files to switch culture specific content at runtime. It is a best practice to create language specific resource files like *.RESOURCE or *.RESX which help setting labels and messages on the fly. In the below code i am calling GetLabelTring() function which pulls labels values either from en-US.resouces file or ar-SA.resources based upon the selected culture.
    <p>GetLabelString("L1000") </p> {html side}
    lblFirstName.Text = GetLabelString("L1001") {ASP side}
    lblLastName.Text = GetLabelString("L1002") {ASP side}

  • The current culture can be saved into session variables which will help maintain the same language across all of the pages for a specific session.

  • The labels and messages can be cached if the frequency of their modification is low which will result in better performance and speed.

  • We can use HTML DIR attribute if the language we are targeting is written right to left such as Arabic and Hebrew. This attribute specifies the base direction (RTL, LTR) of text, or sections of text.

    HTML Markup









    Resulting Display










    We can also specify a single base direction for all of the content available on the website by using the DIR attribute with HTML tag.

  • For everything else on the page other than content can be controlled through style sheets. If our website is blessed with DIV-based layout, we can be rest assured that the style sheet attributes such as float, background-position and margin/padding etc. will take care of the direction (right-to-left / left-to-right) for most of the HTML elements.

  • That’s all from the HTML side. I would like to add a couple of bits here in regards insertion of multilingual text in the database table. The idea is to insert a separate row for every culture and do it for all of the content pages of the website. Of course, we need to enable the Unicode support on the table.


    RecID

    PageName

    PageText

    LangID

    PageID

    PageTitle

    101

    My Website Home Page

    Welcome to my page

    1

    2002

    Home Page

    102

    الصفحة الرئيسية الموقع الخاص بي

    مرحباً بك في الصفحة الخاصة بي

    2

    2002

    الصفحة الرئيسية (Home Page)



  • Last but not least, there are many free translation tools available on the internet that can be of great help for cross-checking the content between the languages. Two such great tools that I have extensively used are Bing Translator and Google Translate.