Mike Borozdin's Blog

A blog about programming, web and IT in general

Why I hate PDF as an E-book Format or PDF vs CHM

PDF (Portable Document Format) is a common choice for e-books, big manuals comprising of several hundred pages and other documents. At a first glance, it seems to be a reasonable choice. PDF is a really cross-platform format, the most popular PDF viewer – Adobe Acrobat – is freely available in all popular operating systems – Windows, Mac OS and Linux. But what is wrong with it?

Well, the first of all, it tends to be slow, of course, it might depend on an application you are viewing your document with, but still opening large files in Adobe Acrobat doesn’t seem to be an easy walk. Of course, it’s not the only reason why I think this format is a poor choice for e-books.

There is a significant disadvantage of PDF – its searching capabilities. Frankly speaking, it’s not format’s fault, but a glitch of the current PDF viewers. The problem with searching through PDF is its linearity, I mean, when finding some word or a phrase it will show you every occurrence of that word or phrase from the top of the document to its bottom. Sure, you can open the “Full Reader Search” window, but still it will just represent a list of matched occurrences.  So, it’s not very convenient to search through a 500 pages document for a word that you might find in its bottom or in the middle of the document.

image

Nevertheless, there is a document word that doesn’t have the above mentioned disadvantages. I suppose everyone must be familiar with it. It’s CHM (Microsoft HTML Help). In fact, the format is just a collection of simple HTML pages. But unlike PDF, CHM is quite fast. It supports chapters, yes, PDF does also can contain chapters in the document, but they are no so convenient. In addition, when you open a PDF document, all its contents get loaded at once, while CHM only loads the pages and the chapters you are reading.

And of course the main advantage of CHM over PDF is its search capabilities. When you search through a CHM documents you will get a list of the relevant chapters and pages ordered by their relevancy.  The CHM search engine is also morphological aware.

image

 

In a conclusion I’m going to say that actually it’s quite obvious that PDF is such common as an e-book format because it is the format that is used for submitting books to a printing office and therefore they don’t have to prepare any other kind of documents to publish an e-book, they can just sell PDFs, while creating a CHM file involves a greater amount of work. As a result such e-books don’t have any significant advantages over printed ones. Sure, they don’t take any space on a bookshelf, they are cheaper than paper books and they don’t require cutting wood to create paper, but still they are not very convenient for reading and finding some information.

Anyway, there are some places on the Net where it is possible to find CHM e-books.


Tags:
Posted by Mike Borozdin on Thursday, July 30, 2009 12:17 PM GMT
Shout it Kick it!  
Permalink | Comments (13) | Post RSSRSS comment feed

Working with Google Maps API in ASP.NET

Recently I have been working on a project where I needed to make use of some geographical data and I decided to use Google Maps for that. So, in this particular tutorial I will explain how one can start working with the Google Maps API in ASP.NET.

Basically, the following topic will be covered:

  • How to find a place on the map by address
  • How to let a user choose a place on the map and retrieve its coordinates and save them in a database.

What is Google Maps API?

But first we need to learn some basic of working with Google Maps. As a matter of fact when integrating Google Maps in your application you have to use the Google Maps API, which is in fact just a set of JavaScript functions. As a result you don’t interact directly with the Google Maps API in ASP.NET, I mean server-side, but instead you place your code to client-side and work with JavaScript.

image

 

So, the Google Maps can be used with any server-side technology/language, like ASP.NET, PHP, Ruby on Rails, Python and etc., but this tutorial is about ASP.NET.

Getting Google Maps API Key

The first important step of getting started with the Google Maps API is obtaining the Google Maps API Key. Don’t worry it is free of charge and you receive the key immediately after filling in a form here.

Creating a Simple Map

Okay, now it’s the right time to open Visual Studio and create a new web site.

Then, add the following code to the <head> tag:

 

<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=<YOUR_API_KEY>&sensor=false"
        type="text/javascript"></script>
<script type="text/javascript">
    function initialize() {
        if (GBrowserIsCompatible()) {
            var map = new GMap2(document.getElementById("map"));
            map.setCenter(new GLatLng(51.5, -0.1), 10);
            map.setUIToDefault();
        }
    }

Don’t forget to change <YOUR_API_KEY> to an appropriate value. As you can see we have just one function called initialize() that creates a new instance of the map object. We also pass the object – a div – that will be a map container. Then, we invoke the setCenter() method that receives two arguments –coordinates and a zoom level. The setUIToDefault() method just adds the UI manipulators, if you remove or comment that line, you will receive a bare map without any UI controls.

Also, you need to add some code that will run the initialize() function and the HTML code for the map container.

<body onload="initialize()" onunload="GUnload()">
    <form id="form1" runat="server">
        <div id="map" style="width: 500px; height: 500px"></div>
    </form>
