M.Efe Ozer’s Weblog

November 18, 2009

Google Visualization Api : Geo Map and Table

Filed under: Asp.Net — Tags: , , — Mehmet Efe Ozer @ 2:22 pm

 

Google Visualization Api is very easy to use and effective. It has very well documentation, lots of examples. Google Visualization Api

It can work different data sources. Google docs as datasource is an another interesting point.

In this sample i used my georss formatted xml file as datasource. Json formatted data called by Jquery.Ajax from PageMethods  .

You can check this article as my starting point

http://www.aspsnippets.com/post/2009/09/04/Drilldown-Maps-using-Google-Geomap-in-ASPNet.aspx

in this sample we need

for Countries; Country(string),Countrycode(string), Visit(number)

for Cities; lat(number), lon(number),Visit(number) and City(string)

Because of Cities  located by latitude and longitude we don’t need to referance google map api. (if city names will be used, we need to add that)

these are my datatables that different from drilldown article:

for countries:

var data = new google.visualization.DataTable();
    data.addRows(response.d.length);
    data.addColumn('string', 'Country');
    data.addColumn('number', 'Visit');
    for (var i = 0; i < response.d.length; i++) {
        data.setValue(i, 0, response.d[i].Country);
        data.setValue(i, 1, response.d[i].Visit);
    }

 

for cities:

var data = new google.visualization.DataTable();
    data.addColumn('number', 'LATITUDE', 'lat');
    data.addColumn('number', 'LONGITUDE', 'lon');
    data.addColumn('number', 'Visit', 'Visit');
    data.addColumn('string', 'City', 'City');

    data.addRows(response.d.length);
    for (var i = 0; i < response.d.length; i++) {
        data.setValue(i, 0, response.d[i].lat);
        data.setValue(i, 1, response.d[i].lon);
        data.setValue(i, 2, response.d[i].Visit);
        data.setValue(i, 3, response.d[i].City);
    }

In api also we can create dataviews. You can hide and reorder columns or filter source datatable with dataviews. Below implementation for city datas.

var table = new google.visualization.Table(document.getElementById('table_div'));
    var dv = new google.visualization.DataView(data);
    dv.hideColumns([0, 1]);
    dv.setColumns([3, 2])
    table.draw(dv, { showRowNumber: true });

In master(country), detail(cities) structure; country codes using as key so they should be right. Also Country names should be recognized by api. (example for Russia you need to use RU as country name, otherwise not shown on country map.)

Here is the link of my GeoMap Sample (Click on the countries for city details and click zoom out for back)

Here are screens

Country Level Visitors Map

countrymap

 

 

City Level Visitors Map

cityvisitors

October 5, 2009

Jquery Plugins From Malsup Dot Com

Filed under: Asp.Net, jquery — Tags: , — Mehmet Efe Ozer @ 12:26 am

 

I really like http://malsup.com/jquery/ plugins, here will be mentioned about Jquery.Corner, Jquery.BlockUI and Jquery.cycle. They all are very good documented, developer friendly and got very good demos.

Highly recommend to look their help pages for more information, written below are very limited to compare their capacities.

Jquery.Corner

Add corners easly to your divs with given parameters