</body>

The code is pretty self-explanatory, it just adds the handlers for the onLoad and onUnLoad events of the page and also we put a div that will contain the map, you can adjust its width and height in order to get a bigger or a smaller map.

After compiling this page you should see a map similar to this one:

image

Finding a place by its address

Well, it was pretty simple, but in real life project you usually have to find a place on the maps by its address. This is also possible with the Google Maps API. All you have to do is to make use of the GClientGeocoder class and its method called getLatLang() that accepts two parameters:

  • address – the address to look for
  • function – a callback function with one parameter point that posses the coordinates of the found place

So, if we want to find a house where Sherlock Holmes lived we have to write the following code:

<script type="text/javascript">
        var map;
        var geocoder;
        function initialize() {
            if (GBrowserIsCompatible()) {
                map = new GMap2(document.getElementById("map"));
                map.setCenter(new GLatLng(51.5, -0.1), 10);
                map.setUIToDefault();

                geocoder = new GClientGeocoder();

                showAddress("221B Baker Street, London, United Kingdom");
            }
        }
        function showAddress(address) {
            geocoder.getLatLng(
                address,
                function (point) {
                    if (!point) {
                        alert(address + " not found");
                    }
                    else {
                        map.setCenter(point, 15);
                        var marker = new GMarker(point);
                        map.addOverlay(marker);
                        marker.openInfoWindow(address);
                    }
                }
            );
        }
        </script>

Also, we create a map overlay that will contain the address information, for this purpose we create an instance of the GMarker class and use the openInfoWindow() method.

User Interaction with Map

Okay, but what if we want to let user enter an address in a form and find its on the map? No problems! Just add the necessary field and write an event-handler.

<script type="text/javascript">
        var map;
        var geocoder;
        function initialize() {
            if (GBrowserIsCompatible()) {
                map = new GMap2(document.getElementById("map"));
                map.setCenter(new GLatLng(51.5, -0.1), 10);
                map.setUIToDefault();

                geocoder = new GClientGeocoder();
            }
        }
        function showAddress() {
            var txtAddress = document.getElementById("<%=txtAddress.ClientID %>");
            var address = txtAddress.value;
            
            geocoder.getLatLng(
                address,
                function (point) {
                    if (!point) {
                        alert(address + " not found");
                    }
                    else {
                        map.setCenter(point, 15);
                        var marker = new GMarker(point);
                        map.addOverlay(marker);
                        marker.openInfoWindow(address);
                    }
                }
            );
        }
        </script>
</head>
<body onload="initialize()" onunload="GUnload()">
    <form id="form1" runat="server">
        <div>
            <asp:TextBox ID="txtAddress" runat="server" />
            <input type="button" value="Find" onclick="showAddress();" />
        </div>
    
        <div id="map" style="width: 500px; height: 500px"></div>
    </form>
</body>

Letting Users to Manually Select a Place on the Map

Well, finding a place by its address is certainly cool, but we can add yet another level of interactivity to our map. Basically, we can let users to use manually choose a place on the map by just dragging a marker.

<script type="text/javascript">
        var map;
        var geocoder;
        function initialize() {
            if (GBrowserIsCompatible()) {
                map = new GMap2(document.getElementById("map"));
                var center = new GLatLng(51.5, -0.1);
                map.setCenter(center, 10);
                map.setUIToDefault();

                var marker = new GMarker(center, { draggable: true });
                map.addOverlay(marker);
                marker.openInfoWindow("Drag the marker to a specific position");

                GEvent.addListener(marker, "dragstart", function() {
                    map.closeInfoWindow();
                });

                GEvent.addListener(marker, "dragend", function() {
                    var hdnLat = document.getElementById("<%=hdnLat.ClientID %>");
                    var hdnLng = document.getElementById("<%=hdnLng.ClientID %>");

                    hdnLat.value = this.getLatLng().lat();
                    hdnLng.value = this.getLatLng().lng();

                    marker.openInfoWindow("New position has been set");
                });
            }
        }
        </script>
</head>
<body onload="initialize()" onunload="GUnload()">
    <form id="form1" runat="server">
        <asp:HiddenField ID="hdnLat" runat="server" />
        <asp:HiddenField ID="hdnLng" runat="server" />
        <div id="map" style="width: 500px; height: 500px"></div>
        <asp:Button ID="btnSubmit" runat="server" Text="Submit" 
            onclick="btnSubmit_Click" />
    </form>
</body>

 