$(‘#maintabs’).corner(); //basic round shape corners

Demo page shows other styles : http://malsup.com/jquery/corner/

Jquery.BlockUI

One of the famous with cycle plugin. Mainly use for blocking user interface. I also used it like loading animation. You can block all page or selected elements. Also can use for modal windows.

Basic use with custom message : $(#containerid).block({ message: msg });

For unblock : $(#containerid).unblock();

If you don’t like default CSS, you can override with:

$.blockUI.defaults.css = {};

With jquery’s extendable structure we can extend $.ajax too. If you aim block all user interface while ajax doing its work, with code below you can handle all of them with one time definition.

$(document).ready(function() {

$().ajaxStart($.blockUI).ajaxStop($.unblockUI);

});

Or you can start blocking in $.ajax.beforeSend and unblock in $.ajax.complete in specific ajax requests. $.ajax.complete is called regardless of if the request was successful, or not. So, for unblock $.ajax.error or $.ajax.success are other options. It is better take a look here: http://docs.jquery.com/Ajax_Events

Jquery.Cycle

I guess most known plugin here. You probably saw it in a lot of list of plugins posts in blogs. My beginning times when I was looking for a gallery plugin, i interested more with some complete, fancy solutions than Jquery.Cycle. But after tried others for reasons like no pagination, low performance or no extensibility problems, started to write my own gallery. (My own gallery means here prepare data for cycle and some required modifications)

I was thinking about to put some codes, but its “options”, “tutorials”, “even more demos” pages are already great.

Here my gallery built with cycle http://www.inaea.org/InAEAGallery.aspx

I mentioned about that in this post : http://mefeozer.wordpress.com/2009/10/03/new-image-gallery-work/

 

Beside these plugins I used some other authors plugins like prettyPhoto, fitted, hoverintent. I will write about them later.

Note : These plugins are used in non-profit educational organization website’s gallery application and no commercial profit for myself too.

October 3, 2009

New Image Gallery Work

Filed under: Asp.Net, BlogEngineNet, News — Tags: , , , — Mehmet Efe Ozer @ 6:19 pm

Finally i am completing (also still testing) gallery application. There is some visual changes can be in later days. Also more features (like error catching etc.) still in progress.

This is on a BlogEngine based website, used different master page then website general.It got it’s own page, not created by BlogEngine but inherits BlogEngine.Core.Web.Controls.BlogBasePage. User brief’s from BlogEngine profiles, album and photo info saved in xml files.

When you open the page you will see user’s brief summary and their galleries. When you point on users, cursor is pointer, but not linked with another pages yet. I am working on user pages. But important part is clicked on galleries, with this way you can browse related gallery photos.

User Gallery

UserGallery

Gallery Page

BrowseGallery

I used jquery and some plugins that i will write about them later days.

It also accepts query strings like:

http://www.inaea.org/inaeagallery.aspx =>start from all user galleries

http://www.inaea.org/inaeagallery.aspx?username=sandrine =>start from specified user’s gallery list

http://www.inaea.org/inaeagallery.aspx?username=sandrine&albumid=sandrinesartwork =>start from specified user’s specified gallery

If you found any bug, share any thought or ask any question feel free to comments.

June 27, 2009

CascadingDropDown ( AjaxControlToolkit ) and PageMethods

Filed under: Asp.Net, Notes to Myself — Tags: , — Mehmet Efe Ozer @ 2:48 pm

 

When i looked cascading dropdowns of AjaxControlToolkit at first i confused so i gave up and wrote my own client scripts. But i found a very easy example in my code sample archive, so here it is.

What i need is 2 pagemethod for populate dropdown items and 1 ( or 2 ) for get values from them. Values in dropdownlists are type of “CascadingDropDownNameValue” . It needs name and value.

In client side scriptmanager “EnablePageMethods” attribute should set true. Extender codes are below :

<ajaxToolkit:CascadingDropDown runat="server" ID="cdd1"
TargetControlID="ddl1" PromptText="Select Type" Category="type" LoadingText="[Loading]"
   
ServiceMethod="GetType" />
<
ajaxToolkit:CascadingDropDown runat="server" ID="cdd2"
TargetControlID="ddl2" ParentControlID="ddl1"
   
PromptText="Select Content" Category="content"
   
LoadingText="[Loading]" ServiceMethod="GetContent" />

start

Attributes are describe themselves. So there are two dropdownlist (ddl1,ddl2) and two PageMethods (“GetType”,”GetContent”) needed.

My aim is populate BlogengineNet’s categories or posts in sub dropdownlist. “CascadingDropDownNameValue[]” is need to returned.

using System.Web.Services; using AjaxControlToolkit;

 

[WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public staticCascadingDropDownNameValue[]
           GetType(stringknownCategoryValues, stringcategory)
    {
            return new[] {
        newCascadingDropDownNameValue("category", "category"),
        newCascadingDropDownNameValue("post", "post") };
      }

    [WebMethod]
    [System.Web.Script.Services.ScriptMethod]
    public staticCascadingDropDownNameValue[]
           GetContent(stringknownCategoryValues, stringcategory)
    {
            if(knownCategoryValues.Contains("category"))
            {
                return(BlogEngine.Core.Category.Categories
                      .Select(c =>
                          newCascadingDropDownNameValue
                        
{ value = c.Id.ToString(), name = c.Title }).ToArray());

            }
            else if(knownCategoryValues.Contains("post"))
            {
                return(BlogEngine.Core.Post.Posts
                      .Select(c =>
                          newCascadingDropDownNameValue
                        
{ value = c.Id.ToString(), name = c.Title }).ToArray());
            }
    }

How values populated are below.

ddl1

ddl2

 

Finally, how are we going to take values? I used a client script which communicate with another pagemethod. In client side, dropdowns “onchange” event:

<asp:DropDownList runat="server" ID="ddl1"
                            onchange="GetSubDDLContent(this.options[this.selectedIndex].value
                            ,this.options[this.selectedIndex].text,'1')"
                                Width="200" />

<asp:DropDownList runat="server" ID="ddl2"
onchange="GetSubDDLContent(this.options[this.selectedIndex].value
,this.options[this.selectedIndex].text,'2')"
    Width="200" />

GetSubDDLContent takes 3 params (third one is non smart identifier for which dropdown sent to value).

Client side:

<scripttype="text/javascript">

     
       function
GetSubDDLContent(id, title, controlid) {

           var param = newArray();

           param[0] = id;

           param[1] = title;

           param[2] = controlid;

           PageMethods.GetSubDDLContent(param,

     OnSubRequestComplete, OnError);

       }

       function OnSubRequestComplete(result) {

//do something

       }

       function OnError(result) {

    //do something      
       }

         
   </script>

On Server Side GetSubDDLContent pagemethod: ( return type is not important )

[WebMethod()]
    [System.Web.Script.Services.ScriptMethod()]
    public static Boolean GetSubDDLContent(IList values)
    {
        if (values[2].ToString() == "1")
        {
          //first dropdown sent 
        }
        else if (values[2].ToString() == "2")
        {
          //second dropdown sent
        }
        return true;
    }
At the end cascadingdropdowns work with pagemethods…

June 4, 2009

BlogEngine Main Menu Extension (just a post, nothing for download)

Filed under: Asp.Net, BlogEngineNet, Notes to Myself — Tags: , , , — Mehmet Efe Ozer @ 1:02 am

 

NavLinkExtension

Admin page of DnANavBar Extension

It was an requirement for who wants to change main menu items and its orders of website from admin panel.

I may publish it, but it is using AjaxControlToolKit and .Net 3.5, so not for now.

I was not so happy with ReorderList control of AjaxCT. When items reordered, update method triggered without  problem, but when update fields with its edit item template, i couldn’t reach the data of item except than index field. In articles people talk about parameters must match in select and update methods. Anyway, i did my updates in OnItemCommand event.

I am thinking about to look JQuery’s drag and drop features next…

May 6, 2009

PrettyPhoto Extension For BlogEngine.Net

Filed under: Asp.Net, BlogEngineNet — Tags: , , , — Mehmet Efe Ozer @ 11:18 pm

I was using Lightbox2 for displaying pictures of posts in a BlogengineNet based website InAEA , but with jquery implementation plans, i decided to use jquery all over the website and found similar Lightbox2 script : PrettyPhoto .

I made little changes on Lightbox2 extension and done. My client websites low traffic and it works well for now. But some code parts can better, for example “Item_Serving” function. I don’t know could cause performance problem or not.

prettyphoto

Some Notes:

  • Current version 2.5.4 Current version 2.5.4.1
  • This extension works with PrettyPhoto Version 2.2.7 This extension works with PrettyPhoto Version 2.5.4 ( update)
  • Now some options (like theme) be able to set in extension page ( edit extension added ) (update)
  • JQuery required. “jquery-1.3.2.min.js” which i used jquery script, (but i didnt add with this extension, you can find an another extension about add jquery to blogengine, don’t want to my own extension before try with another jquery applications.)
  • Placed prettyphoto.cs to “app_code/extensions” and “prettyphoto” folder to root. ( wrote in readme.txt )
  • I just hardcode default path for folder as;

private const string defaultPath = “prettyPhoto”;

actually easy that you need to add rel tag to images like

for single photos => rel=”prettyphoto”

for photos as gallery  => rel=”prettyphoto[ galleryname ]” (without spaces)

DOWNLOAD prettyPhotoExtension

Please write comment for any problem or suggestions…

April 9, 2009

Linq and Group By Multiple Columns

Filed under: .Net, C#, Notes to Myself — Tags: , — Mehmet Efe Ozer @ 2:08 pm

Update Note : I totally delete my own sample , i will put grouping samples from LinqPad and if i found any other good examples.

Grouping by Multiple Keys :

I changed little

from n in new[] { “Tomm”, “Tick”, “Harry”, “Mary”, “Jay” }.AsQueryable()
group n by new
{
FirstLetter = n[0],
Length = n.Length
}
into g
select new {Category=g.Key, word= g.Count() }

 

Nested Grouping :

var query =
from o in Orders
group o by o.ShipCountry into countryGroups
select new
{
Country = countryGroups.Key,
Cities =
from cg in countryGroups
group cg.ShipPostalCode by cg.ShipCity into cityGroups
select new
{
City = cityGroups.Key,
PostCodes = cityGroups.Distinct()
}
};

 

Find Duplicates Using Linq

How to: Query for Duplicate Files in a Directory Tree (LINQ)

 

April 1, 2009

Asp.Net CacheDependency and its Callbacks

Filed under: Asp.Net, C# — Tags: , , , — Mehmet Efe Ozer @ 11:14 pm

 

I am working on a little bit complicated work to reach some information from Second Life.  I need to use a library to do my requests, process them with my classes and need to present on an asp.net website. I will write something about it later.

Just before presentation layer, last callback needed for informed all requested data saved on a xml file. So find a way to track this file is one of the way to handle this problem.

So i decided use cache dependency and CacheItemRemovedCallback.

With cache dependency you create a dependency on a file, on a folder or cached item or items. When your item or items is changed, your dependent item removed from cache.

And it provides two callback that you can catch your item before removed ( CacheItemUpdateCallback ) or after removed( CacheItemRemovedCallback ) from cache.

An important point that these callbacks work with first change on tracked item.So you need to finish your own jobs on your file before creating dependency.  But it gives some options like start to track after definite time past. You need to take a look its overloads.

In my scenario after i reached my data i save it as xml file. File needs to be there so i will create if not. I send a key value pair that i can use in callback for example to understand what is changed in my data file and what was my datafilepath. Xml file creation part is depends on your needs, i just add a root node and an attribute. 20 minute set here for expiration.

private void SetDependency(stringdatafilepath)
    {
       
        XDocument dataxml = newXDocument();
        if(!System.IO.File.Exists(datafilepath))
        {
            dataxml.Declaration
                = newXDeclaration("1.0", "utf-8", "");
            dataxml.Add(newXElement("rootnode"
              
, newXAttribute("rootnodeattr"
                  
, DateTime.Now.ToString())));
            dataxml.Save(datafilepath);
        }
        else
      
{
            dataxml= XDocument.Load(datafilepath);
        }
        CacheDependency dep = newCacheDependency(datafilepath);
        Cache.Insert("keyforitem"
          
, new KeyValuePair<string, XDocument>(datafilepath, dataxml)
            , dep
            , DateTime.Now.AddMinutes(20)
            , TimeSpan.Zero
            , CacheItemPriority.High
            , newCacheItemRemovedCallback(ItemRemovedCallback));
    }

Cachedependency item put in cache with key “keyforitem”, set its value as an keyvaluepair, set 20 mins expiration time. I didn’t try other priority options like “noremove” or else here. (When server resources full server removed items from cache with theirs priority orders.) And finally we assign ItemRemovedCallback.

In my sample i don’t need to use CacheItemUpdateCallback.

Here is CacheItemRemovedCallback

private void ItemRemovedCallback(string key
        , object prevalue, CacheItemRemovedReason reason)
    {
        switch (reason)
        {
            case CacheItemRemovedReason.DependencyChanged:
                {
//my jobs here
                  break;
                }
        }
    }

Dependency Item could be removed from cache by different reasons. Cache priority can be an answer if item removed by memory problems. This sample works on low traffic website so i didn’t faced with problems, also only person is me who change file here.

At the end, if reason is dependencychanged means in this conditions process works ok.

March 10, 2009

Create Data File for SlideShow2 From Picasa Web Albums

Filed under: .Net, BlogEngineNet, Code Stuff — Tags: , , , , , — Mehmet Efe Ozer @ 6:56 pm

I was using SlideShow extension of Danny Douglas. I installed, changed it into xml data provider and used with local photo files.  But after start to thinking about membership system, necessity occurred  uploading and crud operations on albums. Even i coded some management features for local data and photo files. But storage of files,web traffic and one developer dependant management system were other issues that make me stop. So first i start to use Flickr Api. It gives options what i want to do, but for current project i start to work on Picasa Web Albums Data API.

For BlogEngine application that i modified i tried first Rtur.Net’s Picasa Extension.

When you login with your email as in extension’s admin panel you are authenticate to do CRUD options on your albums. But also i was looking for something without login (so no CRUD ) and show it in SlideShow2 which also support Flickr and xml data files.

I like SlideShow2 because customization is so easy in its project structure.

I saw some works for Picasa data provider on project discussions. But this time for some reasons i want to use XML data file for show photos.

So long story short what i did is below. It is based on read Picasa feeds with Google.GData methods and create a xml file with XLinq. I didn’t filter any album or photo, but you can do with using  XLinq.

We need Google.GData.Apps, Google.GData.Client, Google.GData.Extensions, Google.GData.Photos

from here : http://code.google.com/p/google-gdata/downloads/list

Public Shared Sub CreatePicasaSlideShowData()

        Dim service As PicasaService = New PicasaService("myapplicationname")

        dim PicasaUserID as string = "mypicasauserid"

        Dim query As AlbumQuery = New AlbumQuery(PicasaQuery.CreatePicasaUri(PicasaUserID))
        Dim albumfeed As PicasaFeed = service.Query(query)

        Dim xdoc As New XDocument

        xdoc.Declaration = New XDeclaration("1.0", "utf-8", "")
        xdoc.Add(<data startalbumindex="0" transition="CrossFadeTransition"></data>)

        xdoc.Element("data").Add(From albumentry In albumfeed.Entries _
         Let albumAccessor As AlbumAccessor = New AlbumAccessor(CType(albumentry, PicasaEntry)) _
         Let photoquery As PhotoQuery = New PhotoQuery(PicasaQuery.CreatePicasaUri(PicasaUserID, albumAccessor.Id)) _
         Let photofeed As PicasaFeed = service.Query(photoquery) _
             Select New XElement("album" _
                , New XAttribute("title", albumAccessor.AlbumTitle) _
                , New XAttribute("description", albumAccessor.AlbumSummary) _
                , New XAttribute("source", CType(albumentry, PicasaEntry).Media.Thumbnails(0).Attributes("url")) _
                , New XAttribute("transition", "CrossFadeTransition") _
                    , From photoentry In photofeed.Entries _
           Let photoAccessor As PhotoAccessor = New PhotoAccessor(CType(photoentry, PicasaEntry)) _
                        Let photoe As PicasaEntry = CType(photoentry, PicasaEntry) _
                    Select New XElement("slide" _
                        , New XAttribute("title", photoAccessor.PhotoTitle) _
                        , New XAttribute("description", photoAccessor.PhotoSummary) _
                        , New XAttribute("source", photoe.Content.AbsoluteUri) _
                      , New XAttribute("thumbnail", photoe.Media.Thumbnails(1).Attributes("url")) _
                      , New XAttribute("link", String.Empty) _
                      , New XAttribute("datetaken", photoe.Updated.ToShortDateString))))

        xdoc.Save("mydata.xml")
End Sub

You can change thumbnail formats, add “link” for pictures ( i left empty), and find a sensible date field from feed for “datetaken” field or change transition type.


February 27, 2009

GateKeeper on BlogEngineNet

Filed under: Asp.Net, BlogEngineNet — Tags: , , — Mehmet Efe Ozer @ 5:37 am

I was complaining about spiders and crawler entries on my visitor map. It is not only matter of visitor accuracy but also they using traffic. I wrote a http module for blocking some ip numbers which tried my registration page also. But all my works about unwanted visitors were lack of management.

Now I am using GateKeeper of Chris Blankenship and it is working good for me. Has easy implementation and very good admin panel. When i checked honeypot violation’s ip numbers, i found diffrent spider locations than i’ve already know before.

I allowed some known user agents. They are storing in a xml file, so i still could prevent their entires from my visitor map. I added a little extra check to my codes like this :

Add a function to my visitor tracking class that returns ip number is known spider or not:

Public Shared Function IsAllowedSpider(ByVal ip As String) As Boolean

        Return XDocument.Load(AllowedSpiderListDataFilePath) _
        .Descendants.Elements("ipaddress").Elements("entry") _
        .Where(Function(f) f.Attribute("ipaddress").Value = ip).Count > 0

        Return False
End Function

I still suspicious about visitors from some cities but i eliminated a lot.  By the way map is here (little patience for loading map :) ).

Older Posts »

Blog at WordPress.com.