If you look at the HTML code, then you will notice that we have added to hidden field that will contain the coordinates of a chosen place, so the first field is for keeping the latitude and the second one is for keeping the longitude. This time when creating a marker we set its options and one of the option is “draggable: true”, so it lets users to drag the marker over the map. Then, we should add event handlers, the main event is “dragend”. It occurs ever time a user place a marker on a new place. As a result, in its event handler we receive the coordinates of a new position and save them in the hidden fields.

Also, we wrote an event handler for the “dragstart” event, just to close the info window while dragging the marker.

In a real world application there would be some server-side code that would place the received coordinates into a database, but in this particular case, we will just output them:

 

protected void btnSubmit_Click(object sender, EventArgs e)
{
    Response.Write("Latitude: " + hdnLat.Value + " Longitude: " + hdnLng.Value);
}

 

Passing the Coordinates from Server-Side to Google Maps

Now, what if we have the coordinates stores somewhere in the database and want to point to that place on the map? Well, it’s still not difficult. We just have to pass the values from server-side to JavaScript.

<script type="text/javascript">
        var map;
        function initialize() {
            if (GBrowserIsCompatible()) {
                map = new GMap2(document.getElementById("map"));
                
                var lat = <asp:Literal ID="ltrLat" runat="server" />;
                var lng = <asp:Literal ID="ltrLng" runat="server" />;
                
                var center = new GLatLng(lat, lng);
                
                map.setCenter(center, 10);
                map.setUIToDefault();
                
                var marker = new GMarker(center);
                map.addOverlay(marker);
                marker.openInfoWindow("Here");
            }
        }
        </script>

The easiest way to achieve this is to use the ASP.NET Literal controls that doesn’t generate any tags around their values.

Since, those Literal controls are outside of the form tag, we have to use the FindControl() method to access them in code-behind:

protected void Page_Load(object sender, EventArgs e)
{
    Literal ltrLat = (Literal)FindControl("ltrLat");
    Literal ltrLng = (Literal)FindControl("ltrLng");
    
    ltrLat.Text = "51";
    ltrLng.Text = "0";
}

Conclusion

In this tutorial we have covered the basics of working with the Google Maps API. We have learnt how to add a map on a page, how to use geo coding for finding a place by its address on the map. We have also got to know how we can let users interact with a map by dragging a marker and how to receive the marker coordinates and store them on server-side. Finally, we have learnt how to pass the coordinates stored on server-side to the Google Maps API and point to that place on a map.

Also, in this tutorial version 2 of the API was covered, however the 3rd version is currently in Google Labs.

Resources

The main resource for the developers willing to work with the Google Maps API is certainly the Google Code reference page.


Tags:
Posted by Mike Borozdin on Tuesday, July 28, 2009 6:34 AM GMT
Shout it Kick it!  
Permalink | Comments (2) | Post RSSRSS comment feed

Using Live Mesh as a Free Backup Utility

Recently I was looking for a free backup tool that would keep my important documents online and in case any problems with my laptop, I could easily recover them.

I could use my own hosting space, but I thought it wasn’t convenient to manually upload the documents I was constantly working on. So, I decided to look for some automatic solution. Basically, I need the following things:

  • Ability to save the data online
  • Ability to perform automatic synchronization, i.e. when I change a file on my local computer it should get automatically updated on the remote storage and vice versa.

Thus, such things as the built-in Windows utilities that required you save your data on external devices or network drivers wasn’t the thing I was looking for. Moreover, various online services like SkyDrive was still not the best choice, because they just provided an online storage, but didn’t give any mechanism of automatic file synchronization. I also had a look at Live Sync this service was very close to the thing I was looking for, but unfortunately it could only synchronize data only between connected devices, but it didn’t have any online storage. Anyway, I was given an advice to try Live Mesh.

At a first glance Live Mesh is nearly identical to Live Sync, however it has one, but significant difference – it does provide an online storage of 5 GBs which was pretty enough for me.

So, what do you need to do to start backing up important data with Live Mesh? First of all, you need to sign up with it. After that you’ll get an access to Live Desktop where you can create folders and upload files manually. Sure, manual file uploading isn’t the best thing to do and you can download an utility which reside in the system tray and will monitor all the changes of the files you set to synchronize. However, it’s not very clear how one can download the necessary software, in fact, you should select “Add Device" from the main menu.

image

 

After installing the software, you can just select the folder which contents you want to backup in Windows Explorer.

image

And every file you create or edit will be automatically added to your online storage.

Generally, I’m very happy with Live Mesh and would definitely recommend to give it a try. Also, don’t forget that it’s presently in the beta phase, so many features are to come, for example, software for mobile devices, while now you can install it on Windows and Mac.


Tags:
Posted by Mike Borozdin on Wednesday, July 01, 2009 11:09 AM GMT
Shout it Kick it!  
Permalink | Comments (3) | Post RSSRSS comment feed